Пример #1
0
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';
}
Пример #2
0
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;
}