diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php index b31d8a0a408..916cb0d7f76 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -869,7 +869,31 @@ abstract class TestBase { */ protected function tearDown() { global $user, $conf; - $language_interface = language(LANGUAGE_TYPE_INTERFACE); + + // Reset all static variables. + // Unsetting static variables will potentially invoke destruct methods, + // which might call into functions that prime statics and caches again. + // In that case, all functions are still operating on the test environment, + // which means they may need to access its filesystem and database. + drupal_static_reset(); + + // Ensure that TestBase::changeDatabasePrefix() has run and TestBase::$setup + // was not tricked into TRUE, since the following code would delete the + // entire parent site otherwise. + if ($this->setupDatabasePrefix) { + // Remove all prefixed tables. + $connection_info = Database::getConnectionInfo('default'); + $tables = db_find_tables($connection_info['default']['prefix']['default'] . '%'); + $prefix_length = strlen($connection_info['default']['prefix']['default']); + foreach ($tables as $table) { + if (db_drop_table(substr($table, $prefix_length))) { + unset($tables[$table]); + } + } + if (!empty($tables)) { + $this->fail('Failed to drop all prefixed tables.'); + } + } // In case a fatal error occurred that was not in the test process read the // log to pick up any fatal errors. @@ -897,23 +921,31 @@ abstract class TestBase { $GLOBALS['theme'] = $this->originalTheme; // Reset all static variables. + // All destructors of statically cached objects have been invoked above; + // this second reset is guranteed to reset everything to nothing. drupal_static_reset(); - // Reset module list and module load status. - module_list_reset(); - module_load_all(FALSE, TRUE); + // Reset static in language(). + // Restoring drupal_container() makes language() return the proper languages + // already, but it contains an additional static that needs to be reset. The + // reset can happen before the container is restored, as it is unnecessary + // to reset the language_manager service. + language(NULL, TRUE); // Restore original in-memory configuration. $conf = $this->originalConf; // Restore original statics and globals. drupal_container($this->originalContainer); - $language_interface = $this->originalLanguage; $GLOBALS['config_directories'] = $this->originalConfigDirectories; if (isset($this->originalPrefix)) { drupal_valid_test_ua($this->originalPrefix); } + // Reset module list and module load status. + module_list_reset(); + module_load_all(FALSE, TRUE); + // Restore original shutdown callbacks. $callbacks = &drupal_register_shutdown_function(); $callbacks = $this->originalShutdownCallbacks; diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 8ad58efee68..ec800d49527 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -771,32 +771,10 @@ abstract class WebTestBase extends TestBase { * and reset the database prefix. */ protected function tearDown() { - // Ensure that TestBase::changeDatabasePrefix() has run and TestBase::$setup - // was not tricked into TRUE, since the following code would delete the - // entire parent site otherwise. - if (!$this->setupDatabasePrefix) { - return FALSE; - } // Destroy the testing kernel. if (isset($this->kernel)) { $this->kernel->shutdown(); } - // Remove all prefixed tables. - $connection_info = Database::getConnectionInfo('default'); - $tables = db_find_tables($connection_info['default']['prefix']['default'] . '%'); - if (empty($tables)) { - $this->fail('Failed to find test tables to drop.'); - } - $prefix_length = strlen($connection_info['default']['prefix']['default']); - foreach ($tables as $table) { - if (db_drop_table(substr($table, $prefix_length))) { - unset($tables[$table]); - } - } - if (!empty($tables)) { - $this->fail('Failed to drop all prefixed tables.'); - } - parent::tearDown(); // Ensure that internal logged in variable and cURL options are reset.