MDL-37458 testing lock externalization
authorDavid Monllao <davidm@moodle.com>
Fri, 11 Jan 2013 05:57:19 +0000 (13:57 +0800)
committerDavid Monllao <davidm@moodle.com>
Wed, 16 Jan 2013 05:43:25 +0000 (13:43 +0800)
admin/tool/phpunit/cli/util.php
lib/phpunit/classes/util.php
lib/phpunit/lib.php
lib/setup.php
lib/testing/classes/test_lock.php [new file with mode: 0644]

index 5cfd128..a7552fe 100644 (file)
@@ -136,7 +136,7 @@ if ($diag) {
 
 } else if ($drop) {
     // make sure tests do not run in parallel
-    phpunit_util::acquire_test_lock();
+    test_lock::acquire('phpunit');
     phpunit_util::drop_site(true);
     // note: we must stop here because $CFG is messed up and we can not reinstall, sorry
     exit(0);
index 855269d..92d8c9d 100644 (file)
@@ -54,9 +54,6 @@ class phpunit_util {
     /** @var testing_data_generator */
     protected static $generator = null;
 
-    /** @var resource used for prevention of parallel test execution */
-    protected static $lockhandle = null;
-
     /** @var array list of debugging messages triggered during the last test execution */
     protected static $debuggings = array();
 
@@ -73,30 +70,7 @@ class phpunit_util {
      * @return void
      */
     public static function acquire_test_lock() {
-        global $CFG;
-        if (!file_exists("$CFG->phpunit_dataroot/phpunit")) {
-            // dataroot not initialised yet
-            return;
-        }
-        if (!file_exists("$CFG->phpunit_dataroot/phpunit/lock")) {
-            file_put_contents("$CFG->phpunit_dataroot/phpunit/lock", 'This file prevents concurrent execution of Moodle PHPUnit tests');
-            phpunit_boostrap_fix_file_permissions("$CFG->phpunit_dataroot/phpunit/lock");
-        }
-        if (self::$lockhandle = fopen("$CFG->phpunit_dataroot/phpunit/lock", 'r')) {
-            $wouldblock = null;
-            $locked = flock(self::$lockhandle, (LOCK_EX | LOCK_NB), $wouldblock);
-            if (!$locked) {
-                if ($wouldblock) {
-                    echo "Waiting for other test execution to complete...\n";
-                }
-                $locked = flock(self::$lockhandle, LOCK_EX);
-            }
-            if (!$locked) {
-                fclose(self::$lockhandle);
-                self::$lockhandle = null;
-            }
-        }
-        register_shutdown_function(array('phpunit_util', 'release_test_lock'));
+        test_lock::acquire('phpunit');
     }
 
     /**
@@ -106,11 +80,7 @@ class phpunit_util {
      * @return void
      */
     public static function release_test_lock() {
-        if (self::$lockhandle) {
-            flock(self::$lockhandle, LOCK_UN);
-            fclose(self::$lockhandle);
-            self::$lockhandle = null;
-        }
+        test_lock::release('phpunit');
     }
 
     /**
index 95b7f73..64d72f9 100644 (file)
@@ -36,4 +36,4 @@ require_once(__DIR__.'/classes/arraydataset.php');
 require_once(__DIR__.'/classes/advanced_testcase.php');
 require_once(__DIR__.'/classes/unittestcase.php');
 require_once(__DIR__.'/classes/hint_resultprinter.php'); // Loaded here because phpunit.xml does not support relative links for printerFile
-
+require_once(__DIR__.'/../testing/classes/test_lock.php');
index 3037136..84f630f 100644 (file)
@@ -488,7 +488,7 @@ setup_DB();
 
 if (PHPUNIT_TEST and !PHPUNIT_UTIL) {
     // make sure tests do not run in parallel
-    phpunit_util::acquire_test_lock();
+    test_lock::acquire('phpunit');
     $dbhash = null;
     try {
         if ($dbhash = $DB->get_field('config', 'value', array('name'=>'phpunittest'))) {
diff --git a/lib/testing/classes/test_lock.php b/lib/testing/classes/test_lock.php
new file mode 100644 (file)
index 0000000..b48bfd0
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Tests lock
+ *
+ * @package    core
+ * @category   test
+ * @copyright  2012 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once(__DIR__.'/lib.php');
+
+/**
+ * Tests lock to prevent concurrent executions of the same test suite
+ *
+ * @package    core
+ * @category   test
+ * @copyright  2012 Petr Skoda {@link http://skodak.org}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class test_lock {
+
+    /**
+     * @var array Array of resource used for prevention of parallel test execution
+     */
+    protected static $lockhandles = array();
+
+    /**
+     * Prevent parallel test execution - this can not work in Moodle because we modify database and dataroot.
+     *
+     * Note: do not call manually!
+     *
+     * @internal
+     * @static
+     * @param    string  $framework Test framework
+     * @return   void
+     */
+    public static function acquire($framework) {
+        global $CFG;
+
+        $datarootpath = $CFG->{$framework . '_dataroot'} . '/' . $framework;
+        $lockfile = $datarootpath . '/lock';
+        if (!file_exists($datarootpath)) {
+            // Dataroot not initialised yet.
+            return;
+        }
+        if (!file_exists($lockfile)) {
+            file_put_contents($lockfile, 'This file prevents concurrent execution of Moodle ' . $framework . ' tests');
+            testing_fix_file_permissions($lockfile);
+        }
+        if (self::$lockhandles[$framework] = fopen($lockfile, 'r')) {
+            $wouldblock = null;
+            $locked = flock(self::$lockhandles[$framework], (LOCK_EX | LOCK_NB), $wouldblock);
+            if (!$locked) {
+                if ($wouldblock) {
+                    echo "Waiting for other test execution to complete...\n";
+                }
+                $locked = flock(self::$lockhandles[$framework], LOCK_EX);
+            }
+            if (!$locked) {
+                fclose(self::$lockhandles[$framework]);
+                self::$lockhandles[$framework] = null;
+            }
+        }
+        register_shutdown_function(array('test_lock', 'release'), $framework);
+    }
+
+    /**
+     * Note: do not call manually!
+     * @internal
+     * @static
+     * @param    string  $framework phpunit|behat
+     * @return   void
+     */
+    public static function release($framework) {
+        if (self::$lockhandles[$framework]) {
+            flock(self::$lockhandles[$framework], LOCK_UN);
+            fclose(self::$lockhandles[$framework]);
+            self::$lockhandles[$framework] = null;
+        }
+    }
+
+}