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
 * Utils to set Behat config
19
 *
20
 * @package    core
21
 * @category   test
22
 * @copyright  2012 David Monllaó
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
defined('MOODLE_INTERNAL') || die();
27
 
28
require_once(__DIR__ . '/behat_config_util.php');
29
 
30
/**
31
 * Behat configuration manager
32
 *
33
 * Creates/updates Behat config files getting tests
34
 * and steps from Moodle codebase
35
 *
36
 * @package    core
37
 * @category   test
38
 * @copyright  2012 David Monllaó
39
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40
 */
41
class behat_config_manager {
42
 
43
    /**
44
     * @var bool Keep track of the automatic profile conversion. So we can notify user.
45
     */
46
    public static $autoprofileconversion = false;
47
 
48
    /**
49
     * @var behat_config_util keep object of behat_config_util for use.
50
     */
51
    public static $behatconfigutil = null;
52
 
53
    /**
54
     * Returns behat_config_util.
55
     *
56
     * @return behat_config_util
57
     */
58
    private static function get_behat_config_util() {
59
        if (!self::$behatconfigutil) {
60
            self::$behatconfigutil = new behat_config_util();
61
        }
62
 
63
        return self::$behatconfigutil;
64
    }
65
 
66
    /**
67
     * Updates a config file
68
     *
69
     * The tests runner and the steps definitions list uses different
70
     * config files to avoid problems with concurrent executions.
71
     *
72
     * The steps definitions list can be filtered by component so it's
73
     * behat.yml is different from the $CFG->dirroot one.
74
     *
75
     * @param  string $component Restricts the obtained steps definitions to the specified component
76
     * @param  string $testsrunner If the config file will be used to run tests
77
     * @param  string $tags features files including tags.
78
     * @param  bool   $themesuitewithallfeatures if only theme specific features need to be included in the suite.
79
     * @param  int    $parallelruns number of parallel runs.
80
     * @param  int    $run current run for which config needs to be updated.
81
     * @return void
82
     */
83
    public static function update_config_file($component = '', $testsrunner = true, $tags = '',
84
        $themesuitewithallfeatures = false, $parallelruns = 0, $run = 0) {
85
 
86
        global $CFG;
87
 
88
        // Behat must have a separate behat.yml to have access to the whole set of features and steps definitions.
89
        if ($testsrunner === true) {
90
            $configfilepath = behat_command::get_behat_dir($run) . '/behat.yml';
91
        } else {
92
            // Alternative for steps definitions filtering, one for each user.
93
            $configfilepath = self::get_steps_list_config_filepath();
94
        }
95
 
96
        $behatconfigutil = self::get_behat_config_util();
97
        $behatconfigutil->set_theme_suite_to_include_core_features($themesuitewithallfeatures);
98
        $behatconfigutil->set_tag_for_feature_filter($tags);
99
 
100
        // Gets all the components with features, if running the tests otherwise not required.
101
        $features = array();
102
        if ($testsrunner) {
103
            $features = $behatconfigutil->get_components_features();
104
        }
105
 
106
        // Gets all the components with steps definitions.
107
        $stepsdefinitions = $behatconfigutil->get_components_contexts($component);
108
        if (!$testsrunner) {
109
            // Exclude deprecated steps definitions from the available steps list.
110
            foreach (array_keys($stepsdefinitions) as $key) {
111
                if (preg_match('/_deprecated$/', $key)) {
112
                    unset($stepsdefinitions[$key]);
113
                }
114
            }
115
        }
116
 
117
        // Get current run.
118
        if (empty($run) && ($run !== false) && !empty($CFG->behatrunprocess)) {
119
            $run = $CFG->behatrunprocess;
120
        }
121
 
122
        // Get number of parallel runs if not passed.
123
        if (empty($parallelruns) && ($parallelruns !== false)) {
124
            $parallelruns = self::get_behat_run_config_value('parallel');
125
        }
126
 
127
        // Behat config file specifing the main context class,
128
        // the required Behat extensions and Moodle test wwwroot.
129
        $contents = $behatconfigutil->get_config_file_contents($features, $stepsdefinitions, $tags, $parallelruns, $run);
130
 
131
        // Stores the file.
132
        if (!file_put_contents($configfilepath, $contents)) {
133
            behat_error(BEHAT_EXITCODE_PERMISSIONS, 'File ' . $configfilepath . ' can not be created');
134
        }
135
 
136
    }
137
 
138
    /**
139
     * Returns the behat config file path used by the steps definition list
140
     *
141
     * @return string
142
     */
143
    public static function get_steps_list_config_filepath() {
144
        global $USER;
145
 
146
        // We don't cygwin-it as it is called using exec() which uses cmd.exe.
147
        $userdir = behat_command::get_behat_dir() . '/users/' . $USER->id;
148
        make_writable_directory($userdir);
149
 
150
        return $userdir . '/behat.yml';
151
    }
152
 
153
    /**
154
     * Returns the behat config file path used by the behat cli command.
155
     *
156
     * @param int $runprocess Runprocess.
157
     * @return string
158
     */
159
    public static function get_behat_cli_config_filepath($runprocess = 0) {
160
        global $CFG;
161
 
162
        if ($runprocess) {
163
            if (isset($CFG->behat_parallel_run[$runprocess - 1 ]['behat_dataroot'])) {
164
                $command = $CFG->behat_parallel_run[$runprocess - 1]['behat_dataroot'];
165
            } else {
166
                $command = $CFG->behat_dataroot . $runprocess;
167
            }
168
        } else {
169
            $command = $CFG->behat_dataroot;
170
        }
171
        $command .= DIRECTORY_SEPARATOR . 'behat' . DIRECTORY_SEPARATOR . 'behat.yml';
172
 
173
        // Cygwin uses linux-style directory separators.
174
        if (testing_is_cygwin()) {
175
            $command = str_replace('\\', '/', $command);
176
        }
177
 
178
        return $command;
179
    }
180
 
181
    /**
182
     * Returns the path to the parallel run file which specifies if parallel test environment is enabled
183
     * and how many parallel runs to execute.
184
     *
185
     * @return string
186
     */
187
    final public static function get_behat_run_config_file_path() {
188
        return behat_command::get_parent_behat_dir() . '/run_environment.json';
189
    }
190
 
191
    /**
192
     * Get config for parallel run.
193
     *
194
     * @param string $key Key to store
195
     * @return string|int|array value which is stored.
196
     */
197
    final public static function get_behat_run_config_value($key) {
198
        $parallelrunconfigfile = self::get_behat_run_config_file_path();
199
 
200
        if (file_exists($parallelrunconfigfile)) {
201
            if ($parallelrunconfigs = @json_decode(file_get_contents($parallelrunconfigfile), true)) {
202
                if (isset($parallelrunconfigs[$key])) {
203
                    return $parallelrunconfigs[$key];
204
                }
205
            }
206
        }
207
 
208
        return false;
209
    }
210
 
211
    /**
212
     * Save/update config for parallel run.
213
     *
214
     * @param string $key Key to store
215
     * @param string|int|array $value to store.
216
     */
217
    final public static function set_behat_run_config_value($key, $value) {
218
        $parallelrunconfigs = array();
219
        $parallelrunconfigfile = self::get_behat_run_config_file_path();
220
 
221
        // Get any existing config first.
222
        if (file_exists($parallelrunconfigfile)) {
223
            $parallelrunconfigs = @json_decode(file_get_contents($parallelrunconfigfile), true);
224
        }
225
        $parallelrunconfigs[$key] = $value;
226
 
227
        @file_put_contents($parallelrunconfigfile, json_encode($parallelrunconfigs, JSON_PRETTY_PRINT));
228
    }
229
 
230
    /**
231
     * Drops parallel site links.
232
     *
233
     * @return bool true on success else false.
234
     */
235
    final public static function drop_parallel_site_links() {
236
        global $CFG;
237
 
238
        // Get parallel test runs.
239
        $parallelrun = self::get_behat_run_config_value('parallel');
240
 
241
        if (empty($parallelrun)) {
242
            return false;
243
        }
244
 
245
        // If parallel run then remove links and original file.
246
        clearstatcache();
247
        for ($i = 1; $i <= $parallelrun; $i++) {
248
            // Don't delete links for specified sites, as they should be accessible.
249
            if (!empty($CFG->behat_parallel_run['behat_wwwroot'][$i - 1]['behat_wwwroot'])) {
250
                continue;
251
            }
252
            $link = $CFG->dirroot . '/' . BEHAT_PARALLEL_SITE_NAME . $i;
253
            if (file_exists($link) && is_link($link)) {
254
                @unlink($link);
255
            }
256
        }
257
        return true;
258
    }
259
 
260
    /**
261
     * Create parallel site links.
262
     *
263
     * @param int $fromrun first run
264
     * @param int $torun last run.
265
     * @return bool true for sucess, else false.
266
     */
267
    final public static function create_parallel_site_links($fromrun, $torun) {
268
        global $CFG;
269
 
270
        // Create site symlink if necessary.
271
        clearstatcache();
272
        for ($i = $fromrun; $i <= $torun; $i++) {
273
            // Don't create links for specified sites, as they should be accessible.
274
            if (!empty($CFG->behat_parallel_run['behat_wwwroot'][$i - 1]['behat_wwwroot'])) {
275
                continue;
276
            }
277
            $link = $CFG->dirroot.'/'.BEHAT_PARALLEL_SITE_NAME.$i;
278
            clearstatcache();
279
            if (file_exists($link)) {
280
                if (!is_link($link) || !is_dir($link)) {
281
                    echo "File exists at link location ($link) but is not a link or directory!" . PHP_EOL;
282
                    return false;
283
                }
284
            } else if (!symlink($CFG->dirroot, $link)) {
285
                // Try create link in case it's not already present.
286
                echo "Unable to create behat site symlink ($link)" . PHP_EOL;
287
                return false;
288
            }
289
        }
290
        return true;
291
    }
292
}