/** * @covers ::getDefinitions */ public function testGetDefinitions() { // Make sure retrieving all the core migration plugins does not throw any // errors. $migration_plugins = $this->container->get('plugin.manager.migration')->getDefinitions(); // All the plugins provided by core depend on migrate_drupal. $this->assertEmpty($migration_plugins); // Enable a module that provides migrations that do not depend on // migrate_drupal. $this->enableModules(['migrate_external_translated_test']); $migration_plugins = $this->container->get('plugin.manager.migration')->getDefinitions(); // All the plugins provided by migrate_external_translated_test do not // depend on migrate_drupal. $this::assertArrayHasKey('external_translated_test_node', $migration_plugins); $this::assertArrayHasKey('external_translated_test_node_translation', $migration_plugins); // Disable the test module and the list should be empty again. $this->disableModules(['migrate_external_translated_test']); $migration_plugins = $this->container->get('plugin.manager.migration')->getDefinitions(); // All the plugins provided by core depend on migrate_drupal. $this->assertEmpty($migration_plugins); // Enable migrate_drupal to test that the plugins can now be discovered. $this->enableModules(['migrate_drupal']); // Set up a migrate database connection so that plugin discovery works. // Clone the current connection and replace the current prefix. $connection_info = Database::getConnectionInfo('migrate'); if ($connection_info) { Database::renameConnection('migrate', 'simpletest_original_migrate'); } $connection_info = Database::getConnectionInfo('default'); foreach ($connection_info as $target => $value) { $prefix = is_array($value['prefix']) ? $value['prefix']['default'] : $value['prefix']; // Simpletest uses 7 character prefixes at most so this can't cause // collisions. $connection_info[$target]['prefix']['default'] = $prefix . '0'; // Add the original simpletest prefix so SQLite can attach its database. // @see \Drupal\Core\Database\Driver\sqlite\Connection::init() $connection_info[$target]['prefix'][$value['prefix']['default']] = $value['prefix']['default']; } Database::addConnectionInfo('migrate', 'default', $connection_info['default']); $migration_plugins = $this->container->get('plugin.manager.migration')->getDefinitions(); // All the plugins provided by core depend on migrate_drupal. $this->assertNotEmpty($migration_plugins); }
/** * Changes the database connection to the prefixed one. * * @see BrowserTestBase::prepareEnvironment() */ private function changeDatabasePrefix() { 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)) { $database = Database::convertDbUrlToConnectionInfo($db_url, DRUPAL_ROOT); 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. $connection_info[$target]['prefix'] = array('default' => $value['prefix']['default'] . $this->databasePrefix); } Database::addConnectionInfo('default', 'default', $connection_info['default']); } }
/** * Cleans up the test environment and restores the original environment. * * Deletes created files, database tables, and reverts environment changes. * * This method needs to be invoked for both unit and integration tests. * * @see TestBase::prepareDatabasePrefix() * @see TestBase::changeDatabasePrefix() * @see TestBase::prepareEnvironment() */ private function restoreEnvironment() { // Destroy the session if one was started during the test-run. $_SESSION = array(); if (PHP_SAPI !== 'cli' && session_status() === PHP_SESSION_ACTIVE) { session_destroy(); $params = session_get_cookie_params(); setcookie(session_name(), '', REQUEST_TIME - 3600, $params['path'], $params['domain'], $params['secure'], $params['httponly']); } session_name($this->originalSessionName); // Reset all static variables. // Unsetting static variables will potentially invoke destruct methods, // which might call into functions that prime statics and caches again. // In that case, all functions are still operating on the test environment, // which means they may need to access its filesystem and database. drupal_static_reset(); if ($this->container && $this->container->has('state') && ($state = $this->container->get('state'))) { $captured_emails = $state->get('system.test_mail_collector') ?: array(); $emailCount = count($captured_emails); if ($emailCount) { $message = $emailCount == 1 ? '1 email was sent during this test.' : $emailCount . ' emails were sent during this test.'; $this->pass($message, 'Email'); } } // Sleep for 50ms to allow shutdown functions and terminate events to // complete. Further information: https://www.drupal.org/node/2194357. usleep(50000); // Remove all prefixed tables. $original_connection_info = Database::getConnectionInfo('simpletest_original_default'); $original_prefix = $original_connection_info['default']['prefix']['default']; $test_connection_info = Database::getConnectionInfo('default'); $test_prefix = $test_connection_info['default']['prefix']['default']; if ($original_prefix != $test_prefix) { $tables = Database::getConnection()->schema()->findTables('%'); foreach ($tables as $table) { if (Database::getConnection()->schema()->dropTable($table)) { unset($tables[$table]); } } } // In case a fatal error occurred that was not in the test process read the // log to pick up any fatal errors. simpletest_log_read($this->testId, $this->databasePrefix, get_class($this)); // Restore original dependency injection container. $this->container = $this->originalContainer; \Drupal::setContainer($this->originalContainer); // Delete test site directory. file_unmanaged_delete_recursive($this->siteDirectory, array($this, 'filePreDeleteCallback')); // Restore original database connection. Database::removeConnection('default'); Database::renameConnection('simpletest_original_default', 'default'); // Reset all static variables. // All destructors of statically cached objects have been invoked above; // this second reset is guaranteed to reset everything to nothing. drupal_static_reset(); // Restore original in-memory configuration. $GLOBALS['config'] = $this->originalConfig; $GLOBALS['conf'] = $this->originalConf; new Settings($this->originalSettings); // Restore original statics and globals. $GLOBALS['config_directories'] = $this->originalConfigDirectories; // Re-initialize original stream wrappers of the parent site. // This must happen after static variables have been reset and the original // container and $config_directories are restored, as simpletest_log_read() // uses the public stream wrapper to locate the error.log. $this->originalContainer->get('stream_wrapper_manager')->register(); if (isset($this->originalPrefix)) { drupal_valid_test_ua($this->originalPrefix); } else { drupal_valid_test_ua(FALSE); } // Restore original shutdown callbacks. $callbacks =& drupal_register_shutdown_function(); $callbacks = $this->originalShutdownCallbacks; }
/** * Returns the Database connection info to be used for this test. * * This method only exists for tests of the Database component itself, because * they require multiple database connections. Each SQLite :memory: connection * creates a new/separate database in memory. A shared-memory SQLite file URI * triggers PHP open_basedir/allow_url_fopen/allow_url_include restrictions. * Due to that, Database tests are running against a SQLite database that is * located in an actual file in the system's temporary directory. * * Other tests should not override this method. * * @return array * A Database connection info array. * * @internal */ protected function getDatabaseConnectionInfo() { // If the test is run with argument dburl then use it. $db_url = getenv('SIMPLETEST_DB'); if (empty($db_url)) { throw new \Exception('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. See https://www.drupal.org/node/2116263#skipped-tests for more information.'); } else { $database = Database::convertDbUrlToConnectionInfo($db_url, $this->root); Database::addConnectionInfo('default', 'default', $database); } // Clone the current connection and replace the current prefix. $connection_info = Database::getConnectionInfo('default'); if (!empty($connection_info)) { 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. $connection_info[$target]['prefix'] = array('default' => $value['prefix']['default'] . $this->databasePrefix); } } return $connection_info; }
/** * Cleans up the test migrate connection. * * @todo Remove when we don't use global. https://www.drupal.org/node/2552791 */ private function cleanupMigrateConnection() { Database::removeConnection('migrate'); $original_connection_info = Database::getConnectionInfo('simpletest_original_migrate'); if ($original_connection_info) { Database::renameConnection('simpletest_original_migrate', 'migrate'); } }