diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 697f17f..471d5c4 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -519,10 +519,8 @@ function drupal_valid_http_host($host) { * Sets the base URL, cookie domain, and session name from configuration. */ function drupal_settings_initialize() { - global $base_url, $base_path, $base_root, $script_path; - // Export these settings.php variables to the global namespace. - global $databases, $cookie_domain, $conf, $db_prefix, $drupal_hash_salt, $base_secure_url, $base_insecure_url, $config_directories; + global $base_url, $databases, $cookie_domain, $conf, $drupal_hash_salt, $config_directories; $conf = array(); // Make conf_path() available as local variable in settings.php. @@ -532,6 +530,20 @@ function drupal_settings_initialize() { } new Settings(isset($settings) ? $settings : array()); +} + +/** + * Initializes global request variables. + * + * @todo D8: Eliminate this entirely in favor of Request object. + */ +function drupal_request_initialize() { + // Provided by settings.php. + // @see drupal_settings_initialize() + global $base_url, $cookie_domain; + // Set and derived from $base_url by this function. + global $base_path, $base_root, $script_path; + global $base_secure_url, $base_insecure_url; $is_https = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on'; @@ -1910,6 +1922,7 @@ function _drupal_bootstrap_configuration() { drupal_environment_initialize(); // Initialize the configuration, including variables from settings.php. drupal_settings_initialize(); + drupal_request_initialize(); // Make sure we are using the test database prefix in child Drupal sites. if ($test_prefix = drupal_valid_test_ua()) { @@ -1920,6 +1933,10 @@ function _drupal_bootstrap_configuration() { $test_info = &$GLOBALS['drupal_test_info']; $test_info['test_run_id'] = $test_prefix; $test_info['in_child_site'] = TRUE; + + // Log fatal errors to the test site directory. + ini_set('log_errors', 1); + ini_set('error_log', DRUPAL_ROOT . '/sites/simpletest/' . substr($test_prefix, 10) . '/error.log'); } // Activate the class loader. @@ -2167,7 +2184,16 @@ function drupal_valid_test_ua($new_prefix = NULL) { list(, $prefix, $time, $salt, $hmac) = $matches; $check_string = $prefix . ';' . $time . ';' . $salt; // Read the hash salt prepared by drupal_generate_test_ua(). - require DRUPAL_ROOT . '/sites/simpletest/' . substr($prefix, 10) . '/key.php'; + // This function is called before settings.php is read and Drupal's error + // handlers are set up. While Drupal's error handling may be properly + // configured on production sites, the server's PHP error_reporting may not. + // Ensure that no information leaks on production sites. + $key_file = DRUPAL_ROOT . '/sites/simpletest/' . substr($prefix, 10) . '/key.php'; + if (!is_readable($key_file)) { + header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden'); + exit; + } + require $key_file; // The file properties add more entropy not easily accessible to others. $key = $private_key . filectime(__FILE__) . fileinode(__FILE__); $time_diff = REQUEST_TIME - $time; diff --git a/core/includes/common.inc b/core/includes/common.inc index 0099008..cb4e161 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -3060,14 +3060,6 @@ function _drupal_bootstrap_code() { // Make sure all stream wrappers are registered. file_get_stream_wrappers(); - // Now that stream wrappers are registered, log fatal errors from a simpletest - // child site to a test specific file directory. - $test_info = &$GLOBALS['drupal_test_info']; - if (!empty($test_info['in_child_site'])) { - ini_set('log_errors', 1); - ini_set('error_log', 'public://error.log'); - } - // Set the allowed protocols once we have the config available. $allowed_protocols = \Drupal::config('system.filter')->get('protocols'); if (!isset($allowed_protocols)) { diff --git a/core/includes/file.inc b/core/includes/file.inc index 545fca3..622a6ca 100644 --- a/core/includes/file.inc +++ b/core/includes/file.inc @@ -575,12 +575,12 @@ function file_ensure_htaccess() { */ function file_save_htaccess($directory, $private = TRUE) { if (file_uri_scheme($directory)) { - $directory = file_stream_wrapper_uri_normalize($directory); + $htaccess_path = file_stream_wrapper_uri_normalize($directory . '/.htaccess'); } else { $directory = rtrim($directory, '/\\'); + $htaccess_path = $directory . '/.htaccess'; } - $htaccess_path = $directory . '/.htaccess'; if (file_exists($htaccess_path)) { // Short circuit if the .htaccess file already exists. diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 2ef6b95..4897ef2 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -1148,13 +1148,13 @@ function install_settings_form($form, &$form_state, &$install_state) { */ function install_settings_form_validate($form, &$form_state) { $driver = $form_state['values']['driver']; - $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; + + // @todo Remove when PIFR submits 'prefix' instead of 'db_prefix'. + if (!empty($form_state['input'][$driver]['db_prefix'])) { + $form_state['values'][$driver]['prefix'] = $form_state['input'][$driver]['db_prefix']; } + $database = $form_state['values'][$driver]; + $drivers = drupal_get_database_types(); $reflection = new \ReflectionClass($drivers[$driver]); $install_namespace = $reflection->getNamespaceName(); @@ -1162,13 +1162,6 @@ function install_settings_form_validate($form, &$form_state) { $database['namespace'] = substr($install_namespace, 0, strrpos($install_namespace, '\\')); $database['driver'] = $driver; - // @todo PIFR uses 'db_prefix' instead of 'prefix'. Remove this when it gets - // fixed. - if (!$test_prefix && isset($database['db_prefix'])) { - $database['prefix'] = $database['db_prefix']; - } - unset($database['db_prefix']); - $form_state['storage']['database'] = $database; $errors = install_database_errors($database, $form_state['values']['settings_file']); foreach ($errors as $name => $message) { diff --git a/core/lib/Drupal/Core/Database/Install/Tasks.php b/core/lib/Drupal/Core/Database/Install/Tasks.php index e80dd86..f950647 100644 --- a/core/lib/Drupal/Core/Database/Install/Tasks.php +++ b/core/lib/Drupal/Core/Database/Install/Tasks.php @@ -251,14 +251,14 @@ public function getFormOptions(array $database) { '#weight' => 10, ); - $profile = drupal_get_profile(); - $db_prefix = ($profile == 'standard') ? 'drupal_' : $profile . '_'; - $form['advanced_options']['db_prefix'] = array( + $form['advanced_options']['prefix'] = array( '#type' => 'textfield', '#title' => t('Table name prefix'), '#default_value' => '', '#size' => 45, - '#description' => t('If more than one application will be sharing this database, a unique table name prefix–such as %prefix–will prevent collisions.', array('%prefix' => $db_prefix)), + '#description' => t('If more than one application will be sharing this database, a unique table name prefix–such as %prefix–will prevent collisions.', array( + '%prefix' => preg_replace('@[^a-z0-9]@', '_', strtolower(drupal_install_profile_distribution_name())) . '_', + )), '#weight' => 10, ); diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index f6a1810..e7a18b9 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -334,17 +334,13 @@ public function updateModules(array $module_list, array $module_filenames = arra } /** - * Returns the classname based on environment and testing prefix. + * Returns the classname based on environment. * * @return string * The class name. */ protected function getClassName() { $parts = array('service_container', $this->environment); - // Make sure to use a testing-specific container even in the parent site. - if ($prefix = drupal_valid_test_ua()) { - $parts[] = $prefix; - } return implode('_', $parts); } diff --git a/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyReadOnlyStreamWrapper.php b/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyReadOnlyStreamWrapper.php index b427d3f..d230bc5 100644 --- a/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyReadOnlyStreamWrapper.php +++ b/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyReadOnlyStreamWrapper.php @@ -16,7 +16,7 @@ */ class DummyReadOnlyStreamWrapper extends LocalReadOnlyStream { function getDirectoryPath() { - return 'sites/default/files'; + return conf_path() . '/files'; } /** diff --git a/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyStreamWrapper.php b/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyStreamWrapper.php index 4836f09..cbea40f 100644 --- a/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyStreamWrapper.php +++ b/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyStreamWrapper.php @@ -16,7 +16,7 @@ */ class DummyStreamWrapper extends LocalStream { function getDirectoryPath() { - return 'sites/default/files'; + return conf_path() . '/files'; } /** diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php index 2209555..0be7bd9 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -872,20 +872,10 @@ protected function changeDatabasePrefix() { $connection_info = Database::getConnectionInfo('default'); Database::renameConnection('default', 'simpletest_original_default'); foreach ($connection_info as $target => $value) { - $connection_info[$target]['prefix'] = array( - 'default' => $value['prefix']['default'] . $this->databasePrefix, - ); + $connection_info[$target]['prefix'] = $value['prefix']['default'] . $this->databasePrefix; } Database::addConnectionInfo('default', 'default', $connection_info['default']); - // Additionally override global $databases, since the installer does not use - // the Database connection info. - // @see install_verify_database_settings() - // @see install_database_errors() - // @todo Fix installer to use Database connection info. - global $databases; - $databases['default']['default'] = $connection_info['default']; - // Indicate the database prefix was set up correctly. $this->setupDatabasePrefix = TRUE; } @@ -950,29 +940,30 @@ protected function prepareEnvironment() { // Create test directory ahead of installation so fatal errors and debug // information can be logged during installation process. + file_prepare_directory($this->siteDirectory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); + + // Prepare filesystem directory paths. $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->siteDirectory . '/translations'; - // Create the directories - file_prepare_directory($this->siteDirectory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); - // @todo Do not create these for WebTestBase; rely on installer. - file_prepare_directory($this->public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); - file_prepare_directory($this->private_files_directory, FILE_CREATE_DIRECTORY); - file_prepare_directory($this->temp_files_directory, FILE_CREATE_DIRECTORY); - file_prepare_directory($this->translation_files_directory, FILE_CREATE_DIRECTORY); - $this->generatedTestFiles = FALSE; - - // Create and set new configuration directories. - // @todo Only valid for tests not executing the installer (in any way). + // Create filesystem directories, unless the installer will be executed. + // @todo Move into DrupalUnitTestBase::setUp(). if (!$this instanceof WebTestBase) { + file_prepare_directory($this->public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); + file_prepare_directory($this->private_files_directory, FILE_CREATE_DIRECTORY); + file_prepare_directory($this->temp_files_directory, FILE_CREATE_DIRECTORY); + file_prepare_directory($this->translation_files_directory, FILE_CREATE_DIRECTORY); + + // Create and set new configuration directories. $this->prepareConfigDirectories(); } else { $GLOBALS['config_directories'] = array(); $this->configDirectories = array(); } + $this->generatedTestFiles = FALSE; // Reset statics before the old container is replaced so that objects with a // __destruct() method still have access to it. @@ -999,7 +990,7 @@ protected function prepareEnvironment() { // Log fatal errors. ini_set('log_errors', 1); - ini_set('error_log', $this->public_files_directory . '/error.log'); + 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']; @@ -1052,11 +1043,11 @@ protected function prepareConfigDirectories() { * tests can invoke this workaround when requiring services from newly * enabled modules to be immediately available in the same request. */ - protected function rebuildContainer() { + protected function rebuildContainer($environment = 'testing') { // Preserve the request object after the container rebuild. $request = \Drupal::request(); - $this->kernel = new DrupalKernel('testing', drupal_classloader(), FALSE); + $this->kernel = new DrupalKernel($environment, drupal_classloader(), FALSE); $this->kernel->boot(); // DrupalKernel replaces the container in \Drupal::getContainer() with a // different object, so we need to replace the instance on this test class. diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 0d73cfa..3f13782 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -9,6 +9,7 @@ use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\NestedArray; +use Drupal\Component\Utility\Settings; use Drupal\Component\Utility\String; use Drupal\Core\DrupalKernel; use Drupal\Core\Database\Database; @@ -47,7 +48,21 @@ protected $curlHandle; /** - * The headers of the page currently loaded in the internal browser. + * The request headers of all requests performed. + * + * @var array + */ + protected $requestHeaders; + + /** + * The response headers of all requests performed. + * + * @var array + */ + protected $responseHeaders; + + /** + * The response headers of the page currently loaded in the internal browser. * * @var Array */ @@ -731,10 +746,6 @@ protected function setUp() { // Reset all variables to perform tests in a clean environment. $conf = array(); - // Add the parent profile's search path to the child site's search paths. - // @see drupal_system_listing() - $conf['simpletest.settings']['parent_profile'] = $this->originalProfile; - // Define information about the user 1 account. $this->root_user = new UserSession(array( 'uid' => 1, @@ -747,22 +758,84 @@ protected function setUp() { $batch = &batch_get(); $batch = array(); - $this->settingsSet('file_public_path', $this->public_files_directory); + // Get parameters for install_drupal() before removing global variables. + $parameters = $this->installParameters(); + + // Prepare installer settings that are not install_drupal() parameters. + // Copy and prepare an actual settings.php, so as to resemble a regular + // installation. + copy(DRUPAL_ROOT . '/sites/default/default.settings.php', DRUPAL_ROOT . '/' . $this->siteDirectory . '/settings.php'); + + // All file system paths are set up by System module during installation. + // @see system_requirements() + // @see TestBase::prepareEnvironment() + $settings['settings']['file_public_path'] = (object) array( + 'value' => $this->public_files_directory, + 'required' => TRUE, + ); + // @todo While private/temporary filesystem paths can be preset in the + // installer via global configuration overrides, some tests expect the + // values to be configurable through the UI. By setting them in + // settings.php, they are no longer configurable... Why are these not + // settings like the public filesystem path to begin with? (consistency) + /* + $settings['conf']['system.file']['path']['private'] = (object) array( + 'value' => $this->private_files_directory, + 'required' => TRUE, + ); + $settings['conf']['system.file']['path']['temporary'] = (object) array( + 'value' => $this->temp_files_directory, + 'required' => TRUE, + ); + */ + // Use the test mail class instead of the default mail handler class. + $settings['conf']['system.mail']['interface']['default'] = (object) array( + 'value' => 'Drupal\Core\Mail\TestMailCollector', + 'required' => TRUE, + ); + // Add the parent profile's search path to the child site's search paths. + // @see drupal_system_listing() + $settings['conf']['simpletest.settings']['parent_profile'] = (object) array( + 'value' => $this->originalProfile, + 'required' => TRUE, + ); + $this->writeSettings($settings); + + // 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. + drupal_settings_initialize(); + // Execute the non-interactive installer. require_once DRUPAL_ROOT . '/core/includes/install.core.inc'; - $parameters = $this->installParameters(); 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; + } + // 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 // a key.php file containing the private key for drupal_valid_test_ua(), // the site directory has to be writable. // Use chmod() without a Drupal wrapper, so potential errors are visible. + // WebTestBase::tearDown() will delete the entire test site directory. chmod(DRUPAL_ROOT . '/' . $this->siteDirectory, 0777); - // Override install profile in Settings to so the correct profile is used by - // tests. - $this->settingsSet('install_profile', $this->profile); + // Manually provide private and temporary files directories. + // (see @todo above) + file_prepare_directory($this->private_files_directory, FILE_CREATE_DIRECTORY); + file_prepare_directory($this->temp_files_directory, FILE_CREATE_DIRECTORY); + \Drupal::config('system.file') + ->set('path.private', $this->private_files_directory) + ->set('path.temporary', $this->temp_files_directory) + ->save(); $this->rebuildContainer(); @@ -770,13 +843,6 @@ protected function setUp() { $batch = &batch_get(); $batch = $this->originalBatch; - // Set path variables. - - // Set 'parent_profile' of simpletest to add the parent profile's - // search path to the child site's search paths. - // @see drupal_system_listing() - \Drupal::config('simpletest.settings')->set('parent_profile', $this->originalProfile)->save(); - // Collect modules to install. $class = get_class($this); $modules = array(); @@ -791,13 +857,11 @@ protected function setUp() { $success = \Drupal::moduleHandler()->install($modules, TRUE); $this->assertTrue($success, t('Enabled modules: %modules', array('%modules' => implode(', ', $modules)))); $this->rebuildContainer(); - } - // Reset/rebuild all data structures after enabling the modules. - $this->resetAll(); - - // Use the test mail class instead of the default mail handler class. - \Drupal::config('system.mail')->set('interface.default', 'Drupal\Core\Mail\TestMailCollector')->save(); + // Reset static variables after enabling additional test modules. + // Affects e.g. file_get_stream_wrappers(). + drupal_static_reset(); + } drupal_set_time_limit($this->timeLimit); // Temporary fix so that when running from run-tests.sh we don't get an @@ -817,6 +881,10 @@ protected function setUp() { */ protected function installParameters() { $connection_info = Database::getConnectionInfo(); + $driver = $connection_info['default']['driver']; + unset($connection_info['default']['driver']); + unset($connection_info['default']['pdo']); + unset($connection_info['default']['init_commands']); $parameters = array( 'interactive' => FALSE, 'parameters' => array( @@ -824,7 +892,10 @@ protected function installParameters() { 'langcode' => 'en', ), 'forms' => array( - 'install_settings_form' => $connection_info['default'], + 'install_settings_form' => array( + 'driver' => $driver, + $driver => $connection_info['default'], + ), 'install_configure_form' => array( 'site_name' => 'Drupal', 'site_mail' => 'simpletest@example.com', @@ -868,8 +939,7 @@ protected function writeSettings($settings) { } include_once DRUPAL_ROOT . '/core/includes/install.inc'; - $filename = $this->public_files_directory . '/settings.php'; - file_put_contents($filename, "siteDirectory . '/settings.php'; drupal_rewrite_settings($settings, $filename); // Restore the original globals. @@ -919,8 +989,8 @@ protected function writeCustomTranslations() { /** * Overrides \Drupal\simpletest\TestBase::rebuildContainer(). */ - protected function rebuildContainer() { - parent::rebuildContainer(); + protected function rebuildContainer($environment = 'prod') { + parent::rebuildContainer($environment); // Make sure the url generator has a request object, otherwise calls to // $this->drupalGet() will fail. $this->prepareRequestForGenerator(); @@ -1021,6 +1091,7 @@ protected function curlInitialize() { CURLOPT_SSL_VERIFYHOST => FALSE, CURLOPT_HEADERFUNCTION => array(&$this, 'curlHeaderCallback'), CURLOPT_USERAGENT => $this->databasePrefix, + CURLINFO_HEADER_OUT => TRUE, ); if (isset($this->httpauth_credentials)) { $curl_options[CURLOPT_HTTPAUTH] = $this->httpauth_method; @@ -1132,13 +1203,25 @@ 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); + + $this->requestId++; + // cURL incorrectly handles URLs with fragments, so instead of // letting cURL handle redirects we take of them ourselves to // to prevent fragments being sent to the web server as part @@ -1286,7 +1369,10 @@ protected function drupalGet($path, array $options = array(), array $headers = a $verbose = 'GET request to: ' . $path . '
' . check_plain(var_export(array_map('trim', $this->headers), TRUE)) . '';
+ for ($i = 0; $i < $this->requestId; $i++) {
+ $verbose .= '' . check_plain($this->requestHeaders[$i]) . ''; + $verbose .= '
' . check_plain($this->responseHeaders[$i]) . ''; + } } $verbose .= '
' . check_plain(var_export(array_map('trim', $this->headers), TRUE)) . '';
+ for ($i = 0; $i < $this->requestId; $i++) {
+ $verbose .= '' . check_plain($this->requestHeaders[$i]) . ''; + $verbose .= '
' . check_plain($this->responseHeaders[$i]) . ''; + } } $verbose .= '
' . check_plain(var_export(array_map('trim', $this->headers), TRUE)) . '');
+ for ($i = 0; $i < $this->requestId; $i++) {
+ $verbose .= '' . check_plain($this->requestHeaders[$i]) . ''; + $verbose .= '
' . check_plain($this->responseHeaders[$i]) . ''; + } } + $this->verbose($verbose); return $out; } diff --git a/core/modules/simpletest/simpletest.install b/core/modules/simpletest/simpletest.install index 4b940ed..a4a17b7 100644 --- a/core/modules/simpletest/simpletest.install +++ b/core/modules/simpletest/simpletest.install @@ -58,6 +58,20 @@ function simpletest_requirements($phase) { $requirements['php_memory_limit']['description'] = t('The testing framework requires the PHP memory limit to be at least %memory_minimum_limit. The current value is %memory_limit. Follow these steps to continue.', array('%memory_limit' => $memory_limit, '%memory_minimum_limit' => SIMPLETEST_MINIMUM_PHP_MEMORY_LIMIT, '@url' => 'http://drupal.org/node/207036')); } + if ($phase == 'runtime') { + $site_directory = 'sites/simpletest'; + if (!drupal_verify_install_file(DRUPAL_ROOT . '/' . $site_directory, FILE_EXIST|FILE_WRITABLE, 'dir') { + $requirements['simpletest_site_directory'] = array( + 'title' => t('Simpletest site directory'), + 'value' => is_dir(DRUPAL_ROOT . '/' . $site_directory) ? t('Not writable') : t('Missing'), + 'severity' => REQUIREMENT_ERROR, + 'description' => t('The testing framework requires the !test-sites-directory to exist and be writable in order to run tests.', array( + '!test-sites-directory' => '
./' . $site_directory . '',
+ )),
+ );
+ }
+ }
+
return $requirements;
}
@@ -154,6 +168,20 @@ function simpletest_schema() {
}
/**
+ * Implements hook_install().
+ */
+function simpletest_install() {
+ // Attempt to automatically create the sites directory for tests.
+ // @see simpletest_requirements()
+ $site_directory = 'sites/simpletest';
+ if (!drupal_install_mkdir(DRUPAL_ROOT . '/' . $site_directory, FILE_READABLE|FILE_WRITABLE|FILE_EXECUTABLE)) {
+ drupal_set_message(t('The test sites directory !directory could not be created automatically. Create it manually and make it writable for the web server.', array(
+ '!directory' => './' . $site_directory . '',
+ )), 'warning');
+ }
+}
+
+/**
* Implements hook_uninstall().
*/
function simpletest_uninstall() {
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/FileTestBase.php b/core/modules/system/lib/Drupal/system/Tests/File/FileTestBase.php
index 540c19a..70fa934 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/FileTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/FileTestBase.php
@@ -16,16 +16,6 @@
*/
abstract class FileTestBase extends WebTestBase {
- function setUp() {
- parent::setUp();
- // Make sure that custom stream wrappers are registered.
- // @todo This has the potential to be a major bug deeply buried in File API;
- // file_unmanaged_*() API functions and test functions are invoking native
- // PHP functions directly, whereas Drupal's custom stream wrappers are not
- // registered yet.
- file_get_stream_wrappers();
- }
-
/**
* Check that two files have the same values for all fields other than the
* timestamp.
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/ReadOnlyStreamWrapperTest.php b/core/modules/system/lib/Drupal/system/Tests/File/ReadOnlyStreamWrapperTest.php
index ef84796..5f3ea59 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/ReadOnlyStreamWrapperTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/ReadOnlyStreamWrapperTest.php
@@ -30,14 +30,9 @@ public static function getInfo() {
);
}
- function setUp() {
- parent::setUp();
- drupal_static_reset('file_get_stream_wrappers');
- }
-
function tearDown() {
- parent::tearDown();
stream_wrapper_unregister($this->scheme);
+ parent::tearDown();
}
/**
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/StreamWrapperTest.php b/core/modules/system/lib/Drupal/system/Tests/File/StreamWrapperTest.php
index 16bc592..6ce6568 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/StreamWrapperTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/StreamWrapperTest.php
@@ -33,14 +33,9 @@ public static function getInfo() {
);
}
- function setUp() {
- parent::setUp();
- drupal_static_reset('file_get_stream_wrappers');
- }
-
function tearDown() {
- parent::tearDown();
stream_wrapper_unregister($this->scheme);
+ parent::tearDown();
}
/**
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 2598cea..ab6fd81 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -330,11 +330,11 @@ function system_requirements($phase) {
// in the intended site directory, so don't require it.
$directories[] = conf_path(FALSE) . '/files';
}
- if (!empty($conf['system.file']['path.private'])) {
- $directories[] = $conf['system.file']['path.private'];
+ if (!empty($conf['system.file']['path']['private'])) {
+ $directories[] = $conf['system.file']['path']['private'];
}
- if (!empty($conf['system.file']['path.temporary'])) {
- $directories[] = $conf['system.file']['path.temporary'];
+ if (!empty($conf['system.file']['path']['temporary'])) {
+ $directories[] = $conf['system.file']['path']['temporary'];
}
else {
// If the temporary directory is not overridden use an appropriate
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index e9f0ffe..6af207a 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -585,10 +585,9 @@ function simpletest_script_cleanup($test_id, $test_class, $exitcode) {
// Read the log file in case any fatal errors caused the test to crash.
simpletest_log_read($test_id, $db_prefix, $test_class);
- // Check whether a test file directory was setup already.
- // @see prepareEnvironment()
- $public_files = PublicStream::basePath();
- $test_directory = $public_files . '/simpletest/' . substr($db_prefix, 10);
+ // Check whether a test site directory was setup already.
+ // @see \Drupal\simpletest\TestBase::prepareEnvironment()
+ $test_directory = DRUPAL_ROOT . '/sites/simpletest/' . substr($db_prefix, 10);
if (is_dir($test_directory)) {
// Output the error_log.
if (is_file($test_directory . '/error.log')) {
@@ -597,8 +596,7 @@ function simpletest_script_cleanup($test_id, $test_class, $exitcode) {
$messages[] = $errors;
}
}
-
- // Delete the test files directory.
+ // Delete the test site directory.
// simpletest_clean_temporary_directories() cannot be used here, since it
// would also delete file directories of other tests that are potentially
// running concurrently.