MDL-54553 behat: check statuscode of http request
[moodle.git] / lib / behat / classes / util.php
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/>.
17 /**
18  * Utils for behat-related stuff
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  */
26 defined('MOODLE_INTERNAL') || die();
28 require_once(__DIR__ . '/../lib.php');
29 require_once(__DIR__ . '/../../testing/classes/util.php');
30 require_once(__DIR__ . '/behat_command.php');
31 require_once(__DIR__ . '/behat_config_manager.php');
33 require_once(__DIR__ . '/../../filelib.php');
35 /**
36  * Init/reset utilities for Behat database and dataroot
37  *
38  * @package   core
39  * @category  test
40  * @copyright 2013 David MonllaĆ³
41  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42  */
43 class behat_util extends testing_util {
45     /**
46      * The behat test site fullname and shortname.
47      */
48     const BEHATSITENAME = "Acceptance test site";
50     /**
51      * @var array Files to skip when resetting dataroot folder
52      */
53     protected static $datarootskiponreset = array('.', '..', 'behat', 'behattestdir.txt');
55     /**
56      * @var array Files to skip when dropping dataroot folder
57      */
58     protected static $datarootskipondrop = array('.', '..', 'lock');
60     /**
61      * Installs a site using $CFG->dataroot and $CFG->prefix
62      * @throws coding_exception
63      * @return void
64      */
65     public static function install_site() {
66         global $DB, $CFG;
67         require_once($CFG->dirroot.'/user/lib.php');
68         if (!defined('BEHAT_UTIL')) {
69             throw new coding_exception('This method can be only used by Behat CLI tool');
70         }
72         $tables = $DB->get_tables(false);
73         if (!empty($tables)) {
74             behat_error(BEHAT_EXITCODE_INSTALLED);
75         }
77         // New dataroot.
78         self::reset_dataroot();
80         $options = array();
81         $options['adminuser'] = 'admin';
82         $options['adminpass'] = 'admin';
83         $options['fullname'] = self::BEHATSITENAME;
84         $options['shortname'] = self::BEHATSITENAME;
86         install_cli_database($options, false);
88         // We need to keep the installed dataroot filedir files.
89         // So each time we reset the dataroot before running a test, the default files are still installed.
90         self::save_original_data_files();
92         $frontpagesummary = new admin_setting_special_frontpagedesc();
93         $frontpagesummary->write_setting(self::BEHATSITENAME);
95         // Update admin user info.
96         $user = $DB->get_record('user', array('username' => 'admin'));
97         $user->email = 'moodle@example.com';
98         $user->firstname = 'Admin';
99         $user->lastname = 'User';
100         $user->city = 'Perth';
101         $user->country = 'AU';
102         user_update_user($user, false);
104         // Disable email message processor.
105         $DB->set_field('message_processors', 'enabled', '0', array('name' => 'email'));
107         // Sets maximum debug level.
108         set_config('debug', DEBUG_DEVELOPER);
109         set_config('debugdisplay', 1);
111         // Disable some settings that are not wanted on test sites.
112         set_config('noemailever', 1);
114         // Enable web cron.
115         set_config('cronclionly', 0);
117         // Keeps the current version of database and dataroot.
118         self::store_versions_hash();
120         // Stores the database contents for fast reset.
121         self::store_database_state();
122     }
124     /**
125      * Drops dataroot and remove test database tables
126      * @throws coding_exception
127      * @return void
128      */
129     public static function drop_site() {
131         if (!defined('BEHAT_UTIL')) {
132             throw new coding_exception('This method can be only used by Behat CLI tool');
133         }
135         self::reset_dataroot();
136         self::drop_dataroot();
137         self::drop_database(true);
138     }
140     /**
141      * Checks if $CFG->behat_wwwroot is available and using same versions for cli and web.
142      *
143      * @return void
144      */
145     public static function check_server_status() {
146         global $CFG;
148         $url = $CFG->behat_wwwroot . '/admin/tool/behat/tests/behat/fixtures/environment.php';
150         // Get web versions used by behat site.
151         $ch = curl_init($url);
152         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
153         $result = curl_exec($ch);
154         $statuscode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
155         curl_close($ch);
157         if ($statuscode !== 200 || empty($result) || (!$result = json_decode($result, true))) {
159             behat_error (BEHAT_EXITCODE_REQUIREMENT, $CFG->behat_wwwroot . ' is not available, ensure you specified ' .
160                 'correct url and that the server is set up and started.' . PHP_EOL . ' More info in ' .
161                 behat_command::DOCS_URL . '#Running_tests' . PHP_EOL);
162         }
164         // Check if cli version is same as web version.
165         $clienv = self::get_environment();
166         if ($result != $clienv) {
167             $output = 'Differences detected between cli and webserver...'.PHP_EOL;
168             foreach ($result as $key => $version) {
169                 if ($clienv[$key] != $version) {
170                     $output .= ' ' . $key . ': ' . PHP_EOL;
171                     $output .= ' - web server: ' . $version . PHP_EOL;
172                     $output .= ' - cli: ' . $clienv[$key] . PHP_EOL;
173                 }
174             }
175             echo $output;
176             ob_flush();
177         }
178     }
180     /**
181      * Checks whether the test database and dataroot is ready
182      * Stops execution if something went wrong
183      * @throws coding_exception
184      * @return void
185      */
186     protected static function test_environment_problem() {
187         global $CFG, $DB;
189         if (!defined('BEHAT_UTIL')) {
190             throw new coding_exception('This method can be only used by Behat CLI tool');
191         }
193         if (!self::is_test_site()) {
194             behat_error(1, 'This is not a behat test site!');
195         }
197         $tables = $DB->get_tables(false);
198         if (empty($tables)) {
199             behat_error(BEHAT_EXITCODE_INSTALL, '');
200         }
202         if (!self::is_test_data_updated()) {
203             behat_error(BEHAT_EXITCODE_REINSTALL, 'The test environment was initialised for a different version');
204         }
205     }
207     /**
208      * Enables test mode
209      *
210      * It uses CFG->behat_dataroot
211      *
212      * Starts the test mode checking the composer installation and
213      * the test environment and updating the available
214      * features and steps definitions.
215      *
216      * Stores a file in dataroot/behat to allow Moodle to switch
217      * to the test environment when using cli-server.
218      * @throws coding_exception
219      * @return void
220      */
221     public static function start_test_mode() {
222         global $CFG;
224         if (!defined('BEHAT_UTIL')) {
225             throw new coding_exception('This method can be only used by Behat CLI tool');
226         }
228         // Checks the behat set up and the PHP version.
229         if ($errorcode = behat_command::behat_setup_problem()) {
230             exit($errorcode);
231         }
233         // Check that test environment is correctly set up.
234         self::test_environment_problem();
236         // Updates all the Moodle features and steps definitions.
237         behat_config_manager::update_config_file();
239         if (self::is_test_mode_enabled()) {
240             return;
241         }
243         $contents = '$CFG->behat_wwwroot, $CFG->behat_prefix and $CFG->behat_dataroot' .
244             ' are currently used as $CFG->wwwroot, $CFG->prefix and $CFG->dataroot';
245         $filepath = self::get_test_file_path();
246         if (!file_put_contents($filepath, $contents)) {
247             behat_error(BEHAT_EXITCODE_PERMISSIONS, 'File ' . $filepath . ' can not be created');
248         }
249     }
251     /**
252      * Returns the status of the behat test environment
253      *
254      * @return int Error code
255      */
256     public static function get_behat_status() {
258         if (!defined('BEHAT_UTIL')) {
259             throw new coding_exception('This method can be only used by Behat CLI tool');
260         }
262         // Checks the behat set up and the PHP version, returning an error code if something went wrong.
263         if ($errorcode = behat_command::behat_setup_problem()) {
264             return $errorcode;
265         }
267         // Check that test environment is correctly set up, stops execution.
268         self::test_environment_problem();
269     }
271     /**
272      * Disables test mode
273      * @throws coding_exception
274      * @return void
275      */
276     public static function stop_test_mode() {
278         if (!defined('BEHAT_UTIL')) {
279             throw new coding_exception('This method can be only used by Behat CLI tool');
280         }
282         $testenvfile = self::get_test_file_path();
284         if (!self::is_test_mode_enabled()) {
285             echo "Test environment was already disabled\n";
286         } else {
287             if (!unlink($testenvfile)) {
288                 behat_error(BEHAT_EXITCODE_PERMISSIONS, 'Can not delete test environment file');
289             }
290         }
291     }
293     /**
294      * Checks whether test environment is enabled or disabled
295      *
296      * To check is the current script is running in the test
297      * environment
298      *
299      * @return bool
300      */
301     public static function is_test_mode_enabled() {
303         $testenvfile = self::get_test_file_path();
304         if (file_exists($testenvfile)) {
305             return true;
306         }
308         return false;
309     }
311     /**
312      * Returns the path to the file which specifies if test environment is enabled
313      * @return string
314      */
315     protected final static function get_test_file_path() {
316         return behat_command::get_behat_dir() . '/test_environment_enabled.txt';
317     }
319     /**
320      * Reset contents of all database tables to initial values, reset caches, etc.
321      */
322     public static function reset_all_data() {
323         // Reset database.
324         self::reset_database();
326         // Purge dataroot directory.
327         self::reset_dataroot();
329         // Reset all static caches.
330         accesslib_clear_all_caches(true);
331         // Reset the nasty strings list used during the last test.
332         nasty_strings::reset_used_strings();
334         filter_manager::reset_caches();
336         // Reset course and module caches.
337         if (class_exists('format_base')) {
338             // If file containing class is not loaded, there is no cache there anyway.
339             format_base::reset_course_cache(0);
340         }
341         get_fast_modinfo(0, 0, true);
343         // Inform data generator.
344         self::get_data_generator()->reset();
345     }