'zend.assertions=1',
);
-$no_file_cache = '-d opcache.file_cache= -d opcache.file_cache_only=0';
+ $no_file_cache = '-d opcache.file_cache= -d opcache.file_cache_only=0';
+
+ define('PHP_QA_EMAIL', 'qa-reports@lists.php.net');
+ define('QA_SUBMISSION_PAGE', 'http://qa.php.net/buildtest-process.php');
+ define('QA_REPORTS_PAGE', 'http://qa.php.net/reports');
+ define('TRAVIS_CI', (bool)getenv('TRAVIS'));
+
+ // Determine the tests to be run.
+
+ $test_files = array();
+ $redir_tests = array();
+ $test_results = array();
+ $PHP_FAILED_TESTS = array(
+ 'BORKED' => array(),
+ 'FAILED' => array(),
+ 'WARNED' => array(),
+ 'LEAKED' => array(),
+ 'XFAILED' => array(),
+ 'XLEAKED' => array(),
+ 'SLOW' => array()
+ );
+
+ // If parameters given assume they represent selected tests to run.
+ $result_tests_file = false;
+ $failed_tests_file = false;
+ $pass_option_n = false;
+ $pass_options = '';
+
+ $output_file = INIT_DIR . '/php_test_results_' . date('Ymd_Hi') . '.txt';
+
+ $just_save_results = false;
+ $valgrind = null;
+ $html_output = false;
+ $html_file = null;
+ $temp_source = null;
+ $temp_target = null;
+ $temp_urlbase = null;
+ $conf_passed = null;
+ $no_clean = false;
+ $slow_min_ms = INF;
+ $preload = false;
+ $shuffle = false;
+ $workers = null;
+
+ $cfgtypes = array('show', 'keep');
+ $cfgfiles = array('skip', 'php', 'clean', 'out', 'diff', 'exp', 'mem');
+ $cfg = array();
+
+ foreach ($cfgtypes as $type) {
+ $cfg[$type] = array();
+
+ foreach ($cfgfiles as $file) {
+ $cfg[$type][$file] = false;
+ }
+ }
+
+ if (getenv('TEST_PHP_ARGS')) {
+
+ if (!isset($argc, $argv) || !$argc) {
+ $argv = array(__FILE__);
+ }
+
+ $argv = array_merge($argv, explode(' ', getenv('TEST_PHP_ARGS')));
+ $argc = count($argv);
+ }
+
+ if (isset($argc) && $argc > 1) {
+
+ for ($i = 1; $i < $argc; $i++) {
+ $is_switch = false;
+ $switch = substr($argv[$i], 1, 1);
+ $repeat = substr($argv[$i], 0, 1) == '-';
+
+ while ($repeat) {
+
+ if (!$is_switch) {
+ $switch = substr($argv[$i], 1, 1);
+ }
+
+ $is_switch = true;
+
+ if ($repeat) {
+ foreach ($cfgtypes as $type) {
+ if (strpos($switch, '--' . $type) === 0) {
+ foreach ($cfgfiles as $file) {
+ if ($switch == '--' . $type . '-' . $file) {
+ $cfg[$type][$file] = true;
+ $is_switch = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (!$is_switch) {
+ $is_switch = true;
+ break;
+ }
+
+ $repeat = false;
+
+ switch ($switch) {
+ case 'j':
+ $workers = substr($argv[$i], 2);
+ if (!preg_match('/^\d+$/', $workers) || $workers == 0) {
+ error("'$workers' is not a valid number of workers, try e.g. -j16 for 16 workers");
+ }
+ $workers = intval($workers, 10);
+ // Don't use parallel testing infrastructure if there is only one worker.
+ if ($workers === 1) {
+ $workers = null;
+ }
+ break;
+ case 'r':
+ case 'l':
+ $test_list = file($argv[++$i]);
+ if ($test_list) {
+ foreach ($test_list as $test) {
+ $matches = array();
+ if (preg_match('/^#.*\[(.*)\]\:\s+(.*)$/', $test, $matches)) {
+ $redir_tests[] = array($matches[1], $matches[2]);
+ } else {
+ if (strlen($test)) {
+ $test_files[] = trim($test);
+ }
+ }
+ }
+ }
+ if ($switch != 'l') {
+ break;
+ }
+ $i--;
+ // break left intentionally
+ case 'w':
+ $failed_tests_file = fopen($argv[++$i], 'w+t');
+ break;
+ case 'a':
+ $failed_tests_file = fopen($argv[++$i], 'a+t');
+ break;
+ case 'W':
+ $result_tests_file = fopen($argv[++$i], 'w+t');
+ break;
+ case 'c':
+ $conf_passed = $argv[++$i];
+ break;
+ case 'd':
+ $ini_overwrites[] = $argv[++$i];
+ break;
+ case 'g':
+ $SHOW_ONLY_GROUPS = explode(",", $argv[++$i]);
+ break;
+ //case 'h'
+ case '--keep-all':
+ foreach ($cfgfiles as $file) {
+ $cfg['keep'][$file] = true;
+ }
+ break;
+ //case 'l'
+ case 'm':
+ $valgrind = new RuntestsValgrind($environment);
+ break;
+ case 'M':
+ $valgrind = new RuntestsValgrind($environment, $argv[++$i]);
+ break;
+ case 'n':
+ if (!$pass_option_n) {
+ $pass_options .= ' -n';
+ }
+ $pass_option_n = true;
+ break;
+ case 'e':
+ $pass_options .= ' -e';
+ break;
+ case '--preload':
+ $preload = true;
+ break;
+ case '--no-clean':
+ $no_clean = true;
+ break;
+ case 'p':
+ $php = $argv[++$i];
+ putenv("TEST_PHP_EXECUTABLE=$php");
+ $environment['TEST_PHP_EXECUTABLE'] = $php;
+ break;
+ case 'P':
+ $php = PHP_BINARY;
+ putenv("TEST_PHP_EXECUTABLE=$php");
+ $environment['TEST_PHP_EXECUTABLE'] = $php;
+ break;
+ case 'q':
+ putenv('NO_INTERACTION=1');
+ $environment['NO_INTERACTION'] = 1;
+ break;
+ //case 'r'
+ case 's':
+ $output_file = $argv[++$i];
+ $just_save_results = true;
+ break;
+ case '--set-timeout':
+ $environment['TEST_TIMEOUT'] = $argv[++$i];
+ break;
+ case '--show-all':
+ foreach ($cfgfiles as $file) {
+ $cfg['show'][$file] = true;
+ }
+ break;
+ case '--show-slow':
+ $slow_min_ms = $argv[++$i];
+ break;
+ case '--temp-source':
+ $temp_source = $argv[++$i];
+ break;
+ case '--temp-target':
+ $temp_target = $argv[++$i];
+ if ($temp_urlbase) {
+ $temp_urlbase = $temp_target;
+ }
+ break;
+ case '--temp-urlbase':
+ $temp_urlbase = $argv[++$i];
+ break;
+ case 'v':
+ case '--verbose':
+ $DETAILED = true;
+ break;
+ case 'x':
+ $environment['SKIP_SLOW_TESTS'] = 1;
+ break;
+ case '--offline':
+ $environment['SKIP_ONLINE_TESTS'] = 1;
+ break;
+ case '--shuffle':
+ $shuffle = true;
+ break;
+ //case 'w'
+ case '-':
+ // repeat check with full switch
+ $switch = $argv[$i];
+ if ($switch != '-') {
+ $repeat = true;
+ }
+ break;
+ case '--html':
+ $html_file = fopen($argv[++$i], 'wt');
+ $html_output = is_resource($html_file);
+ break;
+ case '--version':
+ echo '$Id$' . "\n";
+ exit(1);
+
+ default:
+ echo "Illegal switch '$switch' specified!\n";
+ case 'h':
+ case '-help':
+ case '--help':
+ echo <<<HELP
+Synopsis:
+ php run-tests.php [options] [files] [directories]
+
+Options:
+ -j<workers> Run <workers> simultaneous testing processes in parallel for
+ quicker testing on systems with multiple logical processors.
+ Note that this is experimental feature.
+
+ -l <file> Read the testfiles to be executed from <file>. After the test
+ has finished all failed tests are written to the same <file>.
+ If the list is empty and no further test is specified then
+ all tests are executed (same as: -r <file> -w <file>).
+
+ -r <file> Read the testfiles to be executed from <file>.
+
+ -w <file> Write a list of all failed tests to <file>.
+
+ -a <file> Same as -w but append rather then truncating <file>.
+
+ -W <file> Write a list of all tests and their result status to <file>.
+
+ -c <file> Look for php.ini in directory <file> or use <file> as ini.
+
+ -n Pass -n option to the php binary (Do not use a php.ini).
+
+ -d foo=bar Pass -d option to the php binary (Define INI entry foo
+ with value 'bar').
+
+ -g Comma separated list of groups to show during test run
+ (possible values: PASS, FAIL, XFAIL, XLEAK, SKIP, BORK, WARN, LEAK, REDIRECT).
+
+ -m Test for memory leaks with Valgrind (equivalent to -M memcheck).
+
+ -M <tool> Test for errors with Valgrind tool.
+
+ -p <php> Specify PHP executable to run.
+
+ -P Use PHP_BINARY as PHP executable to run (default).
+
+ -q Quiet, no user interaction (same as environment NO_INTERACTION).
+
+ -s <file> Write output to <file>.
+
+ -x Sets 'SKIP_SLOW_TESTS' environmental variable.
+
+ --offline Sets 'SKIP_ONLINE_TESTS' environmental variable.
+
+ --verbose
+ -v Verbose mode.
+
+ --help
+ -h This Help.
+
+ --html <file> Generate HTML output.
+
+ --temp-source <sdir> --temp-target <tdir> [--temp-urlbase <url>]
+ Write temporary files to <tdir> by replacing <sdir> from the
+ filenames to generate with <tdir>. If --html is being used and
+ <url> given then the generated links are relative and prefixed
+ with the given url. In general you want to make <sdir> the path
+ to your source files and <tdir> some patch in your web page
+ hierarchy with <url> pointing to <tdir>.
+
+ --keep-[all|php|skip|clean]
+ Do not delete 'all' files, 'php' test file, 'skip' or 'clean'
+ file.
+
+ --set-timeout [n]
+ Set timeout for individual tests, where [n] is the number of
+ seconds. The default value is 60 seconds, or 300 seconds when
+ testing for memory leaks.
+
+ --show-[all|php|skip|clean|exp|diff|out|mem]
+ Show 'all' files, 'php' test file, 'skip' or 'clean' file. You
+ can also use this to show the output 'out', the expected result
+ 'exp', the difference between them 'diff' or the valgrind log
+ 'mem'. The result types get written independent of the log format,
+ however 'diff' only exists when a test fails.
+
+ --show-slow [n]
+ Show all tests that took longer than [n] milliseconds to run.
+
+ --no-clean Do not execute clean section if any.
+
+HELP;
+ exit(1);
+ }
+ }
+
+ if (!$is_switch) {
+ $testfile = realpath($argv[$i]);
+
+ if (!$testfile && strpos($argv[$i], '*') !== false && function_exists('glob')) {
+
+ if (substr($argv[$i], -5) == '.phpt') {
+ $pattern_match = glob($argv[$i]);
+ } else {
+ if (preg_match("/\*$/", $argv[$i])) {
+ $pattern_match = glob($argv[$i] . '.phpt');
+ } else {
+ die('Cannot find test file "' . $argv[$i] . '".' . PHP_EOL);
+ }
+ }
+
+ if (is_array($pattern_match)) {
+ $test_files = array_merge($test_files, $pattern_match);
+ }
+
+ } else {
+ if (is_dir($testfile)) {
+ find_files($testfile);
+ } else {
+ if (substr($testfile, -5) == '.phpt') {
+ $test_files[] = $testfile;
+ } else {
+ die('Cannot find test file "' . $argv[$i] . '".' . PHP_EOL);
+ }
+ }
+ }
+ }
+ }
+
+ // Default to PHP_BINARY as executable
+ if (!isset($environment['TEST_PHP_EXECUTABLE'])) {
+ $php = PHP_BINARY;
+ putenv("TEST_PHP_EXECUTABLE=$php");
+ $environment['TEST_PHP_EXECUTABLE'] = $php;
+ }
+
+ if (strlen($conf_passed)) {
+ if (substr(PHP_OS, 0, 3) == "WIN") {
+ $pass_options .= " -c " . escapeshellarg($conf_passed);
+ } else {
- $pass_options .= " -c '$conf_passed'";
++ $pass_options .= " -c '" . realpath($conf_passed) . "'";
+ }
+ }
+
+ $test_files = array_unique($test_files);
+ $test_files = array_merge($test_files, $redir_tests);
+
+ // Run selected tests.
+ $test_cnt = count($test_files);
+
+ if ($test_cnt) {
+ putenv('NO_INTERACTION=1');
+ verify_config();
+ write_information();
+ usort($test_files, "test_sort");
+ $start_time = time();
+
+ if (!$html_output) {
+ echo "Running selected tests.\n";
+ } else {
+ show_start($start_time);
+ }
+
+ $test_idx = 0;
+ run_all_tests($test_files, $environment);
+ $end_time = time();
+
+ if ($html_output) {
+ show_end($end_time);
+ }
+
+ if ($failed_tests_file) {
+ fclose($failed_tests_file);
+ }
+
+ if ($result_tests_file) {
+ fclose($result_tests_file);
+ }
+
+ compute_summary();
+ if ($html_output) {
+ fwrite($html_file, "<hr/>\n" . get_summary(false, true));
+ }
+ echo "=====================================================================";
+ echo get_summary(false, false);
+
+ if ($html_output) {
+ fclose($html_file);
+ }
+
+ if ($output_file != '' && $just_save_results) {
+ save_or_mail_results();
+ }
+
+ junit_save_xml();
+
+ if (getenv('REPORT_EXIT_STATUS') !== '0' &&
+ getenv('REPORT_EXIT_STATUS') !== 'no' && ($sum_results['FAILED'] || $sum_results['BORKED'] || $sum_results['LEAKED'])) {
+ exit(1);
+ }
+
+ exit(0);
+ }
+ }
+
+ verify_config();
+ write_information();
+
+ // Compile a list of all test files (*.phpt).
+ $test_files = array();
+ $exts_tested = count($exts_to_test);
+ $exts_skipped = 0;
+ $ignored_by_ext = 0;
+ sort($exts_to_test);
+ $test_dirs = array();
+ $optionals = array('Zend', 'tests', 'ext', 'sapi');
+
+ foreach ($optionals as $dir) {
+ if (is_dir($dir)) {
+ $test_dirs[] = $dir;
+ }
+ }
+
+ // Convert extension names to lowercase
+ foreach ($exts_to_test as $key => $val) {
+ $exts_to_test[$key] = strtolower($val);
+ }
+
+ foreach ($test_dirs as $dir) {
+ find_files(TEST_PHP_SRCDIR . "/{$dir}", $dir == 'ext');
+ }
+
+ foreach ($user_tests as $dir) {
+ find_files($dir, $dir == 'ext');
+ }
+
+ $test_files = array_unique($test_files);
+ usort($test_files, "test_sort");
+
+ $start_time = time();
+ show_start($start_time);
+
+ $test_cnt = count($test_files);
+ $test_idx = 0;
+ run_all_tests($test_files, $environment);
+ $end_time = time();
+
+ if ($failed_tests_file) {
+ fclose($failed_tests_file);
+ }
+
+ if ($result_tests_file) {
+ fclose($result_tests_file);
+ }
+
+ // Summarize results
+
+ if (0 == count($test_results)) {
+ echo "No tests were run.\n";
+ return;
+ }
+
+ compute_summary();
+
+ show_end($end_time);
+ show_summary();
+
+ if ($html_output) {
+ fclose($html_file);
+ }
+
+ save_or_mail_results();
+
+ junit_save_xml();
+ if (getenv('REPORT_EXIT_STATUS') !== '0' &&
+ getenv('REPORT_EXIT_STATUS') !== 'no' && ($sum_results['FAILED'] || $sum_results['LEAKED'])) {
+ exit(1);
+ }
+ exit(0);
+}
+
+if (!function_exists("hrtime")) {
+ function hrtime(bool $as_num = false)
+ {
+ $t = microtime(true);
+
+ if ($as_num) {
+ return $t * 1000000000;
+ }
+
+ $s = floor($t);
+ return array(0 => $s, 1 => ($t - $s) * 1000000000);
+ }
+}
+
+function verify_config()
+{
+ global $php;
+
+ if (empty($php) || !file_exists($php)) {
+ error('environment variable TEST_PHP_EXECUTABLE must be set to specify PHP executable!');
+ }
+
+ if (!is_executable($php)) {
+ error("invalid PHP executable specified by TEST_PHP_EXECUTABLE = $php");
+ }
+}
function write_information()
{