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.

485 lines
14 KiB

  1. <?php
  2. /*
  3. +----------------------------------------------------------------------+
  4. | PHP version 4.0 |
  5. +----------------------------------------------------------------------+
  6. | Copyright (c) 1997, 1998, 1999, 2000 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. */
  24. ob_implicit_flush();
  25. define('TEST_PASSED', 0);
  26. define('TEST_FAILED', -1);
  27. define('TEST_SKIPPED', -2);
  28. define('TEST_INTERNAL_ERROR', -3);
  29. initialize();
  30. /*
  31. $opts = parse_options(&$argc, &$argv);
  32. if ($opts['help']) {
  33. usage();
  34. exit;
  35. }
  36. */
  37. do_testing($argc, $argv);
  38. exit;
  39. /*****************************************************************************/
  40. function usage()
  41. {
  42. dowriteln("Usage: run-tests.php [-d] [-h] [dir|file...]");
  43. }
  44. /*
  45. * Please use dowrite() and dowriteln() for all screen output.
  46. * This makes it easier to convert to HTML output later.
  47. */
  48. function dowrite($str)
  49. {
  50. global $term_bold, $term_norm;
  51. $str = str_replace("%b", $term_bold, $str);
  52. $str = str_replace("%B", $term_norm, $str);
  53. print $str;
  54. }
  55. function dowriteln($str)
  56. {
  57. dowrite("$str\n");
  58. }
  59. function initialize()
  60. {
  61. global $term, $windows_p, $php, $skip, $testdirs, $tmpfile,
  62. $skipped, $failed, $passed, $total, $term_bold, $term_norm,
  63. $tests_in_dir;
  64. // XXX Should support HTML output as well.
  65. $term = getenv("TERM");
  66. if (preg_match('/^(xterm|vt220)/', $term)) {
  67. $term_bold = sprintf("%c%c%c%c", 27, 91, 49, 109);
  68. $term_norm = sprintf("%c%c%c", 27, 91, 109);
  69. } elseif (preg_match('/^vt100/', $term)) {
  70. $term_bold = sprintf("%c%c%c%c", 27, 91, 49, 109);
  71. $term_norm = sprintf("%c%c%c", 27, 91, 109);
  72. } else {
  73. $term_bold = $term_norm = "";
  74. }
  75. $windows_p = (substr(php_uname(), 0, 7) == "Windows");
  76. if ($windows_p) {
  77. if (file_exists('Release_TS_inline/php.exe')) {
  78. $php = 'Release_TS_inline\php.exe';
  79. } elseif (file_exists('Release_TS/php.exe')) {
  80. $php = 'Release_TS\php.exe';
  81. } else {
  82. $php = "./php.exe";
  83. }
  84. } else {
  85. $php = $GLOBALS["TOP_BUILDDIR"]."/php";
  86. }
  87. if (!is_executable($php)) {
  88. dowriteln("PHP CGI binary ($php) not executable.");
  89. dowriteln("Please compile PHP as a CGI executable and try again.");
  90. exit;
  91. }
  92. $skip = array(
  93. "CVS" => 1
  94. );
  95. $testdirs = array();
  96. $tmpfile = array();
  97. $tests_in_dir = array();
  98. register_shutdown_function("delete_tmpfiles");
  99. $skipped = $failed = $passed = $total = 0;
  100. }
  101. function &parse_options(&$argc, &$argv)
  102. {
  103. $options = array();
  104. while ($argc > 0 && ($opt = substr($argv[0], 0, 2)) == "--") {
  105. $opt = array_shift($argv);
  106. $argc--;
  107. if ($arg == "--") {
  108. return $options;
  109. }
  110. if (preg_match('/^--([^=]+)=(.*)$/', $opt, $matches)) {
  111. $opt = $matches[1];
  112. $arg = $matches[2];
  113. } else {
  114. $arg = true;
  115. }
  116. $options[$opt] = $arg;
  117. }
  118. return $options;
  119. }
  120. function do_testing($argc, &$argv)
  121. {
  122. global $term, $windows_p, $php, $skip, $testdirs, $tmpfile, $opts,
  123. $skipped, $failed, $passed, $total, $term_bold, $term_norm;
  124. if ($argc > 1) {
  125. if (is_dir($argv[1])) {
  126. $dir = $argv[1];
  127. } else {
  128. for ($i = 1; $i < $argc; $i++) {
  129. switch (run_test($argv[$i])) {
  130. case TEST_SKIPPED:
  131. case TEST_INTERNAL_ERROR:
  132. $skipped++;
  133. break;
  134. case TEST_FAILED:
  135. $failed++;
  136. break;
  137. case TEST_PASSED:
  138. $passed++;
  139. break;
  140. }
  141. $total++;
  142. }
  143. }
  144. } else {
  145. $dir = $GLOBALS["TOP_SRCDIR"];
  146. }
  147. if (isset($dir) && $dir) {
  148. find_testdirs($dir);
  149. for ($i = 0; $i < sizeof($testdirs); $i++) {
  150. run_tests_in_dir($testdirs[$i]);
  151. }
  152. }
  153. $counting = $total - $skipped;
  154. if ($counting <= 0) {
  155. dowriteln("No tests were run.");
  156. return;
  157. }
  158. $total_d = (double)$total;
  159. $counting_d = (double)$counting;
  160. $passed_p = 100 * ($passed / $counting_d);
  161. $failed_p = 100 * ($failed / $counting_d);
  162. $skipped_p = 100 * ($skipped / $total_d);
  163. $passed_pstr = sprintf($passed_p < 10.0 ? "%1.1f" : "%3.0f", $passed_p);
  164. $failed_pstr = sprintf($failed_p < 10.0 ? "%1.1f" : "%3.0f", $failed_p);
  165. $skipped_pstr = sprintf($skipped_p < 10.0 ? "%1.1f" : "%3.0f", $skipped_p);
  166. dowriteln("TEST RESULT SUMMARY");
  167. dowriteln("=============================");
  168. dowriteln(sprintf("Number of tests: %4d", $total));
  169. dowriteln(sprintf("Tests skipped: %4d (%s%%)", $skipped, $skipped_pstr));
  170. dowriteln(sprintf("Tests failed: %4d (%s%%)", $failed, $failed_pstr));
  171. dowriteln(sprintf("Tests passed: %4d (%s%%)", $passed, $passed_pstr));
  172. }
  173. function find_testdirs($dir = '.', $first_pass = true)
  174. {
  175. global $testdirs, $skip;
  176. if ($first_pass && is_dir($dir)) {
  177. $testdirs[] = $dir;
  178. }
  179. $dp = @opendir($dir);
  180. if (!$dp) {
  181. print "Warning: could not open directory $dir\n";
  182. return false;
  183. }
  184. while ($ent = readdir($dp)) {
  185. $path = "$dir/$ent";
  186. if ((isset($skip[$ent]) && $skip[$ent]) || substr($ent, 0, 1) == "." || !is_dir($path)) {
  187. continue;
  188. }
  189. if (strstr("/$path/", "/tests/")) {
  190. $testdirs[] = $path;
  191. }
  192. find_testdirs($path, false);
  193. }
  194. closedir($dp);
  195. }
  196. function run_tests_in_dir($dir = '.')
  197. {
  198. global $skip, $skipped, $failed, $passed, $total, $opts, $tests_in_dir;
  199. $dp = opendir($dir);
  200. if (!$dp) {
  201. print "Warning: could not run tests in $dir\n";
  202. return false;
  203. }
  204. $testfiles = array();
  205. while ($ent = readdir($dp)) {
  206. if ((isset($skip[$ent]) && $skip[$ent]) || substr($ent, 0, 1) == "." || substr($ent, -5) != ".phpt") {
  207. continue;
  208. }
  209. $testfiles[] = "$dir/$ent";
  210. if(isset($tests_in_dir[$dir])) $tests_in_dir[$dir]++; else $tests_in_dir[$dir]=1;
  211. }
  212. closedir($dp);
  213. if (isset($tests_in_dir[$dir]) && ($tests_in_dir[$dir] == 0)) {
  214. return true;
  215. }
  216. $oskipped = $skipped;
  217. if (sizeof($testfiles) == 0) {
  218. return;
  219. }
  220. dowriteln("%bRunning tests in $dir%B");
  221. dowriteln("=================".str_repeat("=", strlen($dir)));
  222. sort($testfiles);
  223. for ($i = 0; $i < sizeof($testfiles); $i++) {
  224. switch (run_test($testfiles[$i])) {
  225. case TEST_SKIPPED:
  226. case TEST_INTERNAL_ERROR:
  227. $skipped++;
  228. break;
  229. case TEST_FAILED:
  230. $failed++;
  231. break;
  232. case TEST_PASSED:
  233. $passed++;
  234. break;
  235. }
  236. $total++;
  237. }
  238. if ($oskipped + (isset($tests_in_dir[$dir])?$tests_in_dir[$dir]:0) == $skipped) {
  239. $skippednow = $skipped - $oskipped;
  240. dowriteln("[all $skippednow test(s) skipped]");
  241. }
  242. dowriteln("");
  243. return true;
  244. }
  245. function skip_headers($fp)
  246. {
  247. while (!feof($fp)) {
  248. if (trim(fgets($fp, 1024)) == "") {
  249. break;
  250. }
  251. }
  252. }
  253. function delete_tmpfiles()
  254. {
  255. global $tmpfile;
  256. reset($tmpfile);
  257. while (list($k, $v) = each($tmpfile)) {
  258. if (file_exists($v)) {
  259. //print "unlink($v): "; var_dump(unlink($v));
  260. unlink($v);
  261. }
  262. }
  263. }
  264. /**
  265. * Compares two files, ignoring blank lines.
  266. *
  267. * @param $file1 string name of first file to compare
  268. * @param $file2 string name of second file to compare
  269. *
  270. * @return bool whether the files were "equal"
  271. */
  272. function compare_results($file1, $file2)
  273. {
  274. $data1 = $data2 = "";
  275. if (!($fp1 = @fopen($file1, "r")) || !($fp2 = @fopen($file2, "r"))) {
  276. return false;
  277. }
  278. while (!(feof($fp1) || feof($fp2))) {
  279. if (!feof($fp1) && trim($line1 = fgets($fp1, 10240)) != "") {
  280. //print "adding line1 $line1\n";
  281. $data1 .= $line1;
  282. }
  283. if (!feof($fp2) && trim($line2 = fgets($fp2, 10240)) != "") {
  284. //print "adding line2 $line2\n";
  285. $data2 .= $line2;
  286. }
  287. }
  288. fclose($fp1);
  289. fclose($fp2);
  290. if (trim($data1) != trim($data2)) {
  291. //print "data1=";var_dump($data1);
  292. //print "data2=";var_dump($data2);
  293. return false;
  294. }
  295. return true;
  296. }
  297. function run_test($file)
  298. {
  299. global $php, $tmpfile, $term_bold, $term_norm;
  300. $variables = array("TEST", "POST", "GET", "FILE", "EXPECT", "SKIPIF",
  301. "OUTPUT");
  302. $fp = @fopen($file, "r");
  303. if (!$fp) {
  304. return TEST_INTERNAL_ERROR;
  305. }
  306. $tmpdir = dirname($file);
  307. $tmpfix = "phpt.";
  308. $tmpfile["FILE"] = tempnam($tmpdir, $tmpfix);
  309. $tmpfile["SKIPIF"] = tempnam($tmpdir, $tmpfix);
  310. $tmpfile["POST"] = tempnam($tmpdir, $tmpfix);
  311. $tmpfile["EXPECT"] = tempnam($tmpdir, $tmpfix);
  312. $tmpfile["OUTPUT"] = tempnam($tmpdir, $tmpfix);
  313. while ($line = fgets($fp, 4096)) {
  314. if (preg_match('/^--([A-Z]+)--$/', $line, $matches)) {
  315. $var = $matches[1];
  316. if (isset($tmpfile[$var]) && $tmpfile[$var]) {
  317. $fps[$var] = @fopen($tmpfile[$var], "w");
  318. } else {
  319. $$var = '';
  320. }
  321. } else {
  322. if (isset($var) && $var) {
  323. if ($var == "POST") {
  324. $line = trim($line);
  325. }
  326. if (isset($fps[$var]) && $fps[$var]) {
  327. fwrite($fps[$var], $line);
  328. } else {
  329. $$var .= $line;
  330. }
  331. }
  332. }
  333. }
  334. if(isset($fps) && is_array($fps)) {
  335. reset($fps);
  336. while (list($k, $v) = each($fps)) {
  337. if (is_resource($v)) {
  338. fclose($v);
  339. }
  340. }
  341. }
  342. putenv("PHP_TEST=1");
  343. putenv("REDIRECT_STATUS=1");
  344. putenv("CONTENT_LENGTH=");
  345. putenv("QUERY_STRING=".(isset($GET)?$GET:""));
  346. $include_path = ini_get("include_path");
  347. if (isset($fps["SKIPIF"])) {
  348. $tmpfile["SKIPIF_OUTPUT"] = tempnam($tmpdir, $tmpfix);
  349. putenv("REQUEST_METHOD=GET");
  350. putenv("CONTENT_TYPE=");
  351. putenv("PATH_TRANSLATED=$tmpfile[SKIPIF]");
  352. putenv("SCRIPT_FILENAME=$tmpfile[SKIPIF]");
  353. $skipifcmd = "$php -q -f $tmpfile[SKIPIF] > $tmpfile[SKIPIF_OUTPUT]";
  354. system($skipifcmd, $ret);
  355. $sp = @fopen($tmpfile["SKIPIF_OUTPUT"], "r");
  356. if ($sp) {
  357. skip_headers($sp);
  358. $skip = trim(fgets($sp, 1024));
  359. fclose($sp);
  360. if ($skip == "skip") {
  361. delete_tmpfiles();
  362. return TEST_SKIPPED;
  363. }
  364. }
  365. }
  366. putenv("PATH_TRANSLATED=$tmpfile[FILE]");
  367. putenv("SCRIPT_FILENAME=$tmpfile[FILE]");
  368. if (isset($fps["POST"])) {
  369. putenv("REQUEST_METHOD=POST");
  370. putenv("CONTENT_TYPE=application/x-www-form-urlencoded");
  371. putenv("CONTENT_LENGTH=".filesize($tmpfile["POST"]));
  372. } else {
  373. putenv("REQUEST_METHOD=GET");
  374. putenv("CONTENT_TYPE=");
  375. putenv("CONTENT_LENGTH=");
  376. }
  377. if (isset($fps["POST"])) {
  378. $cmd = "$php -q $tmpfile[FILE] < $tmpfile[POST]";
  379. } else {
  380. $cmd = "$php -q $tmpfile[FILE]";
  381. }
  382. $ofp = @fopen($tmpfile["OUTPUT"], "w");
  383. if (!$ofp) {
  384. dowriteln("Error: could not write to output file");
  385. delete_tmpfiles();
  386. return TEST_INTERNAL_ERROR;
  387. }
  388. $cp = popen($cmd, "r");
  389. if (!$cp) {
  390. dowriteln("Error: could not execute: $cmd");
  391. delete_tmpfiles();
  392. return TEST_INTERNAL_ERROR;
  393. }
  394. skip_headers($cp);
  395. while ($data = fread($cp, 2048)) {
  396. fwrite($ofp, $data);
  397. }
  398. fclose($ofp);
  399. pclose($cp);
  400. $desc = isset($TEST)?trim($TEST):"";
  401. $outfile = preg_replace('/\.phpt$/', '.out', $file);
  402. $expectfile = preg_replace('/\.phpt$/', '.exp', $file);
  403. $phpfile = preg_replace('/\.phpt$/', '.php', $file);
  404. if (compare_results($tmpfile["OUTPUT"], $tmpfile["EXPECT"])) {
  405. $status = TEST_PASSED;
  406. $text = "passed";
  407. $pre = $post = "";
  408. if (file_exists($outfile)) {
  409. unlink($outfile);
  410. }
  411. if (file_exists($expectfile)) {
  412. unlink($expectfile);
  413. }
  414. if (file_exists($phpfile)) {
  415. unlink($phpfile);
  416. }
  417. } else {
  418. //system("env");
  419. $status = TEST_FAILED;
  420. $text = "failed";
  421. $pre = $term_bold;
  422. $post = $term_norm;
  423. $desc .= " (".basename($file).")";
  424. if (file_exists($outfile)) {
  425. unlink($outfile);
  426. }
  427. copy($tmpfile["OUTPUT"], $outfile);
  428. copy($tmpfile["EXPECT"], $expectfile);
  429. copy($tmpfile["FILE"], $phpfile);
  430. }
  431. dowriteln(sprintf("%s%-68s ... %s%s", $pre, substr($desc, 0, 68),
  432. $text, $post));
  433. // if ($status == TEST_FAILED) {
  434. // for ($i = 0; $i < sizeof($variables); $i++) {
  435. // $var = $variables[$i];
  436. // print "$var:\n";
  437. // if ($tmpfile[$var]) {
  438. // if (file_exists($tmpfile[$var])) {
  439. // system("cat ".$tmpfile[$var]);
  440. // }
  441. // } else {
  442. // print $$var;
  443. // }
  444. // }
  445. // print "--\n\n";
  446. // }
  447. delete_tmpfiles();
  448. return $status;
  449. }
  450. ?>