diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 4757594..f7de151 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -420,7 +420,10 @@ function drupal_settings_initialize() { global $databases, $cookie_domain, $conf, $db_prefix, $drupal_hash_salt, $base_secure_url, $base_insecure_url, $config_directories; $conf = array(); - if (is_readable(DRUPAL_ROOT . '/settings.php')) { + // Read the global /settings.php file. + // Exclude it for test requests to prevent settings of the parent site/ + // test-runner to leak into the test environment. + if (!drupal_valid_test_ua() && is_readable(DRUPAL_ROOT . '/settings.php')) { require DRUPAL_ROOT . '/settings.php'; } @@ -1815,7 +1818,15 @@ function _drupal_bootstrap_configuration() { drupal_settings_initialize(); // Make sure we are using the test database prefix in child Drupal sites. - _drupal_initialize_db_test_prefix(); + if ($test_prefix = drupal_valid_test_ua()) { + if (!empty($GLOBALS['databases']) && strpos($GLOBALS['databases']['default']['default']['prefix'], $test_prefix) === FALSE) { + throw new Exception('Bad prefix.'); + } + // @todo Move into initial (unset) getter logic of drupal_valid_test_ua()? + $test_info = &$GLOBALS['drupal_test_info']; + $test_info['test_run_id'] = $test_prefix; + $test_info['in_child_site'] = TRUE; + } // Activate the class loader. drupal_classloader(); @@ -1905,39 +1916,6 @@ function _drupal_bootstrap_page_cache() { } /** - * In a test environment, get the test db prefix and set it in $databases. - */ -function _drupal_initialize_db_test_prefix() { - // The user agent header is used to pass a database prefix in the request when - // running tests. However, for security reasons, it is imperative that we - // validate we ourselves made the request. - if ($test_prefix = drupal_valid_test_ua()) { - // Set the test run id for use in other parts of Drupal. - $test_info = &$GLOBALS['drupal_test_info']; - $test_info['test_run_id'] = $test_prefix; - $test_info['in_child_site'] = TRUE; - - foreach ($GLOBALS['databases']['default'] as &$value) { - // Extract the current default database prefix. - if (!isset($value['prefix'])) { - $current_prefix = ''; - } - elseif (is_array($value['prefix'])) { - $current_prefix = $value['prefix']['default']; - } - else { - $current_prefix = $value['prefix']; - } - - // Remove the current database prefix and replace it by our own. - $value['prefix'] = array( - 'default' => $current_prefix . $test_prefix, - ); - } - } -} - -/** * Loads system variables and all enabled bootstrap modules. */ function _drupal_bootstrap_variables() { @@ -2074,85 +2052,56 @@ function drupal_valid_test_ua($new_prefix = NULL) { if (isset($new_prefix)) { $test_prefix = $new_prefix; + // A new prefix is only explicitly set within the parent site/test runner. + // Set the global test run ID and info accordingly. + if ($new_prefix) { + $test_info = &$GLOBALS['drupal_test_info']; + $test_info['test_run_id'] = $test_prefix; + if (!isset($test_info['in_child_site'])) { + $test_info['in_child_site'] = FALSE; + } + } + else { + unset($GLOBALS['drupal_test_info']); + } } if (isset($test_prefix)) { return $test_prefix; } - + $test_prefix = FALSE; if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match("/^(simpletest\d+);(.+);(.+);(.+)$/", $_SERVER['HTTP_USER_AGENT'], $matches)) { list(, $prefix, $time, $salt, $hmac) = $matches; $check_string = $prefix . ';' . $time . ';' . $salt; - // We use the salt from settings.php to make the HMAC key, since - // the database is not yet initialized and we can't access any Drupal variables. + // Read the hash salt prepared by drupal_generate_test_ua(). + require DRUPAL_ROOT . '/sites/simpletest/' . substr($prefix, 10) . '/key.php'; // The file properties add more entropy not easily accessible to others. - $key = drupal_get_hash_salt() . filectime(__FILE__) . fileinode(__FILE__); + $key = $private_key . filectime(__FILE__) . fileinode(__FILE__); $time_diff = REQUEST_TIME - $time; - // We can't use Crypt::hmacBase64() yet because this can be called in very - // early bootstrap when autoloader has not been initialized yet. - $test_hmac = base64_encode(hash_hmac('sha256', $check_string, $key, TRUE)); - $test_hmac = strtr($test_hmac, array('+' => '-', '/' => '_', '=' => '')); + $test_hmac = Crypt::hmacBase64($check_string, $key); // Since we are making a local request a 5 second time window is allowed, // and the HMAC must match. - if ($time_diff >= 0 && $time_diff <= 5 && $hmac == $test_hmac) { + if ($time_diff >= 0 && $time_diff <= 5 && $hmac === $test_hmac) { $test_prefix = $prefix; - _drupal_load_test_overrides($test_prefix); - return $test_prefix; } } - - $test_prefix = FALSE; return $test_prefix; } /** - * Overrides low-level and environment-specific configuration. - * - * Very strictly for internal use only. - * - * Loads settings.php from the simpletest public files directory. These files - * can change the global $conf, the global $config_directories, the return - * value of \Drupal\Core\Utility\Site::getPath(), and settings(). - * - * @param string $test_prefix - * The simpletest prefix. - */ -function _drupal_load_test_overrides($test_prefix) { - global $conf, $config_directories; - - // Do not use the parent site's config directories. Use only the child site's. - // @see \Drupal\simpletest\TestBase::prepareConfigDirectories() - $path_prefix = 'simpletest/' . substr($test_prefix, 10); - $config_directories = array(); - foreach (array(CONFIG_ACTIVE_DIRECTORY, CONFIG_STAGING_DIRECTORY) as $type) { - $config_directories[$type] = Site::getPath('files/' . $path_prefix . '/config_' . $type); - } - - // Check for and load a settings.php file in the simpletest files directory. - $filename = Site::getAbsolutePath('files/' . $path_prefix . '/settings.php'); - if (file_exists($filename)) { - $settings = settings()->getAll(); - $conf_path = Site::getPath(); - // This can override $conf, $conf_path, $settings, and $config_directories. - include $filename; - Site::setPath($conf_path); - // Keep the overriden $conf_path alive across drupal_static_reset() calls. - // @see \Drupal\Core\Utility\Site::getSimpletestPath() - $settings['simpletest_conf_path'] = $conf_path; - new Settings($settings); - } -} - -/** * Generates a user agent string with a HMAC and timestamp for simpletest. */ function drupal_generate_test_ua($prefix) { static $key; if (!isset($key)) { - // We use the salt from settings.php to make the HMAC key, since - // the database is not yet initialized and we can't access any Drupal variables. + // Generate and save a hash salt for a test run. + // Consumed by drupal_valid_test_ua() before settings.php is loaded. + $private_key = Crypt::randomStringHashed(55); + $key_file = "server->get('SERVER_PROTOCOL') . ' 403 Forbidden'); + exit; + } + // Perform a minimal bootstrap. // During installation, drupal_settings_initialize() will not attempt to load // settings.php, so as to prime the site path to be used during installation. @@ -296,17 +306,6 @@ function install_begin_request(&$install_state) { // /sites directory, which will be used for installing Drupal. drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION); - // If the hash salt leaks, it becomes possible to forge a valid testing user - // agent, install a new copy of Drupal, and take over the original site. To - // avoid this yet allow for automated testing of the installer, make sure - // there is also a special test-specific settings.php overriding the site - // configuration directory path. _drupal_load_test_overrides() sets the - // simpletest_conf_path in-memory setting in this case. - if ($install_state['interactive'] && drupal_valid_test_ua() && !settings()->get('simpletest_conf_path')) { - header($request->server->get('SERVER_PROTOCOL') . ' 403 Forbidden'); - exit; - } - // If we have a language selected and it is not yet saved in the system // (eg. pre-database data screens we are unable to persistently store // the default language), we should set language_default so the proper @@ -1155,9 +1154,9 @@ function install_settings_form_validate($form, &$form_state) { $database = $form_state['values'][$driver]; // When testing the interactive installer, copy the database password and // the test prefix. + // @todo Remove this; pass prefix in POST data instead. if ($test_prefix = drupal_valid_test_ua()) { $database['prefix'] = $test_prefix; - $database['password'] = $GLOBALS['databases']['default']['default']['password']; } $drivers = drupal_get_database_types(); $reflection = new \ReflectionClass($drivers[$driver]); @@ -1168,7 +1167,7 @@ function install_settings_form_validate($form, &$form_state) { // @todo PIFR uses 'db_prefix' instead of 'prefix'. Remove this when it gets // fixed. - if (!$test_prefix) { + if (!$test_prefix && isset($database['db_prefix'])) { $database['prefix'] = $database['db_prefix']; } unset($database['db_prefix']); @@ -1236,33 +1235,15 @@ function install_settings_form_submit($form, &$form_state) { // Update global settings array and save. $settings = array(); $database = $form_state['storage']['database']; - // Ideally, there is no difference between the code executed by the - // automated test browser and an ordinary browser. However, the database - // settings need a different format and also need to skip the password - // when testing. The hash salt also needs to be skipped because the original - // salt is used to verify the validity of the automated test browser. - // Because of these, there's a little difference in the code following but - // it is small and self-contained. - if ($test_prefix = drupal_valid_test_ua()) { - foreach ($form_state['storage']['database'] as $k => $v) { - if ($k != 'password') { - $settings['databases']['default']['default'][$k] = (object) array( - 'value' => $v, - 'required' => TRUE, - ); - } - } - } - else { - $settings['databases']['default']['default'] = (object) array( - 'value' => $database, - 'required' => TRUE, - ); - $settings['drupal_hash_salt'] = (object) array( - 'value' => Crypt::randomStringHashed(55), - 'required' => TRUE, - ); - } + + $settings['databases']['default']['default'] = (object) array( + 'value' => $database, + 'required' => TRUE, + ); + $settings['drupal_hash_salt'] = (object) array( + 'value' => Crypt::randomStringHashed(55), + 'required' => TRUE, + ); // Remember the profile which was used. $settings['settings'] = array( diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index 0160119..d1badfb 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -342,6 +342,7 @@ public function updateModules(array $module_list, array $module_filenames = arra protected function getClassName() { $parts = array('service_container', $this->environment); // Make sure to use a testing-specific container even in the parent site. + // @todo Obsolete by drupal_valid_test_ua()? if (!empty($GLOBALS['drupal_test_info']['test_run_id'])) { $parts[] = $GLOBALS['drupal_test_info']['test_run_id']; } diff --git a/core/lib/Drupal/Core/StreamWrapper/PublicStream.php b/core/lib/Drupal/Core/StreamWrapper/PublicStream.php index 4fdf72b..cbb596c 100644 --- a/core/lib/Drupal/Core/StreamWrapper/PublicStream.php +++ b/core/lib/Drupal/Core/StreamWrapper/PublicStream.php @@ -39,13 +39,6 @@ public function getExternalUrl() { */ public static function basePath() { $base_path = settings()->get('file_public_path', Site::getPath('files')); - if ($test_prefix = drupal_valid_test_ua()) { - // Append the testing suffix unless already given. - // @see \Drupal\simpletest\WebTestBase::setUp() - if (strpos($base_path, '/simpletest/' . substr($test_prefix, 10)) === FALSE) { - return $base_path . '/simpletest/' . substr($test_prefix, 10); - } - } return $base_path; } diff --git a/core/lib/Drupal/Core/SystemListingInfo.php b/core/lib/Drupal/Core/SystemListingInfo.php index d302699..3575adc 100644 --- a/core/lib/Drupal/Core/SystemListingInfo.php +++ b/core/lib/Drupal/Core/SystemListingInfo.php @@ -28,6 +28,7 @@ protected function profiles($directory) { // For SimpleTest to be able to test modules packaged together with a // distribution we need to include the profile of the parent site (in // which test runs are triggered). + // @todo !drupal_installation_attempted() defeats the whole purpose? if (drupal_valid_test_ua() && !drupal_installation_attempted()) { $testing_profile = \Drupal::config('simpletest.settings')->get('parent_profile'); if ($testing_profile && $testing_profile != $profile) { diff --git a/core/lib/Drupal/Core/Utility/Site.php b/core/lib/Drupal/Core/Utility/Site.php index abb3d20..6711562 100644 --- a/core/lib/Drupal/Core/Utility/Site.php +++ b/core/lib/Drupal/Core/Utility/Site.php @@ -38,6 +38,16 @@ class Site { private $isInstaller; /** + * The original Site instance of the test runner during test execution. + * + * @see \Drupal\Core\Utility\Site::setUpTest() + * @see \Drupal\Core\Utility\Site::tearDownTest() + * + * @var \Drupal\Core\Utility\Site + */ + private $original; + + /** * The Site singleton instance. * * @var \Drupal\Core\Utility\Site @@ -53,18 +63,25 @@ class Site { * (optional) A multi-site mapping, as defined in settings.php. * @param string $custom_path * (optional) An explicit site path to set; skipping site negotiation. - * Internal use by drupal_settings_initialize() only, after reading a - * potential value from the root /settings.php file. + * This can be defined as $conf_path in the root /settings.php file. + * + * @see drupal_settings_initialize() */ public static function init($root_directory, array $sites = NULL, $custom_path = NULL) { if (!isset(self::$instance)) { new self($root_directory); } + // Only the installer environment is allowed instantiate the Site singleton + // prior to drupal_settings_initialize(). + // @see initInstaller() elseif (!self::$instance->isInstaller()) { throw new \BadMethodCallException('Site path is initialized already.'); } + // Force-override the site directory in tests. + if ($test_prefix = drupal_valid_test_ua()) { + $custom_path = 'sites/simpletest/' . substr($test_prefix, 10); + } self::$instance->initializePath($sites, $custom_path); - return self::$instance; } /** @@ -77,12 +94,16 @@ public static function init($root_directory, array $sites = NULL, $custom_path = * * @param string $root_directory * The root directory to use for absolute paths; i.e., DRUPAL_ROOT. + * + * @see install_begin_request() */ public static function initInstaller($root_directory) { - // @todo && !drupal_valid_test_ua() would allow Simpletest to re-invoke this - // from WebTestBase::setUp(), in order to (re-)prime a custom path before - // executing the non-interactive installer. Only tearDown() gets hairy. - // We could add a backup/restore mechanism specifically for tests though. + // WebTestBase::setUp() invokes Site::setUpTest() prior to invoking the + // non-interactive installer, in order to override the singleton and prime + // a custom site directory. + if (drupal_valid_test_ua()) { + return; + } if (isset(self::$instance)) { throw new \BadMethodCallException('Site path is initialized already.'); } @@ -91,15 +112,53 @@ public static function initInstaller($root_directory) { // called by drupal_settings_initialize(), possibly passing new values from // the newly created settings.php file. new self($root_directory, TRUE); - return self::$instance; + } + + /** + * Re-initializes the Site singleton for a test run. + * + * Called by WebTestBase::setUp() prior to invoking the non-interactive + * installer for a test. + * + * @param string $root_directory + * The root directory to use for absolute paths; i.e., DRUPAL_ROOT. + * @param string $custom_path + * The relative site directory path to use during the test run; e.g., + * 'sites/simpletest/123456'. + */ + public static function setUpTest($root_directory, $custom_path) { + if (!drupal_valid_test_ua()) { + throw new \BadMethodCallException('Site is not executing a test.'); + } + if (!file_exists($root_directory . '/' . $custom_path)) { + throw new \InvalidArgumentException("Test site directory '$custom_path' does not exist."); + } + new self($root_directory, TRUE, $custom_path); + } + + /** + * Reverts the Site singleton to the original after a test run. + */ + public static function tearDownTest() { + if (!isset(self::$instance->original)) { + throw new \RuntimeException('No original Site to revert to. Missing invocation of Site::setUpTest()?'); + } + self::$instance = self::$instance->original; } /** * Constructs the Site singleton. */ - private function __construct($root_directory, $is_installer = FALSE) { + private function __construct($root_directory, $is_installer = FALSE, $custom_path = NULL) { + if (isset(self::$instance->original)) { + throw new \RuntimeException('Site is overridden for a test already. Duplicate invocation of Site::setUpTest()?'); + } + if (isset(self::$instance)) { + $this->original = clone self::$instance; + } $this->root = $root_directory; $this->isInstaller = $is_installer; + $this->path = $custom_path; self::$instance = $this; } @@ -121,14 +180,18 @@ private function isInstaller() { * (optional) An explicit site path to set; skipping site negotiation. */ private function initializePath(array $sites = NULL, $custom_path = NULL) { + // When executing the non-interactive installer in the parent site/ + // test-runner, WebTestBase::setUp() primes the site directory path via + // Site::setUpTest() already. + // @todo Remove this case by adding a 'site' parameter to drupal_install(). + if (isset($this->path)) { + return; + } + // An explicitly defined $conf_path in /settings.php takes precedence. if (isset($custom_path)) { $this->path = $custom_path; } - // Check for a Simpletest override. - elseif ($simpletest_path = $this->getSimpletestPath()) { - $this->path = $simpletest_path; - } // If the multi-site functionality was enabled in /settings.php, discover // the path for the current site. // $sites just needs to be defined; an explicit mapping is not required. @@ -193,6 +256,8 @@ private function determinePath(array $sites, $require_settings) { // Check for an alias in $sites. if (isset($sites[$dir])) { $dir = $sites[$dir]; + // A defined site alias from /settings.php should be valid. + // @todo Even skip the settings.php check? if (!$require_settings) { return "sites/$dir"; } @@ -211,56 +276,6 @@ private function determinePath(array $sites, $require_settings) { } /** - * Determines whether to use an overridden value for Site::determinePath(). - * - * Simpletest may provide a secondary, test-specific settings.php file to load - * after the primary one used by the parent site and override its variables. - * - If the child settings.php does not override $conf_path, then this - * function returns FALSE and Site::getPath() returns the directory of the - * primary settings.php. - * - If the child settings.php does override $conf_path, then - * _drupal_load_test_overrides() sets the 'simpletest_conf_path' setting, - * and this function returns that to Site::determinePath(), causing - * installations and upgrades to act on that one. - * - * @return string|false - * The overridden $conf_path, or FALSE if the $conf_path should not - * currently be overridden. - * - * @see \Drupal\Core\Utility\Site::determinePath() - * @see _drupal_load_test_overrides() - */ - private function getSimpletestPath() { - // Ensure that the settings object is available. Site::getPath() is called - // once before the Settings class is included, and at that point it should - // still load the primary $conf_path. See drupal_settings_initialize(). - if (!class_exists('Drupal\Component\Utility\Settings', FALSE)) { - return FALSE; - } - - // If no $simpletest_conf_path is set, use the normal $conf_path. - - // @todo Critical race condition: This class discovers settings.php, and - // settings.php declares the $settings for instantiating Settings. - // The Settings singleton is not and cannot be instantiated at this point - // in time. - - if (!($simpletest_conf_path = Settings::getSingleton()->get('simpletest_conf_path'))) { - return FALSE; - } - - // Ensure that this is actually a simpletest request. We can't check this - // before settings.php is loaded. - if (!drupal_valid_test_ua()) { - return FALSE; - } - - // When the $simpletest_conf_path is set in a valid test request, return - // that path. - return $simpletest_conf_path; - } - - /** * Prefixes a given filepath with the site directory, if any. * * @param string $filepath @@ -285,7 +300,7 @@ private function resolvePath($filepath) { } /** - * Returns the relative path to the site directory with an optional suffix. + * Returns a given path as relative path to the site directory. * * Use this function instead of appending strings to the site path manually, * because the site directory may be the root directory and thus the resulting @@ -304,7 +319,7 @@ public static function getPath($filepath = '') { } /** - * Returns the absolute path to the site directory with an optional suffix. + * Returns a given path as absolute path in the site directory. * * @param string $filepath * (optional) A relative filepath to append to the site path. @@ -325,17 +340,4 @@ public static function getAbsolutePath($filepath = '') { } } - /** - * Sets the site directory to a given path. - * - * @param string $path - * The relative path to the site directory to set. - * - * @todo Add special re-initialization method for WebTestBase::setUp() and - * remove this. - */ - public static function setPath($path) { - self::$instance->path = $path; - } - } diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php index 6725cb7..8fb43bc 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -37,6 +37,13 @@ protected $testId; /** + * The site directory of this test run. + * + * @var string + */ + protected $siteDirectory = NULL; + + /** * The database prefix of this test run. * * @var string @@ -838,7 +845,9 @@ public function run(array $methods = array()) { * @see WebTestBase::setUp() */ protected function prepareDatabasePrefix() { - $this->databasePrefix = 'simpletest' . mt_rand(1000, 1000000); + $suffix = mt_rand(1000, 1000000); + $this->databasePrefix = 'simpletest' . $suffix; + $this->siteDirectory = 'sites/simpletest/' . $suffix; // As soon as the database prefix is set, the test might start to execute. // All assertions as well as the SimpleTest batch operations are associated @@ -947,10 +956,10 @@ protected function prepareEnvironment() { // Create test directory ahead of installation so fatal errors and debug // information can be logged during installation process. - // Use temporary files directory with the same prefix as the database. - $this->public_files_directory = $this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10); - $this->private_files_directory = $this->public_files_directory . '/private'; - $this->temp_files_directory = $this->private_files_directory . '/temp'; + // @todo Do not execute this for WebTestBase. + $this->public_files_directory = $this->siteDirectory . '/files'; + $this->private_files_directory = $this->siteDirectory . '/private'; + $this->temp_files_directory = $this->siteDirectory . '/temp'; $this->translation_files_directory = $this->public_files_directory . '/translations'; // Create the directories @@ -961,7 +970,14 @@ protected function prepareEnvironment() { $this->generatedTestFiles = FALSE; // Create and set new configuration directories. - $this->prepareConfigDirectories(); + // @todo Only valid for tests not executing the installer (in any way). + if (!$this instanceof WebTestBase) { + $this->prepareConfigDirectories(); + } + else { + $GLOBALS['config_directories'] = array(); + $this->configDirectories = array(); + } // Reset statics before the old container is replaced so that objects with a // __destruct() method still have access to it. @@ -1014,7 +1030,7 @@ protected function prepareConfigDirectories() { include_once DRUPAL_ROOT . '/core/includes/install.inc'; foreach (array(CONFIG_ACTIVE_DIRECTORY, CONFIG_STAGING_DIRECTORY) as $type) { // Assign the relative path to the global variable. - $path = Site::getPath('files/simpletest/' . substr($this->databasePrefix, 10) . '/config_' . $type); + $path = $this->siteDirectory . '/config_' . $type; $GLOBALS['config_directories'][$type] = $path; // Ensure the directory can be created and is writeable. if (!install_ensure_config_directory($type)) { @@ -1107,8 +1123,8 @@ protected function tearDown() { // log to pick up any fatal errors. simpletest_log_read($this->testId, $this->databasePrefix, get_class($this), TRUE); - // Delete temporary files directory. - file_unmanaged_delete_recursive($this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10), array($this, 'filePreDeleteCallback')); + // Delete test site directory. + file_unmanaged_delete_recursive($this->siteDirectory, array($this, 'filePreDeleteCallback')); // Restore original database connection. Database::removeConnection('default'); @@ -1139,6 +1155,9 @@ protected function tearDown() { if (isset($this->originalPrefix)) { drupal_valid_test_ua($this->originalPrefix); } + else { + drupal_valid_test_ua(FALSE); + } // Restore original shutdown callbacks. $callbacks = &drupal_register_shutdown_function(); diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 265012e..a17e64b 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -17,6 +17,7 @@ use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\UserSession; use Drupal\Core\StreamWrapper\PublicStream; +use Drupal\Core\Utility\Site; use Drupal\Core\Datetime\DrupalDateTime; use Symfony\Component\HttpFoundation\Request; @@ -748,6 +749,10 @@ protected function setUp() { return FALSE; } + // After preparing the environment and changing the database prefix, we are + // in a valid test environment. + drupal_valid_test_ua($this->databasePrefix); + // Set the 'simpletest_parent_profile' variable to add the parent profile's // search path to the child site's search paths. // @see drupal_system_listing() @@ -781,26 +786,16 @@ protected function setUp() { $this->settingsSet('file_public_path', $this->public_files_directory); // Execute the non-interactive installer. require_once DRUPAL_ROOT . '/core/includes/install.core.inc'; - $this->settingsSet('cache', array('default' => 'cache.backend.memory')); + + Site::setUpTest(DRUPAL_ROOT, $this->siteDirectory); + $parameters = $this->installParameters(); install_drupal($parameters); - // Set the install_profile so that web requests to the requests to the child - // site have the correct profile. - $settings = array( - 'settings' => array( - 'install_profile' => (object) array( - 'value' => $this->profile, - 'required' => TRUE, - ), - ), - ); - $this->writeSettings($settings); // Override install profile in Settings to so the correct profile is used by // tests. $this->settingsSet('install_profile', $this->profile); - $this->settingsSet('cache', array()); $this->rebuildContainer(); // Restore the original Simpletest batch. @@ -863,6 +858,7 @@ protected function setUp() { * @see install_state_defaults() */ protected function installParameters() { + // The prefix is prepared in TestBase::changeDatabasePrefix() already. $connection_info = Database::getConnectionInfo(); $parameters = array( 'interactive' => FALSE, @@ -1026,6 +1022,7 @@ protected function tearDown() { $this->kernel->shutdown(); } parent::tearDown(); + Site::tearDownTest(); // Ensure that internal logged in variable and cURL options are reset. $this->loggedInUser = FALSE; diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module index bd50676..ba3e9d5 100644 --- a/core/modules/simpletest/simpletest.module +++ b/core/modules/simpletest/simpletest.module @@ -367,7 +367,7 @@ function simpletest_last_test_get($test_id) { * * @param $test_id * The test ID to which the log relates. - * @param $prefix + * @param $database_prefix * The database prefix to which the log relates. * @param $test_class * The test class to which the log relates. @@ -377,8 +377,8 @@ function simpletest_last_test_get($test_id) { * @return * Found any entries in log. */ -function simpletest_log_read($test_id, $prefix, $test_class, $during_test = FALSE) { - $log = 'public://' . ($during_test ? '' : '/simpletest/' . substr($prefix, 10)) . '/error.log'; +function simpletest_log_read($test_id, $database_prefix, $test_class, $during_test = FALSE) { + $log = 'sites/simpletest/' . substr($database_prefix, 10) . '/error.log'; $found = FALSE; if (file_exists($log)) { foreach (file($log) as $line) { @@ -632,14 +632,12 @@ function simpletest_clean_database() { */ function simpletest_clean_temporary_directories() { $count = 0; - if (is_dir('public://simpletest')) { - $files = scandir('public://simpletest'); + if (is_dir('sites/simpletest')) { + $files = scandir('sites/simpletest'); foreach ($files as $file) { - $path = 'public://simpletest/' . $file; - if (is_dir($path) && (is_numeric($file) || strpos($file, 'config_simpletest') !== FALSE)) { - file_unmanaged_delete_recursive($path, array('Drupal\simpletest\TestBase', 'filePreDeleteCallback')); - $count++; - } + $path = 'sites/simpletest/' . $file; + file_unmanaged_delete_recursive($path, array('Drupal\simpletest\TestBase', 'filePreDeleteCallback')); + $count++; } }