function run_test($php, $file, $env) { global $log_format, $info_params, $ini_overwrites, $cwd, $PHP_FAILED_TESTS; global $pass_options, $DETAILED, $IN_REDIRECT, $test_cnt, $test_idx; global $leak_check, $temp_source, $temp_target, $cfg, $environment; global $no_clean; global $valgrind_version; $temp_filenames = null; $org_file = $file; if (isset($env['TEST_PHP_CGI_EXECUTABLE'])) { $php_cgi = $env['TEST_PHP_CGI_EXECUTABLE']; } if (is_array($file)) { $file = $file[0]; } if ($DETAILED) { echo "\n=================\nTEST {$file}\n"; } // Load the sections of the test file. $section_text = array('TEST' => ''); $fp = fopen($file, "rb") or error("Cannot open test file: {$file}"); $borked = false; $bork_info = ''; if (!feof($fp)) { $line = fgets($fp); if ($line === false) { $bork_info = "cannot read test"; $borked = true; } } else { $bork_info = "empty test [{$file}]"; $borked = true; } if (!$borked && strncmp('--TEST--', $line, 8)) { $bork_info = "tests must start with --TEST-- [{$file}]"; $borked = true; } $section = 'TEST'; $secfile = false; $secdone = false; while (!feof($fp)) { $line = fgets($fp); if ($line === false) { break; } // Match the beginning of a section. if (preg_match('/^--([_A-Z]+)--/', $line, $r)) { $section = $r[1]; settype($section, STRING_TYPE); if (isset($section_text[$section])) { $bork_info = "duplicated {$section} section"; $borked = true; } $section_text[$section] = binary_section($section) ? '' : ''; $secfile = $section == 'FILE' || $section == 'FILEEOF' || $section == 'FILE_EXTERNAL'; $secdone = false; continue; } if (!binary_section($section)) { $line = unicode_decode($line, "utf-8"); if ($line == false) { $bork_info = "cannot read test"; $borked = true; break; } } // Add to the section text. if (!$secdone) { $section_text[$section] .= $line; } // End of actual test? if ($secfile && preg_match('/^===DONE===\\s*$/', $line)) { $secdone = true; } } // the redirect section allows a set of tests to be reused outside of // a given test dir if (!$borked) { if (@count($section_text['REDIRECTTEST']) == 1) { if ($IN_REDIRECT) { $borked = true; $bork_info = "Can't redirect a test from within a redirected test"; } else { $borked = false; } } else { if (@count($section_text['FILE']) + @count($section_text['FILEEOF']) + @count($section_text['FILE_EXTERNAL']) != 1) { $bork_info = "missing section --FILE--"; $borked = true; } if (@count($section_text['FILEEOF']) == 1) { $section_text['FILE'] = preg_replace("/[\r\n]+\$/", '', $section_text['FILEEOF']); unset($section_text['FILEEOF']); } if (@count($section_text['FILE_EXTERNAL']) == 1) { // don't allow tests to retrieve files from anywhere but this subdirectory $section_text['FILE_EXTERNAL'] = dirname($file) . '/' . trim(str_replace('..', '', $section_text['FILE_EXTERNAL'])); if (file_exists($section_text['FILE_EXTERNAL'])) { $section_text['FILE'] = file_get_contents($section_text['FILE_EXTERNAL'], FILE_BINARY); unset($section_text['FILE_EXTERNAL']); } else { $bork_info = "could not load --FILE_EXTERNAL-- " . dirname($file) . '/' . trim($section_text['FILE_EXTERNAL']); $borked = true; } } if (@count($section_text['EXPECT']) + @count($section_text['EXPECTF']) + @count($section_text['EXPECTREGEX']) != 1) { $bork_info = "missing section --EXPECT--, --EXPECTF-- or --EXPECTREGEX--"; $borked = true; } } } fclose($fp); $shortname = str_replace($cwd . '/', '', $file); $tested_file = $shortname; if ($borked) { show_result("BORK", $bork_info, $tested_file); $PHP_FAILED_TESTS['BORKED'][] = array('name' => $file, 'test_name' => '', 'output' => '', 'diff' => '', 'info' => "{$bork_info} [{$file}]"); return 'BORKED'; } $tested = trim($section_text['TEST']); /* For GET/POST tests, check if cgi sapi is available and if it is, use it. */ if (!empty($section_text['GET']) || !empty($section_text['POST']) || !empty($section_text['POST_RAW']) || !empty($section_text['COOKIE']) || !empty($section_text['EXPECTHEADERS'])) { if (isset($php_cgi)) { $old_php = $php; $php = $php_cgi . ' -C '; } else { if (!strncasecmp(PHP_OS, "win", 3) && file_exists(dirname($php) . "/php-cgi.exe")) { $old_php = $php; $php = realpath(dirname($php) . "/php-cgi.exe") . ' -C '; } else { if (file_exists(dirname($php) . "/../../sapi/cgi/php-cgi")) { $old_php = $php; $php = realpath(dirname($php) . "/../../sapi/cgi/php-cgi") . ' -C '; } else { if (file_exists("./sapi/cgi/php-cgi")) { $old_php = $php; $php = realpath("./sapi/cgi/php-cgi") . ' -C '; } else { show_result('SKIP', $tested, $tested_file, "reason: CGI not available"); return 'SKIPPED'; } } } } } show_test($test_idx, $shortname); if (is_array($IN_REDIRECT)) { $temp_dir = $test_dir = $IN_REDIRECT['dir']; } else { $temp_dir = $test_dir = realpath(dirname($file)); } if ($temp_source && $temp_target) { $temp_dir = str_replace($temp_source, $temp_target, $temp_dir); } $main_file_name = basename($file, 'phpt'); $diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'diff'; $log_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'log'; $exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'exp'; $output_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'out'; $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'mem'; $sh_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'sh'; $temp_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'php'; $test_file = $test_dir . DIRECTORY_SEPARATOR . $main_file_name . 'php'; $temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'skip.php'; $test_skipif = $test_dir . DIRECTORY_SEPARATOR . $main_file_name . 'skip.php'; $temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'clean.php'; $test_clean = $test_dir . DIRECTORY_SEPARATOR . $main_file_name . 'clean.php'; $tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('/phpt.'); $tmp_relative_file = str_replace(__DIR__ . DIRECTORY_SEPARATOR, '', $test_file) . 't'; if ($temp_source && $temp_target) { $temp_skipif .= 's'; $temp_file .= 's'; $temp_clean .= 's'; $copy_file = $temp_dir . DIRECTORY_SEPARATOR . basename(is_array($file) ? $file[1] : $file) . '.phps'; if (!is_dir(dirname($copy_file))) { mkdir(dirname($copy_file), 0777, true) or error("Cannot create output directory - " . dirname($copy_file)); } if (isset($section_text['FILE'])) { save_text($copy_file, $section_text['FILE']); } $temp_filenames = array('file' => $copy_file, 'diff' => $diff_filename, 'log' => $log_filename, 'exp' => $exp_filename, 'out' => $output_filename, 'mem' => $memcheck_filename, 'sh' => $sh_filename, 'php' => $temp_file, 'skip' => $temp_skipif, 'clean' => $temp_clean); } if (is_array($IN_REDIRECT)) { $tested = $IN_REDIRECT['prefix'] . ' ' . trim($section_text['TEST']); $tested_file = $tmp_relative_file; } // unlink old test results @unlink($diff_filename); @unlink($log_filename); @unlink($exp_filename); @unlink($output_filename); @unlink($memcheck_filename); @unlink($sh_filename); @unlink($temp_file); @unlink($test_file); @unlink($temp_skipif); @unlink($test_skipif); @unlink($tmp_post); @unlink($temp_clean); @unlink($test_clean); // Reset environment from any previous test. $env['REDIRECT_STATUS'] = ''; $env['QUERY_STRING'] = ''; $env['PATH_TRANSLATED'] = ''; $env['SCRIPT_FILENAME'] = ''; $env['REQUEST_METHOD'] = ''; $env['CONTENT_TYPE'] = ''; $env['CONTENT_LENGTH'] = ''; $env['TZ'] = ''; if (!empty($section_text['ENV'])) { foreach (explode("\n", trim($section_text['ENV'])) as $e) { $e = explode('=', trim($e), 2); if (!empty($e[0]) && isset($e[1])) { $env[$e[0]] = $e[1]; } } } // Default ini settings $ini_settings = array(); // additional ini overwrites //$ini_overwrites[] = 'setting=value'; settings2array($ini_overwrites, $ini_settings); // Any special ini settings // these may overwrite the test defaults... if (array_key_exists('INI', $section_text)) { if (strpos($section_text['INI'], '{PWD}') !== false) { $section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']); } settings2array(preg_split("/[\n\r]+/", $section_text['INI']), $ini_settings); } settings2params($ini_settings); // Check if test should be skipped. $info = ''; $warn = false; if (array_key_exists('SKIPIF', $section_text)) { if (trim($section_text['SKIPIF'])) { show_file_block('skip', $section_text['SKIPIF']); save_text($test_skipif, $section_text['SKIPIF'], $temp_skipif); $extra = substr(PHP_OS, 0, 3) !== "WIN" ? "unset REQUEST_METHOD; unset QUERY_STRING; unset PATH_TRANSLATED; unset SCRIPT_FILENAME; unset REQUEST_METHOD;" : ""; if ($leak_check) { $env['USE_ZEND_ALLOC'] = '0'; } else { $env['USE_ZEND_ALLOC'] = '1'; } $output = system_with_timeout("{$extra} {$php} {$pass_options} -q {$ini_settings} -d display_errors=0 {$test_skipif}", $env); if (!$cfg['keep']['skip']) { @unlink($test_skipif); } if (!strncasecmp('skip', ltrim($output), 4)) { if (preg_match('/^\\s*skip\\s*(.+)\\s*/i', $output, $m)) { show_result('SKIP', $tested, $tested_file, "reason: {$m['1']}", $temp_filenames); } else { show_result('SKIP', $tested, $tested_file, '', $temp_filenames); } if (isset($old_php)) { $php = $old_php; } if (!$cfg['keep']['skip']) { @unlink($test_skipif); } return 'SKIPPED'; } if (!strncasecmp('info', ltrim($output), 4)) { if (preg_match('/^\\s*info\\s*(.+)\\s*/i', $output, $m)) { $info = " (info: {$m['1']})"; } } if (!strncasecmp('warn', ltrim($output), 4)) { if (preg_match('/^\\s*warn\\s*(.+)\\s*/i', $output, $m)) { $warn = true; /* only if there is a reason */ $info = " (warn: {$m['1']})"; } } } } if (@count($section_text['REDIRECTTEST']) == 1) { $test_files = array(); $IN_REDIRECT = eval($section_text['REDIRECTTEST']); $IN_REDIRECT['via'] = "via [{$shortname}]\n\t"; $IN_REDIRECT['dir'] = realpath(dirname($file)); $IN_REDIRECT['prefix'] = trim($section_text['TEST']); if (count($IN_REDIRECT['TESTS']) == 1) { if (is_array($org_file)) { $test_files[] = $org_file[1]; } else { $GLOBALS['test_files'] = $test_files; find_files($IN_REDIRECT['TESTS']); foreach ($GLOBALS['test_files'] as $f) { $test_files[] = array($f, $file); } } $test_cnt += @count($test_files) - 1; $test_idx--; show_redirect_start($IN_REDIRECT['TESTS'], $tested, $tested_file); // set up environment $redirenv = array_merge($environment, $IN_REDIRECT['ENV']); $redirenv['REDIR_TEST_DIR'] = realpath($IN_REDIRECT['TESTS']) . DIRECTORY_SEPARATOR; usort($test_files, "test_sort"); run_all_tests($test_files, $redirenv, $tested); show_redirect_ends($IN_REDIRECT['TESTS'], $tested, $tested_file); // a redirected test never fails $IN_REDIRECT = false; return 'REDIR'; } else { $bork_info = "Redirect info must contain exactly one TEST string to be used as redirect directory."; show_result("BORK", $bork_info, '', $temp_filenames); $PHP_FAILED_TESTS['BORKED'][] = array('name' => $file, 'test_name' => '', 'output' => '', 'diff' => '', 'info' => "{$bork_info} [{$file}]"); } } if (is_array($org_file) || @count($section_text['REDIRECTTEST']) == 1) { if (is_array($org_file)) { $file = $org_file[0]; } $bork_info = "Redirected test did not contain redirection info"; show_result("BORK", $bork_info, '', $temp_filenames); $PHP_FAILED_TESTS['BORKED'][] = array('name' => $file, 'test_name' => '', 'output' => '', 'diff' => '', 'info' => "{$bork_info} [{$file}]"); return 'BORKED'; } // We've satisfied the preconditions - run the test! show_file_block('php', $section_text['FILE'], 'TEST'); save_text($test_file, $section_text['FILE'], $temp_file); if (array_key_exists('GET', $section_text)) { $query_string = trim($section_text['GET']); } else { $query_string = ''; } $env['REDIRECT_STATUS'] = '1'; $env['QUERY_STRING'] = $query_string; $env['PATH_TRANSLATED'] = $test_file; $env['SCRIPT_FILENAME'] = $test_file; if (array_key_exists('COOKIE', $section_text)) { $env['HTTP_COOKIE'] = trim($section_text['COOKIE']); } else { $env['HTTP_COOKIE'] = ''; } $args = isset($section_text['ARGS']) ? ' -- ' . $section_text['ARGS'] : ''; if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) { $post = trim($section_text['POST_RAW']); $raw_lines = explode("\n", $post); $request = ''; $started = false; foreach ($raw_lines as $line) { if (empty($env['CONTENT_TYPE']) && preg_match('/^Content-Type:(.*)/i', $line, $res)) { $env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1])); continue; } if ($started) { $request .= "\n"; } $started = true; $request .= $line; } $env['CONTENT_LENGTH'] = strlen($request); $env['REQUEST_METHOD'] = 'POST'; if (empty($request)) { return 'BORKED'; } save_text($tmp_post, $request); $cmd = "{$php} {$pass_options} {$ini_settings} -f \"{$test_file}\" 2>&1 < {$tmp_post}"; } else { if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) { $post = trim($section_text['POST']); if (array_key_exists('GZIP_POST', $section_text) && function_exists('gzencode')) { $post = gzencode($post, 9, FORCE_GZIP); $env['HTTP_CONTENT_ENCODING'] = 'gzip'; } else { if (array_key_exists('DEFLATE_POST', $section_text) && function_exists('gzcompress')) { $post = gzcompress($post, 9); $env['HTTP_CONTENT_ENCODING'] = 'deflate'; } } save_text($tmp_post, $post); $content_length = strlen($post); $env['REQUEST_METHOD'] = 'POST'; $env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; $env['CONTENT_LENGTH'] = $content_length; $cmd = "{$php} {$pass_options} {$ini_settings} -f \"{$test_file}\" 2>&1 < {$tmp_post}"; } else { $env['REQUEST_METHOD'] = 'GET'; $env['CONTENT_TYPE'] = ''; $env['CONTENT_LENGTH'] = ''; $cmd = "{$php} {$pass_options} {$ini_settings} -f \"{$test_file}\" {$args} 2>&1"; } } if ($leak_check) { $env['USE_ZEND_ALLOC'] = '0'; if ($valgrind_version >= 330) { /* valgrind 3.3.0+ doesn't have --log-file-exactly option */ $cmd = "valgrind -q --tool=memcheck --trace-children=yes --log-file={$memcheck_filename} {$cmd}"; } else { $cmd = "valgrind -q --tool=memcheck --trace-children=yes --log-file-exactly={$memcheck_filename} {$cmd}"; } } else { $env['USE_ZEND_ALLOC'] = '1'; } if ($DETAILED) { echo "\nCONTENT_LENGTH = " . $env['CONTENT_LENGTH'] . "\nCONTENT_TYPE = " . $env['CONTENT_TYPE'] . "\nPATH_TRANSLATED = " . $env['PATH_TRANSLATED'] . "\nQUERY_STRING = " . $env['QUERY_STRING'] . "\nREDIRECT_STATUS = " . $env['REDIRECT_STATUS'] . "\nREQUEST_METHOD = " . $env['REQUEST_METHOD'] . "\nSCRIPT_FILENAME = " . $env['SCRIPT_FILENAME'] . "\nHTTP_COOKIE = " . $env['HTTP_COOKIE'] . "\nCOMMAND {$cmd}\n"; } $out = (string) system_with_timeout($cmd, $env, isset($section_text['STDIN']) ? $section_text['STDIN'] : null); 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 (!$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); } } } @unlink($tmp_post); $leaked = false; $passed = false; if ($leak_check) { // leak check $leaked = filesize($memcheck_filename) > 0; if (!$leaked) { @unlink($memcheck_filename); } } // 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 = ""; 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]); } } } $failed_headers = false; if (isset($section_text['EXPECTHEADERS'])) { $want = array(); $wanted_headers = array(); $lines = preg_split("/[\n\r]+/", (string) $section_text['EXPECTHEADERS']); 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]); } } $org_headers = $headers; $headers = array(); $output_headers = array(); foreach ($want as $k => $v) { if (isset($org_headers[$k])) { $headers = $org_headers[$k]; $output_headers[] = $k . ': ' . $org_headers[$k]; } if (!isset($org_headers[$k]) || $org_headers[$k] != $v) { $failed_headers = true; } } ksort($wanted_headers); $wanted_headers = join("\n", $wanted_headers); ksort($output_headers); $output_headers = join("\n", $output_headers); } show_file_block('out', $output); if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) { if (isset($section_text['EXPECTF'])) { $wanted = trim($section_text['EXPECTF']); } else { $wanted = trim($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; } } 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%'), version_compare(PHP_VERSION, '6.0.0-dev') == -1 ? 'string' : 'binary string', $wanted_re); $wanted_re = str_replace(array('%unicode_string_optional%'), version_compare(PHP_VERSION, '6.0.0-dev') == -1 ? 'string' : 'Unicode string', $wanted_re); $wanted_re = str_replace(array('%unicode\\|string%', '%string\\|unicode%'), version_compare(PHP_VERSION, '6.0.0-dev') == -1 ? 'string' : 'unicode', $wanted_re); $wanted_re = str_replace(array('%u\\|b%', '%b\\|u%'), version_compare(PHP_VERSION, '6.0.0-dev') == -1 ? '' : '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); return 'PASSED'; } } } } else { $wanted = (string) 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; 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); return 'PASSED'; } } } $wanted_re = null; } // Test failed so we need to report details. if ($failed_headers) { $passed = false; $wanted = (string) $wanted_headers . "\n--HEADERS--\n" . (string) $wanted; $output = (string) $output_headers . "\n--HEADERS--\n" . (string) $output; if (isset($wanted_re)) { $wanted_re = preg_quote($wanted_headers . "\n--HEADERS--\n", '/') . $wanted_re; } } if ($leaked) { $restype[] = 'LEAK'; } if ($warn) { $restype[] = 'WARN'; } if (!$passed) { if (isset($section_text['XFAIL'])) { $restype[] = 'XFAIL'; $info = ' XFAIL REASON: ' . $section_text['XFAIL']; } else { $restype[] = 'FAIL'; } } if (!$passed) { // write .exp if (strpos($log_format, 'E') !== false && file_put_contents($exp_filename, (string) $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, (string) $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, (string) $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\n\n{$cmd}\n", FILE_BINARY) === false) { 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, "\n---- EXPECTED OUTPUT\n{$wanted}\n---- ACTUAL OUTPUT\n{$output}\n---- FAILED\n", FILE_BINARY) === false) { error("Cannot create test log - {$log_filename}"); error_report($file, $log_filename, $tested); } } 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); } if (isset($old_php)) { $php = $old_php; } return $restype[0] . 'ED'; }
function &parse_file($file) { if (!is_file($file)) { error("{$file} does not exist"); } // parse the test $file // Load the sections of the test file. $section_text = array('TEST' => ''); $fp = fopen($file, "rb") or error("Cannot open test file: {$file}"); if (!feof($fp)) { $line = fgets($fp); if ($line === false) { error("cannot read test '{$file}'"); } } else { error("empty test '{$file}'"); } if (strncmp('--TEST--', $line, 8)) { error("tests '{$file}' must start with --TEST--"); } $section = 'TEST'; $secfile = false; $secdone = false; while (!feof($fp)) { $line = fgets($fp); if ($line === false) { break; } // Match the beginning of a section. if (preg_match('/^--([_A-Z]+)--/', $line, $r)) { $section = $r[1]; settype($section, 'string'); if (isset($section_text[$section])) { error("duplicated {$section} section"); } $section_text[$section] = binary_section($section) ? '' : ''; $secfile = $section == 'FILE' || $section == 'FILEEOF' || $section == 'FILE_EXTERNAL'; $secdone = false; continue; } if (!binary_section($section)) { $line = (string) $line; if ($line == false) { error("cannot read test '{$file}'"); break; } } // Add to the section text. if (!$secdone) { if ($section == 'EXPECTF') { // modify Phalangers different error message format, ", column %d" at the end. if (StartsWith($line, 'Warning:') || StartsWith($line, 'Notice:') || StartsWith($line, 'Error:')) { $line = substr($line, 0, 7) . "%s\n"; } //', column %d.'; } $section_text[$section] .= $line; } // End of actual test? if ($secfile && preg_match('/^===DONE===\\s*$/', $line)) { $secdone = true; } } // the redirect section allows a set of tests to be reused outside of // a given test dir if (@count($section_text['REDIRECTTEST']) == 1) { //if ($IN_REDIRECT) { //$borked = true; //$bork_info = "Can't redirect a test from within a redirected test"; //} else { //$borked = false; //} } else { if (@count($section_text['FILE']) + @count($section_text['FILEEOF']) + @count($section_text['FILE_EXTERNAL']) != 1) { error("missing section --FILE-- in '{$file}'"); } if (@count($section_text['FILEEOF']) == 1) { $section_text['FILE'] = preg_replace("/[\r\n]+\$/", '', $section_text['FILEEOF']); unset($section_text['FILEEOF']); } if (@count($section_text['FILE_EXTERNAL']) == 1) { // don't allow tests to retrieve files from anywhere but this subdirectory $section_text['FILE_EXTERNAL'] = dirname($file) . '/' . trim(str_replace('..', '', $section_text['FILE_EXTERNAL'])); if (file_exists($section_text['FILE_EXTERNAL'])) { $section_text['FILE'] = _file_get_contents($section_text['FILE_EXTERNAL'], FILE_BINARY, null, &$dummyheaders); unset($section_text['FILE_EXTERNAL']); } else { error("could not load --FILE_EXTERNAL-- " . dirname($file) . '/' . trim($section_text['FILE_EXTERNAL']) . " in test '{$file}'"); } } if (@count($section_text['EXPECT']) + @count($section_text['EXPECTF']) + @count($section_text['EXPECTREGEX']) != 1) { error("missing section --EXPECT--, --EXPECTF-- or --EXPECTREGEX-- in '{$file}'"); } } fclose($fp); // return sections return $section_text; }