示例#1
0
文件: WebTestBase.php 项目: Wylbur/gj
 /**
  * Initializes the kernel after installation.
  *
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   Request object.
  *
  * @return \Symfony\Component\DependencyInjection\ContainerInterface
  *   The container.
  */
 protected function initKernel(Request $request)
 {
     $this->kernel = DrupalKernel::createFromRequest($request, $this->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 accidentally load the parent site.
     return $this->kernel->rebuildContainer();
 }
示例#2
0
 /**
  * Bootstraps a kernel for a test.
  */
 private function bootKernel()
 {
     $this->setSetting('container_yamls', []);
     // Allow for test-specific overrides.
     $settings_services_file = $this->root . '/sites/default' . '/testing.services.yml';
     if (file_exists($settings_services_file)) {
         // Copy the testing-specific service overrides in place.
         $testing_services_file = $this->root . '/' . $this->siteDirectory . '/services.yml';
         copy($settings_services_file, $testing_services_file);
         $this->setSetting('container_yamls', [$testing_services_file]);
     }
     // Allow for global test environment overrides.
     if (file_exists($test_env = $this->root . '/sites/default/testing.services.yml')) {
         $GLOBALS['conf']['container_yamls']['testing'] = $test_env;
     }
     // Add this test class as a service provider.
     $GLOBALS['conf']['container_service_providers']['test'] = $this;
     $modules = self::getModulesToEnable(get_class($this));
     // Prepare a precompiled container for all tests of this class.
     // Substantially improves performance, since ContainerBuilder::compile()
     // is very expensive. Encourages testing best practices (small tests).
     // Normally a setUpBeforeClass() operation, but object scope is required to
     // inject $this test class instance as a service provider (see above).
     $rc = new \ReflectionClass(get_class($this));
     $test_method_count = count(array_filter($rc->getMethods(), function ($method) {
         // PHPUnit's @test annotations are intentionally ignored/not supported.
         return strpos($method->getName(), 'test') === 0;
     }));
     if ($test_method_count > 1 && !$this->isTestInIsolation()) {
         // Clone a precompiled, empty ContainerBuilder instance for each test.
         $container = $this->getCompiledContainerBuilder($modules);
     }
     // Bootstrap the kernel. Do not use createFromRequest() to retain Settings.
     $kernel = new DrupalKernel('testing', $this->classLoader, FALSE);
     $kernel->setSitePath($this->siteDirectory);
     // Boot the precompiled container. The kernel will enhance it with synthetic
     // services.
     if (isset($container)) {
         $kernel->setContainer($container);
         unset($container);
     } elseif ($modules && ($extensions = $this->getExtensionsForModules($modules))) {
         $kernel->updateModules($extensions, $extensions);
     }
     // DrupalKernel::boot() is not sufficient as it does not invoke preHandle(),
     // which is required to initialize legacy global variables.
     $request = Request::create('/');
     $kernel->prepareLegacyRequest($request);
     // register() is only called if a new container was built/compiled.
     $this->container = $kernel->getContainer();
     // Ensure database tasks have been run.
     require_once __DIR__ . '/../../../includes/install.inc';
     $connection = Database::getConnection();
     $errors = db_installer_object($connection->driver())->runTasks();
     if (!empty($errors)) {
         $this->fail('Failed to run installer database tasks: ' . implode(', ', $errors));
     }
     if ($modules) {
         $this->container->get('module_handler')->loadAll();
     }
     $this->container->get('request_stack')->push($request);
     // Setup the destion to the be frontpage by default.
     \Drupal::destination()->set('/');
     // Write the core.extension configuration.
     // Required for ConfigInstaller::installDefaultConfig() to work.
     $this->container->get('config.storage')->write('core.extension', array('module' => array_fill_keys($modules, 0), 'theme' => array()));
     $settings = Settings::getAll();
     $settings['php_storage']['default'] = ['class' => '\\Drupal\\Component\\PhpStorage\\FileStorage'];
     new Settings($settings);
     // 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.
     $GLOBALS['config']['system.mail']['interface']['default'] = 'test_mail_collector';
 }
示例#3
0
 /**
  * Installs Drupal into the Simpletest site.
  */
 public function installDrupal()
 {
     // Define information about the user 1 account.
     $this->rootUser = new UserSession(array('uid' => 1, 'name' => 'admin', 'mail' => '*****@*****.**', 'passRaw' => $this->randomMachineName()));
     // The child site derives its session name from the database prefix when
     // running web tests.
     $this->generateSessionName($this->databasePrefix);
     // 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->publicFilesDirectory, 'required' => TRUE);
     $this->writeSettings($settings);
     // Allow for test-specific overrides.
     $settings_testing_file = DRUPAL_ROOT . '/' . $this->originalSiteDirectory . '/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->originalSiteDirectory . '/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(DRUPAL_ROOT, $directory, $this->classLoader);
     // 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(DRUPAL_ROOT, $directory, $this->classLoader);
     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, $this->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 accidentally 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->privateFilesDirectory, FILE_CREATE_DIRECTORY);
     file_prepare_directory($this->tempFilesDirectory, FILE_CREATE_DIRECTORY);
     $config->getEditable('system.file')->set('path.private', $this->privateFilesDirectory)->set('path.temporary', $this->tempFilesDirectory)->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->getEditable('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://www.drupal.org/node/2259167
     $config->getEditable('system.logging')->set('error_level', 'verbose')->save();
     $config->getEditable('system.performance')->set('css.preprocess', FALSE)->set('js.preprocess', FALSE)->save();
     // 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_installer')->install($modules, TRUE);
         $this->assertTrue($success, SafeMarkup::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. StreamWrapperManagerInterface::getWrappers().
     // @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);
 }
示例#4
0
 /**
  * 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->rootUser = new UserSession(array('uid' => 1, 'name' => 'admin', 'mail' => '*****@*****.**', 'pass_raw' => $this->randomMachineName()));
     // The child site derives its session name from the database prefix when
     // running web tests.
     $this->generateSessionName($this->databasePrefix);
     // 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');
     copy(DRUPAL_ROOT . '/sites/default/default.services.yml', $directory . '/services.yml');
     // 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->publicFilesDirectory, 'required' => TRUE);
     $settings['settings']['file_private_path'] = (object) array('value' => $this->privateFilesDirectory, '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\Extension\ExtensionDiscovery::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);
     $settings['settings']['apcu_ensure_unique_prefix'] = (object) array('value' => FALSE, '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');
     }
     if ($this->strictConfigSchema) {
         // Add a listener to validate configuration schema on save.
         $yaml = new \Symfony\Component\Yaml\Yaml();
         $services = $yaml->parse($directory . '/services.yml');
         $services['services']['simpletest.config_schema_checker'] = ['class' => 'Drupal\\Core\\Config\\Testing\\ConfigSchemaChecker', 'arguments' => ['@config.typed'], 'tags' => [['name' => 'event_subscriber']]];
         file_put_contents($directory . '/services.yml', $yaml->dump($services));
     }
     // Since Drupal is bootstrapped already, install_begin_request() will not
     // bootstrap again. Hence, we have to reload the newly written custom
     // settings.php manually.
     $class_loader = (require DRUPAL_ROOT . '/autoload.php');
     Settings::initialize(DRUPAL_ROOT, $this->siteDirectory, $class_loader);
     // Execute the non-interactive installer.
     require_once DRUPAL_ROOT . '/core/includes/install.core.inc';
     install_drupal($class_loader, $parameters);
     // Import new settings.php written by the installer.
     Settings::initialize(DRUPAL_ROOT, $this->siteDirectory, $class_loader);
     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, $class_loader, '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 accidentally 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->privateFilesDirectory, FILE_CREATE_DIRECTORY);
     file_prepare_directory($this->tempFilesDirectory, FILE_CREATE_DIRECTORY);
     $config->getEditable('system.file')->set('path.temporary', $this->tempFilesDirectory)->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->getEditable('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://www.drupal.org/node/2259167
     $config->getEditable('system.logging')->set('error_level', 'verbose')->save();
     $config->getEditable('system.performance')->set('css.preprocess', FALSE)->set('js.preprocess', FALSE)->save();
     // 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);
         try {
             $success = $container->get('module_installer')->install($modules, TRUE);
             $this->assertTrue($success, SafeMarkup::format('Enabled modules: %modules', array('%modules' => implode(', ', $modules))));
         } catch (\Drupal\Core\Extension\MissingDependencyException $e) {
             // The exception message has all the details.
             $this->fail($e->getMessage());
         }
         $this->rebuildContainer();
     }
     // Restore the original Simpletest batch.
     $batch =& batch_get();
     $batch = $this->originalBatch;
     // 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.
     // @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);
     // Explicitly call register() again on the container registered in \Drupal.
     // @todo This should already be called through
     //   DrupalKernel::prepareLegacyRequest() -> DrupalKernel::boot() but that
     //   appears to be calling a different container.
     $this->container->get('stream_wrapper_manager')->register();
 }