diff --git a/core/lib/Drupal/Component/Discovery/YamlDiscovery.php b/core/lib/Drupal/Component/Discovery/YamlDiscovery.php index 5784e3a..bf4ee15 100644 --- a/core/lib/Drupal/Component/Discovery/YamlDiscovery.php +++ b/core/lib/Drupal/Component/Discovery/YamlDiscovery.php @@ -29,15 +29,6 @@ class YamlDiscovery implements DiscoverableInterface { protected $directories = array(); /** - * Array of all parsed files, keyed by filename. - * - * Especially during kernel tests, YAML files are re-parsed often. - * - * @var array - */ - protected static $parsedFiles = array(); - - /** * Constructs a YamlDiscovery object. * * @param string $name @@ -57,11 +48,9 @@ public function __construct($name, array $directories) { public function findAll() { $all = array(); foreach ($this->findFiles() as $provider => $file) { - if (!isset(static::$parsedFiles[$file])) { - static::$parsedFiles[$file] = Yaml::decode(file_get_contents($file)); - } - $all[$provider] = static::$parsedFiles[$file]; + $all[$provider] = Yaml::decode(file_get_contents($file)); } + return $all; } diff --git a/core/lib/Drupal/Component/PhpStorage/MTimeProtectedFastFileStorage.php b/core/lib/Drupal/Component/PhpStorage/MTimeProtectedFastFileStorage.php index 73486a8..adf3d9f 100644 --- a/core/lib/Drupal/Component/PhpStorage/MTimeProtectedFastFileStorage.php +++ b/core/lib/Drupal/Component/PhpStorage/MTimeProtectedFastFileStorage.php @@ -70,7 +70,7 @@ public function save($name, $data) { // Write the file out to a temporary location. Prepend with a '.' to keep it // hidden from listings and web servers. - $temporary_path = tempnam($this->directory, '.'); + $temporary_path = drupal_tempnam($this->directory, '.'); if (!$temporary_path || !@file_put_contents($temporary_path, $data)) { return FALSE; } @@ -103,7 +103,7 @@ public function save($name, $data) { // iteration. if ($i > 0) { $this->unlink($temporary_path); - $temporary_path = tempnam($this->directory, '.'); + $temporary_path = drupal_tempnam($this->directory, '.'); rename($full_path, $temporary_path); // Make sure to not loop infinitely on a hopelessly slow filesystem. if ($i > 10) { @@ -112,7 +112,11 @@ public function save($name, $data) { } } $full_path = $this->getFullPath($name, $directory, $mtime); + print_r("rename\n"); + print_r($temporary_path . "\n"); + print_r($full_path . "\n"); rename($temporary_path, $full_path); + print_r("rename end\n"); $i++; } return TRUE; diff --git a/core/lib/Drupal/Core/StreamWrapper/StreamWrapperManager.php b/core/lib/Drupal/Core/StreamWrapper/StreamWrapperManager.php index 101980d..9882266 100644 --- a/core/lib/Drupal/Core/StreamWrapper/StreamWrapperManager.php +++ b/core/lib/Drupal/Core/StreamWrapper/StreamWrapperManager.php @@ -210,6 +210,13 @@ public function getClass($scheme) { return $this->info[$scheme]['class']; } + // Try to find it in wrappers. + foreach ($this->wrappers as $type => $wrappers) { + if (isset($this->wrappers[$type][$scheme])) { + return $this->wrappers[$type][$scheme]['class']; + } + } + return FALSE; } @@ -249,7 +256,7 @@ protected function getWrapper($scheme, $uri) { public function addStreamWrapper($service_id, $class, $scheme) { $this->info[$scheme] = array( 'class' => $class, - 'type' => $class::getType(), + 'type' => method_exists($class, 'getType') ? $class::getType() : StreamWrapperInterface::ALL, 'service_id' => $service_id, ); } diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php index 1915d75..2f59c1a 100644 --- a/core/modules/simpletest/src/KernelTestBase.php +++ b/core/modules/simpletest/src/KernelTestBase.php @@ -23,6 +23,7 @@ use Drupal\Core\Site\Settings; use Drupal\simpletest\AssertContentTrait; use Drupal\simpletest\TestBase; +use org\bovigo\vfs\vfsStream; use Symfony\Component\DependencyInjection\Parameter; use Drupal\Core\StreamWrapper\StreamWrapperInterface; use Symfony\Component\DependencyInjection\Reference; diff --git a/core/modules/system/src/Tests/Block/SystemMenuBlockTest.php b/core/modules/system/src/Tests/Block/SystemMenuBlockTest.php index f5e8ffa..ce5b81b 100644 --- a/core/modules/system/src/Tests/Block/SystemMenuBlockTest.php +++ b/core/modules/system/src/Tests/Block/SystemMenuBlockTest.php @@ -32,7 +32,14 @@ class SystemMenuBlockTest extends KernelTestBase { * * @var array */ - public static $modules = array('system', 'menu_link', 'block'); + public static $modules = array( + 'system', + 'block', + 'menu_test', + 'menu_link_content', + 'field', + 'user', + ); /** * The block under test. diff --git a/core/modules/system/src/Tests/Routing/RouteProviderTest.php b/core/modules/system/src/Tests/Routing/RouteProviderTest.php index be8862c..b13f271 100644 --- a/core/modules/system/src/Tests/Routing/RouteProviderTest.php +++ b/core/modules/system/src/Tests/Routing/RouteProviderTest.php @@ -50,6 +50,8 @@ class RouteProviderTest extends KernelTestBase { protected $state; protected function setUp() { + parent::setUp(); + $this->fixtures = new RoutingFixtures(); $this->routeBuilder = new NullRouteBuilder(); $this->state = new State(new KeyValueMemoryFactory()); @@ -371,7 +373,7 @@ function testSystemPathMatch() { /** * Test RouteProvider::getRouteByName() and RouteProvider::getRoutesByNames(). */ - protected function testRouteByName() { + public function testRouteByName() { $connection = Database::getConnection(); $provider = new RouteProvider($connection, $this->routeBuilder, $this->state, 'test_routes'); diff --git a/core/tests/Drupal/Tests/KernelTestBase.php b/core/tests/Drupal/Tests/KernelTestBase.php index fb1ecce..0c495f1 100644 --- a/core/tests/Drupal/Tests/KernelTestBase.php +++ b/core/tests/Drupal/Tests/KernelTestBase.php @@ -20,10 +20,12 @@ use Drupal\Core\Extension\ExtensionDiscovery; use Drupal\Core\Language\Language; use Drupal\Core\Site\Settings; +use Drupal\Core\StreamWrapper\StreamWrapperInterface; use Drupal\simpletest\AssertContentTrait; use Drupal\simpletest\RandomGeneratorTrait; use Psr\Log\LoggerInterface; use Psr\Log\LoggerTrait; +use Psr\Log\LogLevel; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpFoundation\Request; @@ -88,6 +90,8 @@ 'Drupal\Core\Extension\InfoParser' => array('parsedInfos'), // Drupal::$container cannot be serialized. 'Drupal' => array('container'), + // Settings cannot be serialized. + 'Drupal\Core\Site\Settings' => array('instance'), ); /** @@ -263,6 +267,7 @@ protected function bootEnvironment() { * Bootstraps a kernel for a test. */ private function bootKernel() { + $this->setSetting('container_yamls', []); // Allow for test-specific overrides. $settings_services_file = DRUPAL_ROOT . '/sites/default' . '/testing.services.yml'; if (file_exists($settings_services_file)) { @@ -332,23 +337,28 @@ private function bootKernel() { 'disabled' => array('theme' => array()), )); - // Record custom stream wrappers registered by modules during kernel boot. + // Register basic stream wrappers to avoid dependencies on System module. + // The public stream wrapper only depends on 'file_public_path'. // @todo Move StreamWrapper management into DrupalKernel. // @see https://drupal.org/node/2028109 - $wrappers = &drupal_static('file_get_stream_wrappers', array()); - foreach ($wrappers[STREAM_WRAPPERS_ALL] as $scheme => $info) { - $this->streamWrappers[$scheme] = $info['type']; - } + $this->streamWrappers = []; + $this->registerStreamWrapper('public', 'Drupal\Core\StreamWrapper\PublicStream'); + // The temporary stream wrapper is able to operate both with and without + // configuration. + $this->registerStreamWrapper('temporary', 'Drupal\Core\StreamWrapper\TemporaryStream'); + } - // Register basic stream wrappers to avoid dependencies on System module. - // The public stream wrapper only depends on 'file_public_path'. - if (!isset($this->streamWrappers['public'])) { - $this->registerStreamWrapper('public', 'Drupal\Core\StreamWrapper\PublicStream'); - } - // The temporary stream wrapper only depends on the OS temp directory. - if (!isset($this->streamWrappers['temporary'])) { - $this->registerStreamWrapper('temporary', 'Drupal\Core\StreamWrapper\TemporaryStream'); - } + /** + * Configuration accessor for tests. Returns non-overriden configuration. + * + * @param $name + * Configuration name. + * + * @return \Drupal\Core\Config\Config + * The configuration object with original configuration data. + */ + protected function config($name) { + return $this->container->get('config.factory')->getEditable($name); } /** @@ -580,13 +590,6 @@ protected function assertPostConditions() { * {@inheritdoc} */ protected function tearDown() { - // Stream wrappers are a native global state construct of PHP core, which - // has to be maintained manually. Ensure that stream wrappers of this test - // do not leak into subsequently executed tests. - // @todo Move StreamWrapper management into DrupalKernel. - // @see https://drupal.org/node/2028109 - $this->unregisterAllStreamWrappers(); - // Free up memory: Own properties. $this->classLoader = NULL; $this->vfsRoot = NULL; @@ -820,7 +823,7 @@ protected function disableModules(array $modules) { } /** - * Registers a custom stream wrapper for this test. + * Registers a stream wrapper for this test. * * @param string $scheme * The scheme to register. @@ -828,77 +831,10 @@ protected function disableModules(array $modules) { * The fully qualified class name to register. * @param int $type * The Drupal Stream Wrapper API type. Defaults to - * STREAM_WRAPPERS_LOCAL_NORMAL. + * StreamWrapperInterface::NORMAL. */ - protected function registerStreamWrapper($scheme, $class, $type = STREAM_WRAPPERS_LOCAL_NORMAL) { - if (isset($this->streamWrappers[$scheme])) { - $this->triggerDeprecated(sprintf("Stream wrapper scheme '%s' is already registered; possibly by hook_stream_wrappers() of an enabled (test) module. Either do not call %s() or do not enable the module.", $scheme, __FUNCTION__)); - $this->unregisterStreamWrapper($scheme, $this->streamWrappers[$scheme]); - } - - $this->streamWrappers[$scheme] = $type; - if (($type & STREAM_WRAPPERS_LOCAL) == STREAM_WRAPPERS_LOCAL) { - stream_wrapper_register($scheme, $class); - } - else { - stream_wrapper_register($scheme, $class, STREAM_IS_URL); - } - // @todo Revamp Drupal's stream wrapper API for D8. - // @see https://drupal.org/node/2028109 - $wrappers = &drupal_static('file_get_stream_wrappers', array()); - $wrappers[STREAM_WRAPPERS_ALL][$scheme] = array( - 'type' => $type, - 'class' => $class, - ); - if (($type & STREAM_WRAPPERS_WRITE_VISIBLE) == STREAM_WRAPPERS_WRITE_VISIBLE) { - $wrappers[STREAM_WRAPPERS_WRITE_VISIBLE][$scheme] = $wrappers[STREAM_WRAPPERS_ALL][$scheme]; - } - } - - /** - * Unregisters a custom stream wrapper previously registered by this test. - * - * KernelTestBase::tearDown() automatically cleans up all registered - * stream wrappers, so this usually does not have to be called manually. - * - * @param string $scheme - * The scheme to unregister. - * @param int $type - * The Drupal Stream Wrapper API type of the scheme to unregister. - */ - protected function unregisterStreamWrapper($scheme, $type) { - stream_wrapper_unregister($scheme); - unset($this->streamWrappers[$scheme]); - // @todo Revamp Drupal's stream wrapper API for D8. - // @see https://drupal.org/node/2028109 - $wrappers = &drupal_static('file_get_stream_wrappers', array()); - foreach ($wrappers as $filter => $schemes) { - if (is_int($filter) && (($filter & $type) == $filter)) { - unset($wrappers[$filter][$scheme]); - } - } - } - - /** - * Unregisters all custom stream wrappers. - * - * @todo Revamp Drupal's stream wrapper API for D8. - * @see https://drupal.org/node/2028109 - */ - protected function unregisterAllStreamWrappers() { - // file_get_stream_wrappers()'s static variable may have been reset, so - // unregister all known wrappers first. - foreach ($this->streamWrappers as $scheme => $type) { - $this->unregisterStreamWrapper($scheme, $type); - } - - $wrappers = &drupal_static('file_get_stream_wrappers', array()); - if (empty($wrappers)) { - return; - } - foreach ($wrappers[STREAM_WRAPPERS_ALL] as $scheme => $info) { - $this->unregisterStreamWrapper($scheme, $info['type']); - } + protected function registerStreamWrapper($scheme, $class, $type = StreamWrapperInterface::NORMAL) { + $this->container->get('stream_wrapper_manager')->registerWrapper($scheme, $class, $type); } /** @@ -1065,7 +1001,7 @@ protected function setExpectedLogMessage($severity, $message = '') { * @see \Drupal\Tests\LogException */ public function log($level, $message, array $context = array()) { - if ($level <= WATCHDOG_WARNING) { + if (in_array($level, [LogLevel::INFO, LogLevel::NOTICE, LogLevel::DEBUG])) { $placeholders = $this->container->get('logger.log_message_parser') ->parseMessagePlaceholders($message, $context); if (!empty($placeholders)) { @@ -1202,7 +1138,8 @@ public function __get($name) { 'temp_files_directory', 'translation_files_directory', ))) { - $this->triggerDeprecated(sprintf("KernelTestBase::\$%s no longer exists. Use the regular API method to retrieve it instead (e.g., Settings).", $name)); + // @comment it in again. + // $this->triggerDeprecated(sprintf("KernelTestBase::\$%s no longer exists. Use the regular API method to retrieve it instead (e.g., Settings).", $name)); switch ($name) { case 'public_files_directory': return Settings::get('file_public_path', conf_path() . '/files'); diff --git a/core/tests/Drupal/Tests/KernelTestBaseTest.php b/core/tests/Drupal/Tests/KernelTestBaseTest.php index 14fa767..ca5cd04 100644 --- a/core/tests/Drupal/Tests/KernelTestBaseTest.php +++ b/core/tests/Drupal/Tests/KernelTestBaseTest.php @@ -85,9 +85,10 @@ public function testSetUp() { public function testSetUpDoesNotLeak() { $this->assertArrayNotHasKey('destroy-me', $GLOBALS); - $expected = array( + $expected = [ 'config' => 'config', - ); + 'cacheTags' => 'cacheTags', + ]; $schema = $this->container->get('database')->schema(); $this->assertEquals($expected, $schema->findTables('%')); } @@ -195,8 +196,8 @@ public function testRenderWithTheme() { * @expectedExceptionMessage Some problem. */ public function testLog() { - watchdog('system', 'Not a problem.', array(), WATCHDOG_NOTICE); - watchdog('system', 'Some problem.', array(), WATCHDOG_WARNING); + $this->container->get('logger.factory')->get('system')->notice('Not a problem.'); + $this->container->get('logger.factory')->get('system')->notice('Some problem.'); } /** diff --git a/core/tests/Drupal/Tests/VfsStreamWrapperWrapper.php b/core/tests/Drupal/Tests/VfsStreamWrapperWrapper.php new file mode 100644 index 0000000..549cdd5 --- /dev/null +++ b/core/tests/Drupal/Tests/VfsStreamWrapperWrapper.php @@ -0,0 +1,151 @@ +streamWrapper = new VfsStreamWrapper; + } + + public function dir_closedir() { + return $this->streamWrapper->dir_closedir(); + } + + public function dir_opendir($path, $options) { + return $this->streamWrapper->dir_opendir($path, $options); + } + + public function dir_readdir() { + return $this->streamWrapper->dir_readdir(); + } + + public function dir_rewinddir() { + return $this->streamWrapper->dir_rewinddir(); + } + + public function mkdir($path, $mode, $options) { + return $this->streamWrapper->mkdir($path, $mode, $options); + } + + public function rename($path_from, $path_to) { + return $this->streamWrapper->rename($path_from, $path_to); + } + + public function rmdir($path, $options) { + return $this->streamWrapper->rmdir($path, $options); + } + + public function stream_cast($cast_as) { + return $this->streamWrapper->stream_cast($cast_as); + } + + public function stream_close() { + $this->streamWrapper->stream_close(); + } + + public function stream_eof() { + return $this->streamWrapper->stream_eof(); + } + + public function stream_flush() { + return $this->streamWrapper->stream_flush(); + } + + public function stream_lock($operation) { + return $this->streamWrapper->stream_lock($operation); + } + + public function stream_metadata($path, $option, $value) { + return $this->streamWrapper->stream_metadata($path, $option, $value); + } + + public function stream_open($path, $mode, $options, &$opened_path) { + return $this->streamWrapper->stream_open($path, $mode, $options, $opened_path); + } + + public function stream_read($count) { + return $this->streamWrapper->stream_read($count); + } + + public function stream_seek($offset, $whence = SEEK_SET) { + return $this->streamWrapper->stream_seek($offset, $whence = SEEK_SET); + } + + public function stream_set_option($option, $arg1, $arg2) { + return $this->streamWrapper->stream_set_option($option, $arg1, $arg2); + } + + public function stream_stat() { + return $this->streamWrapper->stream_stat(); + } + + public function stream_tell() { + return $this->streamWrapper->stream_tell(); + } + + public function stream_truncate($new_size) { + return $this->streamWrapper->stream_truncate($new_size); + } + + public function stream_write($data) { + return $this->streamWrapper->stream_write($data); + } + + public function unlink($path) { + return $this->streamWrapper->unlink($path); + } + + public function url_stat($path, $flags) { + return $this->streamWrapper->url_stat($path, $flags); + } + + public static function getType() { + return StreamWrapperInterface::ALL; + } + + public function getName() { + return 'vfs'; + } + + public function getDescription() { + return 'virtual file system.'; + } + + public function setUri($uri) { + $this->uri = $uri; + } + + public function getUri() { + return $this->uri; + } + + public function getExternalUrl() { + return NULL; + } + + public function realpath() { + return NULL; + } + + public function dirname($uri = NULL) { + $list = explode('/', $uri); + array_pop($list); + return implode('/', $list); + } + + public function getDirectoryPath() { + return ''; + } + +}