. /** * Prepares PHPUnit environment, it is called automatically. * * Exit codes: * 0 - success * 1 - general error * 130 - coding error * 131 - configuration problem * 132 - install new test database * 133 - drop old data, then install new test database * * @package core * @category phpunit * @copyright 2012 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ // we want to know about all problems error_reporting(E_ALL | E_STRICT); ini_set('display_errors', '1'); ini_set('log_errors', '1'); if (isset($_SERVER['REMOTE_ADDR'])) { phpunit_bootstrap_error('Unit tests can be executed only from command line!', 1); } if (defined('PHPUNIT_TEST')) { phpunit_bootstrap_error("PHPUNIT_TEST constant must not be manually defined anywhere!", 130); } /** PHPUnit testing framework active */ define('PHPUNIT_TEST', true); if (!defined('PHPUNIT_LONGTEST')) { /** Execute longer version of tests */ define('PHPUNIT_LONGTEST', false); } if (!defined('PHPUNIT_UTIL')) { /** Identifies utility scripts */ define('PHPUNIT_UTIL', false); } if (defined('CLI_SCRIPT')) { phpunit_bootstrap_error('CLI_SCRIPT must not be manually defined in any PHPUnit test scripts', 130); } define('CLI_SCRIPT', true); define('NO_OUTPUT_BUFFERING', true); // only load CFG from config.php define('ABORT_AFTER_CONFIG', true); require(__DIR__ . '/../../config.php'); // remove error handling overrides done in config.php error_reporting(E_ALL | E_STRICT); ini_set('display_errors', '1'); ini_set('log_errors', '1'); set_time_limit(0); // no time limit in CLI scripts, user may cancel execution // prepare dataroot umask(0); if (isset($CFG->phpunit_directorypermissions)) { $CFG->directorypermissions = $CFG->phpunit_directorypermissions; } else { $CFG->directorypermissions = 02777; } $CFG->filepermissions = ($CFG->directorypermissions & 0666); if (!isset($CFG->phpunit_dataroot)) { phpunit_bootstrap_error('Missing $CFG->phpunit_dataroot in config.php, can not run tests!', 131); } if (isset($CFG->dataroot) and $CFG->phpunit_dataroot === $CFG->dataroot) { phpunit_bootstrap_error('$CFG->dataroot and $CFG->phpunit_dataroot must not be identical, can not run tests!', 131); } if (!file_exists($CFG->phpunit_dataroot)) { mkdir($CFG->phpunit_dataroot, $CFG->directorypermissions); } if (!is_dir($CFG->phpunit_dataroot)) { phpunit_bootstrap_error('$CFG->phpunit_dataroot directory can not be created, can not run tests!', 131); } if (!is_writable($CFG->phpunit_dataroot)) { // try to fix premissions if possible if (function_exists('posix_getuid')) { $chmod = fileperms($CFG->phpunit_dataroot); if (fileowner($dir) == posix_getuid()) { $chmod = $chmod | 0700; chmod($CFG->phpunit_dataroot, $chmod); } } if (!is_writable($CFG->phpunit_dataroot)) { phpunit_bootstrap_error('$CFG->phpunit_dataroot directory is not writable, can not run tests!', 131); } } if (!file_exists("$CFG->phpunit_dataroot/phpunittestdir.txt")) { if ($dh = opendir($CFG->phpunit_dataroot)) { while (($file = readdir($dh)) !== false) { if ($file === 'phpunit' or $file === '.' or $file === '..' or $file === '.DS_store') { continue; } phpunit_bootstrap_error('$CFG->phpunit_dataroot directory is not empty, can not run tests! Is it used for anything else?', 131); } closedir($dh); unset($dh); unset($file); } // now we are 100% sure this dir is used only for phpunit tests phpunit_bootstrap_initdataroot($CFG->phpunit_dataroot); } // verify db prefix if (!isset($CFG->phpunit_prefix)) { phpunit_bootstrap_error('Missing $CFG->phpunit_prefix in config.php, can not run tests!', 131); } if ($CFG->phpunit_prefix === '') { phpunit_bootstrap_error('$CFG->phpunit_prefix can not be empty, can not run tests!', 131); } if (isset($CFG->prefix) and $CFG->prefix === $CFG->phpunit_prefix) { phpunit_bootstrap_error('$CFG->prefix and $CFG->phpunit_prefix must not be identical, can not run tests!', 131); } // throw away standard CFG settings $CFG->dataroot = $CFG->phpunit_dataroot; $CFG->prefix = $CFG->phpunit_prefix; $allowed = array('wwwroot', 'dataroot', 'dirroot', 'admin', 'directorypermissions', 'filepermissions', 'dbtype', 'dblibrary', 'dbhost', 'dbname', 'dbuser', 'dbpass', 'prefix', 'dboptions'); $productioncfg = (array)$CFG; $CFG = new stdClass(); foreach ($productioncfg as $key=>$value) { if (!in_array($key, $allowed) and strpos($key, 'phpunit_') !== 0) { // ignore continue; } $CFG->{$key} = $value; } unset($key); unset($value); unset($allowed); unset($productioncfg); // force the same CFG settings in all sites $CFG->debug = (E_ALL | E_STRICT); // can not use DEBUG_DEVELOPER yet $CFG->debugdisplay = 1; error_reporting($CFG->debug); ini_set('display_errors', '1'); ini_set('log_errors', '0'); $CFG->passwordsaltmain = 'phpunit'; // makes login via normal UI impossible $CFG->noemailever = true; // better not mail anybody from tests, override temporarily if necessary $CFG->cachetext = 0; // disable this very nasty setting // some ugly hacks $CFG->themerev = 1; $CFG->jsrev = 1; // load test case stub classes and other stuff require_once("$CFG->dirroot/lib/phpunit/lib.php"); // finish moodle init define('ABORT_AFTER_CONFIG_CANCEL', true); require("$CFG->dirroot/lib/setup.php"); raise_memory_limit(MEMORY_EXTRA); if (PHPUNIT_UTIL) { // we are not going to do testing, this is 'true' in utility scripts that init database usually return; } // is database and dataroot ready for testing? $problem = phpunit_util::testing_ready_problem(); if ($problem) { switch ($problem) { case 132: phpunit_bootstrap_error('Database was not initialised to run unit tests, please use "php admin/tool/phpunit/cli/util.php --install"', $problem); case 133: 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); default: phpunit_bootstrap_error('Unknown problem initialising test database', $problem); } } // prepare for the first test run - store fresh globals, reset dataroot, etc. phpunit_util::bootstrap_init(); //========================================================= /** * Print error and stop execution * @param string $text An error message to display * @param int $errorcode The error code (see docblock for detailed list) * @return void stops code execution with error code */ function phpunit_bootstrap_error($text, $errorcode = 1) { fwrite(STDERR, $text."\n"); exit($errorcode); } /** * Mark empty dataroot to be used for testing. * @param string $dataroot The dataroot directory * @return void */ function phpunit_bootstrap_initdataroot($dataroot) { global $CFG; file_put_contents("$dataroot/phpunittestdir.txt", 'Contents of this directory are used during tests only, do not delete this file!'); chmod("$dataroot/phpunittestdir.txt", $CFG->filepermissions); if (!file_exists("$CFG->phpunit_dataroot/phpunit")) { mkdir("$CFG->phpunit_dataroot/phpunit", $CFG->directorypermissions); } }