MDL-32323 all-in-one PHPUnit init script
[moodle.git] / lib / phpunit / bootstrap.php
CommitLineData
5bd40408
PS
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 * Prepares PHPUnit environment, it is called automatically.
19 *
20 * Exit codes:
21 * 0 - success
22 * 1 - general error
23 * 130 - coding error
24 * 131 - configuration problem
a3d5830a
PS
25 * 132 - install new test database
26 * 133 - drop old data, then install new test database
5bd40408 27 *
7aea08e1 28 * @package core
5bd40408
PS
29 * @category phpunit
30 * @copyright 2012 Petr Skoda {@link http://skodak.org}
31 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32 */
33
34// we want to know about all problems
35error_reporting(E_ALL | E_STRICT);
36ini_set('display_errors', '1');
37ini_set('log_errors', '1');
38
39if (isset($_SERVER['REMOTE_ADDR'])) {
a3d5830a 40 phpunit_bootstrap_error('Unit tests can be executed only from command line!', 1);
5bd40408
PS
41}
42
a3d5830a
PS
43if (defined('PHPUNIT_TEST')) {
44 phpunit_bootstrap_error("PHPUNIT_TEST constant must not be manually defined anywhere!", 130);
45}
46/** PHPUnit testing framework active */
47define('PHPUNIT_TEST', true);
48
a3d5830a
PS
49if (!defined('PHPUNIT_UTIL')) {
50 /** Identifies utility scripts */
51 define('PHPUNIT_UTIL', false);
5bd40408 52}
5bd40408
PS
53
54if (defined('CLI_SCRIPT')) {
55 phpunit_bootstrap_error('CLI_SCRIPT must not be manually defined in any PHPUnit test scripts', 130);
56}
57define('CLI_SCRIPT', true);
58
59define('NO_OUTPUT_BUFFERING', true);
60
61// only load CFG from config.php
62define('ABORT_AFTER_CONFIG', true);
63require(__DIR__ . '/../../config.php');
64
7514f9c2
PS
65if (!defined('PHPUNIT_LONGTEST')) {
66 /** Execute longer version of tests */
67 define('PHPUNIT_LONGTEST', false);
68}
69
5bd40408 70// remove error handling overrides done in config.php
a3d5830a 71error_reporting(E_ALL | E_STRICT);
5bd40408
PS
72ini_set('display_errors', '1');
73ini_set('log_errors', '1');
a3d5830a 74set_time_limit(0); // no time limit in CLI scripts, user may cancel execution
5bd40408
PS
75
76// prepare dataroot
77umask(0);
78if (isset($CFG->phpunit_directorypermissions)) {
79 $CFG->directorypermissions = $CFG->phpunit_directorypermissions;
80} else {
81 $CFG->directorypermissions = 02777;
82}
83$CFG->filepermissions = ($CFG->directorypermissions & 0666);
84if (!isset($CFG->phpunit_dataroot)) {
85 phpunit_bootstrap_error('Missing $CFG->phpunit_dataroot in config.php, can not run tests!', 131);
86}
87if (isset($CFG->dataroot) and $CFG->phpunit_dataroot === $CFG->dataroot) {
88 phpunit_bootstrap_error('$CFG->dataroot and $CFG->phpunit_dataroot must not be identical, can not run tests!', 131);
89}
90if (!file_exists($CFG->phpunit_dataroot)) {
91 mkdir($CFG->phpunit_dataroot, $CFG->directorypermissions);
92}
93if (!is_dir($CFG->phpunit_dataroot)) {
94 phpunit_bootstrap_error('$CFG->phpunit_dataroot directory can not be created, can not run tests!', 131);
95}
96if (!is_writable($CFG->phpunit_dataroot)) {
97 // try to fix premissions if possible
98 if (function_exists('posix_getuid')) {
99 $chmod = fileperms($CFG->phpunit_dataroot);
100 if (fileowner($dir) == posix_getuid()) {
101 $chmod = $chmod | 0700;
102 chmod($CFG->phpunit_dataroot, $chmod);
103 }
104 }
105 if (!is_writable($CFG->phpunit_dataroot)) {
106 phpunit_bootstrap_error('$CFG->phpunit_dataroot directory is not writable, can not run tests!', 131);
107 }
108}
109if (!file_exists("$CFG->phpunit_dataroot/phpunittestdir.txt")) {
110 if ($dh = opendir($CFG->phpunit_dataroot)) {
111 while (($file = readdir($dh)) !== false) {
112 if ($file === 'phpunit' or $file === '.' or $file === '..' or $file === '.DS_store') {
113 continue;
114 }
115 phpunit_bootstrap_error('$CFG->phpunit_dataroot directory is not empty, can not run tests! Is it used for anything else?', 131);
116 }
117 closedir($dh);
118 unset($dh);
119 unset($file);
120 }
121
122 // now we are 100% sure this dir is used only for phpunit tests
123 phpunit_bootstrap_initdataroot($CFG->phpunit_dataroot);
124}
125
126
127// verify db prefix
128if (!isset($CFG->phpunit_prefix)) {
a3d5830a
PS
129 phpunit_bootstrap_error('Missing $CFG->phpunit_prefix in config.php, can not run tests!', 131);
130}
131if ($CFG->phpunit_prefix === '') {
132 phpunit_bootstrap_error('$CFG->phpunit_prefix can not be empty, can not run tests!', 131);
5bd40408
PS
133}
134if (isset($CFG->prefix) and $CFG->prefix === $CFG->phpunit_prefix) {
135 phpunit_bootstrap_error('$CFG->prefix and $CFG->phpunit_prefix must not be identical, can not run tests!', 131);
136}
137
138// throw away standard CFG settings
139
140$CFG->dataroot = $CFG->phpunit_dataroot;
141$CFG->prefix = $CFG->phpunit_prefix;
142
143$allowed = array('wwwroot', 'dataroot', 'dirroot', 'admin', 'directorypermissions', 'filepermissions',
144 'dbtype', 'dblibrary', 'dbhost', 'dbname', 'dbuser', 'dbpass', 'prefix', 'dboptions');
145$productioncfg = (array)$CFG;
146$CFG = new stdClass();
147foreach ($productioncfg as $key=>$value) {
148 if (!in_array($key, $allowed) and strpos($key, 'phpunit_') !== 0) {
149 // ignore
150 continue;
151 }
152 $CFG->{$key} = $value;
153}
154unset($key);
155unset($value);
156unset($allowed);
157unset($productioncfg);
158
159// force the same CFG settings in all sites
a3d5830a 160$CFG->debug = (E_ALL | E_STRICT); // can not use DEBUG_DEVELOPER yet
5bd40408
PS
161$CFG->debugdisplay = 1;
162error_reporting($CFG->debug);
163ini_set('display_errors', '1');
164ini_set('log_errors', '0');
165
a3d5830a
PS
166$CFG->passwordsaltmain = 'phpunit'; // makes login via normal UI impossible
167
5bd40408
PS
168$CFG->noemailever = true; // better not mail anybody from tests, override temporarily if necessary
169$CFG->cachetext = 0; // disable this very nasty setting
170
171// some ugly hacks
172$CFG->themerev = 1;
173$CFG->jsrev = 1;
174
175// load test case stub classes and other stuff
176require_once("$CFG->dirroot/lib/phpunit/lib.php");
177
178// finish moodle init
179define('ABORT_AFTER_CONFIG_CANCEL', true);
180require("$CFG->dirroot/lib/setup.php");
181
182raise_memory_limit(MEMORY_EXTRA);
183
a3d5830a
PS
184if (PHPUNIT_UTIL) {
185 // we are not going to do testing, this is 'true' in utility scripts that init database usually
5bd40408
PS
186 return;
187}
188
a3d5830a
PS
189// is database and dataroot ready for testing?
190$problem = phpunit_util::testing_ready_problem();
5bd40408 191
a3d5830a
PS
192if ($problem) {
193 switch ($problem) {
194 case 132:
195 phpunit_bootstrap_error('Database was not initialised to run unit tests, please use "php admin/tool/phpunit/cli/util.php --install"', $problem);
196 case 133:
197 phpunit_bootstrap_error('Database was initialised for different version, please use "php admin/tool/phpunit/cli/util.php --drop; php admin/tool/phpunit/cli/util.php --install"', $problem);
198 default:
199 phpunit_bootstrap_error('Unknown problem initialising test database', $problem);
200 }
201}
5bd40408 202
a3d5830a
PS
203// prepare for the first test run - store fresh globals, reset dataroot, etc.
204phpunit_util::bootstrap_init();
5bd40408
PS
205
206
207//=========================================================
208
209/**
210 * Print error and stop execution
7aea08e1
SH
211 * @param string $text An error message to display
212 * @param int $errorcode The error code (see docblock for detailed list)
213 * @return void stops code execution with error code
5bd40408
PS
214 */
215function phpunit_bootstrap_error($text, $errorcode = 1) {
216 fwrite(STDERR, $text."\n");
217 exit($errorcode);
218}
219
220/**
221 * Mark empty dataroot to be used for testing.
7aea08e1 222 * @param string $dataroot The dataroot directory
5bd40408
PS
223 * @return void
224 */
225function phpunit_bootstrap_initdataroot($dataroot) {
226 global $CFG;
227
728eadac
PS
228 if (!file_exists("$dataroot/phpunittestdir.txt")) {
229 file_put_contents("$dataroot/phpunittestdir.txt", 'Contents of this directory are used during tests only, do not delete this file!');
230 }
5bd40408
PS
231 chmod("$dataroot/phpunittestdir.txt", $CFG->filepermissions);
232 if (!file_exists("$CFG->phpunit_dataroot/phpunit")) {
233 mkdir("$CFG->phpunit_dataroot/phpunit", $CFG->directorypermissions);
234 }
235}