TestSetupTrait.php 6.19 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<?php

namespace Drupal\Core\Test;

use Drupal\Core\Database\Database;

/**
 * Provides a trait for shared test setup functionality.
 */
trait TestSetupTrait {

  /**
   * An array of config object names that are excluded from schema checking.
   *
   * @var string[]
   */
17
  protected static $configSchemaCheckerExclusions = [
18 19 20 21 22 23 24 25
    // Following are used to test lack of or partial schema. Where partial
    // schema is provided, that is explicitly tested in specific tests.
    'config_schema_test.noschema',
    'config_schema_test.someschema',
    'config_schema_test.schema_data_types',
    'config_schema_test.no_schema_data_types',
    // Used to test application of schema to filtering of configuration.
    'config_test.dynamic.system',
26
  ];
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94

  /**
   * The dependency injection container used in the test.
   *
   * @var \Symfony\Component\DependencyInjection\ContainerInterface
   */
  protected $container;

  /**
   * The site directory of this test run.
   *
   * @var string
   */
  protected $siteDirectory = NULL;

  /**
   * The public file directory for the test environment.
   *
   * @see \Drupal\simpletest\TestBase::prepareEnvironment()
   * @see \Drupal\Tests\BrowserTestBase::prepareEnvironment()
   *
   * @var string
   */
  protected $publicFilesDirectory;

  /**
   * The site directory of the original parent site.
   *
   * @var string
   */
  protected $originalSite;

  /**
   * The private file directory for the test environment.
   *
   * @see \Drupal\simpletest\TestBase::prepareEnvironment()
   * @see \Drupal\Tests\BrowserTestBase::prepareEnvironment()
   *
   * @var string
   */
  protected $privateFilesDirectory;

  /**
   * The original installation profile.
   *
   * @var string
   */
  protected $originalProfile;

  /**
   * Set to TRUE to strict check all configuration saved.
   *
   * @see \Drupal\Core\Config\Testing\ConfigSchemaChecker
   *
   * @var bool
   */
  protected $strictConfigSchema = TRUE;

  /**
   * The DrupalKernel instance used in the test.
   *
   * @var \Drupal\Core\DrupalKernel
   */
  protected $kernel;

  /**
   * The temporary file directory for the test environment.
   *
95 96 97
   * This value has to match the temporary directory created in
   * install_base_system() for test installs.
   *
98 99
   * @see \Drupal\simpletest\TestBase::prepareEnvironment()
   * @see \Drupal\Tests\BrowserTestBase::prepareEnvironment()
100
   * @see install_base_system()
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
   *
   * @var string
   */
  protected $tempFilesDirectory;

  /**
   * The test run ID.
   *
   * @var string
   */
  protected $testId;

  /**
   * Returns the database connection to the site running Simpletest.
   *
   * @return \Drupal\Core\Database\Connection
   *   The database connection to use for inserting assertions.
   */
  public static function getDatabaseConnection() {
    return TestDatabase::getConnection();
  }

  /**
   * Generates a database prefix for running tests.
   *
   * The database prefix is used by prepareEnvironment() to setup a public files
   * directory for the test to be run, which also contains the PHP error log,
   * which is written to in case of a fatal error. Since that directory is based
   * on the database prefix, all tests (even unit tests) need to have one, in
   * order to access and read the error log.
   *
   * The generated database table prefix is used for the Drupal installation
   * being performed for the test. It is also used as user agent HTTP header
   * value by the cURL-based browser of WebTestBase, which is sent to the Drupal
   * installation of the test. During early Drupal bootstrap, the user agent
   * HTTP header is parsed, and if it matches, all database queries use the
   * database table prefix that has been generated here.
   *
   * @see \Drupal\Tests\BrowserTestBase::prepareEnvironment()
   * @see \Drupal\simpletest\WebTestBase::curlInitialize()
   * @see \Drupal\simpletest\TestBase::prepareEnvironment()
   * @see drupal_valid_test_ua()
   */
144
  protected function prepareDatabasePrefix() {
145 146 147 148 149 150 151 152
    $test_db = new TestDatabase();
    $this->siteDirectory = $test_db->getTestSitePath();
    $this->databasePrefix = $test_db->getDatabasePrefix();
  }

  /**
   * Changes the database connection to the prefixed one.
   */
153
  protected function changeDatabasePrefix() {
154 155 156 157 158 159 160
    if (empty($this->databasePrefix)) {
      $this->prepareDatabasePrefix();
    }

    // If the test is run with argument dburl then use it.
    $db_url = getenv('SIMPLETEST_DB');
    if (!empty($db_url)) {
161 162 163
      // Ensure no existing database gets in the way. If a default database
      // exists already it must be removed.
      Database::removeConnection('default');
164
      $database = Database::convertDbUrlToConnectionInfo($db_url, isset($this->root) ? $this->root : DRUPAL_ROOT);
165 166 167 168 169 170 171 172 173 174 175 176 177
      Database::addConnectionInfo('default', 'default', $database);
    }

    // Clone the current connection and replace the current prefix.
    $connection_info = Database::getConnectionInfo('default');
    if (is_null($connection_info)) {
      throw new \InvalidArgumentException('There is no database connection so no tests can be run. You must provide a SIMPLETEST_DB environment variable to run PHPUnit based functional tests outside of run-tests.sh.');
    }
    else {
      Database::renameConnection('default', 'simpletest_original_default');
      foreach ($connection_info as $target => $value) {
        // Replace the full table prefix definition to ensure that no table
        // prefixes of the test runner leak into the test.
178
        $connection_info[$target]['prefix'] = [
179
          'default' => $value['prefix']['default'] . $this->databasePrefix,
180
        ];
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
      }
      Database::addConnectionInfo('default', 'default', $connection_info['default']);
    }
  }

  /**
   * Gets the config schema exclusions for this test.
   *
   * @return string[]
   *   An array of config object names that are excluded from schema checking.
   */
  protected function getConfigSchemaExclusions() {
    $class = get_class($this);
    $exceptions = [];
    while ($class) {
      if (property_exists($class, 'configSchemaCheckerExclusions')) {
        $exceptions = array_merge($exceptions, $class::$configSchemaCheckerExclusions);
      }
      $class = get_parent_class($class);
    }
    // Filter out any duplicates.
    return array_unique($exceptions);
  }

}