mirror of
https://github.com/php/php-src.git
synced 2024-11-27 11:53:33 +08:00
590 lines
17 KiB
PHP
Executable File
590 lines
17 KiB
PHP
Executable File
<?php
|
|
/*
|
|
+----------------------------------------------------------------------+
|
|
| PHP version 4.0 |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 1997-2001 The PHP Group |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 2.02 of the PHP license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available at through the world-wide-web at |
|
|
| http://www.php.net/license/2_02.txt. |
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
| Authors: Stig Bakken <ssb@fast.no> |
|
|
| (based on the PHP 3 test framework by Rasmus Lerdorf) |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
|
|
ob_implicit_flush();
|
|
|
|
define('TEST_PASSED', 0);
|
|
define('TEST_FAILED', -1);
|
|
define('TEST_SKIPPED', -2);
|
|
define('TEST_INTERNAL_ERROR', -3);
|
|
|
|
define('EXT_DIR_NAME','/php4/ext/');
|
|
define('EXT_DIR_NAME_LEN',strlen(EXT_DIR_NAME));
|
|
|
|
initialize();
|
|
/*
|
|
$opts = parse_options(&$argc, &$argv);
|
|
if ($opts['help']) {
|
|
usage();
|
|
exit;
|
|
}
|
|
*/
|
|
do_testing($argc, $argv);
|
|
|
|
exit;
|
|
|
|
/*****************************************************************************/
|
|
|
|
function usage()
|
|
{
|
|
dowriteln("Usage: run-tests.php [-d] [-h] [dir|file...]");
|
|
}
|
|
|
|
/*
|
|
* Please use dowrite() and dowriteln() for all screen output.
|
|
* This makes it easier to convert to HTML output later.
|
|
*/
|
|
|
|
function dowrite($str)
|
|
{
|
|
global $term_bold, $term_norm;
|
|
$str = str_replace("%b", $term_bold, $str);
|
|
$str = str_replace("%B", $term_norm, $str);
|
|
print $str;
|
|
}
|
|
|
|
function dowriteln($str)
|
|
{
|
|
dowrite("$str\n");
|
|
}
|
|
|
|
function create_compiled_in_modules_list() {
|
|
global $compiled_in_modules;
|
|
$compiled_in_modules = @get_loaded_extensions();
|
|
}
|
|
|
|
function extract_module_name_from_path($path) {
|
|
if ($pos1=strpos($path,EXT_DIR_NAME)) {
|
|
$pos3=strpos($path,'/',$pos1+EXT_DIR_NAME_LEN);
|
|
return substr($path,$pos2=$pos1+EXT_DIR_NAME_LEN,$pos3-$pos2);
|
|
}
|
|
}
|
|
|
|
|
|
function create_found_tests_4_modules_list() {
|
|
global $modules_2_test,$testdirs;
|
|
|
|
foreach ($testdirs AS $path) {
|
|
if ($mod_name=extract_module_name_from_path($path))
|
|
$modules_2_test[$mod_name]=TRUE;
|
|
}
|
|
}
|
|
|
|
function create_modules_2_test_list() {
|
|
global $compiled_in_modules,$modules_2_test,$modules_available;
|
|
foreach ($compiled_in_modules AS $value)
|
|
if ($modules_2_test[$value]) $modules_available[]=$value;
|
|
}
|
|
|
|
|
|
|
|
function in_path($program)
|
|
{
|
|
global $HTTP_ENV_VARS;
|
|
if (substr(PHP_OS, 0, 3) == "WIN") {
|
|
$delim = ";";
|
|
$ext = ".exe";
|
|
} else {
|
|
$delim = ":";
|
|
$ext = "";
|
|
}
|
|
$slash = DIRECTORY_SEPARATOR;
|
|
$path_components = explode($delim, $HTTP_ENV_VARS['PATH']);
|
|
foreach ($path_components as $path) {
|
|
$test = "{$path}{$slash}php{$ext}";
|
|
if (@is_executable($test)) {
|
|
return $test;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
function initialize()
|
|
{
|
|
global $term, $windows_p, $php, $skip, $testdirs, $tmpfile,
|
|
$skipped, $failed, $passed, $total, $term_bold, $term_norm,
|
|
$tests_in_dir;
|
|
|
|
// XXX Should support HTML output as well.
|
|
$php = "";
|
|
if((substr(PHP_OS, 0, 3) == "WIN")) {
|
|
$ext = ".exe";
|
|
$windows_p = true;
|
|
$term = getenv("COMSPEC");
|
|
} else {
|
|
$ext = "";
|
|
$term = getenv("TERM");
|
|
if (ereg('^(xterm|vt220)', $term)) {
|
|
$term_bold = sprintf("%c%c%c%c", 27, 91, 49, 109);
|
|
$term_norm = sprintf("%c%c%c", 27, 91, 109);
|
|
} elseif (ereg('^vt100', $term)) {
|
|
$term_bold = sprintf("%c%c%c%c", 27, 91, 49, 109);
|
|
$term_norm = sprintf("%c%c%c", 27, 91, 109);
|
|
} else {
|
|
$term_bold = $term_norm = "";
|
|
}
|
|
}
|
|
|
|
if (isset($GLOBALS["TOP_BUILDDIR"]) && @is_executable($GLOBALS["TOP_BUILDDIR"]."/php{$ext}")) {
|
|
$php = $GLOBALS["TOP_BUILDDIR"]."/php{$ext}";
|
|
} elseif (@is_executable("./php{$ext}")) {
|
|
$php = getcwd() . "/php{$ext}";
|
|
}
|
|
if (empty($php)) {
|
|
$php = in_path("php");
|
|
}
|
|
if (empty($php)) {
|
|
dowriteln("Unable to find PHP executable (php{$ext}).");
|
|
dowriteln("Please build PHP as a CGI executable or make sure it is");
|
|
dowriteln("available in the PATH environment variable.");
|
|
exit;
|
|
}
|
|
|
|
create_compiled_in_modules_list();
|
|
|
|
$skip = array(
|
|
"CVS" => 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++;
|
|
}
|
|
}
|
|
} else {
|
|
// $dir = $GLOBALS["TOP_SRCDIR"]; // XXX ??? where should this variable be set?
|
|
$dir=str_replace('\\','/',trim(($windows_p ? getenv("TEST_DIR"):`pwd`)));
|
|
}
|
|
if (isset($dir) && $dir) {
|
|
find_testdirs($dir);
|
|
|
|
create_found_tests_4_modules_list();
|
|
create_modules_2_test_list();
|
|
|
|
for ($i = 0; $i < sizeof($testdirs); $i++) {
|
|
run_tests_in_dir($testdirs[$i]);
|
|
}
|
|
}
|
|
|
|
$counting = $total - $skipped;
|
|
|
|
if ($counting <= 0) {
|
|
dowriteln("No tests were run.");
|
|
return;
|
|
}
|
|
|
|
$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.");
|
|
dowriteln("PHP Version: ".phpversion());
|
|
}
|
|
|
|
function find_testdirs($dir = '.', $first_pass = true)
|
|
{
|
|
global $testdirs, $skip;
|
|
|
|
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";
|
|
|
|
if ((isset($skip[$ent]) && $skip[$ent])
|
|
|| substr($ent, 0, 1) == "."
|
|
|| !is_dir($path)
|
|
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
if (strstr("/$path/", "/tests/")) {
|
|
$testdirs[] = $path;
|
|
}
|
|
find_testdirs($path, false);
|
|
}
|
|
closedir($dp);
|
|
|
|
}
|
|
|
|
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;
|
|
}
|
|
closedir($dp);
|
|
if (isset($tests_in_dir[$dir]) && ($tests_in_dir[$dir] == 0)) {
|
|
return true;
|
|
}
|
|
$oskipped = $skipped;
|
|
if (sizeof($testfiles) == 0) {
|
|
return;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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("");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function skip_headers($fp)
|
|
{
|
|
while (!feof($fp)) {
|
|
if (trim(fgets($fp, 1024)) == "") {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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)
|
|
{
|
|
$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";
|
|
|
|
$data1 .= trim($line1);
|
|
}
|
|
if (!feof($fp2) && trim($line2 = fgets($fp2, 10240)) != "") {
|
|
//print "adding line2 $line2\n";
|
|
|
|
$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;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function run_test($file)
|
|
{
|
|
global $php, $tmpfile, $term_bold, $term_norm, $term, $windows_p;
|
|
|
|
$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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(isset($fps) && is_array($fps)) {
|
|
reset($fps);
|
|
while (list($k, $v) = each($fps)) {
|
|
if (is_resource($v)) {
|
|
fclose($v);
|
|
}
|
|
}
|
|
}
|
|
putenv("PHP_TEST=1");
|
|
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("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;
|
|
}
|
|
//echo $cmd;
|
|
$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;
|
|
}
|
|
|
|
?>
|