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.

509 lines
14 KiB

25 years ago
25 years ago
  1. <?php
  2. /*
  3. +----------------------------------------------------------------------+
  4. | PHP Version 4 |
  5. +----------------------------------------------------------------------+
  6. | Copyright (c) 1997-2002 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: Preston L. Bannister <pbannister@php.net> |
  17. | Sander Roobol <sander@php.net> |
  18. | Marcus Boerger <helly@php.net> |
  19. | (based on version by: Stig Bakken <ssb@fast.no>) |
  20. | (based on the PHP 3 test framework by Rasmus Lerdorf) |
  21. +----------------------------------------------------------------------+
  22. */
  23. /*
  24. Require exact specification of PHP executable to test (no guessing!).
  25. Die if any internal errors encountered in test script.
  26. Regularized output for simpler post-processing of output.
  27. Optionally output error lines indicating the failing test source and log
  28. for direct jump with MSVC or Emacs.
  29. */
  30. /*
  31. * TODO:
  32. * - do not test PEAR components if base class and/or component class cannot be instanciated
  33. */
  34. set_time_limit(0);
  35. ob_implicit_flush();
  36. error_reporting(E_ALL);
  37. if (ini_get('safe_mode')) {
  38. echo <<< SAFE_MODE_WARNING
  39. +-----------------------------------------------------------+
  40. | ! WARNING ! |
  41. | You are running the test-suite with "safe_mode" ENABLED ! |
  42. | |
  43. | Chances are high that no test will work at all, |
  44. | depending on how you configured "safe_mode" ! |
  45. +-----------------------------------------------------------+
  46. SAFE_MODE_WARNING;
  47. }
  48. // Don't ever guess at the PHP executable location.
  49. // Require the explicit specification.
  50. // Otherwise we could end up testing the wrong file!
  51. if (isset($_ENV['TEST_PHP_EXECUTABLE'])) {
  52. $php = $_ENV['TEST_PHP_EXECUTABLE'];
  53. } else {
  54. error("environment variable TEST_PHP_EXECUTABLE must be set to specify PHP executable!");
  55. }
  56. if (isset($_ENV['TEST_PHP_LOG_FORMAT'])) {
  57. $log_format = strtoupper($_ENV['TEST_PHP_LOG_FORMAT']);
  58. } else {
  59. $log_format = 'LEOD';
  60. }
  61. if (!@is_executable($php)) {
  62. error("invalid PHP executable specified by TEST_PHP_EXECUTABLE = " . $php);
  63. }
  64. // Check whether a detailed log is wanted.
  65. if (isset($_ENV['TEST_PHP_DETAILED'])) {
  66. define('DETAILED', $_ENV['TEST_PHP_DETAILED']);
  67. } else {
  68. define('DETAILED', 0);
  69. }
  70. // Write test context information.
  71. echo "
  72. =====================================================================
  73. CWD : " . getcwd() . "
  74. PHP : $php
  75. PHP_SAPI : " . PHP_SAPI . "
  76. PHP_VERSION : " . PHP_VERSION . "
  77. PHP_OS : " . PHP_OS . "
  78. INI actual : " . realpath(get_cfg_var('cfg_file_path')) . "
  79. INI wanted : " . realpath('php.ini-dist') . "
  80. =====================================================================
  81. ";
  82. // Make sure we are using the proper php.ini.
  83. $php_ini = realpath("php.ini-dist");
  84. if (realpath(get_cfg_var('cfg_file_path')) != $php_ini) {
  85. error("php.ini-dist was not used!");
  86. }
  87. $php .= " -c $php_ini";
  88. // Determine the tests to be run.
  89. $test_to_run = array();
  90. $test_files = array();
  91. $test_results = array();
  92. // If parameters given assume they represent selected tests to run.
  93. if (isset($argc) && $argc > 1) {
  94. for ($i=1; $i<$argc; $i++) {
  95. $testfile = realpath($argv[$i]);
  96. $test_to_run[$testfile] = 1;
  97. }
  98. // Run selected tests.
  99. if (count($test_to_run)) {
  100. echo "Running selected tests.\n";
  101. foreach($test_to_run AS $name=>$runnable) {
  102. echo "test: $name runnable: $runnable\n";
  103. if ($runnable) {
  104. $test_results[$name] = run_test($php,$name);
  105. }
  106. }
  107. exit(0);
  108. }
  109. }
  110. // Compile a list of all test files (*.phpt).
  111. $test_files = array();
  112. $exts_to_test = get_loaded_extensions();
  113. $exts_tested = count($exts_to_test);
  114. $exts_skipped = 0;
  115. $ignored_by_ext = 0;
  116. sort($exts_to_test);
  117. $test_dirs = array('tests', 'pear', 'ext');
  118. $cwd=getcwd();
  119. foreach ($test_dirs as $dir) {
  120. find_files("{$cwd}/{$dir}", $dir=='ext');
  121. }
  122. function find_files($dir,$is_ext_dir=false,$ignore=false)
  123. {
  124. global $test_files, $exts_to_test, $ignored_by_ext, $exts_skipped, $exts_tested;
  125. $o = opendir($dir) or error("cannot open directory: $dir");
  126. while (($name = readdir($o)) !== false) {
  127. if (is_dir("{$dir}/{$name}") && !in_array($name, array('.', '..', 'CVS'))) {
  128. $skip_ext = ($is_ext_dir && !in_array($name, $exts_to_test));
  129. if ($skip_ext) {
  130. $exts_skipped++;
  131. }
  132. find_files("{$dir}/{$name}", false, $ignore || $skip_ext);
  133. }
  134. // Cleanup any left-over tmp files from last run.
  135. if (substr($name, -4) == '.tmp') {
  136. @unlink("$dir/$name");
  137. continue;
  138. }
  139. // Otherwise we're only interested in *.phpt files.
  140. if (substr($name, -5) == '.phpt') {
  141. if ($ignore) {
  142. $ignored_by_ext++;
  143. } else {
  144. $testfile = realpath("{$dir}/{$name}");
  145. $test_files[] = $testfile;
  146. }
  147. }
  148. }
  149. closedir($o);
  150. }
  151. sort($test_files);
  152. $start_time = time();
  153. echo "TIME START " . date('Y-m-d H:i:s', $start_time) . "
  154. =====================================================================
  155. ";
  156. $path_current = '';
  157. foreach ($test_files as $name) {
  158. $path = dirname($name);
  159. if ($path_current != $path) {
  160. $path_current = $path;
  161. echo " entering directory $path\n";
  162. }
  163. $test_results[$name] = run_test($php,$name);
  164. }
  165. $end_time = time();
  166. // Summarize results
  167. if (0 == count($test_results)) {
  168. echo "No tests were run.\n";
  169. return;
  170. }
  171. $n_total = count($test_results);
  172. $n_total += $ignored_by_ext;
  173. $sum_results = array('PASSED'=>0, 'SKIPPED'=>0, 'FAILED'=>0);
  174. foreach ($test_results as $v) {
  175. $sum_results[$v]++;
  176. }
  177. $sum_results['SKIPPED'] += $ignored_by_ext;
  178. $percent_results = array();
  179. while (list($v,$n) = each($sum_results)) {
  180. $percent_results[$v] = (100.0 * $n) / $n_total;
  181. }
  182. echo "
  183. =====================================================================
  184. TIME END " . date('Y-m-d H:i:s', $end_time) . "
  185. =====================================================================
  186. TEST RESULT SUMMARY
  187. ---------------------------------------------------------------------
  188. Exts skipped : " . sprintf("%4d",$exts_skipped) . "
  189. Exts tested : " . sprintf("%4d",$exts_tested) . "
  190. ---------------------------------------------------------------------
  191. Number of tests : " . sprintf("%4d",$n_total) . "
  192. Tests skipped : " . sprintf("%4d (%2.1f%%)",$sum_results['SKIPPED'],$percent_results['SKIPPED']) . "
  193. Tests failed : " . sprintf("%4d (%2.1f%%)",$sum_results['FAILED'],$percent_results['FAILED']) . "
  194. Tests passed : " . sprintf("%4d (%2.1f%%)",$sum_results['PASSED'],$percent_results['PASSED']) . "
  195. ---------------------------------------------------------------------
  196. Time taken : " . sprintf("%4d seconds", $end_time - $start_time) . "
  197. =====================================================================
  198. ";
  199. //
  200. // Write the given text to a temporary file, and return the filename.
  201. //
  202. function save_text($filename,$text)
  203. {
  204. $fp = @fopen($filename,'w') or error("Cannot open file '" . $filename . "' (save_text)");
  205. fwrite($fp,$text);
  206. fclose($fp);
  207. if (1 < DETAILED) echo "
  208. FILE $filename {{{
  209. $text
  210. }}}
  211. ";
  212. }
  213. //
  214. // Write an error in a format recognizable to Emacs or MSVC.
  215. //
  216. function error_report($testname,$logname,$tested)
  217. {
  218. $testname = realpath($testname);
  219. $logname = realpath($logname);
  220. switch (strtoupper(getenv('TEST_PHP_ERROR_STYLE'))) {
  221. case 'MSVC':
  222. echo $testname . "(1) : $tested\n";
  223. echo $logname . "(1) : $tested\n";
  224. break;
  225. case 'EMACS':
  226. echo $testname . ":1: $tested\n";
  227. echo $logname . ":1: $tested\n";
  228. break;
  229. }
  230. }
  231. //
  232. // Run an individual test case.
  233. //
  234. function run_test($php,$file)
  235. {
  236. global $log_format;
  237. if (DETAILED) echo "
  238. =================
  239. TEST $file
  240. ";
  241. // Load the sections of the test file.
  242. $section_text = array(
  243. 'TEST' => '(unnamed test)',
  244. 'SKIPIF' => '',
  245. 'GET' => '',
  246. 'ARGS' => '',
  247. );
  248. $fp = @fopen($file, "r")
  249. or error("Cannot open test file: $file");
  250. $section = '';
  251. while (!feof($fp)) {
  252. $line = fgets($fp);
  253. // Match the beginning of a section.
  254. if (ereg('^--([A-Z]+)--',$line,$r)) {
  255. $section = $r[1];
  256. $section_text[$section] = '';
  257. continue;
  258. }
  259. // Add to the section text.
  260. $section_text[$section] .= $line;
  261. }
  262. fclose($fp);
  263. $tested = trim($section_text['TEST']).' ('.basename($file).')';
  264. $tmp = realpath(dirname($file));
  265. $tmp_skipif = $tmp.uniqid('/phpt.');
  266. $tmp_file = $tmp.uniqid('/phpt.');
  267. $tmp_post = $tmp.uniqid('/phpt.');
  268. @unlink($tmp_skipif);
  269. @unlink($tmp_file);
  270. @unlink($tmp_post);
  271. // Reset environment from any previous test.
  272. putenv("REDIRECT_STATUS=");
  273. putenv("QUERY_STRING=");
  274. putenv("PATH_TRANSLATED=");
  275. putenv("SCRIPT_FILENAME=");
  276. putenv("REQUEST_METHOD=");
  277. putenv("CONTENT_TYPE=");
  278. putenv("CONTENT_LENGTH=");
  279. // unlink old test results
  280. @unlink(ereg_replace('\.phpt$','.diff',$file));
  281. @unlink(ereg_replace('\.phpt$','.log',$file));
  282. @unlink(ereg_replace('\.phpt$','.exp',$file));
  283. @unlink(ereg_replace('\.phpt$','.out',$file));
  284. // Check if test should be skipped.
  285. if (array_key_exists('SKIPIF', $section_text)) {
  286. if (trim($section_text['SKIPIF'])) {
  287. save_text($tmp_skipif, $section_text['SKIPIF']);
  288. $output = `$php $tmp_skipif`;
  289. @unlink($tmp_skipif);
  290. if(trim($output)=='skip') {
  291. echo "SKIP $tested\n";
  292. return 'SKIPPED';
  293. }
  294. }
  295. }
  296. // Any special ini settings
  297. $ini_settings = '';
  298. if (array_key_exists('INI', $section_text)) {
  299. foreach(preg_split( "/[\n\r]+/", $section_text['INI']) as $setting)
  300. if (strlen($setting))
  301. $ini_settings .= " -d '$setting'";
  302. }
  303. // We've satisfied the preconditions - run the test!
  304. save_text($tmp_file,$section_text['FILE']);
  305. if (array_key_exists('GET', $section_text))
  306. $query_string = trim($section_text['GET']);
  307. else
  308. $query_string = '';
  309. putenv("REDIRECT_STATUS=1");
  310. putenv("QUERY_STRING=$query_string");
  311. putenv("PATH_TRANSLATED=$tmp_file");
  312. putenv("SCRIPT_FILENAME=$tmp_file");
  313. $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : '';
  314. if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
  315. $post = trim($section_text['POST']);
  316. save_text($tmp_post,$post);
  317. $content_length = strlen($post);
  318. putenv("REQUEST_METHOD=POST");
  319. putenv("CONTENT_TYPE=application/x-www-form-urlencoded");
  320. putenv("CONTENT_LENGTH=$content_length");
  321. $cmd = "$php$ini_settings -f $tmp_file 2>&1 < $tmp_post";
  322. } else {
  323. putenv("REQUEST_METHOD=GET");
  324. putenv("CONTENT_TYPE=");
  325. putenv("CONTENT_LENGTH=");
  326. $cmd = "$php$ini_settings -f $tmp_file$args 2>&1";
  327. }
  328. if (DETAILED) echo "
  329. CONTENT_LENGTH = " . getenv("CONTENT_LENGTH") . "
  330. CONTENT_TYPE = " . getenv("CONTENT_TYPE") . "
  331. PATH_TRANSLATED = " . getenv("PATH_TRANSLATED") . "
  332. QUERY_STRING = " . getenv("QUERY_STRING") . "
  333. REDIRECT_STATUS = " . getenv("REDIRECT_STATUS") . "
  334. REQUEST_METHOD = " . getenv("REQUEST_METHOD") . "
  335. SCRIPT_FILENAME = " . getenv("SCRIPT_FILENAME") . "
  336. COMMAND $cmd
  337. ";
  338. $out = `$cmd`;
  339. @unlink($tmp_post);
  340. @unlink($tmp_file);
  341. // Does the output match what is expected?
  342. $output = trim($out);
  343. $wanted = trim($section_text['EXPECT']);
  344. $output = preg_replace('/\r\n/',"\n",$output);
  345. $wanted = preg_replace('/\r\n/',"\n",$wanted);
  346. // compare and leave on success
  347. $ok = (0 == strcmp($output,$wanted));
  348. if ($ok) {
  349. echo "PASS $tested\n";
  350. return 'PASSED';
  351. }
  352. // Test failed so we need to report details.
  353. echo "FAIL $tested\n";
  354. // write .exp
  355. if (strpos($log_format,'E')!==false) {
  356. $logname = ereg_replace('\.phpt$','.exp',$file);
  357. $log = fopen($logname,'w') or error("Cannot create test log - $logname");
  358. fwrite($log,$wanted);
  359. fclose($log);
  360. }
  361. // write .out
  362. if (strpos($log_format,'O')!==false) {
  363. $logname = ereg_replace('\.phpt$','.out',$file);
  364. $log = fopen($logname,'w') or error("Cannot create test log - $logname");
  365. fwrite($log,$output);
  366. fclose($log);
  367. }
  368. // write .diff
  369. if (strpos($log_format,'D')!==false) {
  370. $logname = ereg_replace('\.phpt$','.diff',$file);
  371. $log = fopen($logname,'w') or error("Cannot create test log - $logname");
  372. fwrite($log,generate_diff($wanted,$output));
  373. fclose($log);
  374. }
  375. // write .log
  376. if (strpos($log_format,'L')!==false) {
  377. $logname = ereg_replace('\.phpt$','.log',$file);
  378. $log = fopen($logname,'w') or error("Cannot create test log - $logname");
  379. fwrite($log,"
  380. ---- EXPECTED OUTPUT
  381. $wanted
  382. ---- ACTUAL OUTPUT
  383. $output
  384. ---- FAILED
  385. ");
  386. fclose($log);
  387. error_report($file,$logname,$tested);
  388. }
  389. return 'FAILED';
  390. }
  391. function generate_diff($wanted,$output)
  392. {
  393. $w = explode("\n", $wanted);
  394. $o = explode("\n", $output);
  395. $w1 = array_diff($w,$o);
  396. $o1 = array_diff($o,$w);
  397. $w2 = array();
  398. $o2 = array();
  399. foreach($w1 as $idx => $val) $w2[sprintf("%03d<",$idx)] = sprintf("%03d- ", $idx+1).$val;
  400. foreach($o1 as $idx => $val) $o2[sprintf("%03d>",$idx)] = sprintf("%03d+ ", $idx+1).$val;
  401. $diff = array_merge($w2, $o2);
  402. ksort($diff);
  403. return implode("\r\n", $diff);
  404. }
  405. function error($message)
  406. {
  407. echo "ERROR: {$message}\n";
  408. exit(1);
  409. }
  410. /*
  411. * Local variables:
  412. * tab-width: 4
  413. * c-basic-offset: 4
  414. * indent-tabs-mode: t
  415. * End:
  416. */
  417. ?>