Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * Tests lock
19
 *
20
 * @package    core
21
 * @category   test
22
 * @copyright  2012 Petr Skoda {@link http://skodak.org}
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
require_once(__DIR__.'/../lib.php');
27
 
28
/**
29
 * Tests lock to prevent concurrent executions of the same test suite
30
 *
31
 * @package    core
32
 * @category   test
33
 * @copyright  2012 Petr Skoda {@link http://skodak.org}
34
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
 */
36
class test_lock {
37
 
38
    /**
39
     * @var array Array of resource used for prevention of parallel test execution
40
     */
41
    protected static $lockhandles = array();
42
 
43
    /**
44
     * Prevent parallel test execution - this can not work in Moodle because we modify database and dataroot.
45
     *
46
     * Note: do not call manually!
47
     *
48
     * @internal
49
     * @static
50
     * @param   string $framework phpunit|behat
51
     * @param   string $lockfilesuffix A sub-type used by the framework
52
     * @return  void
53
     */
54
    public static function acquire(string $framework, string $lockfilesuffix = '') {
55
        global $CFG;
56
 
57
        $datarootpath = $CFG->{$framework . '_dataroot'} . '/' . $framework;
58
        $lockfile = "{$datarootpath}/lock{$lockfilesuffix}";
59
        if (!file_exists($datarootpath)) {
60
            // Dataroot not initialised yet.
61
            return;
62
        }
63
        if (!file_exists($lockfile)) {
64
            file_put_contents($lockfile, 'This file prevents concurrent execution of Moodle ' . $framework . ' tests');
65
            testing_fix_file_permissions($lockfile);
66
        }
67
 
68
        $lockhandlename = self::get_lock_handle_name($framework, $lockfilesuffix);
69
        if (self::$lockhandles[$lockhandlename] = fopen($lockfile, 'r')) {
70
            $wouldblock = null;
71
            $locked = flock(self::$lockhandles[$lockhandlename], (LOCK_EX | LOCK_NB), $wouldblock);
72
            if (!$locked) {
73
                if ($wouldblock) {
74
                    echo "Waiting for other test execution to complete...\n";
75
                }
76
                $locked = flock(self::$lockhandles[$lockhandlename], LOCK_EX);
77
            }
78
            if (!$locked) {
79
                fclose(self::$lockhandles[$lockhandlename]);
80
                self::$lockhandles[$lockhandlename] = null;
81
            }
82
        }
83
        register_shutdown_function(['test_lock', 'release'], $framework, $lockfilesuffix);
84
    }
85
 
86
    /**
87
     * Note: do not call manually!
88
     * @internal
89
     * @static
90
     * @param   string $framework phpunit|behat
91
     * @param   string $lockfilesuffix A sub-type used by the framework
92
     * @return  void
93
     */
94
    public static function release(string $framework, string $lockfilesuffix = '') {
95
        $lockhandlename = self::get_lock_handle_name($framework, $lockfilesuffix);
96
 
97
        if (self::$lockhandles[$lockhandlename]) {
98
            flock(self::$lockhandles[$lockhandlename], LOCK_UN);
99
            fclose(self::$lockhandles[$lockhandlename]);
100
            self::$lockhandles[$lockhandlename] = null;
101
        }
102
    }
103
 
104
    /**
105
     * Get the name of the lock handle stored in the class.
106
     *
107
     * @param   string $framework
108
     * @param   string $lockfilesuffix
109
     * @return  string
110
     */
111
    protected static function get_lock_handle_name(string $framework, string $lockfilesuffix): string {
112
        $lockhandlepieces = [$framework];
113
 
114
        if (!empty($lockfilesuffix)) {
115
            $lockhandlepieces[] = $lockfilesuffix;
116
        }
117
 
118
        return implode('%', $lockhandlepieces);
119
    }
120
 
121
}