You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

564 lines
16 KiB

  1. <?php
  2. /*
  3. +----------------------------------------------------------------------+
  4. | PHP version 4.0 |
  5. +----------------------------------------------------------------------+
  6. | Copyright (c) 1997-2001 The PHP Group |
  7. +----------------------------------------------------------------------+
  8. | This source file is subject to version 2.02 of the PHP license, |
  9. | that is bundled with this package in the file LICENSE, and is |
  10. | available at through the world-wide-web at |
  11. | http://www.php.net/license/2_02.txt. |
  12. | If you did not receive a copy of the PHP license and are unable to |
  13. | obtain it through the world-wide-web, please send a note to |
  14. | license@php.net so we can mail you a copy immediately. |
  15. +----------------------------------------------------------------------+
  16. | Authors: Stig Bakken <ssb@fast.no> |
  17. | (based on the PHP 3 test framework by Rasmus Lerdorf) |
  18. +----------------------------------------------------------------------+
  19. */
  20. /*
  21. * TODO:
  22. * - look for test-specific php.ini files
  23. * - implement module skipping for PEAR
  24. * - do not test PEAR components if base class and/or component class cannot be instanciated
  25. */
  26. ob_implicit_flush();
  27. define('TEST_PASSED', 0);
  28. define('TEST_FAILED', -1);
  29. define('TEST_SKIPPED', -2);
  30. define('TEST_INTERNAL_ERROR', -3);
  31. define('EXT_DIR_NAME','/php4/ext/');
  32. define('EXT_DIR_NAME_LEN',strlen(EXT_DIR_NAME));
  33. initialize();
  34. /*
  35. $opts = parse_options(&$argc, &$argv);
  36. if ($opts['help']) {
  37. usage();
  38. exit;
  39. }
  40. */
  41. do_testing($argc, $argv);
  42. exit;
  43. /*****************************************************************************/
  44. function usage()
  45. {
  46. dowriteln("Usage: run-tests.php [-d] [-h] [dir|file...]");
  47. }
  48. /*
  49. * Please use dowrite() and dowriteln() for all screen output.
  50. * This makes it easier to convert to HTML output later.
  51. */
  52. function dowrite($str)
  53. {
  54. global $term_bold, $term_norm;
  55. $str = str_replace("%b", $term_bold, $str);
  56. $str = str_replace("%B", $term_norm, $str);
  57. print $str;
  58. }
  59. function dowriteln($str)
  60. {
  61. dowrite("$str\n");
  62. }
  63. function create_compiled_in_modules_list() {
  64. global $compiled_in_modules;
  65. $compiled_in_modules = @get_loaded_extensions();
  66. }
  67. function extract_module_name_from_path($path) {
  68. if ($pos1=strpos($path,EXT_DIR_NAME)) {
  69. $pos3=strpos($path,'/',$pos1+EXT_DIR_NAME_LEN);
  70. return substr($path,$pos2=$pos1+EXT_DIR_NAME_LEN,$pos3-$pos2);
  71. }
  72. }
  73. function create_found_tests_4_modules_list() {
  74. global $modules_2_test,$testdirs;
  75. foreach ($testdirs AS $path) {
  76. if ($mod_name=extract_module_name_from_path($path))
  77. $modules_2_test[$mod_name]=TRUE;
  78. }
  79. }
  80. function create_modules_2_test_list() {
  81. global $compiled_in_modules,$modules_2_test,$modules_available;
  82. foreach ($compiled_in_modules AS $value)
  83. if ($modules_2_test[$value]) $modules_available[]=$value;
  84. }
  85. function initialize()
  86. {
  87. global $term, $windows_p, $php, $skip, $testdirs, $tmpfile,
  88. $skipped, $failed, $passed, $total, $term_bold, $term_norm,
  89. $tests_in_dir;
  90. // XXX Should support HTML output as well.
  91. $term = getenv("TERM");
  92. if (ereg('^(xterm|vt220)', $term)) {
  93. $term_bold = sprintf("%c%c%c%c", 27, 91, 49, 109);
  94. $term_norm = sprintf("%c%c%c", 27, 91, 109);
  95. } elseif (ereg('^vt100', $term)) {
  96. $term_bold = sprintf("%c%c%c%c", 27, 91, 49, 109);
  97. $term_norm = sprintf("%c%c%c", 27, 91, 109);
  98. } else {
  99. $term_bold = $term_norm = "";
  100. }
  101. if((substr(PHP_OS, 0, 3) == "WIN")) {
  102. $windows_p = true;
  103. $term = getenv("COMSPEC");
  104. $null = getenv("TOP_BUILDDIR");
  105. $php = ($null ? $null : getcwd()) . "/php.exe";
  106. unset($null);
  107. } else {
  108. if (isset($GLOBALS["TOP_BUILDDIR"])) {
  109. $php = $GLOBALS["TOP_BUILDDIR"]."/php";
  110. } else {
  111. $php = getcwd() . '/php';
  112. }
  113. }
  114. create_compiled_in_modules_list();
  115. if (!is_executable($php) && !$windows_p) {
  116. dowriteln("PHP CGI binary ($php) is not executable.");
  117. dowriteln("Please compile PHP as a CGI executable and try again.");
  118. exit;
  119. }
  120. $skip = array(
  121. "CVS" => 1
  122. );
  123. $testdirs = array();
  124. $tmpfile = array();
  125. $tests_in_dir = array();
  126. register_shutdown_function("delete_tmpfiles");
  127. $skipped = $failed = $passed = $total = 0;
  128. }
  129. function &parse_options(&$argc, &$argv)
  130. {
  131. $options = array();
  132. while ($argc > 0 && ($opt = substr($argv[0], 0, 2)) == "--") {
  133. $opt = array_shift($argv);
  134. $argc--;
  135. if ($arg == "--") {
  136. return $options;
  137. }
  138. if (ereg('^--([^=]+)=(.*)$', $opt, $matches)) {
  139. $opt = $matches[1];
  140. $arg = $matches[2];
  141. } else {
  142. $arg = true;
  143. }
  144. $options[$opt] = $arg;
  145. }
  146. return $options;
  147. }
  148. function do_testing($argc, &$argv)
  149. {
  150. global $term, $windows_p, $php, $skip, $testdirs, $tmpfile, $opts,
  151. $skipped, $failed, $passed, $total, $term_bold, $term_norm, $skipped_extensions;
  152. if ($argc > 1) {
  153. if (is_dir($argv[1])) {
  154. $dir = $argv[1];
  155. } else {
  156. for ($i = 1; $i < $argc; $i++) {
  157. switch (run_test($argv[$i])) {
  158. case TEST_SKIPPED:
  159. case TEST_INTERNAL_ERROR:
  160. $skipped++;
  161. break;
  162. case TEST_FAILED:
  163. $failed++;
  164. break;
  165. case TEST_PASSED:
  166. $passed++;
  167. break;
  168. }
  169. $total++;
  170. }
  171. }
  172. } else {
  173. // $dir = $GLOBALS["TOP_SRCDIR"]; // XXX ??? where should this variable be set?
  174. $dir=str_replace('\\','/',trim(($windows_p ? getenv("TEST_DIR"):`pwd`)));
  175. }
  176. if (isset($dir) && $dir) {
  177. find_testdirs($dir);
  178. create_found_tests_4_modules_list();
  179. create_modules_2_test_list();
  180. for ($i = 0; $i < sizeof($testdirs); $i++) {
  181. run_tests_in_dir($testdirs[$i]);
  182. }
  183. }
  184. $counting = $total - $skipped;
  185. if ($counting <= 0) {
  186. dowriteln("No tests were run.");
  187. return;
  188. }
  189. $total_d = (double)$total;
  190. $counting_d = (double)$counting;
  191. $passed_p = 100 * ($passed / $counting_d);
  192. $failed_p = 100 * ($failed / $counting_d);
  193. $skipped_p = 100 * ($skipped / $total_d);
  194. $passed_pstr = sprintf($passed_p < 10.0 ? "%1.1f" : "%3.0f", $passed_p);
  195. $failed_pstr = sprintf($failed_p < 10.0 ? "%1.1f" : "%3.0f", $failed_p);
  196. $skipped_pstr = sprintf($skipped_p < 10.0 ? "%1.1f" : "%3.0f", $skipped_p);
  197. dowriteln("TEST RESULT SUMMARY");
  198. dowriteln("=============================");
  199. dowriteln(sprintf("Number of tests: %4d", $total));
  200. dowriteln(sprintf("Tests skipped: %4d (%s%%)", $skipped, $skipped_pstr));
  201. dowriteln(sprintf("Tests failed: %4d (%s%%)", $failed, $failed_pstr));
  202. dowriteln(sprintf("Tests passed: %4d (%s%%)", $passed, $passed_pstr));
  203. dowriteln("=============================");
  204. dowriteln("Skipped ".sizeof($skipped_extensions)." extensions.");
  205. dowriteln("PHP Version: ".phpversion());
  206. }
  207. function find_testdirs($dir = '.', $first_pass = true)
  208. {
  209. global $testdirs, $skip;
  210. if ($first_pass && is_dir($dir)) {
  211. $testdirs[] = $dir;
  212. }
  213. $dp = @opendir($dir);
  214. if (!$dp) {
  215. print "Warning: could not open directory $dir\n";
  216. return false;
  217. }
  218. while ($ent = readdir($dp)) {
  219. $path = "$dir/$ent";
  220. if ((isset($skip[$ent]) && $skip[$ent])
  221. || substr($ent, 0, 1) == "."
  222. || !is_dir($path)
  223. ) {
  224. continue;
  225. }
  226. if (strstr("/$path/", "/tests/")) {
  227. $testdirs[] = $path;
  228. }
  229. find_testdirs($path, false);
  230. }
  231. closedir($dp);
  232. }
  233. function run_tests_in_dir($dir = '.')
  234. {
  235. global $skip, $skipped, $failed, $passed, $total, $opts, $tests_in_dir,$modules_available,$skipped_extensions;
  236. $dp = opendir($dir);
  237. if (!$dp) {
  238. print "Warning: could not run tests in $dir\n";
  239. return false;
  240. }
  241. $testfiles = array();
  242. while ($ent = readdir($dp)) {
  243. if ((isset($skip[$ent]) && $skip[$ent]) || substr($ent, 0, 1) == "." || substr($ent, -5) != ".phpt") {
  244. continue;
  245. }
  246. $testfiles[] = "$dir/$ent";
  247. if(isset($tests_in_dir[$dir])) $tests_in_dir[$dir]++; else $tests_in_dir[$dir]=1;
  248. }
  249. closedir($dp);
  250. if (isset($tests_in_dir[$dir]) && ($tests_in_dir[$dir] == 0)) {
  251. return true;
  252. }
  253. $oskipped = $skipped;
  254. if (sizeof($testfiles) == 0) {
  255. return;
  256. }
  257. if ($mod_name=extract_module_name_from_path($dir)) {
  258. if ($ext_found=in_array($mod_name,$modules_available))
  259. dowriteln("Testing extension: $mod_name");
  260. else $skipped_extensions[$mod_name]=TRUE;
  261. }
  262. if (!isset($ext_found) or $ext_found!==FALSE) {
  263. dowriteln("%bRunning tests in $dir%B");
  264. dowriteln("=================".str_repeat("=", strlen($dir)));
  265. sort($testfiles);
  266. for ($i = 0; $i < sizeof($testfiles); $i++) {
  267. switch (run_test($testfiles[$i])) {
  268. case TEST_SKIPPED:
  269. case TEST_INTERNAL_ERROR:
  270. $skipped++;
  271. break;
  272. case TEST_FAILED:
  273. $failed++;
  274. break;
  275. case TEST_PASSED:
  276. $passed++;
  277. break;
  278. }
  279. $total++;
  280. }
  281. if ($oskipped + (isset($tests_in_dir[$dir])?$tests_in_dir[$dir]:0) == $skipped) {
  282. $skippednow = $skipped - $oskipped;
  283. dowriteln("[all $skippednow test(s) skipped]");
  284. }
  285. dowriteln("");
  286. }
  287. return true;
  288. }
  289. function skip_headers($fp)
  290. {
  291. while (!feof($fp)) {
  292. if (trim(fgets($fp, 1024)) == "") {
  293. break;
  294. }
  295. }
  296. }
  297. function delete_tmpfiles()
  298. {
  299. global $tmpfile;
  300. reset($tmpfile);
  301. while (list($k, $v) = each($tmpfile)) {
  302. if (file_exists($v)) {
  303. //print "unlink($v): "; var_dump(unlink($v));
  304. unlink($v);
  305. }
  306. }
  307. }
  308. /**
  309. * Compares two files, ignoring blank lines.
  310. *
  311. * @param $file1 string name of first file to compare
  312. * @param $file2 string name of second file to compare
  313. *
  314. * @return bool whether the files were "equal"
  315. */
  316. function compare_results($file1, $file2)
  317. {
  318. $data1 = $data2 = "";
  319. if (!($fp1 = @fopen($file1, "r")) || !($fp2 = @fopen($file2, "r"))) {
  320. return false;
  321. }
  322. while (!(feof($fp1) || feof($fp2))) {
  323. if (!feof($fp1) && trim($line1 = fgets($fp1, 10240)) != "") {
  324. //print "adding line1 $line1\n";
  325. $data1 .= trim($line1);
  326. }
  327. if (!feof($fp2) && trim($line2 = fgets($fp2, 10240)) != "") {
  328. //print "adding line2 $line2\n";
  329. $data2 .= trim($line2);
  330. }
  331. }
  332. fclose($fp1);
  333. fclose($fp2);
  334. if ((trim($data1) != trim($data2))
  335. || ($data1=='' && $data2=='')) {
  336. //print "data1=";var_dump($data1);
  337. //print "data2=";var_dump($data2);
  338. return false;
  339. }
  340. return true;
  341. }
  342. function run_test($file)
  343. {
  344. global $php, $tmpfile, $term_bold, $term_norm, $term, $windows_p;
  345. $variables = array("TEST", "POST", "GET", "FILE", "EXPECT", "SKIPIF",
  346. "OUTPUT");
  347. $fp = @fopen($file, "r");
  348. if (!$fp) {
  349. return TEST_INTERNAL_ERROR;
  350. }
  351. $tmpdir = dirname($file);
  352. $tmpfix = "phpt.";
  353. $tmpfile["FILE"] = tempnam($tmpdir, $tmpfix);
  354. $tmpfile["SKIPIF"] = tempnam($tmpdir, $tmpfix);
  355. $tmpfile["POST"] = tempnam($tmpdir, $tmpfix);
  356. $tmpfile["EXPECT"] = tempnam($tmpdir, $tmpfix);
  357. $tmpfile["OUTPUT"] = tempnam($tmpdir, $tmpfix);
  358. while ($line = fgets($fp, 4096)) {
  359. if (ereg('^--([A-Z]+)--', $line, $matches)) {
  360. $var = $matches[1];
  361. if (isset($tmpfile[$var]) && $tmpfile[$var]) {
  362. $fps[$var] = @fopen($tmpfile[$var], "w");
  363. } else {
  364. $$var = '';
  365. }
  366. } else {
  367. if (isset($var) && $var) {
  368. if ($var == "POST") {
  369. $line = trim($line);
  370. }
  371. if (isset($fps[$var]) && $fps[$var]) {
  372. fwrite($fps[$var], $line);
  373. } else {
  374. $$var .= $line;
  375. }
  376. }
  377. }
  378. }
  379. if(isset($fps) && is_array($fps)) {
  380. reset($fps);
  381. while (list($k, $v) = each($fps)) {
  382. if (is_resource($v)) {
  383. fclose($v);
  384. }
  385. }
  386. }
  387. putenv("PHP_TEST=1");
  388. putenv("REDIRECT_STATUS=1");
  389. putenv("CONTENT_LENGTH=");
  390. putenv("QUERY_STRING=".(isset($GET)?$GET:""));
  391. $include_path = ini_get("include_path");
  392. if (isset($fps["SKIPIF"])) {
  393. $tmpfile["SKIPIF_OUTPUT"] = tempnam($tmpdir, $tmpfix);
  394. putenv("REQUEST_METHOD=GET");
  395. putenv("CONTENT_TYPE=");
  396. putenv("PATH_TRANSLATED=$tmpfile[SKIPIF]");
  397. putenv("SCRIPT_FILENAME=$tmpfile[SKIPIF]");
  398. $skipifcmd = "$php -q -f $tmpfile[SKIPIF] > $tmpfile[SKIPIF_OUTPUT]";
  399. system($skipifcmd, $ret);
  400. $sp = @fopen($tmpfile["SKIPIF_OUTPUT"], "r");
  401. if ($sp) {
  402. skip_headers($sp);
  403. $skip = trim(fgets($sp, 1024));
  404. fclose($sp);
  405. if ($skip == "skip") {
  406. delete_tmpfiles();
  407. return TEST_SKIPPED;
  408. }
  409. }
  410. }
  411. putenv("PATH_TRANSLATED=$tmpfile[FILE]");
  412. putenv("SCRIPT_FILENAME=$tmpfile[FILE]");
  413. if (isset($fps["POST"])) {
  414. putenv("REQUEST_METHOD=POST");
  415. putenv("CONTENT_TYPE=application/x-www-form-urlencoded");
  416. putenv("CONTENT_LENGTH=".filesize($tmpfile["POST"]));
  417. } else {
  418. putenv("REQUEST_METHOD=GET");
  419. putenv("CONTENT_TYPE=");
  420. putenv("CONTENT_LENGTH=");
  421. }
  422. if (isset($fps["POST"])) {
  423. if(!$windows_p) {
  424. $cmd = "2>&1 $php -q $tmpfile[FILE] < $tmpfile[POST]";
  425. }
  426. else {
  427. $cmd = "$term /c " . realpath($php) ." -q $tmpfile[FILE] < $tmpfile[POST]";
  428. }
  429. } else {
  430. if(!$windows_p) {
  431. $cmd = "2>&1 $php -q $tmpfile[FILE]";
  432. }
  433. else {
  434. $cmd = "$term /c " . realpath($php) ." -q $tmpfile[FILE]";;
  435. }
  436. }
  437. $ofp = @fopen($tmpfile["OUTPUT"], "w");
  438. if (!$ofp) {
  439. dowriteln("Error: could not write to output file");
  440. delete_tmpfiles();
  441. return TEST_INTERNAL_ERROR;
  442. }
  443. //echo $cmd;
  444. $cp = popen($cmd, "r");
  445. if (!$cp) {
  446. dowriteln("Error: could not execute: $cmd");
  447. delete_tmpfiles();
  448. return TEST_INTERNAL_ERROR;
  449. }
  450. skip_headers($cp);
  451. while ($data = fread($cp, 2048)) {
  452. fwrite($ofp, $data);
  453. }
  454. fclose($ofp);
  455. pclose($cp);
  456. $desc = isset($TEST)?trim($TEST):"";
  457. $outfile = ereg_replace('\.phpt$', '.out', $file);
  458. $expectfile = ereg_replace('\.phpt$', '.exp', $file);
  459. $phpfile = ereg_replace('\.phpt$', '.php', $file);
  460. if (compare_results($tmpfile["OUTPUT"], $tmpfile["EXPECT"])) {
  461. $status = TEST_PASSED;
  462. $text = "passed";
  463. $pre = $post = "";
  464. if (file_exists($outfile)) {
  465. unlink($outfile);
  466. }
  467. if (file_exists($expectfile)) {
  468. unlink($expectfile);
  469. }
  470. if (file_exists($phpfile)) {
  471. unlink($phpfile);
  472. }
  473. } else {
  474. //system("env");
  475. $status = TEST_FAILED;
  476. $text = "failed";
  477. $pre = $term_bold;
  478. $post = $term_norm;
  479. $desc .= " (".basename($file).")";
  480. if (file_exists($outfile)) {
  481. unlink($outfile);
  482. }
  483. copy($tmpfile["OUTPUT"], $outfile);
  484. copy($tmpfile["EXPECT"], $expectfile);
  485. copy($tmpfile["FILE"], $phpfile);
  486. }
  487. dowriteln(sprintf("%s%-68s ... %s%s", $pre, substr($desc, 0, 68),
  488. $text, $post));
  489. // if ($status == TEST_FAILED) {
  490. // for ($i = 0; $i < sizeof($variables); $i++) {
  491. // $var = $variables[$i];
  492. // print "$var:\n";
  493. // if ($tmpfile[$var]) {
  494. // if (file_exists($tmpfile[$var])) {
  495. // system("cat ".$tmpfile[$var]);
  496. // }
  497. // } else {
  498. // print $$var;
  499. // }
  500. // }
  501. // print "--\n\n";
  502. // }
  503. delete_tmpfiles();
  504. return $status;
  505. }
  506. ?>