/** * 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 by the cookie value of * SIMPLETEST_USER_AGENT by the Mink controlled browser. During early Drupal * bootstrap, the cookie is parsed, and if it matches, all database queries * use the database table prefix that has been generated here. * * @see drupal_valid_test_ua() * @see BrowserTestBase::prepareEnvironment() */ private function prepareDatabasePrefix() { $test_db = new TestDatabase(); $this->siteDirectory = $test_db->getTestSitePath(); $this->databasePrefix = $test_db->getDatabasePrefix(); }
/** * Setup a consistent PHP environment. * * This method sets PHP environment options we want to be sure are set * correctly for security or just saneness. * * @param string $app_root * (optional) The path to the application root as a string. If not supplied, * the application root will be computed. */ public static function bootEnvironment($app_root = NULL) { if (static::$isEnvironmentInitialized) { return; } // Determine the application root if it's not supplied. if ($app_root === NULL) { $app_root = static::guessApplicationRoot(); } // Include our bootstrap file. require_once $app_root . '/core/includes/bootstrap.inc'; // Enforce E_STRICT, but allow users to set levels not part of E_STRICT. error_reporting(E_STRICT | E_ALL); // Override PHP settings required for Drupal to work properly. // sites/default/default.settings.php contains more runtime settings. // The .htaccess file contains settings that cannot be changed at runtime. // Use session cookies, not transparent sessions that puts the session id in // the query string. ini_set('session.use_cookies', '1'); ini_set('session.use_only_cookies', '1'); ini_set('session.use_trans_sid', '0'); // Don't send HTTP headers using PHP's session handler. // Send an empty string to disable the cache limiter. ini_set('session.cache_limiter', ''); // Use httponly session cookies. ini_set('session.cookie_httponly', '1'); // Set sane locale settings, to ensure consistent string, dates, times and // numbers handling. setlocale(LC_ALL, 'C'); // Detect string handling method. Unicode::check(); // Indicate that code is operating in a test child site. if (!defined('DRUPAL_TEST_IN_CHILD_SITE')) { if ($test_prefix = drupal_valid_test_ua()) { $test_db = new TestDatabase($test_prefix); // 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); // Web tests are to be conducted with runtime assertions active. assert_options(ASSERT_ACTIVE, TRUE); // Now synchronize PHP 5 and 7's handling of assertions as much as // possible. Handle::register(); // Log fatal errors to the test site directory. ini_set('log_errors', 1); ini_set('error_log', $app_root . '/' . $test_db->getTestSitePath() . '/error.log'); // Ensure that a rewritten settings.php is used if opcache is on. ini_set('opcache.validate_timestamps', 'on'); ini_set('opcache.revalidate_freq', 0); } else { // Ensure that no other code defines this. define('DRUPAL_TEST_IN_CHILD_SITE', FALSE); } } // Set the Drupal custom error handler. set_error_handler('_drupal_error_handler'); set_exception_handler('_drupal_exception_handler'); static::$isEnvironmentInitialized = TRUE; }
/** * Sets up the filesystem, so things like the file directory. */ protected function setUpFilesystem() { $test_db = new TestDatabase($this->databasePrefix); $test_site_path = $test_db->getTestSitePath(); $this->vfsRoot = vfsStream::setup('root'); $this->vfsRoot->addChild(vfsStream::newDirectory($test_site_path)); $this->siteDirectory = vfsStream::url('root/' . $test_site_path); mkdir($this->siteDirectory . '/files', 0775); mkdir($this->siteDirectory . '/files/config/' . CONFIG_SYNC_DIRECTORY, 0775, TRUE); $settings = Settings::getInstance() ? Settings::getAll() : []; $settings['file_public_path'] = $this->siteDirectory . '/files'; new Settings($settings); $GLOBALS['config_directories'] = array(CONFIG_SYNC_DIRECTORY => $this->siteDirectory . '/files/config/sync'); }
/** * @covers ::__construct * @covers ::getDatabasePrefix * @covers ::getTestSitePath * * @dataProvider providerTestConstructor */ public function testConstructor($db_prefix, $expected_db_prefix, $expected_site_path) { $test_db = new TestDatabase($db_prefix); $this->assertEquals($expected_db_prefix, $test_db->getDatabasePrefix()); $this->assertEquals($expected_site_path, $test_db->getTestSitePath()); }
/** * 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. * * @see TestBase::prepareEnvironment() * * 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 WebTestBase::curlInitialize() * @see drupal_valid_test_ua() */ private function prepareDatabasePrefix() { $test_db = new TestDatabase(); $this->siteDirectory = $test_db->getTestSitePath(); $this->databasePrefix = $test_db->getDatabasePrefix(); // As soon as the database prefix is set, the test might start to execute. // All assertions as well as the SimpleTest batch operations are associated // with the testId, so the database prefix has to be associated with it. $affected_rows = self::getDatabaseConnection()->update('simpletest_test_id') ->fields(array('last_prefix' => $this->databasePrefix)) ->condition('test_id', $this->testId) ->execute(); if (!$affected_rows) { throw new \RuntimeException('Failed to set up database prefix.'); } }
/** * Test to be run and the results confirmed. * * Here we force test results which must match the expected results from * confirmStubResults(). */ function stubTest() { // Ensure the .htkey file exists since this is only created just before a // request. This allows the stub test to make requests. The event does not // fire here and drupal_generate_test_ua() can not generate a key for a // test in a test since the prefix has changed. // @see \Drupal\Core\Test\HttpClientMiddleware\TestHttpClientMiddleware::onBeforeSendRequest() // @see drupal_generate_test_ua(); $test_db = new TestDatabase($this->databasePrefix); $key_file = DRUPAL_ROOT . '/' . $test_db->getTestSitePath() . '/.htkey'; $private_key = Crypt::randomBytesBase64(55); $site_path = $this->container->get('site.path'); file_put_contents($key_file, $private_key); // Check to see if runtime assertions are indeed on, if successful this // will be the first of sixteen passes asserted in confirmStubResults() try { // Test with minimum possible arguments to make sure no notice for // missing argument is thrown. assert(FALSE); $this->fail('Runtime assertions are not working.'); } catch (\AssertionError $e) { try { // Now test with an error message to ensure it is correctly passed // along by the rethrow. assert(FALSE, 'Lorem Ipsum'); } catch (\AssertionError $e) { $this->assertEqual($e->getMessage(), 'Lorem Ipsum', 'Runtime assertions Enabled and running.'); } } // This causes the second of the sixteen passes asserted in // confirmStubResults(). $this->pass($this->passMessage); // The first three fails are caused by enabling a non-existent module in // setUp(). // This causes the fourth of the five fails asserted in // confirmStubResults(). $this->fail($this->failMessage); // This causes the third to fifth of the sixteen passes asserted in // confirmStubResults(). $user = $this->drupalCreateUser(array($this->validPermission), 'SimpleTestTest'); // This causes the fifth of the five fails asserted in confirmStubResults(). $this->drupalCreateUser(array($this->invalidPermission)); // Test logging in as a user. // This causes the sixth to tenth of the sixteen passes asserted in // confirmStubResults(). $this->drupalLogin($user); // This causes the eleventh of the sixteen passes asserted in // confirmStubResults(). $this->pass(t('Test ID is @id.', array('@id' => $this->testId))); // These cause the twelfth to fifteenth of the sixteen passes asserted in // confirmStubResults(). $this->assertTrue(file_exists($site_path . '/settings.testing.php')); // Check the settings.testing.php file got included. $this->assertTrue(function_exists('simpletest_test_stub_settings_function')); // Check that the test-specific service file got loaded. $this->assertTrue($this->container->has('site.service.yml')); $this->assertIdentical(get_class($this->container->get('cache.backend.database')), 'Drupal\\Core\\Cache\\MemoryBackendFactory'); // These cause the two exceptions asserted in confirmStubResults(). // Call trigger_error() without the required argument to trigger an E_WARNING. trigger_error(); // Generates a warning inside a PHP function. array_key_exists(NULL, NULL); // This causes the sixteenth of the sixteen passes asserted in // confirmStubResults(). $this->assertNothing(); // This causes the debug message asserted in confirmStubResults(). debug('Foo', 'Debug', FALSE); }