From e74422f6f9ed218b0f13fa1edd6cc4d22c5e2ea9 Mon Sep 17 00:00:00 2001
From: drugan <drugan@1578644.no-reply.drupal.org>
Date: Sun, 18 Dec 2016 05:58:53 +0200
Subject: [PATCH] Issue #2745123 by Mile23, drugan, slasher13, drunken monkey,
 blazey, Yogesh Pawar: Simpletest module crashes on cleanup,
 uninstall

---
 core/modules/simpletest/simpletest.module   |   25 ++++++++++++++++++-------
 core/modules/simpletest/src/TestBase.php    |   19 ++-----------------
 core/scripts/run-tests.sh                   |   12 +++++-------
 core/tests/Drupal/Tests/BrowserTestBase.php |   22 ++--------------------
 4 files changed, 27 insertions(+), 51 deletions(-)

diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module
index f72ca5c..ca532b1 100644
--- a/core/modules/simpletest/simpletest.module
+++ b/core/modules/simpletest/simpletest.module
@@ -674,24 +674,35 @@ function simpletest_clean_database() {
 /**
  * Finds all leftover temporary directories and removes them.
  */
-function simpletest_clean_temporary_directories() {
+function simpletest_clean_temporary_directories($directory = NULL) {
   $count = 0;
-  if (is_dir(DRUPAL_ROOT . '/sites/simpletest')) {
-    $files = scandir(DRUPAL_ROOT . '/sites/simpletest');
+  $root = \Drupal::root() . '/sites/simpletest/';
+
+  if (is_dir($root)) {
+    if (is_dir($directory) && strstr($directory, $root)) {
+      $dir = explode($root, $directory);
+    }
+    $files = empty($dir[1]) ? scandir($root) : [$dir[1]];
     foreach ($files as $file) {
       if ($file[0] != '.') {
-        $path = DRUPAL_ROOT . '/sites/simpletest/' . $file;
-        file_unmanaged_delete_recursive($path, array('Drupal\simpletest\TestBase', 'filePreDeleteCallback'));
+        $path = "{$root}{$file}";
+        file_unmanaged_delete_recursive($path, function ($any_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 chmod errors.
+          @chmod($any_path, 0700);
+        });
         $count++;
       }
     }
   }
 
   if ($count > 0) {
-    drupal_set_message(\Drupal::translation()->formatPlural($count, 'Removed 1 temporary directory.', 'Removed @count temporary directories.'));
+    drupal_set_message(\Drupal::translation()->formatPlural($count, 'Removed 1 temporary directory in @root.', 'Removed @count temporary directories in @root.', ['@root' => $root]));
   }
   else {
-    drupal_set_message(t('No temporary directories to remove.'));
+    drupal_set_message(t('No temporary directories to remove in @root.', ['@root' => $root]));
   }
 }
 
diff --git a/core/modules/simpletest/src/TestBase.php b/core/modules/simpletest/src/TestBase.php
index f4a23e7..68aae02 100644
--- a/core/modules/simpletest/src/TestBase.php
+++ b/core/modules/simpletest/src/TestBase.php
@@ -1363,8 +1363,8 @@ private function restoreEnvironment() {
     $this->container = $this->originalContainer;
     \Drupal::setContainer($this->originalContainer);
 
-    // Delete test site directory.
-    file_unmanaged_delete_recursive($this->siteDirectory, array($this, 'filePreDeleteCallback'));
+    // Delete the current test site directory.
+    simpletest_clean_temporary_directories(\Drupal::root() . '/' . $this->siteDirectory);
 
     // Restore original database connection.
     Database::removeConnection('default');
@@ -1525,21 +1525,6 @@ 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/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 2936723..dfd2d7d 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -862,7 +862,7 @@ function simpletest_script_cleanup($test_id, $test_class, $exitcode) {
   // Check whether a test site directory was setup already.
   // @see \Drupal\simpletest\TestBase::prepareEnvironment()
   $test_db = new TestDatabase($db_prefix);
-  $test_directory = DRUPAL_ROOT . '/' . $test_db->getTestSitePath();
+  $test_directory = \Drupal::root() . '/' . $test_db->getTestSitePath();
   if (is_dir($test_directory)) {
     // Output the error_log.
     if (is_file($test_directory . '/error.log')) {
@@ -871,12 +871,10 @@ function simpletest_script_cleanup($test_id, $test_class, $exitcode) {
         $messages[] = $errors;
       }
     }
-    // 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.";
+    // Delete the current test site directory leaving alone other tests that
+    // are potentially running concurrently.
+    simpletest_clean_temporary_directories($test_directory);
+    $messages[] = "- Removed test site directory in {$test_directory}.";
   }
 
   // Clear out all database tables from the test.
diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php
index 1306489..5e6e17e 100644
--- a/core/tests/Drupal/Tests/BrowserTestBase.php
+++ b/core/tests/Drupal/Tests/BrowserTestBase.php
@@ -520,24 +520,6 @@ 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() {
@@ -555,8 +537,8 @@ protected function cleanupEnvironment() {
       }
     }
 
-    // Delete test site directory.
-    file_unmanaged_delete_recursive($this->siteDirectory, array($this, 'filePreDeleteCallback'));
+    // Delete the current test site directory.
+    simpletest_clean_temporary_directories(\Drupal::root() . '/' . $this->siteDirectory);
   }
 
   /**
-- 
1.7.9.5

