diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module index 70f75d6..ba07282 100644 --- a/core/modules/simpletest/simpletest.module +++ b/core/modules/simpletest/simpletest.module @@ -690,9 +690,10 @@ function simpletest_clean_database() { * to be of the following pattern: sites/simpletest/12345678. If ommited, all * the test sites' directories found in sites/simpletest will be removed. * - * @return bool - * TRUE if directory is removed, FALSE otherwise. Additionally watchdog - * messages will be emitted if any path attempted to remove fails. + * @return null|bool + * Returns TRUE if all attempted to remove directories are removed, FALSE if + * at least one directory was not removed successfully, NULL if there is + * nothing to remove or the directory is not eligible for removing. * * @see file_unmanaged_delete() * @see http://php.net/manual/en/function.unlink.php @@ -700,7 +701,7 @@ function simpletest_clean_database() { function simpletest_clean_temporary_directories($directory = NULL) { $directories = []; $count = 0; - $result = FALSE; + $result = NULL; $simpletest_root = \Drupal::root() . '/sites/simpletest/'; if (is_dir($simpletest_root)) { @@ -718,8 +719,7 @@ function simpletest_clean_temporary_directories($directory = NULL) { $directories = scandir($simpletest_root); } else { - $logger = \Drupal::logger('Testing'); - $logger->error('The %path is not eligible for removing in %func().', ['%path' => $path, '%func' => __FUNCTION__]); + drupal_set_message(t('The %path is not eligible for removing in %func().', ['%path' => $path, '%func' => __FUNCTION__])); } foreach ($directories as $file) { @@ -729,25 +729,25 @@ function simpletest_clean_temporary_directories($directory = NULL) { // runner, we can make read-only files writable again. If not, chmod // will fail while the file deletion still works if file permissions // have been configured correctly. Thus, we ignore any chmod errors. - $result = file_unmanaged_delete_recursive($path, function ($any_path) { - // @see http://php.net/manual/en/function.chmod.php + $deleted = file_unmanaged_delete_recursive($path, function ($any_path) { @chmod($any_path, 0700); }); - $count++; + $result = $result === FALSE ? $result : $deleted; + if ($deleted) { + $count++; + } + else { + drupal_set_message(t('This directory is failed to be removed: @path.', ['@path' => $path])); + } } } } - // To prevent some tests failure do not display any messages if this function - // was called from within a test instead of using "Clean environment" button. - // @see https://www.drupal.org/node/2745123#comment-11837053 - if ($directory === NULL) { - if ($count > 0) { - drupal_set_message(\Drupal::translation()->formatPlural($count, 'Removed 1 temporary directory.', 'Removed @count temporary directories.')); - } - else { - drupal_set_message(t('No temporary directories to remove.')); - } + if ($count > 0) { + drupal_set_message(\Drupal::translation()->formatPlural($count, 'Removed 1 temporary directory.', 'Removed @count temporary directories.')); + } + else { + drupal_set_message(t('No temporary directories to remove.')); } return $result; diff --git a/core/modules/simpletest/src/TestBase.php b/core/modules/simpletest/src/TestBase.php index b6e2c3e..14d7909 100644 --- a/core/modules/simpletest/src/TestBase.php +++ b/core/modules/simpletest/src/TestBase.php @@ -1231,8 +1231,8 @@ private function restoreEnvironment() { $this->container = $this->originalContainer; \Drupal::setContainer($this->originalContainer); - // Delete the current test site directory. - simpletest_clean_temporary_directories($this->siteDirectory); + // Delete test site directory. + file_unmanaged_delete_recursive($this->siteDirectory, array($this, 'filePreDeleteCallback')); // Restore original database connection. Database::removeConnection('default'); @@ -1393,6 +1393,21 @@ public static function generatePermutations($parameters) { } /** + * Ensures test files are deletable within file_unmanaged_delete_recursive(). + * + * Some tests chmod generated files to be read only. During + * TestBase::restoreEnvironment() and other cleanup operations, these files + * need to get deleted too. + */ + public static function filePreDeleteCallback($path) { + // When the webserver runs with the same system user as the test runner, we + // can make read-only files writable again. If not, chmod will fail while + // the file deletion still works if file permissions have been configured + // correctly. Thus, we ignore any problems while running chmod. + @chmod($path, 0700); + } + + /** * Configuration accessor for tests. Returns non-overridden configuration. * * @param $name diff --git a/core/modules/simpletest/src/Tests/UiCleanTemporaryDirectoriesTest.php b/core/modules/simpletest/src/Tests/UiCleanTemporaryDirectoriesTest.php new file mode 100644 index 0000000..05235f4 --- /dev/null +++ b/core/modules/simpletest/src/Tests/UiCleanTemporaryDirectoriesTest.php @@ -0,0 +1,70 @@ +drupalLogin($this->drupalCreateUser(array('administer unit tests'))); + } + + /** + * Tests removing a temporary directory through the UI. + */ + public function testCleanTemporaryDirectories() { + $simpletest = \Drupal::root() . '/sites/simpletest'; + $test_site_directory = basename($this->siteDirectory); + $clean_environment = t('Clean environment'); + $this->drupalGet('admin/config/development/testing'); + + $this->assertFieldByXPath('//input', $clean_environment, 'Displayed the "Clean environment" button.'); + $this->assertNull(simpletest_clean_temporary_directories('sites/simpletest/test_site_directory'), 'The sites/simpletest/test_site_directory folder does not exist.'); + + $this->recurse_copy_test_site_directory("$simpletest/$test_site_directory", "$simpletest/test_site_directory"); + + $this->assertTrue(is_dir("$simpletest/test_site_directory"), 'The test site directory is copied to the sites/simpletest/test_site_directory folder.'); + + $this->drupalPostForm(NULL, [], $clean_environment); + + $this->assertText(t('Removed @count temporary directory.', ['@count' => 1]), 'Displayed a message: "Removed 1 temporary directory.".'); + $this->assertNoText(t('This directory is failed to be removed:'), 'The message "This directory is failed to be removed:" is not displayed.'); + $this->assertNull(simpletest_clean_temporary_directories('sites/simpletest/test_site_directory'), 'The sites/simpletest/test_site_directory folder does not exist any more.'); + } + + /** + * Creates the exact copy of the test site temporary directory. + */ + protected function recurse_copy_test_site_directory($source, $destination) { + $directory = opendir($source); + mkdir($destination); + + while(($file = readdir($directory)) !== FALSE) { + if ($file != '.' && $file != '..') { + if (is_dir("$source/$file")) { + $this->recurse_copy_test_site_directory("$source/$file", "$destination/$file"); + } + else { + copy("$source/$file", "$destination/$file"); + } + } + } + closedir($directory); + } + +} diff --git a/core/modules/simpletest/tests/modules/testing_page_test/testing_page_test.info.yml b/core/modules/simpletest/tests/modules/testing_page_test/testing_page_test.info.yml new file mode 100644 index 0000000..33773ba --- /dev/null +++ b/core/modules/simpletest/tests/modules/testing_page_test/testing_page_test.info.yml @@ -0,0 +1,6 @@ +name: 'Testing page test' +type: module +description: 'Provides customizations for the simpletest testing page.' +package: Testing +version: VERSION +core: 8.x diff --git a/core/modules/simpletest/tests/modules/testing_page_test/testing_page_test.module b/core/modules/simpletest/tests/modules/testing_page_test/testing_page_test.module new file mode 100644 index 0000000..da2d82b --- /dev/null +++ b/core/modules/simpletest/tests/modules/testing_page_test/testing_page_test.module @@ -0,0 +1,22 @@ +getTestSitePath()); + // Delete the test site directory. + // simpletest_clean_temporary_directories() cannot be used here, since it + // would also delete file directories of other tests that are potentially + // running concurrently. + file_unmanaged_delete_recursive($test_directory, array('Drupal\simpletest\TestBase', 'filePreDeleteCallback')); $messages[] = "- Removed test site directory."; } diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php index 554d8f1..d4968f4 100644 --- a/core/tests/Drupal/Tests/BrowserTestBase.php +++ b/core/tests/Drupal/Tests/BrowserTestBase.php @@ -457,6 +457,24 @@ protected function setUp() { } /** + * Ensures test files are deletable within file_unmanaged_delete_recursive(). + * + * Some tests chmod generated files to be read only. During + * BrowserTestBase::cleanupEnvironment() and other cleanup operations, + * these files need to get deleted too. + * + * @param string $path + * The file path. + */ + public static function filePreDeleteCallback($path) { + // When the webserver runs with the same system user as phpunit, we can + // make read-only files writable again. If not, chmod will fail while the + // file deletion still works if file permissions have been configured + // correctly. Thus, we ignore any problems while running chmod. + @chmod($path, 0700); + } + + /** * Clean up the Simpletest environment. */ protected function cleanupEnvironment() { @@ -474,8 +492,8 @@ protected function cleanupEnvironment() { } } - // Delete the current test site directory. - simpletest_clean_temporary_directories($this->siteDirectory); + // Delete test site directory. + file_unmanaged_delete_recursive($this->siteDirectory, array($this, 'filePreDeleteCallback')); } /**