Hi! I also have a patch for run-tests sitting around for quite some time, which adds concurrent test execution support. I already fixed a lot of non re-entrant tests in the past, but there might still be quite some of them.
Tests in ./Zend take 8 seconds instead of 30 on my box. Please find the hack attached. Thoughts, praises, death threats? -- Regards, Mike
diff --git a/run-tests.php b/run-tests.php index 1b5bcec..8c53340 100755 --- a/run-tests.php +++ b/run-tests.php @@ -136,6 +136,13 @@ if ((substr(PHP_OS, 0, 3) == "WIN") && empty($environment["SystemRoot"])) { $environment["SystemRoot"] = getenv("SystemRoot"); } +if (is_readable("/proc/cpuinfo")) { + $concurrency = min(64, max(1, preg_match_all("/^processor/mi", file_get_contents("/proc/cpuinfo")))); +} else { + $concurrency = 2; +} +$procs = array(); + // Don't ever guess at the PHP executable location. // Require the explicit specification. // Otherwise we could end up testing the wrong file! @@ -246,7 +253,7 @@ $ini_overwrites = array( function write_information($show_html) { - global $cwd, $php, $php_cgi, $php_info, $user_tests, $ini_overwrites, $pass_options, $exts_to_test, $leak_check, $valgrind_header; + global $cwd, $php, $php_cgi, $php_info, $user_tests, $ini_overwrites, $pass_options, $exts_to_test, $leak_check, $valgrind_header, $concurrency; // Get info from php $info_file = __DIR__ . '/run-test-info.php'; @@ -306,6 +313,7 @@ Extra dirs : "; } echo " VALGRIND : " . ($leak_check ? $valgrind_header : 'Not used') . " +CONCURRENCY : " . $concurrency . " ===================================================================== "; } @@ -664,6 +672,9 @@ if (isset($argc) && $argc > 1) { case '--version': echo '$Id$' . "\n"; exit(1); + case '--concurrency': + $concurrency = min(64, max(1, $argv[++$i])); + break; default: echo "Illegal switch '$switch' specified!\n"; @@ -1066,6 +1077,90 @@ function error_report($testname, $logname, $tested) } } +function system_loop_over_procs($timeout) +{ + global $procs; + + $r = array(); + $w = null; + $e = null; + + $done = array(); + $table = array(); + foreach ($procs as &$proc) { + $table[(int) $proc["pipes"][1]] = &$proc; + $r[] = $proc["pipes"][1]; + } + + $ts = microtime(true); + $n = @stream_select($r, $w, $e, $timeout); + $ts -= microtime(true); + + array_walk($procs, function(&$proc) use ($ts) { + $proc["timeout"] += $ts; + }); + + if ($n > 0) { + foreach ($r as $pipe) { + $proc = &$table[(int) $pipe]; + $line = fread($pipe, 8192); + if (!strlen($line)) { + /* EOF */ + $stat = proc_get_status($proc["proc"]); + if ($stat['signaled']) { + $proc["data"] .= "\nTermsig=" . $stat['stopsig']; + } + proc_close($proc["proc"]); + unset($procs[(int) $proc["proc"]]); + $done[] = $proc; + } else { + $proc["data"] .= $line; + } + } + } + + foreach ($procs as $proc_id => &$proc_ar) { + if ($proc_ar["timeout"] < 0) { + /* timed out */ + $proc_ar["data"] .= "\n ** ERROR: process timed out **\n"; + proc_terminate($proc_id, 9); + unset($procs[$proc_id]); + $done[] = $proc_ar; + } + } + + array_walk($done, function($proc) { + $proc["cb_result"]($proc["cb_end_test"]($proc["data"])); + }); + + show_test_active(array_map(function($proc) { + return $proc["test_idx"]; + }, $procs)); +} + +function system_with_callback($commandline, $env, $stdin, $cb_result, $cb_end_test) +{ + global $cwd, $procs, $leak_check, $test_idx; + + $proc = proc_open($commandline, array( + 0 => array('pipe', 'r'), + 1 => array('pipe', 'w'), + 2 => array('pipe', 'w') + ), $pipes, $cwd, (array) $env, array('suppress_errors' => true, 'binary_pipes' => true)); + + if (!$proc) { + return false; + } + if (!is_null($stdin)) { + fwrite($pipes[0], $stdin); + } + fclose($pipes[0]); + + $data = ""; + $timeout = $leak_check ? 300 : (isset($env['TEST_TIMEOUT']) ? $env['TEST_TIMEOUT'] : 60); + $procs[(int) $proc] = compact("proc", "pipes", "timeout", "data", "cb_end_test", "cb_result", "test_idx"); +} + function system_with_timeout($commandline, $env = null, $stdin = null) { global $leak_check, $cwd; @@ -1132,7 +1227,7 @@ function system_with_timeout($commandline, $env = null, $stdin = null) function run_all_tests($test_files, $env, $redir_tested = null) { - global $test_results, $failed_tests_file, $php, $test_cnt, $test_idx; + global $test_results, $failed_tests_file, $php, $test_cnt, $test_idx, $concurrency, $procs; foreach($test_files as $name) { @@ -1148,14 +1243,26 @@ function run_all_tests($test_files, $env, $redir_tested = null) $index = $name; } $test_idx++; - $result = run_test($php, $name, $env); - - if (!is_array($name) && $result != 'REDIR') { - $test_results[$index] = $result; - if ($failed_tests_file && ($result == 'XFAILED' || $result == 'FAILED' || $result == 'WARNED' || $result == 'LEAKED')) { - fwrite($failed_tests_file, "$index\n"); + + if ($concurrency <= count($procs)) { + while ($concurrency <= count($procs)) { + system_loop_over_procs(1); } + } else { + system_loop_over_procs(0); } + run_test($php, $name, $env, function($result) use (&$test_results, $index, $name, $failed_tests_file) { + if (!is_array($name) && $result != 'REDIR') { + $test_results[$index] = $result; + if ($failed_tests_file && ($result == 'XFAILED' || $result == 'FAILED' || $result == 'WARNED' || $result == 'LEAKED')) { + fwrite($failed_tests_file, "$index\n"); + } + } + }); + } + + while (count($procs)) { + system_loop_over_procs(1); } } @@ -1178,13 +1285,15 @@ function show_file_block($file, $block, $section = null) } } +$test_map = array(); + // // Run an individual test case. // -function run_test($php, $file, $env) +function run_test($php, $file, $env, $cb) { global $log_format, $info_params, $ini_overwrites, $cwd, $PHP_FAILED_TESTS; - global $pass_options, $DETAILED, $IN_REDIRECT, $test_cnt, $test_idx; + global $pass_options, $DETAILED, $IN_REDIRECT, $test_cnt, $test_idx, $test_map; global $leak_check, $temp_source, $temp_target, $cfg, $environment; global $no_clean; global $valgrind_version; @@ -1811,329 +1920,334 @@ COMMAND $cmd junit_start_timer($shortname); - $out = system_with_timeout($cmd, $env, isset($section_text['STDIN']) ? $section_text['STDIN'] : null); + system_with_callback($cmd, $env, isset($section_text['STDIN']) ? $section_text['STDIN'] : null, $cb, + function($out) use($php, &$old_php, $cmd, $env, $shortname, $info, $file, $tested, $tested_file, $section_text, $ini_overwrites, $memcheck_filename, $pass_options, $temp_clean, $test_clean, $tmp_post, $warn, $temp_filenames, $exp_filename, $output_filename, $diff_filename, $sh_filename, $log_filename, $test_file, $IN_REDIRECT) { + global $cfg, $cwd, $leak_check, $no_clean, $log_format, $PHP_FAILED_TESTS; - junit_finish_timer($shortname); + junit_finish_timer($shortname); - if (array_key_exists('CLEAN', $section_text) && (!$no_clean || $cfg['keep']['clean'])) { + if (array_key_exists('CLEAN', $section_text) && (!$no_clean || $cfg['keep']['clean'])) { - if (trim($section_text['CLEAN'])) { - show_file_block('clean', $section_text['CLEAN']); - save_text($test_clean, trim($section_text['CLEAN']), $temp_clean); + if (trim($section_text['CLEAN'])) { + show_file_block('clean', $section_text['CLEAN']); + save_text($test_clean, trim($section_text['CLEAN']), $temp_clean); - if (!$no_clean) { - $clean_params = array(); - settings2array($ini_overwrites, $clean_params); - settings2params($clean_params); - $extra = substr(PHP_OS, 0, 3) !== "WIN" ? - "unset REQUEST_METHOD; unset QUERY_STRING; unset PATH_TRANSLATED; unset SCRIPT_FILENAME; unset REQUEST_METHOD;": ""; - system_with_timeout("$extra $php $pass_options -q $clean_params \"$test_clean\"", $env); - } + if (!$no_clean) { + $clean_params = array(); + settings2array($ini_overwrites, $clean_params); + settings2params($clean_params); + $extra = substr(PHP_OS, 0, 3) !== "WIN" ? + "unset REQUEST_METHOD; unset QUERY_STRING; unset PATH_TRANSLATED; unset SCRIPT_FILENAME; unset REQUEST_METHOD;": ""; + system_with_timeout("$extra $php $pass_options -q $clean_params \"$test_clean\"", $env); + } - if (!$cfg['keep']['clean']) { - @unlink($test_clean); + if (!$cfg['keep']['clean']) { + @unlink($test_clean); + } + } } - } - } - @unlink($tmp_post); + @unlink($tmp_post); - $leaked = false; - $passed = false; + $leaked = false; + $passed = false; - if ($leak_check) { // leak check - $leaked = filesize($memcheck_filename) > 0; + if ($leak_check) { // leak check + $leaked = filesize($memcheck_filename) > 0; - if (!$leaked) { - @unlink($memcheck_filename); - } - } + if (!$leaked) { + @unlink($memcheck_filename); + } + } - // Does the output match what is expected? - $output = preg_replace("/\r\n/", "\n", trim($out)); + // Does the output match what is expected? + $output = preg_replace("/\r\n/", "\n", trim($out)); - /* when using CGI, strip the headers from the output */ - $headers = ""; + /* when using CGI, strip the headers from the output */ + $headers = ""; - if (isset($old_php) && preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $out, $match)) { - $output = trim($match[2]); - $rh = preg_split("/[\n\r]+/", $match[1]); - $headers = array(); + if (isset($old_php) && preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $out, $match)) { + $output = trim($match[2]); + $rh = preg_split("/[\n\r]+/", $match[1]); + $headers = array(); - foreach ($rh as $line) { - if (strpos($line, ':') !== false) { - $line = explode(':', $line, 2); - $headers[trim($line[0])] = trim($line[1]); + foreach ($rh as $line) { + if (strpos($line, ':') !== false) { + $line = explode(':', $line, 2); + $headers[trim($line[0])] = trim($line[1]); + } + } } - } - } - - $failed_headers = false; - if (isset($section_text['EXPECTHEADERS'])) { - $want = array(); - $wanted_headers = array(); - $lines = preg_split("/[\n\r]+/", $section_text['EXPECTHEADERS']); + $failed_headers = false; - foreach($lines as $line) { - if (strpos($line, ':') !== false) { - $line = explode(':', $line, 2); - $want[trim($line[0])] = trim($line[1]); - $wanted_headers[] = trim($line[0]) . ': ' . trim($line[1]); - } - } + if (isset($section_text['EXPECTHEADERS'])) { + $want = array(); + $wanted_headers = array(); + $lines = preg_split("/[\n\r]+/", $section_text['EXPECTHEADERS']); - $org_headers = $headers; - $headers = array(); - $output_headers = array(); + foreach($lines as $line) { + if (strpos($line, ':') !== false) { + $line = explode(':', $line, 2); + $want[trim($line[0])] = trim($line[1]); + $wanted_headers[] = trim($line[0]) . ': ' . trim($line[1]); + } + } - foreach($want as $k => $v) { + $org_headers = $headers; + $headers = array(); + $output_headers = array(); - if (isset($org_headers[$k])) { - $headers = $org_headers[$k]; - $output_headers[] = $k . ': ' . $org_headers[$k]; - } + foreach($want as $k => $v) { - if (!isset($org_headers[$k]) || $org_headers[$k] != $v) { - $failed_headers = true; - } - } + if (isset($org_headers[$k])) { + $headers = $org_headers[$k]; + $output_headers[] = $k . ': ' . $org_headers[$k]; + } - ksort($wanted_headers); - $wanted_headers = join("\n", $wanted_headers); - ksort($output_headers); - $output_headers = join("\n", $output_headers); - } + if (!isset($org_headers[$k]) || $org_headers[$k] != $v) { + $failed_headers = true; + } + } - show_file_block('out', $output); + ksort($wanted_headers); + $wanted_headers = join("\n", $wanted_headers); + ksort($output_headers); + $output_headers = join("\n", $output_headers); + } - if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) { + show_file_block('out', $output); - if (isset($section_text['EXPECTF'])) { - $wanted = trim($section_text['EXPECTF']); - } else { - $wanted = trim($section_text['EXPECTREGEX']); - } + if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) { - show_file_block('exp', $wanted); - $wanted_re = preg_replace('/\r\n/', "\n", $wanted); - - if (isset($section_text['EXPECTF'])) { - - // do preg_quote, but miss out any %r delimited sections - $temp = ""; - $r = "%r"; - $startOffset = 0; - $length = strlen($wanted_re); - while($startOffset < $length) { - $start = strpos($wanted_re, $r, $startOffset); - if ($start !== false) { - // we have found a start tag - $end = strpos($wanted_re, $r, $start+2); - if ($end === false) { - // unbalanced tag, ignore it. - $end = $start = $length; - } + if (isset($section_text['EXPECTF'])) { + $wanted = trim($section_text['EXPECTF']); } else { - // no more %r sections - $start = $end = $length; + $wanted = trim($section_text['EXPECTREGEX']); } - // quote a non re portion of the string - $temp = $temp . preg_quote(substr($wanted_re, $startOffset, ($start - $startOffset)), '/'); - // add the re unquoted. - if ($end > $start) { - $temp = $temp . '(' . substr($wanted_re, $start+2, ($end - $start-2)). ')'; - } - $startOffset = $end + 2; - } - $wanted_re = $temp; - $wanted_re = str_replace( - array('%binary_string_optional%'), - 'string', - $wanted_re - ); - $wanted_re = str_replace( - array('%unicode_string_optional%'), - 'string', - $wanted_re - ); - $wanted_re = str_replace( - array('%unicode\|string%', '%string\|unicode%'), - 'string', - $wanted_re - ); - $wanted_re = str_replace( - array('%u\|b%', '%b\|u%'), - '', - $wanted_re - ); - // Stick to basics - $wanted_re = str_replace('%e', '\\' . DIRECTORY_SEPARATOR, $wanted_re); - $wanted_re = str_replace('%s', '[^\r\n]+', $wanted_re); - $wanted_re = str_replace('%S', '[^\r\n]*', $wanted_re); - $wanted_re = str_replace('%a', '.+', $wanted_re); - $wanted_re = str_replace('%A', '.*', $wanted_re); - $wanted_re = str_replace('%w', '\s*', $wanted_re); - $wanted_re = str_replace('%i', '[+-]?\d+', $wanted_re); - $wanted_re = str_replace('%d', '\d+', $wanted_re); - $wanted_re = str_replace('%x', '[0-9a-fA-F]+', $wanted_re); - $wanted_re = str_replace('%f', '[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?', $wanted_re); - $wanted_re = str_replace('%c', '.', $wanted_re); - // %f allows two points "-.0.0" but that is the best *simple* expression - } -/* DEBUG YOUR REGEX HERE - var_dump($wanted_re); - print(str_repeat('=', 80) . "\n"); - var_dump($output); -*/ - if (preg_match("/^$wanted_re\$/s", $output)) { - $passed = true; - if (!$cfg['keep']['php']) { - @unlink($test_file); - } - if (isset($old_php)) { - $php = $old_php; - } + show_file_block('exp', $wanted); + $wanted_re = preg_replace('/\r\n/', "\n", $wanted); + + if (isset($section_text['EXPECTF'])) { + + // do preg_quote, but miss out any %r delimited sections + $temp = ""; + $r = "%r"; + $startOffset = 0; + $length = strlen($wanted_re); + while($startOffset < $length) { + $start = strpos($wanted_re, $r, $startOffset); + if ($start !== false) { + // we have found a start tag + $end = strpos($wanted_re, $r, $start+2); + if ($end === false) { + // unbalanced tag, ignore it. + $end = $start = $length; + } + } else { + // no more %r sections + $start = $end = $length; + } + // quote a non re portion of the string + $temp = $temp . preg_quote(substr($wanted_re, $startOffset, ($start - $startOffset)), '/'); + // add the re unquoted. + if ($end > $start) { + $temp = $temp . '(' . substr($wanted_re, $start+2, ($end - $start-2)). ')'; + } + $startOffset = $end + 2; + } + $wanted_re = $temp; + + $wanted_re = str_replace( + array('%binary_string_optional%'), + 'string', + $wanted_re + ); + $wanted_re = str_replace( + array('%unicode_string_optional%'), + 'string', + $wanted_re + ); + $wanted_re = str_replace( + array('%unicode\|string%', '%string\|unicode%'), + 'string', + $wanted_re + ); + $wanted_re = str_replace( + array('%u\|b%', '%b\|u%'), + '', + $wanted_re + ); + // Stick to basics + $wanted_re = str_replace('%e', '\\' . DIRECTORY_SEPARATOR, $wanted_re); + $wanted_re = str_replace('%s', '[^\r\n]+', $wanted_re); + $wanted_re = str_replace('%S', '[^\r\n]*', $wanted_re); + $wanted_re = str_replace('%a', '.+', $wanted_re); + $wanted_re = str_replace('%A', '.*', $wanted_re); + $wanted_re = str_replace('%w', '\s*', $wanted_re); + $wanted_re = str_replace('%i', '[+-]?\d+', $wanted_re); + $wanted_re = str_replace('%d', '\d+', $wanted_re); + $wanted_re = str_replace('%x', '[0-9a-fA-F]+', $wanted_re); + $wanted_re = str_replace('%f', '[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?', $wanted_re); + $wanted_re = str_replace('%c', '.', $wanted_re); + // %f allows two points "-.0.0" but that is the best *simple* expression + } + /* DEBUG YOUR REGEX HERE + var_dump($wanted_re); + print(str_repeat('=', 80) . "\n"); + var_dump($output); + */ + if (preg_match("/^$wanted_re\$/s", $output)) { + $passed = true; + if (!$cfg['keep']['php']) { + @unlink($test_file); + } + if (isset($old_php)) { + $php = $old_php; + } - if (!$leaked && !$failed_headers) { - if (isset($section_text['XFAIL'] )) { - $warn = true; - $info = " (warn: XFAIL section but test passes)"; - }else { - show_result("PASS", $tested, $tested_file, '', $temp_filenames); - junit_mark_test_as('PASS', $shortname, $tested); - return 'PASSED'; + if (!$leaked && !$failed_headers) { + if (isset($section_text['XFAIL'] )) { + $warn = true; + $info = " (warn: XFAIL section but test passes)"; + }else { + show_result("PASS", $tested, $tested_file, '', $temp_filenames); + junit_mark_test_as('PASS', $shortname, $tested); + return 'PASSED'; + } + } } - } - } - } else { + } else { - $wanted = trim($section_text['EXPECT']); - $wanted = preg_replace('/\r\n/',"\n", $wanted); - show_file_block('exp', $wanted); + $wanted = trim($section_text['EXPECT']); + $wanted = preg_replace('/\r\n/',"\n", $wanted); + show_file_block('exp', $wanted); - // compare and leave on success - if (!strcmp($output, $wanted)) { - $passed = true; + // compare and leave on success + if (!strcmp($output, $wanted)) { + $passed = true; - if (!$cfg['keep']['php']) { - @unlink($test_file); - } + if (!$cfg['keep']['php']) { + @unlink($test_file); + } - if (isset($old_php)) { - $php = $old_php; - } + if (isset($old_php)) { + $php = $old_php; + } - if (!$leaked && !$failed_headers) { - if (isset($section_text['XFAIL'] )) { - $warn = true; - $info = " (warn: XFAIL section but test passes)"; - }else { - show_result("PASS", $tested, $tested_file, '', $temp_filenames); - junit_mark_test_as('PASS', $shortname, $tested); - return 'PASSED'; + if (!$leaked && !$failed_headers) { + if (isset($section_text['XFAIL'] )) { + $warn = true; + $info = " (warn: XFAIL section but test passes)"; + }else { + show_result("PASS", $tested, $tested_file, '', $temp_filenames); + junit_mark_test_as('PASS', $shortname, $tested); + return 'PASSED'; + } + } } - } - } - $wanted_re = null; - } + $wanted_re = null; + } - // Test failed so we need to report details. - if ($failed_headers) { - $passed = false; - $wanted = $wanted_headers . "\n--HEADERS--\n" . $wanted; - $output = $output_headers . "\n--HEADERS--\n" . $output; + // Test failed so we need to report details. + if ($failed_headers) { + $passed = false; + $wanted = $wanted_headers . "\n--HEADERS--\n" . $wanted; + $output = $output_headers . "\n--HEADERS--\n" . $output; - if (isset($wanted_re)) { - $wanted_re = preg_quote($wanted_headers . "\n--HEADERS--\n", '/') . $wanted_re; - } - } + if (isset($wanted_re)) { + $wanted_re = preg_quote($wanted_headers . "\n--HEADERS--\n", '/') . $wanted_re; + } + } - if ($leaked) { - $restype[] = 'LEAK'; - } + if ($leaked) { + $restype[] = 'LEAK'; + } - if ($warn) { - $restype[] = 'WARN'; - } + if ($warn) { + $restype[] = 'WARN'; + } - if (!$passed) { - if (isset($section_text['XFAIL'])) { - $restype[] = 'XFAIL'; - $info = ' XFAIL REASON: ' . rtrim($section_text['XFAIL']); - } else { - $restype[] = 'FAIL'; - } - } + if (!$passed) { + if (isset($section_text['XFAIL'])) { + $restype[] = 'XFAIL'; + $info = ' XFAIL REASON: ' . rtrim($section_text['XFAIL']); + } else { + $restype[] = 'FAIL'; + } + } - if (!$passed) { + if (!$passed) { - // write .exp - if (strpos($log_format, 'E') !== false && file_put_contents($exp_filename, $wanted, FILE_BINARY) === false) { - error("Cannot create expected test output - $exp_filename"); - } + // write .exp + if (strpos($log_format, 'E') !== false && file_put_contents($exp_filename, $wanted, FILE_BINARY) === false) { + error("Cannot create expected test output - $exp_filename"); + } - // write .out - if (strpos($log_format, 'O') !== false && file_put_contents($output_filename, $output, FILE_BINARY) === false) { - error("Cannot create test output - $output_filename"); - } + // write .out + if (strpos($log_format, 'O') !== false && file_put_contents($output_filename, $output, FILE_BINARY) === false) { + error("Cannot create test output - $output_filename"); + } - // write .diff - $diff = generate_diff($wanted, $wanted_re, $output); - if (is_array($IN_REDIRECT)) { - $diff = "# original source file: $shortname\n" . $diff; - } - show_file_block('diff', $diff); - if (strpos($log_format, 'D') !== false && file_put_contents($diff_filename, $diff, FILE_BINARY) === false) { - error("Cannot create test diff - $diff_filename"); - } + // write .diff + $diff = generate_diff($wanted, $wanted_re, $output); + if (is_array($IN_REDIRECT)) { + $diff = "# original source file: $shortname\n" . $diff; + } + show_file_block('diff', $diff); + if (strpos($log_format, 'D') !== false && file_put_contents($diff_filename, $diff, FILE_BINARY) === false) { + error("Cannot create test diff - $diff_filename"); + } - // write .sh - if (strpos($log_format, 'S') !== false && file_put_contents($sh_filename, "#!/bin/sh + // write .sh + if (strpos($log_format, 'S') !== false && file_put_contents($sh_filename, "#!/bin/sh {$cmd} ", FILE_BINARY) === false) { - error("Cannot create test shell script - $sh_filename"); - } - chmod($sh_filename, 0755); + error("Cannot create test shell script - $sh_filename"); + } + chmod($sh_filename, 0755); - // write .log - if (strpos($log_format, 'L') !== false && file_put_contents($log_filename, " + // write .log + if (strpos($log_format, 'L') !== false && file_put_contents($log_filename, " ---- EXPECTED OUTPUT $wanted ---- ACTUAL OUTPUT $output ---- FAILED ", FILE_BINARY) === false) { - error("Cannot create test log - $log_filename"); - error_report($file, $log_filename, $tested); - } - } + error("Cannot create test log - $log_filename"); + error_report($file, $log_filename, $tested); + } + } - show_result(implode('&', $restype), $tested, $tested_file, $info, $temp_filenames); + show_result(implode('&', $restype), $tested, $tested_file, $info, $temp_filenames); - foreach ($restype as $type) { - $PHP_FAILED_TESTS[$type.'ED'][] = array ( - 'name' => $file, - 'test_name' => (is_array($IN_REDIRECT) ? $IN_REDIRECT['via'] : '') . $tested . " [$tested_file]", - 'output' => $output_filename, - 'diff' => $diff_filename, - 'info' => $info, - ); - } + foreach ($restype as $type) { + $PHP_FAILED_TESTS[$type.'ED'][] = array ( + 'name' => $file, + 'test_name' => (is_array($IN_REDIRECT) ? $IN_REDIRECT['via'] : '') . $tested . " [$tested_file]", + 'output' => $output_filename, + 'diff' => $diff_filename, + 'info' => $info, + ); + } - if (isset($old_php)) { - $php = $old_php; - } - - $diff = empty($diff) ? '' : preg_replace('/\e/', '<esc>', $diff); + if (isset($old_php)) { + $php = $old_php; + } - junit_mark_test_as($restype, str_replace($cwd . '/', '', $tested_file), $tested, null, $info, $diff); + $diff = empty($diff) ? '' : preg_replace('/\e/', '<esc>', $diff); + $diff = empty($diff) ? '' : "<![CDATA[\n " . preg_replace('/\e/', '<esc>', $diff) . "\n]]>"; - return $restype[0] . 'ED'; + junit_mark_test_as($restype, str_replace($cwd . '/', '', $tested_file), $tested, null, $info, $diff); + + return $restype[0] . 'ED'; + } + ); } function comp_line($l1, $l2, $is_reg) @@ -2556,8 +2670,20 @@ function show_test($test_idx, $shortname) { global $test_cnt; global $line_length; + global $test_map; + + $test_map[$shortname] = $test_idx; + + $str = sprintf("%5d TEST $test_idx/$test_cnt [$shortname]\r", $test_idx); + $line_length = strlen($str); + echo $str; + flush(); +} - $str = "TEST $test_idx/$test_cnt [$shortname]\r"; +function show_test_active($active) { + global $test_idx, $test_cnt, $line_length; + + $str = sprintf("TEST %d/%d [no. %s still running]\r", $test_idx, $test_cnt, implode(", ", (array) $active)); $line_length = strlen($str); echo $str; flush(); @@ -2566,14 +2692,15 @@ function show_test($test_idx, $shortname) function show_result($result, $tested, $tested_file, $extra = '', $temp_filenames = null) { global $html_output, $html_file, $temp_target, $temp_urlbase, $line_length, $SHOW_ONLY_GROUPS; + global $test_idx, $test_map; if (!$SHOW_ONLY_GROUPS || in_array($result, $SHOW_ONLY_GROUPS)) { - echo "$result $tested [$tested_file] $extra\n"; + echo sprintf("%5d $result $tested [$tested_file] $extra\n", $test_map[$tested_file]); } else { // Write over the last line to avoid random trailing chars on next echo echo str_repeat(" ", $line_length), "\r"; } - + if ($html_output) { if (isset($temp_filenames['file']) && file_exists($temp_filenames['file'])) {
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php