diff --git a/core/tests/Drupal/TestSite/Commands/TestSiteTearDownCommand.php b/core/tests/Drupal/TestSite/Commands/TestSiteTearDownCommand.php index bbb635ed8c..e0019a047f 100644 --- a/core/tests/Drupal/TestSite/Commands/TestSiteTearDownCommand.php +++ b/core/tests/Drupal/TestSite/Commands/TestSiteTearDownCommand.php @@ -3,8 +3,6 @@ namespace Drupal\TestSite\Commands; use Drupal\Core\Database\Database; -use Drupal\Core\DrupalKernel; -use Drupal\Core\Site\Settings; use Drupal\Core\Test\TestDatabase; use Drupal\Tests\BrowserTestBase; use Symfony\Component\Console\Command\Command; @@ -76,10 +74,8 @@ protected function execute(InputInterface $input, OutputInterface $output) { $db_url = $input->getOption('db_url'); putenv("SIMPLETEST_DB=$db_url"); - $kernel = $this->bootstrapDrupal($test_database); - // Handle the cleanup of the test site. - $this->tearDown($test_database, $db_url, $kernel->getAppRoot()); + $this->tearDown($test_database, $db_url); $output->writeln("Successfully uninstalled $db_prefix test site"); } @@ -90,14 +86,13 @@ protected function execute(InputInterface $input, OutputInterface $output) { * The test database object. * @param string $db_url * The database URL. - * @param string $app_root - * The app root. * * @see \Drupal\Tests\BrowserTestBase::cleanupEnvironment() */ - protected function tearDown(TestDatabase $test_database, $db_url, $app_root) { + protected function tearDown(TestDatabase $test_database, $db_url) { // Connect to the test database. - $database = Database::convertDbUrlToConnectionInfo($db_url, $app_root); + $root = dirname(dirname(dirname(dirname(dirname(__DIR__))))); + $database = Database::convertDbUrlToConnectionInfo($db_url, $root); $database['prefix'] = ['default' => $test_database->getDatabasePrefix()]; Database::addConnectionInfo(__CLASS__, 'default', $database); @@ -107,30 +102,46 @@ protected function tearDown(TestDatabase $test_database, $db_url, $app_root) { array_walk($tables, [$schema, 'dropTable']); // Delete test site directory. - file_unmanaged_delete_recursive($test_database->getTestSitePath(), [BrowserTestBase::class, 'filePreDeleteCallback']); + $this->fileUnmanagedDeleteRecursive($test_database->getTestSitePath(), [BrowserTestBase::class, 'filePreDeleteCallback']); } /** - * Bootstraps the drupal kernel. + * Deletes all files and directories in the specified filepath recursively. * - * @param \Drupal\Core\Test\TestDatabase $test_database - * The test database object. + * Note this version has no dependencies on Drupal core to ensure that the + * test site can be torn down even if something in the test site is broken. + * + * @param $path + * A string containing either an URI or a file or directory path. + * @param callable $callback + * (optional) Callback function to run on each file prior to deleting it and + * on each directory prior to traversing it. For example, can be used to + * modify permissions. * - * @return \Drupal\Core\DrupalKernel - * The Drupal kernel. + * @return bool + * TRUE for success or if path does not exist, FALSE in the event of an + * error. + * + * @see file_unmanaged_delete_recursive() */ - protected function bootstrapDrupal(TestDatabase $test_database) { - $kernel = new DrupalKernel($this->getApplication()->getName(), $this->autoloader, FALSE); - $kernel->setSitePath($test_database->getTestSitePath()); - require_once $kernel->getAppRoot() . '/core/includes/bootstrap.inc'; - drupal_valid_test_ua($test_database->getDatabasePrefix()); - - // Finish booting Drupal in order to use functions like - // file_unmanaged_delete_recursive(). - Settings::initialize($kernel->getAppRoot(), $kernel->getSitePath(), $this->autoloader); - $kernel->boot(); - $kernel->loadLegacyIncludes(); - return $kernel; + protected function fileUnmanagedDeleteRecursive($path, $callback = NULL) { + if (isset($callback)) { + call_user_func($callback, $path); + } + if (is_dir($path)) { + $dir = dir($path); + while (($entry = $dir->read()) !== FALSE) { + if ($entry == '.' || $entry == '..') { + continue; + } + $entry_path = $path . '/' . $entry; + $this->fileUnmanagedDeleteRecursive($entry_path, $callback); + } + $dir->close(); + + return rmdir($path); + } + return unlink($path); } } diff --git a/core/tests/Drupal/Tests/Scripts/TestSiteApplicationTest.php b/core/tests/Drupal/Tests/Scripts/TestSiteApplicationTest.php index 4f764df60b..657dba615d 100644 --- a/core/tests/Drupal/Tests/Scripts/TestSiteApplicationTest.php +++ b/core/tests/Drupal/Tests/Scripts/TestSiteApplicationTest.php @@ -80,6 +80,10 @@ public function testInstallWithNonSetupClass() { * @coversNothing */ public function testInstallScript() { + $simpletest_path = $this->root . DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . 'simpletest'; + if (!is_writable($simpletest_path)) { + $this->markTestSkipped("Requires the directory $simpletest_path to exist and be writable"); + } $php_binary_finder = new PhpExecutableFinder(); $php_inary_path = $php_binary_finder->find(); @@ -146,7 +150,10 @@ public function testInstallScript() { $test_file = $this->root . DIRECTORY_SEPARATOR . $test_database->getTestSitePath() . DIRECTORY_SEPARATOR . '.htkey'; $this->assertFileExists($test_file); - // Tear down the other site installed. + // Tear down the other site installed. Tear down should work if the test + // site is broken. Prove this by removing its settings.php. + $test_site_settings = $this->root . DIRECTORY_SEPARATOR . $test_database->getTestSitePath() . DIRECTORY_SEPARATOR . 'settings.php'; + $this->assertTrue(unlink($test_site_settings)); $command_line = $php_inary_path . ' core/scripts/test-site.php tear-down ' . $other_db_prefix . ' --db_url "' . getenv('SIMPLETEST_DB') . '"'; $process = new Process($command_line, $this->root); // Set the timeout to a value that allows debugging. @@ -164,6 +171,10 @@ public function testInstallScript() { * @coversNothing */ public function testInstallInDifferentLanguage() { + $simpletest_path = $this->root . DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . 'simpletest'; + if (!is_writable($simpletest_path)) { + $this->markTestSkipped("Requires the directory $simpletest_path to exist and be writable"); + } $php_binary_finder = new PhpExecutableFinder(); $php_binary_path = $php_binary_finder->find();