From: Preston L. Bannister Date: Thu, 16 May 2002 21:48:28 +0000 (+0000) Subject: Updated to run cleanly on Win32, and perform a more controlled test. X-Git-Tag: php-4.3.0dev-ZendEngine2-Preview1~11 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3d1d6022cd3d6e609a46d5cbe194b413bd2f8bf3;p=php Updated to run cleanly on Win32, and perform a more controlled test. --- diff --git a/run-tests.php b/run-tests.php index d5bf760f21..d0a066a5a2 100755 --- a/run-tests.php +++ b/run-tests.php @@ -13,20 +13,46 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Stig Bakken | + | (based on version by: Stig Bakken ) | | (based on the PHP 3 test framework by Rasmus Lerdorf) | +----------------------------------------------------------------------+ */ +/* + History + ------- + + 2002-05-07 Preston L. Bannister + + Rewrote and updated to run on Win32. + + Require exact specification of PHP executable to test (no guessing!). + + Require a specific tests/php.ini (rather than whatever is lying around), + and test that this is indeed what we are using. + + Die if any internal errors encountered in test script. + + Regularized output for simpler post-processing of output. + + Optionally output error lines indicating the failing test source and log + for direct jump with MSVC or Emacs. + + Run basic (non-extension) tests first. Treat PEAR as extension. + + Tested on Windows 2000 with the Cygnus Win32 toolkit installed. +*/ + /* * TODO: - * - look for test-specific php.ini files - * - implement module skipping for PEAR * - do not test PEAR components if base class and/or component class cannot be instanciated */ +set_time_limit(0); +ob_implicit_flush(); + if (ini_get('safe_mode')) { - echo << 1 - ); - $testdirs = array(); - $tmpfile = array(); - $tests_in_dir = array(); - - register_shutdown_function("delete_tmpfiles"); - - $skipped = $failed = $passed = $total = 0; -} - -function &parse_options(&$argc, &$argv) -{ - $options = array(); - while ($argc > 0 && ($opt = substr($argv[0], 0, 2)) == "--") { - $opt = array_shift($argv); - $argc--; - if ($arg == "--") { - return $options; - } - if (ereg('^--([^=]+)=(.*)$', $opt, $matches)) { - $opt = $matches[1]; - $arg = $matches[2]; - } else { - $arg = true; - } - $options[$opt] = $arg; - } - return $options; -} - -function do_testing($argc, &$argv) -{ - global $term, $windows_p, $php, $skip, $testdirs, $tmpfile, $opts, - $skipped, $failed, $passed, $total, $term_bold, $term_norm, $skipped_extensions; - - if ($argc > 1) { - if (is_dir($argv[1])) { - $dir = $argv[1]; - } else { - for ($i = 1; $i < $argc; $i++) { - switch (run_test($argv[$i])) { - case TEST_SKIPPED: - case TEST_INTERNAL_ERROR: - $skipped++; - break; - case TEST_FAILED: - $failed++; - break; - case TEST_PASSED: - $passed++; - break; - } - $total++; + $o = opendir($path) or die("Cannot open directory - $path\n"); + while ($name = readdir($o)) { + if (is_dir("$path/$name")) { + if ('.' == $name) continue; + if ('..' == $name) continue; + if ('CVS' == $name) continue; + $directories[] = "$path/$name"; + continue; + } + + // Cleanup any left-over tmp files from last run. + if (ereg('[.]tmp$',$name)) { + @unlink("$path/$name"); + continue; } + + // Otherwise we're only interested in *.phpt files. + if (!ereg('[.]phpt$',$name)) continue; + //echo "Runnable '" . $name . "' in '" . $path . "'\n"; + $testfile = realpath("$path/$name"); + $test_files[] = $testfile; + $module_of_test[$testfile] = $module; } - } else { - // $dir = $_ENV["TOP_SRCDIR"]; // XXX ??? where should this variable be set? - $dir=str_replace('\\','/',trim(($windows_p ? getenv("TEST_DIR"):`pwd`))); + closedir($o); } - if (isset($dir) && $dir) { - find_testdirs($dir); +} - create_found_tests_4_modules_list(); - create_modules_2_test_list(); +// Run only selected tests, if specified. - for ($i = 0; $i < sizeof($testdirs); $i++) { - run_tests_in_dir($testdirs[$i]); - } +if (count($test_to_run)) { + echo "Running selected tests.\n"; + while (list($name,$runnable) = each($test_to_run)) { + echo "test: $name runnable: $runnable\n"; + if (!$runnable) continue; + $test_results[$name] = run_test($php,$name); } + exit; +} - $counting = $total - $skipped; - - if ($counting <= 0) { - dowriteln("No tests were run."); - return; - } +// We need to know the compiled in modules so we know what to test. - $total_d = (double)$total; - $counting_d = (double)$counting; - $passed_p = 100 * ($passed / $counting_d); - $failed_p = 100 * ($failed / $counting_d); - $skipped_p = 100 * ($skipped / $total_d); - $passed_pstr = sprintf($passed_p < 10.0 ? "%1.1f" : "%3.0f", $passed_p); - $failed_pstr = sprintf($failed_p < 10.0 ? "%1.1f" : "%3.0f", $failed_p); - $skipped_pstr = sprintf($skipped_p < 10.0 ? "%1.1f" : "%3.0f", $skipped_p); - - dowriteln("TEST RESULT SUMMARY"); - dowriteln("============================="); - dowriteln(sprintf("Number of tests: %4d", $total)); - dowriteln(sprintf("Tests skipped: %4d (%s%%)", $skipped, $skipped_pstr)); - dowriteln(sprintf("Tests failed: %4d (%s%%)", $failed, $failed_pstr)); - dowriteln(sprintf("Tests passed: %4d (%s%%)", $passed, $passed_pstr)); - dowriteln("============================="); - dowriteln("Skipped ".sizeof($skipped_extensions)." extensions."); - $php_bin_info_cmd = "$php -q -f ".$_ENV["TOP_BUILDDIR"]."/tests/bin-info.inc"; - system($php_bin_info_cmd); +$modules_compiled = @get_loaded_extensions(); +$modules_to_test = array( + '' => 1, + 'PEAR' => 1, +); +foreach ($modules_compiled as $module) { + echo "Will test compiled extension: $module\n"; + $modules_to_test[$module] = 1; } -function find_testdirs($dir = '.', $first_pass = true) -{ - global $testdirs, $skip; +echo ' +===================================================================== +'; - if ($first_pass && is_dir($dir)) { - $testdirs[] = $dir; - } - $dp = @opendir($dir); - if (!$dp) { - print "Warning: could not open directory $dir\n"; - return false; - } - while ($ent = readdir($dp)) { - $path = "$dir/$ent"; +sort($test_files); +$modules_skipped = array(); - if ((isset($skip[$ent]) && $skip[$ent]) - || substr($ent, 0, 1) == "." - || !is_dir($path) +// Run non-module tests. - ) { - continue; - } +$module_current = ''; +$path_current = ''; +foreach ($test_files as $name) { - if (strstr("/$path/", "/tests/")) { - $testdirs[] = $path; - } - find_testdirs($path, false); + // Only non-module tests wanted for this pass. + if ($module_of_test[$name]) continue; + + $path = dirname($name); + if ($path_current != $path) { + $path_current = $path; + echo ".... directory $path\n"; } - closedir($dp); + $test_results[$name] = run_test($php,$name); } -function run_tests_in_dir($dir = '.') -{ - global $skip, $skipped, $failed, $passed, $total, $opts, $tests_in_dir,$modules_available,$skipped_extensions; - $dp = opendir($dir); - if (!$dp) { - print "Warning: could not run tests in $dir\n"; - return false; - } - $testfiles = array(); - while ($ent = readdir($dp)) { - if ((isset($skip[$ent]) && $skip[$ent]) || substr($ent, 0, 1) == "." || substr($ent, -5) != ".phpt") { - continue; - } - $testfiles[] = "$dir/$ent"; - if(isset($tests_in_dir[$dir])) $tests_in_dir[$dir]++; else $tests_in_dir[$dir]=1; +// Run module tests (or at least those applicable to this PHP build). + +$module_current = ''; +$path_current = ''; +foreach ($test_files as $name) { + $module = $module_of_test[$name]; + + // Already ran non-module tests. + if (!$module) continue; + + if ($module_current != $module) { + $module_current = $module; + echo " +--------------------------------------------------------------------- +.... " . ($modules_to_test[$module] ? "testing " : "skipped ") . ($module ? "extension: $module" : "generic PHP") . " +"; } - closedir($dp); - if (isset($tests_in_dir[$dir]) && ($tests_in_dir[$dir] == 0)) { - return true; + + // Can we run the test for the given module? + if (!$modules_to_test[$module]) { + $modules_skipped[$module] += 1; + $test_results[$name] = 'SKIPPED'; + continue; } - $oskipped = $skipped; - if (sizeof($testfiles) == 0) { - return; + + $path = dirname($name); + if ($path_current != $path) { + $path_current = $path; + echo ".... directory $path\n"; } - if ($mod_name=extract_module_name_from_path($dir)) { - if ($ext_found=in_array($mod_name,$modules_available)) - dowriteln("Testing extension: $mod_name"); - else $skipped_extensions[$mod_name]=TRUE; - } + // We've gotten this far - run the test! + + $test_results[$name] = run_test($php,$name); +} - if (!isset($ext_found) or $ext_found!==FALSE) { - dowriteln("%bRunning tests in $dir%B"); - dowriteln("=================".str_repeat("=", strlen($dir))); - sort($testfiles); - for ($i = 0; $i < sizeof($testfiles); $i++) { - switch (run_test($testfiles[$i])) { - case TEST_SKIPPED: - case TEST_INTERNAL_ERROR: - $skipped++; - break; - case TEST_FAILED: - $failed++; - break; - case TEST_PASSED: - $passed++; - break; - } - $total++; - } - if ($oskipped + (isset($tests_in_dir[$dir])?$tests_in_dir[$dir]:0) == $skipped) { - $skippednow = $skipped - $oskipped; - dowriteln("[all $skippednow test(s) skipped]"); - } - dowriteln(""); - } +// Summarize results - return true; +if (0 == count($test_results)) { + echo "No tests were run.\n"; + return; } -function skip_headers($fp) -{ - // "cli" version of PHP does not output headers - if (php_sapi_name() == "cli") { - return; - } - while (!feof($fp)) { - if (trim(fgets($fp, 1024)) == "") { - break; - } - } +$n_total = count($test_results); +$sum_results = array(); +foreach ($test_results as $v) { + $sum_results[$v]++; } - -function delete_tmpfiles() -{ - global $tmpfile; - reset($tmpfile); - while (list($k, $v) = each($tmpfile)) { - if (file_exists($v)) { - //print "unlink($v): "; var_dump(unlink($v)); - unlink($v); - } - } +$percent_results = array(); +while (list($v,$n) = each($sum_results)) { + $percent_results[$v] = (100.0 * $n) / $n_total; } -/** - * Compares two files, ignoring blank lines. - * - * @param $file1 string name of first file to compare - * @param $file2 string name of second file to compare - * - * @return bool whether the files were "equal" - */ -function compare_results($file1, $file2) +echo " +===================================================================== +TIME " . date('Y-m-d H:i:s') . " - end of test run + +TEST RESULT SUMMARY +===================================================================== +Number of tests : " . sprintf("%4d",$n_total) . " +Tests skipped : " . sprintf("%4d (%2.1f%%)",$sum_results['SKIPPED'],$percent_results['SKIPPED']) . " +Tests failed : " . sprintf("%4d (%2.1f%%)",$sum_results['FAILED'],$percent_results['FAILED']) . " +Tests passed : " . sprintf("%4d (%2.1f%%)",$sum_results['PASSED'],$percent_results['PASSED']) . " +===================================================================== +Skipped " . count($modules_skipped) . " extensions +"; + +// +// Write the given text to a temporary file, and return the filename. +// + +function save_text($filename,$text) { - $data1 = $data2 = ""; - if (!($fp1 = @fopen($file1, "r")) || !($fp2 = @fopen($file2, "r"))) { - return false; - } - - while (!(feof($fp1) || feof($fp2))) { - if (!feof($fp1) && trim($line1 = fgets($fp1, 10240)) != "") { - //print "adding line1 $line1\n"; + $fp = @fopen($filename,'w') + or die("Cannot open file '" . $filename . "'!\n"); + fwrite($fp,$text); + fclose($fp); + if (1 < DETAILED) echo " +FILE $filename {{{ +$text +}}} +"; +} - $data1 .= trim($line1); - } - if (!feof($fp2) && trim($line2 = fgets($fp2, 10240)) != "") { - //print "adding line2 $line2\n"; +// +// Write an error in a format recognizable to Emacs or MSVC. +// - $data2 .= trim($line2); - } - } - fclose($fp1); - fclose($fp2); - if ((trim($data1) != trim($data2)) - || ($data1=='' && $data2=='')) { - //print "data1=";var_dump($data1); - //print "data2=";var_dump($data2); - return false; +function error_report($testname,$logname,$tested) +{ + $testname = realpath($testname); + $logname = realpath($logname); + switch (strtoupper(getenv('TEST_PHP_ERROR_STYLE'))) { + case 'MSVC': + echo $testname . "(1) : $tested\n"; + echo $logname . "(1) : $tested\n"; + break; + case 'EMACS': + echo $testname . ":1: $tested\n"; + echo $logname . ":1: $tested\n"; + break; } - return true; } -function run_test($file) -{ - global $php, $tmpfile, $term_bold, $term_norm, $term, $windows_p; +// +// Run an individual test case. +// - $variables = array("TEST", "POST", "GET", "FILE", "EXPECT", "SKIPIF", - "OUTPUT"); - $fp = @fopen($file, "r"); - if (!$fp) { - return TEST_INTERNAL_ERROR; - } - $tmpdir = dirname($file); - $tmpfix = "phpt."; - $tmpfile["FILE"] = tempnam($tmpdir, $tmpfix); - $tmpfile["SKIPIF"] = tempnam($tmpdir, $tmpfix); - $tmpfile["POST"] = tempnam($tmpdir, $tmpfix); - - $tmpfile["EXPECT"] = tempnam($tmpdir, $tmpfix); - $tmpfile["OUTPUT"] = tempnam($tmpdir, $tmpfix); - - - while ($line = fgets($fp, 4096)) { - if (ereg('^--([A-Z]+)--', $line, $matches)) { - $var = $matches[1]; - if (isset($tmpfile[$var]) && $tmpfile[$var]) { - $fps[$var] = @fopen($tmpfile[$var], "w"); - } else { - $$var = ''; - } - } else { - if (isset($var) && $var) { - if ($var == "POST") { - $line = trim($line); - } - if (isset($fps[$var]) && $fps[$var]) { - fwrite($fps[$var], $line); - } else { - $$var .= $line; - } - } +function run_test($php,$file) +{ + if (DETAILED) echo " +================= +TEST $file +"; + + // Load the sections of the test file. + + $section_text = array( + 'TEST' => '(unnamed test)', + 'SKIPIF' => '', + 'GET' => '', + ); + + $fp = @fopen($file, "r") + or die("Cannot open test file: $file\n"); + + $section = ''; + while (!feof($fp)) { + $line = fgets($fp); + + // Match the beginning of a section. + if (ereg('^--([A-Z]+)--',$line,$r)) { + $section = $r[1]; + $section_text[$section] = ''; + continue; } + + // Add to the section text. + $section_text[$section] .= $line; } - if(isset($fps) && is_array($fps)) { - reset($fps); - while (list($k, $v) = each($fps)) { - if (is_resource($v)) { - fclose($v); - } + fclose($fp); + + $tmp = dirname($file); + $tmp_skipif = realpath("$tmp/_SKIPIF"); + $tmp_file = realpath("$tmp/_FILE"); + $tmp_post = realpath("$tmp/_POST"); + + @unlink($tmp_skipif); + @unlink($tmp_file); + @unlink($tmp_post); + + // Reset environment from any previous test. + + putenv("REDIRECT_STATUS="); + putenv("QUERY_STRING="); + putenv("PATH_TRANSLATED="); + putenv("SCRIPT_FILENAME="); + putenv("REQUEST_METHOD="); + putenv("CONTENT_TYPE="); + putenv("CONTENT_LENGTH="); + + // Check if test should be skipped. + + if (trim($section_text['SKIPIF'])) { + save_text($tmp_skipif,$section_text['SKIPIF']); + $output = `$php -f $tmp_skipif`; + @unlink($tmp_skipif); + $output = trim($output); + if (0 == strcmp('skip',$output)) { + return 'SKIPPED'; } } - putenv("PHP_TEST=1"); + + // We've satisfied the preconditions - run the test! + + save_text($tmp_file,$section_text['FILE']); + $query_string = trim($section_text['GET']); + putenv("REDIRECT_STATUS=1"); - putenv("CONTENT_LENGTH="); - putenv("QUERY_STRING=".(isset($GET)?$GET:"")); - $include_path = ini_get("include_path"); - if (isset($fps["SKIPIF"])) { - $tmpfile["SKIPIF_OUTPUT"] = tempnam($tmpdir, $tmpfix); + putenv("QUERY_STRING=$query_string"); + putenv("PATH_TRANSLATED=$tmp_file"); + putenv("SCRIPT_FILENAME=$tmp_file"); + + if (isset($section_text['POST'])) { + + $post = trim($section_text['POST']); + save_text($tmp_post,$post); + $content_length = strlen($post); + + putenv("REQUEST_METHOD=POST"); + putenv("CONTENT_TYPE=application/x-www-form-urlencoded"); + putenv("CONTENT_LENGTH=$content_length"); + + $cmd = "$php 2>&1 < $tmp_post"; + + } else { + putenv("REQUEST_METHOD=GET"); putenv("CONTENT_TYPE="); - putenv("PATH_TRANSLATED=$tmpfile[SKIPIF]"); - putenv("SCRIPT_FILENAME=$tmpfile[SKIPIF]"); - $skipifcmd = "$php -q -f $tmpfile[SKIPIF] > $tmpfile[SKIPIF_OUTPUT]"; - system($skipifcmd, $ret); - $sp = @fopen($tmpfile["SKIPIF_OUTPUT"], "r"); - if ($sp) { - skip_headers($sp); - $skip = trim(fgets($sp, 1024)); - fclose($sp); - if ($skip == "skip") { - delete_tmpfiles(); - return TEST_SKIPPED; - } - } - } - putenv("PATH_TRANSLATED=$tmpfile[FILE]"); - putenv("SCRIPT_FILENAME=$tmpfile[FILE]"); - if (isset($fps["POST"])) { - putenv("REQUEST_METHOD=POST"); - putenv("CONTENT_TYPE=application/x-www-form-urlencoded"); - putenv("CONTENT_LENGTH=".filesize($tmpfile["POST"])); - } else { - putenv("REQUEST_METHOD=GET"); - putenv("CONTENT_TYPE="); - putenv("CONTENT_LENGTH="); - } - if (isset($fps["POST"])) { - if(!$windows_p) { - $cmd = "2>&1 $php -q $tmpfile[FILE] < $tmpfile[POST]"; - } - else { - $cmd = "$term /c " . realpath($php) ." -q $tmpfile[FILE] < $tmpfile[POST]"; - } - } else { - if(!$windows_p) { - $cmd = "2>&1 $php -q $tmpfile[FILE]"; - } - else { - $cmd = "$term /c " . realpath($php) ." -q $tmpfile[FILE]";; - } - } - $ofp = @fopen($tmpfile["OUTPUT"], "w"); - if (!$ofp) { - dowriteln("Error: could not write to output file"); - delete_tmpfiles(); - return TEST_INTERNAL_ERROR; - } - $cp = popen($cmd, "r"); - if (!$cp) { - dowriteln("Error: could not execute: $cmd"); - delete_tmpfiles(); - return TEST_INTERNAL_ERROR; - } - skip_headers($cp); - while ($data = fread($cp, 2048)) { - fwrite($ofp, $data); - } - fclose($ofp); - pclose($cp); - $desc = isset($TEST)?trim($TEST):""; - $outfile = ereg_replace('\.phpt$', '.out', $file); - $expectfile = ereg_replace('\.phpt$', '.exp', $file); - $phpfile = ereg_replace('\.phpt$', '.php', $file); - if (compare_results($tmpfile["OUTPUT"], $tmpfile["EXPECT"])) { - $status = TEST_PASSED; - $text = "passed"; - $pre = $post = ""; - if (file_exists($outfile)) { - unlink($outfile); - } - if (file_exists($expectfile)) { - unlink($expectfile); - } - if (file_exists($phpfile)) { - unlink($phpfile); - } - } else { - //system("env"); - $status = TEST_FAILED; - $text = "failed"; - $pre = $term_bold; - $post = $term_norm; - $desc .= " (".basename($file).")"; - if (file_exists($outfile)) { - unlink($outfile); - } - copy($tmpfile["OUTPUT"], $outfile); - copy($tmpfile["EXPECT"], $expectfile); - copy($tmpfile["FILE"], $phpfile); - } - dowriteln(sprintf("%s%-68s ... %s%s", $pre, substr($desc, 0, 68), - $text, $post)); -// if ($status == TEST_FAILED) { -// for ($i = 0; $i < sizeof($variables); $i++) { -// $var = $variables[$i]; -// print "$var:\n"; -// if ($tmpfile[$var]) { -// if (file_exists($tmpfile[$var])) { -// system("cat ".$tmpfile[$var]); -// } -// } else { -// print $$var; -// } -// } -// print "--\n\n"; -// } - delete_tmpfiles(); - return $status; + putenv("CONTENT_LENGTH="); + + $cmd = "$php 2>&1"; + + } + + if (DETAILED) echo " +CONTENT_LENGTH = " . getenv("CONTENT_LENGTH") . " +CONTENT_TYPE = " . getenv("CONTENT_TYPE") . " +PATH_TRANSLATED = " . getenv("PATH_TRANSLATED") . " +QUERY_STRING = " . getenv("QUERY_STRING") . " +REDIRECT_STATUS = " . getenv("REDIRECT_STATUS") . " +REQUEST_METHOD = " . getenv("REQUEST_METHOD") . " +SCRIPT_FILENAME = " . getenv("SCRIPT_FILENAME") . " +COMMAND $cmd +"; + + $out = `$cmd`; + + @unlink($tmp_post); + @unlink($tmp_file); + + // Does the output match what is expected? + + $tested = trim($section_text['TEST']); + + $output = trim(preg_replace('/^(..+\n)+\n/','',$out)); + $wanted = trim($section_text['EXPECT']); + + $output = preg_replace('/\r\n/',"\n",$output); + $wanted = preg_replace('/\r\n/',"\n",$wanted); + + $ok = (0 == strcmp($output,$wanted)); + if ($ok) { + echo "PASS $tested\n"; + return 'PASSED'; + } + + // Test failed so we need to report details. + + echo "FAIL $tested (" . basename($file) . ").\n"; + + $logname = ereg_replace('\.phpt$','.log',$file); + $log = fopen($logname,'w') + or die("Cannot create test log - $logname\n"); + + fwrite($log," +---- EXPECTED OUTPUT +$wanted +---- ACTUAL OUTPUT +$output +---- FAILED +"); + fclose($log); + + error_report($file,$logname,$tested); + + return 'FAILED'; } /*