/** * Tests \Drupal\Core\EventSubscriber\ReplicaDatabaseIgnoreSubscriber::checkReplicaServer(). */ function testSystemInitIgnoresSecondaries() { // Clone the master credentials to a replica connection. // Note this will result in two independent connection objects that happen // to point to the same place. $connection_info = Database::getConnectionInfo('default'); Database::addConnectionInfo('default', 'replica', $connection_info['default']); db_ignore_replica(); $kernel = new DrupalKernel('testing', drupal_classloader(), FALSE); $event = new GetResponseEvent($kernel, Request::create('http://example.com'), HttpKernelInterface::MASTER_REQUEST); $subscriber = new ReplicaDatabaseIgnoreSubscriber(); $subscriber->checkReplicaServer($event); $db1 = Database::getConnection('default', 'default'); $db2 = Database::getConnection('replica', 'default'); $this->assertIdentical($db1, $db2, 'System Init ignores secondaries when requested.'); }
/** * Build a kernel for testings. * * Because the bootstrap is in DrupalKernel::boot and that involved loading * settings from the filesystem we need to go to extra lengths to build a kernel * for testing. * * @param \Symfony\Component\HttpFoundation\Request $request * A request object to use in booting the kernel. * @param array $modules_enabled * A list of modules to enable on the kernel. * @param bool $read_only * Build the kernel in a read only state. * @return DrupalKernel */ protected function getTestKernel(Request $request, array $modules_enabled = NULL, $read_only = FALSE) { // Manually create kernel to avoid replacing settings. $kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'testing'); $this->settingsSet('hash_salt', $this->databasePrefix); if (isset($modules_enabled)) { $kernel->updateModules($modules_enabled); } $kernel->boot(); if ($read_only) { $php_storage = Settings::get('php_storage'); $php_storage['service_container']['class'] = 'Drupal\\Component\\PhpStorage\\FileReadOnlyStorage'; $this->settingsSet('php_storage', $php_storage); } return $kernel; }
/** * Sets up a Drupal site for running functional and integration tests. * * Installs Drupal with the installation profile specified in * \Drupal\simpletest\WebTestBase::$profile into the prefixed database. * Afterwards, installs any additional modules specified in the static * \Drupal\simpletest\WebTestBase::$modules property of each class in the * class hierarchy. * * After installation all caches are flushed and several configuration values * are reset to the values of the parent site executing the test, since the * default values may be incompatible with the environment in which tests are * being executed. */ protected function setUp() { // When running tests through the Simpletest UI (vs. on the command line), // Simpletest's batch conflicts with the installer's batch. Batch API does // not support the concept of nested batches (in which the nested is not // progressive), so we need to temporarily pretend there was no batch. // Backup the currently running Simpletest batch. $this->originalBatch = batch_get(); // Define information about the user 1 account. $this->root_user = new UserSession(array('uid' => 1, 'name' => 'admin', 'mail' => '*****@*****.**', 'pass_raw' => $this->randomName())); // Some tests (SessionTest and SessionHttpsTest) need to examine whether the // proper session cookies were set on a response. Because the child site // uses the same session name as the test runner, it is necessary to make // that available to test-methods. $this->session_name = $this->originalSessionName; // Reset the static batch to remove Simpletest's batch operations. $batch =& batch_get(); $batch = array(); // 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. // Not using File API; a potential error must trigger a PHP warning. $directory = DRUPAL_ROOT . '/' . $this->siteDirectory; copy(DRUPAL_ROOT . '/sites/default/default.settings.php', $directory . '/settings.php'); // All file system paths are created 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); // Save the original site directory path, so that extensions in the // site-specific directory can still be discovered in the test site // environment. // @see \Drupal\Core\SystemListing::scan() $settings['settings']['test_parent_site'] = (object) array('value' => $this->originalSite, 'required' => TRUE); // Add the parent profile's search path to the child site's search paths. // @see \Drupal\Core\Extension\ExtensionDiscovery::getProfileDirectories() $settings['conf']['simpletest.settings']['parent_profile'] = (object) array('value' => $this->originalProfile, 'required' => TRUE); $this->writeSettings($settings); // Allow for test-specific overrides. $settings_testing_file = DRUPAL_ROOT . '/' . $this->originalSite . '/settings.testing.php'; if (file_exists($settings_testing_file)) { // Copy the testing-specific settings.php overrides in place. copy($settings_testing_file, $directory . '/settings.testing.php'); // Add the name of the testing class to settings.php and include the // testing specific overrides file_put_contents($directory . '/settings.php', "\n\$test_class = '" . get_class($this) . "';\n" . 'include DRUPAL_ROOT . \'/\' . $site_path . \'/settings.testing.php\';' . "\n", FILE_APPEND); } $settings_services_file = DRUPAL_ROOT . '/' . $this->originalSite . '/testing.services.yml'; if (file_exists($settings_services_file)) { // Copy the testing-specific service overrides in place. copy($settings_services_file, $directory . '/services.yml'); } // Since Drupal is bootstrapped already, install_begin_request() will not // bootstrap into DRUPAL_BOOTSTRAP_CONFIGURATION (again). Hence, we have to // reload the newly written custom settings.php manually. Settings::initialize($directory); // Execute the non-interactive installer. require_once DRUPAL_ROOT . '/core/includes/install.core.inc'; install_drupal($parameters); // Import new settings.php written by the installer. Settings::initialize($directory); foreach ($GLOBALS['config_directories'] as $type => $path) { $this->configDirectories[$type] = $path; } // After writing settings.php, the installer removes write permissions // from the site directory. To allow drupal_generate_test_ua() to write // a file containing the private key for drupal_valid_test_ua(), the site // directory has to be writable. // TestBase::restoreEnvironment() will delete the entire site directory. // Not using File API; a potential error must trigger a PHP warning. chmod($directory, 0777); $request = \Drupal::request(); $this->kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'prod', TRUE); $this->kernel->prepareLegacyRequest($request); // Force the container to be built from scratch instead of loaded from the // disk. This forces us to not accidently load the parent site. $container = $this->kernel->rebuildContainer(); $config = $container->get('config.factory'); // Manually create and configure private and temporary files directories. // While these could be preset/enforced in settings.php like the public // files directory above, some tests expect them to be configurable in the // UI. If declared in settings.php, they would no longer be configurable. file_prepare_directory($this->private_files_directory, FILE_CREATE_DIRECTORY); file_prepare_directory($this->temp_files_directory, FILE_CREATE_DIRECTORY); $config->get('system.file')->set('path.private', $this->private_files_directory)->set('path.temporary', $this->temp_files_directory)->save(); // Manually configure the test mail collector implementation to prevent // tests from sending out emails and collect them in state instead. // While this should be enforced via settings.php prior to installation, // some tests expect to be able to test mail system implementations. $config->get('system.mail')->set('interface.default', 'test_mail_collector')->save(); // By default, verbosely display all errors and disable all production // environment optimizations for all tests to avoid needless overhead and // ensure a sane default experience for test authors. // @see https://drupal.org/node/2259167 $config->get('system.logging')->set('error_level', 'verbose')->save(); $config->get('system.performance')->set('css.preprocess', FALSE)->set('js.preprocess', FALSE)->save(); // Restore the original Simpletest batch. $batch =& batch_get(); $batch = $this->originalBatch; // Collect modules to install. $class = get_class($this); $modules = array(); while ($class) { if (property_exists($class, 'modules')) { $modules = array_merge($modules, $class::$modules); } $class = get_parent_class($class); } if ($modules) { $modules = array_unique($modules); $success = $container->get('module_handler')->install($modules, TRUE); $this->assertTrue($success, String::format('Enabled modules: %modules', array('%modules' => implode(', ', $modules)))); $this->rebuildContainer(); } // Reset/rebuild all data structures after enabling the modules, primarily // to synchronize all data structures and caches between the test runner and // the child site. // Affects e.g. file_get_stream_wrappers(). // @see \Drupal\Core\DrupalKernel::bootCode() // @todo Test-specific setUp() methods may set up further fixtures; find a // way to execute this after setUp() is done, or to eliminate it entirely. $this->resetAll(); $this->kernel->prepareLegacyRequest($request); // Temporary fix so that when running from run-tests.sh we don't get an // empty current path which would indicate we're on the home page. $path = current_path(); if (empty($path)) { _current_path('run-tests'); } }
/** * {@inheritdoc} */ protected function setUp() { $this->keyValueFactory = new KeyValueMemoryFactory(); // Allow for test-specific overrides. $settings_services_file = DRUPAL_ROOT . '/' . $this->originalSite . '/testing.services.yml'; if (file_exists($settings_services_file)) { // Copy the testing-specific service overrides in place. copy($settings_services_file, DRUPAL_ROOT . '/' . $this->siteDirectory . '/services.yml'); } parent::setUp(); // Create and set new configuration directories. $this->prepareConfigDirectories(); // Add this test class as a service provider. // @todo Remove the indirection; implement ServiceProviderInterface instead. $GLOBALS['conf']['container_service_providers']['TestServiceProvider'] = 'Drupal\\simpletest\\TestServiceProvider'; // Back up settings from TestBase::prepareEnvironment(). $settings = Settings::getAll(); // Bootstrap a new kernel. Don't use createFromRequest so we don't mess with settings. $this->kernel = new DrupalKernel('testing', drupal_classloader(), FALSE); $request = Request::create('/'); $this->kernel->setSitePath(DrupalKernel::findSitePath($request)); $this->kernel->boot(); // Restore and merge settings. // DrupalKernel::boot() initializes new Settings, and the containerBuild() // method sets additional settings. new Settings($settings + Settings::getAll()); // Set the request scope. $this->container = $this->kernel->getContainer(); $this->container->get('request_stack')->push($request); $this->container->get('state')->set('system.module.files', $this->moduleFiles); $this->container->get('state')->set('system.theme.files', $this->themeFiles); // Create a minimal core.extension configuration object so that the list of // enabled modules can be maintained allowing // \Drupal\Core\Config\ConfigInstaller::installDefaultConfig() to work. // Write directly to active storage to avoid early instantiation of // the event dispatcher which can prevent modules from registering events. \Drupal::service('config.storage')->write('core.extension', array('module' => array(), 'theme' => array())); // Collect and set a fixed module list. $class = get_class($this); $modules = array(); while ($class) { if (property_exists($class, 'modules')) { // Only add the modules, if the $modules property was not inherited. $rp = new \ReflectionProperty($class, 'modules'); if ($rp->class == $class) { $modules[$class] = $class::$modules; } } $class = get_parent_class($class); } // Modules have been collected in reverse class hierarchy order; modules // defined by base classes should be sorted first. Then, merge the results // together. $modules = array_reverse($modules); $modules = call_user_func_array('array_merge_recursive', $modules); if ($modules) { $this->enableModules($modules); } // In order to use theme functions default theme config needs to exist. \Drupal::config('system.theme')->set('default', 'stark'); // Tests based on this class are entitled to use Drupal's File and // StreamWrapper APIs. // @todo Move StreamWrapper management into DrupalKernel. // @see https://drupal.org/node/2028109 $this->streamWrappers = array(); // The public stream wrapper only depends on the file_public_path setting, // which is provided by UnitTestBase::setUp(). $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'); }
/** * Overrides WebTestBase::setUp(). */ protected function setUp() { $this->isInstalled = FALSE; // Define information about the user 1 account. $this->root_user = new UserSession(array('uid' => 1, 'name' => 'admin', 'mail' => '*****@*****.**', 'pass_raw' => $this->randomMachineName())); // If any $settings are defined for this test, copy and prepare an actual // settings.php, so as to resemble a regular installation. if (!empty($this->settings)) { // Not using File API; a potential error must trigger a PHP warning. copy(DRUPAL_ROOT . '/sites/default/default.settings.php', DRUPAL_ROOT . '/' . $this->siteDirectory . '/settings.php'); $this->writeSettings($this->settings); } // Note that WebTestBase::installParameters() returns form input values // suitable for a programmed drupal_form_submit(). // @see WebTestBase::translatePostValues() $this->parameters = $this->installParameters(); // Set up a minimal container (required by WebTestBase). // @see install_begin_request() $request = Request::create($GLOBALS['base_url'] . '/core/install.php'); $this->container = new ContainerBuilder(); $request_stack = new RequestStack(); $request_stack->push($request); $this->container->set('request_stack', $request_stack); $this->container->setParameter('language.default_values', Language::$defaultValues); $this->container->register('language.default', 'Drupal\\Core\\Language\\LanguageDefault')->addArgument('%language.default_values%'); $this->container->register('language_manager', 'Drupal\\Core\\Language\\LanguageManager')->addArgument(new Reference('language.default')); $this->container->register('string_translation', 'Drupal\\Core\\StringTranslation\\TranslationManager')->addArgument(new Reference('language_manager')); \Drupal::setContainer($this->container); $this->drupalGet($GLOBALS['base_url'] . '/core/install.php'); // Select language. $this->setUpLanguage(); // Select profile. $this->setUpProfile(); // Configure settings. $this->setUpSettings(); // @todo Allow test classes based on this class to act on further installer // screens. // Configure site. $this->setUpSite(); // Import new settings.php written by the installer. $request = Request::createFromGlobals(); Settings::initialize(DrupalKernel::findSitePath($request)); foreach ($GLOBALS['config_directories'] as $type => $path) { $this->configDirectories[$type] = $path; } // After writing settings.php, the installer removes write permissions // from the site directory. To allow drupal_generate_test_ua() to write // a file containing the private key for drupal_valid_test_ua(), the site // directory has to be writable. // WebTestBase::tearDown() will delete the entire test site directory. // Not using File API; a potential error must trigger a PHP warning. chmod(DRUPAL_ROOT . '/' . $this->siteDirectory, 0777); $this->kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'prod', FALSE); $this->kernel->prepareLegacyRequest($request); $this->container = $this->kernel->getContainer(); $config = $this->container->get('config.factory'); // Manually configure the test mail collector implementation to prevent // tests from sending out e-mails and collect them in state instead. $config->get('system.mail')->set('interface.default', 'test_mail_collector')->save(); // When running from run-tests.sh we don't get an empty current path which // would indicate we're on the home page. $path = current_path(); if (empty($path)) { _current_path('run-tests'); } $this->isInstalled = TRUE; }
/** * {@inheritdoc} */ public function boot() { if ($this->booted) { return $this; } // Start a page timer: Timer::start('page'); drupal_classloader(); // Load legacy and other functional code. require_once DRUPAL_ROOT . '/core/includes/common.inc'; require_once DRUPAL_ROOT . '/core/includes/database.inc'; require_once DRUPAL_ROOT . '/' . Settings::get('path_inc', 'core/includes/path.inc'); require_once DRUPAL_ROOT . '/core/includes/module.inc'; require_once DRUPAL_ROOT . '/core/includes/theme.inc'; require_once DRUPAL_ROOT . '/core/includes/pager.inc'; require_once DRUPAL_ROOT . '/' . Settings::get('menu_inc', 'core/includes/menu.inc'); require_once DRUPAL_ROOT . '/core/includes/tablesort.inc'; require_once DRUPAL_ROOT . '/core/includes/file.inc'; require_once DRUPAL_ROOT . '/core/includes/unicode.inc'; require_once DRUPAL_ROOT . '/core/includes/form.inc'; require_once DRUPAL_ROOT . '/core/includes/mail.inc'; require_once DRUPAL_ROOT . '/core/includes/ajax.inc'; require_once DRUPAL_ROOT . '/core/includes/errors.inc'; require_once DRUPAL_ROOT . '/core/includes/schema.inc'; require_once DRUPAL_ROOT . '/core/includes/entity.inc'; // Ensure that findSitePath is set. if (!$this->sitePath) { throw new \Exception('Kernel does not have site path set before calling boot()'); } // Intialize the container. $this->initializeContainer(); // Ensure mt_rand() is reseeded to prevent random values from one page load // being exploited to predict random values in subsequent page loads. $seed = unpack("L", Crypt::randomBytes(4)); mt_srand($seed[1]); $this->booted = TRUE; return $this; }