diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index bd4638a..4928acc 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -522,6 +522,7 @@ function drupal_settings_initialize() { // Export these settings.php variables to the global namespace. global $base_url, $databases, $cookie_domain, $conf, $drupal_hash_salt, $config_directories; $conf = array(); + $settings = array(); // Make conf_path() available as local variable in settings.php. $conf_path = conf_path(); @@ -529,7 +530,7 @@ function drupal_settings_initialize() { require DRUPAL_ROOT . '/' . $conf_path . '/settings.php'; } - new Settings(isset($settings) ? $settings : array()); + new Settings($settings); } /** @@ -537,7 +538,7 @@ function drupal_settings_initialize() { * * @todo D8: Eliminate this entirely in favor of Request object. */ -function drupal_request_initialize() { +function _drupal_request_initialize() { // Provided by settings.php. // @see drupal_settings_initialize() global $base_url, $cookie_domain; @@ -1922,17 +1923,16 @@ function _drupal_bootstrap_configuration() { drupal_environment_initialize(); // Initialize the configuration, including variables from settings.php. drupal_settings_initialize(); - drupal_request_initialize(); + _drupal_request_initialize(); // Make sure we are using the test database prefix in child Drupal sites. 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; + // Indicate that code is operating in a test child site. + // Only code that interfaces directly with tests should rely on this + // constant; e.g., the error/exception handler conditionally adds further + // error information into HTTP response headers that are consumed by + // Simpletest's internal browser. + define('DRUPAL_TEST_IN_CHILD_SITE', TRUE); // Log fatal errors to the test site directory. ini_set('log_errors', 1); @@ -2158,27 +2158,11 @@ function module_hook($module, $hook) { * HMAC and timestamp. */ function drupal_valid_test_ua($new_prefix = NULL) { - global $drupal_test_info; static $test_prefix; 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. - // @see \Drupal\simpletest\TestBase::setUp() - if ($new_prefix) { - $drupal_test_info['test_run_id'] = $test_prefix; - if (!isset($drupal_test_info['in_child_site'])) { - $drupal_test_info['in_child_site'] = FALSE; - } - } - // An explicit value of FALSE is passed after test run completion. - // @see \Drupal\simpletest\TestBase::tearDown() - else { - unset($drupal_test_info); - } } - if (isset($test_prefix)) { return $test_prefix; } @@ -2228,7 +2212,7 @@ function drupal_generate_test_ua($prefix) { // as the inbound request. A newly generated private key for the same test // prefix would invalidate all subsequent inbound requests. // @see \Drupal\Core\Http\Plugin\SimpletestHttpRequestSubscriber - if (($parent_prefix = drupal_valid_test_ua()) && !empty($GLOBALS['drupal_test_info']['in_child_site'])) { + if (($parent_prefix = drupal_valid_test_ua()) && defined('DRUPAL_TEST_IN_CHILD_SITE')) { if ($parent_prefix != $prefix) { throw new \RuntimeException("Malformed forwarded User-Agent: Expected '$parent_prefix' but got '$prefix'."); } diff --git a/core/includes/errors.inc b/core/includes/errors.inc index 4f5c923..84f5a1f 100644 --- a/core/includes/errors.inc +++ b/core/includes/errors.inc @@ -132,8 +132,7 @@ function _drupal_log_error($error, $fatal = FALSE) { // When running inside the testing framework, we relay the errors // to the tested site by the way of HTTP headers. - $test_info = &$GLOBALS['drupal_test_info']; - if (!empty($test_info['in_child_site']) && !headers_sent() && (!defined('SIMPLETEST_COLLECT_ERRORS') || SIMPLETEST_COLLECT_ERRORS)) { + if (defined('DRUPAL_TEST_IN_CHILD_SITE') && !headers_sent() && (!defined('SIMPLETEST_COLLECT_ERRORS') || SIMPLETEST_COLLECT_ERRORS)) { // $number does not use drupal_static as it should not be reset // as it uniquely identifies each PHP error. static $number = 0; diff --git a/core/lib/Drupal/Core/Controller/ExceptionController.php b/core/lib/Drupal/Core/Controller/ExceptionController.php index 06a89a8..0b10516 100644 --- a/core/lib/Drupal/Core/Controller/ExceptionController.php +++ b/core/lib/Drupal/Core/Controller/ExceptionController.php @@ -270,8 +270,7 @@ public function on500Html(FlattenException $exception, Request $request) { // When running inside the testing framework, we relay the errors // to the tested site by the way of HTTP headers. - $test_info = &$GLOBALS['drupal_test_info']; - if (!empty($test_info['in_child_site']) && !headers_sent() && (!defined('SIMPLETEST_COLLECT_ERRORS') || SIMPLETEST_COLLECT_ERRORS)) { + if (defined('DRUPAL_TEST_IN_CHILD_SITE') && !headers_sent() && (!defined('SIMPLETEST_COLLECT_ERRORS') || SIMPLETEST_COLLECT_ERRORS)) { // $number does not use drupal_static as it should not be reset // as it uniquely identifies each PHP error. static $number = 0; diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldImportCreateTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldImportCreateTest.php index ff1c584..2461165 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldImportCreateTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldImportCreateTest.php @@ -95,11 +95,12 @@ function testImportCreate() { // Add the new files to the staging directory. $src_dir = drupal_get_path('module', 'field_test_config') . '/staging'; - $this->assertTrue(file_unmanaged_copy("$src_dir/$field_config_name.yml", "public://config_staging/$field_config_name.yml")); - $this->assertTrue(file_unmanaged_copy("$src_dir/$instance_config_name.yml", "public://config_staging/$instance_config_name.yml")); - $this->assertTrue(file_unmanaged_copy("$src_dir/$field_config_name_2.yml", "public://config_staging/$field_config_name_2.yml")); - $this->assertTrue(file_unmanaged_copy("$src_dir/$instance_config_name_2a.yml", "public://config_staging/$instance_config_name_2a.yml")); - $this->assertTrue(file_unmanaged_copy("$src_dir/$instance_config_name_2b.yml", "public://config_staging/$instance_config_name_2b.yml")); + $target_dir = $this->configDirectories[CONFIG_STAGING_DIRECTORY]; + $this->assertTrue(file_unmanaged_copy("$src_dir/$field_config_name.yml", "$target_dir/$field_config_name.yml")); + $this->assertTrue(file_unmanaged_copy("$src_dir/$instance_config_name.yml", "$target_dir/$instance_config_name.yml")); + $this->assertTrue(file_unmanaged_copy("$src_dir/$field_config_name_2.yml", "$target_dir/$field_config_name_2.yml")); + $this->assertTrue(file_unmanaged_copy("$src_dir/$instance_config_name_2a.yml", "$target_dir/$instance_config_name_2a.yml")); + $this->assertTrue(file_unmanaged_copy("$src_dir/$instance_config_name_2b.yml", "$target_dir/$instance_config_name_2b.yml")); // Import the content of the staging directory. $this->configImporter()->import(); diff --git a/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php b/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php index c6d4b7a..1d59ca1 100644 --- a/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php @@ -71,7 +71,8 @@ public function testImportCreate() { $this->copyConfig($active, $staging); // Manually add new node type. $src_dir = drupal_get_path('module', 'node_test_config') . '/staging'; - $this->assertTrue(file_unmanaged_copy("$src_dir/$node_type_config_name.yml", "public://config_staging/$node_type_config_name.yml")); + $target_dir = $this->configDirectories[CONFIG_STAGING_DIRECTORY]; + $this->assertTrue(file_unmanaged_copy("$src_dir/$node_type_config_name.yml", "$target_dir/$node_type_config_name.yml")); // Import the content of the staging directory. $this->configImporter()->import(); diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php index 0a58f64..9654182 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -992,11 +992,6 @@ protected function prepareEnvironment() { ini_set('log_errors', 1); ini_set('error_log', $this->siteDirectory . '/error.log'); - // Set the test information for use in other parts of Drupal. - $test_info = &$GLOBALS['drupal_test_info']; - $test_info['test_run_id'] = $this->databasePrefix; - $test_info['in_child_site'] = FALSE; - // Indicate the environment was set up correctly. $this->setupEnvironment = TRUE; } diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/MissingCheckedRequirementsTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/MissingCheckedRequirementsTest.php index 8725e88..24b4348 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/MissingCheckedRequirementsTest.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/MissingCheckedRequirementsTest.php @@ -39,7 +39,7 @@ function setUp() { * Overrides checkRequirements(). */ protected function checkRequirements() { - if (!empty($GLOBALS['drupal_test_info']['in_child_site'])) { + if ($this->isInChildSite()) { return array( 'Test is not allowed to run.' ); @@ -53,7 +53,7 @@ protected function checkRequirements() { protected function testCheckRequirements() { // If this is the main request, run the web test script and then assert // that the child tests did not run. - if (empty($GLOBALS['drupal_test_info']['in_child_site'])) { + if (!$this->isInChildSite()) { // Run this test from web interface. $edit['Drupal\simpletest\Tests\MissingCheckedRequirementsTest'] = TRUE; $this->drupalPostForm('admin/config/development/testing', $edit, t('Run tests')); diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php index e830297..7fceebf 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php @@ -39,7 +39,7 @@ public static function getInfo() { } function setUp() { - if (!$this->inCURL()) { + if (!$this->isInChildSite()) { parent::setUp(); // Create and log in an admin user. $this->drupalLogin($this->drupalCreateUser(array('administer unit tests'))); @@ -54,7 +54,7 @@ function setUp() { * Test the internal browsers functionality. */ function testInternalBrowser() { - if (!$this->inCURL()) { + if (!$this->isInChildSite()) { // Retrieve the test page and check its title and headers. $this->drupalGet('test-page'); $this->assertTrue($this->drupalGetHeader('Date'), 'An HTTP header was received.'); @@ -94,7 +94,7 @@ function testInternalBrowser() { // Remove the Simpletest settings.php so we can test the protection // against requests that forge a valid testing user agent to gain access // to the installer. - drupal_unlink($this->public_files_directory . '/settings.php'); + drupal_unlink($this->siteDirectory . '/key.php'); global $base_url; $this->drupalGet(url($base_url . '/core/install.php', array('external' => TRUE, 'absolute' => TRUE))); $this->assertResponse(403, 'Cannot access install.php.'); @@ -105,7 +105,7 @@ function testInternalBrowser() { * Test validation of the User-Agent header we use to perform test requests. */ function testUserAgentValidation() { - if (!$this->inCURL()) { + if (!$this->isInChildSite()) { global $base_url; $system_path = $base_url . '/' . drupal_get_path('module', 'system'); $HTTP_path = $system_path .'/tests/http.php?q=node'; @@ -147,7 +147,7 @@ function testWebTestRunner() { $this->valid_permission = 'access content'; $this->invalid_permission = 'invalid permission'; - if ($this->inCURL()) { + if ($this->isInChildSite()) { // Only run following code if this test is running itself through a CURL // request. $this->stubTest(); @@ -335,10 +335,4 @@ function asText(\SimpleXMLElement $element) { return trim(html_entity_decode(strip_tags($element->asXML()))); } - /** - * Check if the test is being run from inside a CURL request. - */ - function inCURL() { - return (bool) !empty($GLOBALS['drupal_test_info']['in_child_site']); - } } diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 34b7d67..93519a5 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -803,22 +803,18 @@ protected function setUp() { // Since Drupal is bootstrapped already, install_begin_request() will not // bootstrap into DRUPAL_BOOTSTRAP_CONFIGURATION (again). Hence, we have to - // reload the new settings.php manually. + // reload the newly written custom settings.php manually. drupal_settings_initialize(); // Execute the non-interactive installer. require_once DRUPAL_ROOT . '/core/includes/install.core.inc'; install_drupal($parameters); - // Import new settings.php. - global $databases, $config_directories, $settings, $conf; - $settings = array(); - include DRUPAL_ROOT . '/' . $this->siteDirectory . '/settings.php'; - foreach ($config_directories as $type => $path) { - $this->configDirectories[$type] = $this->siteDirectory . '/' . $path; + // Import new settings.php written by the installer. + drupal_settings_initialize(); + foreach ($GLOBALS['config_directories'] as $type => $path) { + $this->configDirectories[$type] = $path; } - // Consume new settings written by the installer. - new Settings($settings); // After writing settings.php, the installer removes write permissions // from the site directory. To allow drupal_generate_test_ua() to write @@ -928,32 +924,18 @@ protected function installParameters() { } /** - * Writes a test-specific settings.php file for the child site. - * - * The child site loads this after the parent site's settings.php, so settings - * here override those. + * Rewrites the settings.php file of the test site. * - * @param $settings An array of settings to write out, in the format expected - * by drupal_rewrite_settings(). + * @param array $settings + * An array of settings to write out, in the format expected by + * drupal_rewrite_settings(). * - * @see _drupal_load_test_overrides() * @see drupal_rewrite_settings() */ - protected function writeSettings($settings) { - // drupal_rewrite_settings() sets the in-memory global variables in addition - // to writing the file. We'll want to restore the original globals. - foreach (array_keys($settings) as $variable_name) { - $original_globals[$variable_name] = isset($GLOBALS[$variable_name]) ? $GLOBALS[$variable_name] : NULL; - } - + protected function writeSettings(array $settings) { include_once DRUPAL_ROOT . '/core/includes/install.inc'; $filename = $this->siteDirectory . '/settings.php'; drupal_rewrite_settings($settings, $filename); - - // Restore the original globals. - foreach ($original_globals as $variable_name => $value) { - $GLOBALS[$variable_name] = $value; - } } /** @@ -1036,9 +1018,13 @@ protected function resetAll() { * database to ensure that the most up-to-date set of variables is loaded. */ protected function refreshVariables() { - global $conf; cache('bootstrap')->delete('variables'); - $conf = variable_initialize(); + // To retain in-memory global $conf from settings.php, we simply re-invoke + // DRUPAL_BOOTSTRAP_VARIABLES. + // @todo Should this reload $conf overrides from settings.php, so as to + // eliminate any additional global $conf vars that may have been set? + _drupal_bootstrap_variables(); + // Clear the tag cache. drupal_static_reset('Drupal\Core\Cache\CacheBackendInterface::tagCache'); \Drupal::service('config.factory')->reset(); @@ -1211,22 +1197,22 @@ protected function curlExec($curl_options, $redirect = FALSE) { if (!$redirect) { // Reset headers, the session ID and the redirect counter. $this->session_id = NULL; + $this->headers = array(); $this->requestId = 0; $this->requestHeaders = array(); $this->responseHeaders = array(); $this->redirect_count = 0; } - $this->headers = array(); $content = curl_exec($this->curlHandle); $status = curl_getinfo($this->curlHandle, CURLINFO_HTTP_CODE); $this->requestHeaders[$this->requestId] = curl_getinfo($this->curlHandle, CURLINFO_HEADER_OUT); - $response_headers = $this->headers; - $this->responseHeaders[$this->requestId] = array_shift($response_headers); - sort($response_headers); - $this->responseHeaders[$this->requestId] .= implode('', $response_headers); + // Sort response headers alphabetically, but keep the HTTP status first. + $response_headers = array_shift($this->responseHeaders[$this->requestId]); + sort($this->responseHeaders[$this->requestId]); + $this->responseHeaders[$this->requestId] = $response_headers . implode('', $this->responseHeaders[$this->requestId]); $this->requestId++; @@ -1274,9 +1260,11 @@ protected function curlHeaderCallback($curlHandler, $header) { if ($header[0] == ' ' || $header[0] == "\t") { // Normalize whitespace between chucks. $this->headers[] = array_pop($this->headers) . ' ' . trim($header); + $this->responseHeaders[$this->requestId][] = array_pop($this->responseHeaders[$this->requestId]) . ' ' . trim($header); } else { $this->headers[] = $header; + $this->responseHeaders[$this->requestId][] = $header; } // Errors are being sent via X-Drupal-Assertion-* headers, @@ -1319,6 +1307,21 @@ protected function curlClose() { } /** + * Returns whether the test is being executed from within a test site. + * + * Mainly used by recursive tests (i.e. to test the testing framework). + * + * @return bool + * TRUE if this test was instantiated in a request within the test site, + * FALSE otherwise. + * + * @see _drupal_bootstrap_configuration() + */ + protected function isInChildSite() { + return defined('DRUPAL_TEST_IN_CHILD_SITE'); + } + + /** * Parse content returned from curlExec using DOM and SimpleXML. * * @return diff --git a/core/modules/simpletest/simpletest.api.php b/core/modules/simpletest/simpletest.api.php index e11c651..dad9a39 100644 --- a/core/modules/simpletest/simpletest.api.php +++ b/core/modules/simpletest/simpletest.api.php @@ -6,18 +6,6 @@ */ /** - * Global variable that holds information about the tests being run. - * - * An array, with the following keys: - * - 'test_run_id': the ID of the test being run, in the form 'simpletest_%" - * - 'in_child_site': TRUE if the current request is a cURL request from - * the parent site. - * - * @var array - */ -global $drupal_test_info; - -/** * @addtogroup hooks * @{ */