diff --git a/admin/tool/phpunit/cli/util.php b/admin/tool/phpunit/cli/util.php index 5cfd1285690..a7552fe8e43 100644 --- a/admin/tool/phpunit/cli/util.php +++ b/admin/tool/phpunit/cli/util.php @@ -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); diff --git a/lib/phpunit/classes/util.php b/lib/phpunit/classes/util.php index 855269d67c8..92d8c9dfa19 100644 --- a/lib/phpunit/classes/util.php +++ b/lib/phpunit/classes/util.php @@ -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'); } /** diff --git a/lib/phpunit/lib.php b/lib/phpunit/lib.php index 95b7f73466d..64d72f9e0fd 100644 --- a/lib/phpunit/lib.php +++ b/lib/phpunit/lib.php @@ -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'); diff --git a/lib/setup.php b/lib/setup.php index 3037136f282..84f630fb301 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -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 index 00000000000..b48bfd0e163 --- /dev/null +++ b/lib/testing/classes/test_lock.php @@ -0,0 +1,98 @@ +. + +/** + * 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; + } + } + +}