Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
// Ugly hack to make Greg's run-tests compatible with the old one (the old one won't work on windows)
3
include dirname(__FILE__) . '/tests-config';
4
foreach ($conf as $key => $value) {
5
    putenv("$key=$value");
6
}
7
/*
8
   +----------------------------------------------------------------------+
9
   | PHP Version 4                                                        |
10
   +----------------------------------------------------------------------+
11
   | Copyright (c) 1997-2002 The PHP Group                                |
12
   +----------------------------------------------------------------------+
13
   | This source file is subject to version 2.02 of the PHP license,      |
14
   | that is bundled with this package in the file LICENSE, and is        |
15
   | available at through the world-wide-web at                           |
16
   | http://www.php.net/license/2_02.txt.                                 |
17
   | If you did not receive a copy of the PHP license and are unable to   |
18
   | obtain it through the world-wide-web, please send a note to          |
19
   | license@php.net so we can mail you a copy immediately.               |
20
   +----------------------------------------------------------------------+
21
   | Authors: Ilia Alshanetsky <iliaa@php.net>                            |
22
   |          Preston L. Bannister <pbannister@php.net>                   |
23
   |          Marcus Boerger <helly@php.net>                              |
24
   |          Derick Rethans <derick@php.net>                             |
25
   |          Sander Roobol <sander@php.net>                              |
26
   | (based on version by: Stig Bakken <ssb@fast.no>)                     |
27
   | (based on the PHP 3 test framework by Rasmus Lerdorf)                |
28
   +----------------------------------------------------------------------+
29
 */
30
 
31
/*
32
	Require exact specification of PHP executable to test (no guessing!).
33
	Die if any internal errors encountered in test script.
34
	Regularized output for simpler post-processing of output.
35
	Optionally output error lines indicating the failing test source and log
36
	for direct jump with MSVC or Emacs.
37
*/
38
 
39
/*
40
 * TODO:
41
 * - do not test PEAR components if base class and/or component class cannot be instanciated
42
 */
43
 
44
 
45
/* Sanity check to ensure that pcre extension needed by this script is avaliable.
46
 * In the event it is not, print a nice error message indicating that this script will
47
 * not run without it.
48
 */
49
 
50
if (!extension_loaded("pcre")) {
51
	echo <<<NO_PCRE_ERROR
52
 
53
+-----------------------------------------------------------+
54
|                       ! ERROR !                           |
55
| The test-suite requires that you have pcre extension      |
56
| enabled. To enable this extension either compile your PHP |
57
| with --with-pcre-regex or if you've compiled pcre as a    |
58
| shared module load it via php.ini.                        |
59
+-----------------------------------------------------------+
60
 
61
NO_PCRE_ERROR;
62
exit;
63
}
64
 
65
// change into the PHP source directory.
66
 
67
if (getenv('TEST_PHP_SRCDIR')) {
68
	@chdir(getenv('TEST_PHP_SRCDIR'));
69
}
70
 
71
$cwd = getcwd();
72
set_time_limit(0);
73
 
74
// delete as much output buffers as possible
75
while(@ob_end_clean());
76
if (ob_get_level()) echo "Not all buffers were deleted.\n";
77
 
78
error_reporting(E_ALL);
79
ini_set('magic_quotes_runtime',0); // this would break tests by modifying EXPECT sections
80
 
81
if (ini_get('safe_mode')) {
82
	echo <<< SAFE_MODE_WARNING
83
 
84
+-----------------------------------------------------------+
85
|                       ! WARNING !                         |
86
| You are running the test-suite with "safe_mode" ENABLED ! |
87
|                                                           |
88
| Chances are high that no test will work at all,           |
89
| depending on how you configured "safe_mode" !             |
90
+-----------------------------------------------------------+
91
 
92
 
93
SAFE_MODE_WARNING;
94
}
95
 
96
// Don't ever guess at the PHP executable location.
97
// Require the explicit specification.
98
// Otherwise we could end up testing the wrong file!
99
 
100
if (getenv('TEST_PHP_EXECUTABLE')) {
101
	$php = getenv('TEST_PHP_EXECUTABLE');
102
	if ($php=='auto') {
103
		$php = $cwd.'/sapi/cli/php';
104
		putenv("TEST_PHP_EXECUTABLE=$php");
105
	}
106
}
107
if (empty($php) || !file_exists($php)) {
108
	error("environment variable TEST_PHP_EXECUTABLE must be set to specify PHP executable!");
109
}
110
 
111
global $log_format, $cwd;
112
if (getenv('TEST_PHP_LOG_FORMAT')) {
113
	$log_format = strtoupper(getenv('TEST_PHP_LOG_FORMAT'));
114
} else {
115
	$log_format = 'LEOD';
116
}
117
 
118
if (function_exists('is_executable') && !@is_executable($php)) {
119
	error("invalid PHP executable specified by TEST_PHP_EXECUTABLE  = " . $php);
120
}
121
 
122
// Check whether a detailed log is wanted.
123
if (getenv('TEST_PHP_DETAILED')) {
124
	define('DETAILED', getenv('TEST_PHP_DETAILED'));
125
} else {
126
	define('DETAILED', 0);
127
}
128
 
129
// Check whether user test dirs are requested.
130
if (getenv('TEST_PHP_USER')) {
131
	$user_tests = explode (',', getenv('TEST_PHP_USER'));
132
} else {
133
	$user_tests = array();
134
}
135
 
136
global $info_file;
137
// Get info from php
138
$info_file = realpath(dirname(__FILE__)) . '/run-test-info.php';
139
@unlink($info_file);
140
global $php_info;
141
$php_info = '<?php echo "
142
PHP_SAPI    : " . PHP_SAPI . "
143
PHP_VERSION : " . phpversion() . "
144
ZEND_VERSION: " . zend_version() . "
145
PHP_OS      : " . PHP_OS . " - " . php_uname() . "
146
INI actual  : " . realpath(get_cfg_var("cfg_file_path")) . "
147
More .INIs  : " . (function_exists(\'php_ini_scanned_files\') ? str_replace("\n","", php_ini_scanned_files()) : "** not determined **"); ?>';
148
save_text($info_file, $php_info);
149
global $ini_overwrites;
150
$ini_overwrites = array(
151
		'mbstring.script_encoding=pass',
152
		'output_handler=',
153
		'zlib.output_compression=Off',
154
		'open_basedir=',
155
		'safe_mode=0',
156
		'disable_functions=',
157
		'output_buffering=Off',
158
		'error_reporting=2047',
159
		'display_errors=1',
160
		'log_errors=0',
161
		'html_errors=0',
162
		'track_errors=1',
163
		'report_memleaks=1',
164
		'docref_root=/phpmanual/',
165
		'docref_ext=.html',
166
		'error_prepend_string=',
167
		'error_append_string=',
168
		'auto_prepend_file=',
169
		'auto_append_file=',
170
		'magic_quotes_runtime=0',
171
	);
172
global $info_params;
173
$info_params = array();
174
settings2array($ini_overwrites,$info_params);
175
$save = $info_params;
176
settings2paramsnoquotes($info_params);
177
$curdir = getcwd();
178
chdir(dirname($info_file));
179
$info_filename = basename($info_file);
180
$php_info = `"$php" $info_params $info_filename`;
181
chdir($curdir);
182
@unlink($info_file);
183
//$info_params = $save;
184
//settings2params($info_params);
185
define('TESTED_PHP_VERSION', `"$php" -r 'echo PHP_VERSION;'`);
186
 
187
// Write test context information.
188
 
189
echo "
190
=====================================================================
191
CWD         : $cwd
192
PHP         : $php $php_info
193
Extra dirs  : ";
194
foreach ($user_tests as $test_dir) {
195
	echo "{$test_dir}\n              ";
196
}
197
echo "
198
=====================================================================
199
";
200
 
201
// Determine the tests to be run.
202
global $test_files, $test_results;
203
$test_files = array();
204
$test_results = array();
205
$GLOBALS['__PHP_FAILED_TESTS__'] = array();
206
 
207
// If parameters given assume they represent selected tests to run.
208
if (isset($argc) && $argc > 1) {
209
	for ($i=1; $i<$argc; $i++) {
210
		$testfile = realpath($argv[$i]);
211
		if (is_dir($testfile)) {
212
			find_files($testfile);
213
		} else if (preg_match("/\.phpt$/", $testfile)) {
214
			$test_files[] = $testfile;
215
		}
216
	}
217
	$test_files = array_unique($test_files);
218
 
219
	// Run selected tests.
220
	if (count($test_files)) {
221
		usort($test_files, "test_sort");
222
		echo "Running selected tests.\n";
223
		foreach($test_files AS $name) {
224
			$test_results[$name] = run_test($php,$name);
225
		}
226
		if (getenv('REPORT_EXIT_STATUS') == 1 and @ereg('FAILED( |$)', implode(' ', $test_results))) {
227
			exit(1);
228
		}
229
		exit(0);
230
	}
231
}
232
 
233
// Compile a list of all test files (*.phpt).
234
$test_files = array();
235
$exts_to_test = get_loaded_extensions();
236
$exts_tested = count($exts_to_test);
237
$exts_skipped = 0;
238
$ignored_by_ext = 0;
239
sort($exts_to_test);
240
$test_dirs = array('tests', 'pear', 'ext');
241
 
242
foreach ($test_dirs as $dir) {
243
	find_files("{$cwd}/{$dir}", ($dir == 'ext'));
244
}
245
 
246
foreach ($user_tests as $dir) {
247
	find_files($dir, ($dir == 'ext'));
248
}
249
 
250
function find_files($dir,$is_ext_dir=FALSE,$ignore=FALSE)
251
{
252
    print($dir . "\n");
253
	global $test_files, $exts_to_test, $ignored_by_ext, $exts_skipped, $exts_tested;
254
 
255
	$o = opendir($dir) or error("cannot open directory: $dir");
256
	while (($name = readdir($o)) !== FALSE) {
257
		if (is_dir("{$dir}/{$name}") && !in_array($name, array('.', '..', 'CVS'))) {
258
			$skip_ext = ($is_ext_dir && !in_array($name, $exts_to_test));
259
			if ($skip_ext) {
260
				$exts_skipped++;
261
			}
262
			find_files("{$dir}/{$name}", FALSE, $ignore || $skip_ext);
263
		}
264
 
265
		// Cleanup any left-over tmp files from last run.
266
		if (substr($name, -4) == '.tmp') {
267
			@unlink("$dir/$name");
268
			continue;
269
		}
270
 
271
		// Otherwise we're only interested in *.phpt files.
272
		if (substr($name, -5) == '.phpt') {
273
			if ($ignore) {
274
				$ignored_by_ext++;
275
			} else {
276
				$testfile = realpath("{$dir}/{$name}");
277
				$test_files[] = $testfile;
278
			}
279
		}
280
	}
281
	closedir($o);
282
}
283
 
284
function test_sort($a, $b) {
285
	global $cwd;
286
 
287
	$ta = strpos($a, "{$cwd}/tests")===0 ? 1 + (strpos($a, "{$cwd}/tests/run-test")===0 ? 1 : 0) : 0;
288
	$tb = strpos($b, "{$cwd}/tests")===0 ? 1 + (strpos($b, "{$cwd}/tests/run-test")===0 ? 1 : 0) : 0;
289
	if ($ta == $tb) {
290
		return strcmp($a, $b);
291
	} else {
292
		return $tb - $ta;
293
	}
294
}
295
 
296
$test_files = array_unique($test_files);
297
usort($test_files, "test_sort");
298
 
299
$start_time = time();
300
 
301
echo "TIME START " . date('Y-m-d H:i:s', $start_time) . "
302
=====================================================================
303
";
304
 
305
foreach ($test_files as $name) {
306
	$test_results[$name] = run_test($php,$name);
307
}
308
 
309
$end_time = time();
310
 
311
// Summarize results
312
 
313
if (0 == count($test_results)) {
314
	echo "No tests were run.\n";
315
	return;
316
}
317
 
318
$n_total = count($test_results);
319
$n_total += $ignored_by_ext;
320
 
321
$sum_results = array('PASSED'=>0, 'WARNED'=>0, 'SKIPPED'=>0, 'FAILED'=>0);
322
foreach ($test_results as $v) {
323
	$sum_results[$v]++;
324
}
325
$sum_results['SKIPPED'] += $ignored_by_ext;
326
$percent_results = array();
327
while (list($v,$n) = each($sum_results)) {
328
	$percent_results[$v] = (100.0 * $n) / $n_total;
329
}
330
 
331
echo "
332
=====================================================================
333
TIME END " . date('Y-m-d H:i:s', $end_time);
334
 
335
$summary = "
336
=====================================================================
337
TEST RESULT SUMMARY
338
---------------------------------------------------------------------
339
Exts skipped    : " . sprintf("%4d",$exts_skipped) . "
340
Exts tested     : " . sprintf("%4d",$exts_tested) . "
341
---------------------------------------------------------------------
342
Number of tests : " . sprintf("%4d",$n_total) . "
343
Tests skipped   : " . sprintf("%4d (%2.1f%%)",$sum_results['SKIPPED'],$percent_results['SKIPPED']) . "
344
Tests warned    : " . sprintf("%4d (%2.1f%%)",$sum_results['WARNED'],$percent_results['WARNED']) . "
345
Tests failed    : " . sprintf("%4d (%2.1f%%)",$sum_results['FAILED'],$percent_results['FAILED']) . "
346
Tests passed    : " . sprintf("%4d (%2.1f%%)",$sum_results['PASSED'],$percent_results['PASSED']) . "
347
---------------------------------------------------------------------
348
Time taken      : " . sprintf("%4d seconds", $end_time - $start_time) . "
349
=====================================================================
350
";
351
echo $summary;
352
 
353
$failed_test_summary = '';
354
if (count($GLOBALS['__PHP_FAILED_TESTS__'])) {
355
	$failed_test_summary .= "
356
=====================================================================
357
FAILED TEST SUMMARY
358
---------------------------------------------------------------------
359
";
360
	foreach ($GLOBALS['__PHP_FAILED_TESTS__'] as $failed_test_data) {
361
		$failed_test_summary .=  $failed_test_data['test_name'] . $failed_test_data['info'] . "\n";
362
	}
363
	$failed_test_summary .=  "=====================================================================\n";
364
}
365
 
366
if ($failed_test_summary && !getenv('NO_PHPTEST_SUMMARY')) {
367
	echo $failed_test_summary;
368
}
369
 
370
define('PHP_QA_EMAIL', 'php-qa@lists.php.net');
371
define('QA_SUBMISSION_PAGE', 'http://qa.php.net/buildtest-process.php');
372
 
373
/* We got failed Tests, offer the user to send and e-mail to QA team, unless NO_INTERACTION is set */
374
if (!getenv('NO_INTERACTION')) {
375
	$fp = fopen("php://stdin", "r+");
376
	echo "\nPlease allow this report to be sent to the PHP QA\nteam. This will give us a better understanding in how\n";
377
	echo "PHP's test cases are doing.  Note that the report will include\ndetailed configuration data about your system\n";
378
	echo "so if you are worried about exposing sensitive data,\nsave this to a file first and remove any sensitive data\n";
379
	echo "and then send this file to php-qa@lists.php.net.\n";
380
	echo "(choose \"s\" to just save the results to a file)? [Yns]: ";
381
	flush();
382
	$user_input = fgets($fp, 10);
383
	$just_save_results = (strtolower($user_input[0]) == 's');
384
 
385
	if ($just_save_results || strlen(trim($user_input)) == 0 || strtolower($user_input[0]) == 'y') {
386
		/*
387
		 * Collect information about the host system for our report
388
		 * Fetch phpinfo() output so that we can see the PHP enviroment
389
		 * Make an archive of all the failed tests
390
		 * Send an email
391
		 */
392
 
393
		/* Ask the user to provide an email address, so that QA team can contact the user */
394
		if (!strncasecmp($user_input, 'y', 1) || strlen(trim($user_input)) == 0) {
395
			echo "\nPlease enter your email address.\n(You address will be mangled so that it will not go out on any\nmailinglist in plain text): ";
396
			flush();
397
			$fp = fopen("php://stdin", "r+");
398
			$user_email = trim(fgets($fp, 1024));
399
			$user_email = str_replace("@", " at ", str_replace(".", " dot ", $user_email));
400
		}
401
 
402
		$failed_tests_data = '';
403
		$sep = "\n" . str_repeat('=', 80) . "\n";
404
 
405
		$failed_tests_data .= $failed_test_summary . "\n";
406
		$failed_tests_data .= $summary . "\n";
407
 
408
		if ($sum_results['FAILED']) {
409
			foreach ($GLOBALS['__PHP_FAILED_TESTS__'] as $test_info) {
410
				$failed_tests_data .= $sep . $test_info['name'] . $test_info['info'];
411
				$failed_tests_data .= $sep . file_get_contents(realpath($test_info['output']));
412
				$failed_tests_data .= $sep . file_get_contents(realpath($test_info['diff']));
413
				$failed_tests_data .= $sep . "\n\n";
414
			}
415
			$status = "failed";
416
		} else {
417
			$status = "success";
418
		}
419
 
420
		$failed_tests_data .= "\n" . $sep . 'BUILD ENVIRONMENT' . $sep;
421
		$failed_tests_data .= "OS:\n" . PHP_OS . " - " . php_uname() . "\n\n";
422
		$ldd = $automake = $autoconf = $libtool = $compiler = 'N/A';
423
 
424
		if (substr(PHP_OS, 0, 3) != "WIN") {
425
			$automake = shell_exec('automake --version');
426
			$autoconf = shell_exec('autoconf --version');
427
			/* Always use the generated libtool - Mac OSX uses 'glibtool' */
428
			$libtool = shell_exec('./libtool --version');
429
			/* Try the most common flags for 'version' */
430
			$flags = array('-v', '-V', '--version');
431
			$cc_status=0;
432
			foreach($flags AS $flag) {
433
				system(getenv('CC')." $flag >/dev/null 2>&1", $cc_status);
434
				if ($cc_status == 0) {
435
					$compiler = shell_exec(getenv('CC')." $flag 2>&1");
436
					break;
437
				}
438
			}
439
			$ldd = shell_exec("ldd $php");
440
		}
441
		$failed_tests_data .= "Automake:\n$automake\n";
442
		$failed_tests_data .= "Autoconf:\n$autoconf\n";
443
		$failed_tests_data .= "Libtool:\n$libtool\n";
444
		$failed_tests_data .= "Compiler:\n$compiler\n";
445
		$failed_tests_data .= "Bison:\n". @shell_exec('bison --version'). "\n";
446
		$failed_tests_data .= "Libraries:\n$ldd\n";
447
		$failed_tests_data .= "\n";
448
 
449
		if (isset($user_email)) {
450
			$failed_tests_data .= "User's E-mail: ".$user_email."\n\n";
451
		}
452
 
453
		$failed_tests_data .= $sep . "PHPINFO" . $sep;
454
		$failed_tests_data .= shell_exec($php.' -dhtml_errors=0 -i');
455
 
456
		$compression = 0;
457
 
458
		if ($just_save_results || !mail_qa_team($failed_tests_data, $compression, $status)) {
459
			$output_file = 'php_test_results_' . date('Ymd') . ( $compression ? '.txt.gz' : '.txt' );
460
			$fp = fopen($output_file, "w");
461
			fwrite($fp, $failed_tests_data);
462
			fclose($fp);
463
 
464
			if (!$just_save_results) {
465
			    echo "\nThe test script was unable to automatically send the report to PHP's QA Team\n";
466
			}
467
 
468
			echo "Please send ".$output_file." to ".PHP_QA_EMAIL." manually, thank you.\n";
469
		} else {
470
			fwrite($fp, "\nThank you for helping to make PHP better.\n");
471
			fclose($fp);
472
		}
473
	}
474
}
475
 
476
if (getenv('REPORT_EXIT_STATUS') == 1 and $sum_results['FAILED']) {
477
	exit(1);
478
}
479
 
480
//
481
// Send Email to QA Team
482
//
483
 
484
function mail_qa_team($data, $compression, $status = FALSE)
485
{
486
	$url_bits = parse_url(QA_SUBMISSION_PAGE);
487
	if (empty($url_bits['port'])) $url_bits['port'] = 80;
488
 
489
	$data = "php_test_data=" . urlencode(base64_encode(preg_replace("/[\\x00]/", "[0x0]", $data)));
490
	$data_length = strlen($data);
491
 
492
	$fs = fsockopen($url_bits['host'], $url_bits['port'], $errno, $errstr, 10);
493
	if (!$fs) {
494
		return FALSE;
495
	}
496
 
497
	$php_version = urlencode(TESTED_PHP_VERSION);
498
 
499
	echo "\nPosting to {$url_bits['host']} {$url_bits['path']}\n";
500
	fwrite($fs, "POST ".$url_bits['path']."?status=$status&version=$php_version HTTP/1.1\r\n");
501
	fwrite($fs, "Host: ".$url_bits['host']."\r\n");
502
	fwrite($fs, "User-Agent: QA Browser 0.1\r\n");
503
	fwrite($fs, "Content-Type: application/x-www-form-urlencoded\r\n");
504
	fwrite($fs, "Content-Length: ".$data_length."\r\n\r\n");
505
	fwrite($fs, $data);
506
	fwrite($fs, "\r\n\r\n");
507
	fclose($fs);
508
 
509
	return 1;
510
}
511
 
512
 
513
//
514
//  Write the given text to a temporary file, and return the filename.
515
//
516
 
517
function save_text($filename,$text)
518
{
519
	$fp = @fopen($filename,'w') or error("Cannot open file '" . $filename . "' (save_text)");
520
	fwrite($fp,$text);
521
	fclose($fp);
522
	if (1 < DETAILED) echo "
523
FILE $filename {{{
524
$text
525
}}}
526
";
527
}
528
 
529
//
530
//  Write an error in a format recognizable to Emacs or MSVC.
531
//
532
 
533
function error_report($testname,$logname,$tested)
534
{
535
	$testname = realpath($testname);
536
	$logname  = realpath($logname);
537
	switch (strtoupper(getenv('TEST_PHP_ERROR_STYLE'))) {
538
	case 'MSVC':
539
		echo $testname . "(1) : $tested\n";
540
		echo $logname . "(1) :  $tested\n";
541
		break;
542
	case 'EMACS':
543
		echo $testname . ":1: $tested\n";
544
		echo $logname . ":1:  $tested\n";
545
		break;
546
	}
547
}
548
 
549
//
550
//  Run an individual test case.
551
//
552
 
553
function run_test($php,$file)
554
{
555
	global $log_format, $info_params, $ini_overwrites;
556
 
557
	if (DETAILED) echo "
558
=================
559
TEST $file
560
";
561
 
562
	// Load the sections of the test file.
563
	$section_text = array(
564
		'TEST'   => '(unnamed test)',
565
		'SKIPIF' => '',
566
		'GET'    => '',
567
		'ARGS'   => '',
568
	);
569
 
570
	$fp = @fopen($file, "r") or error("Cannot open test file: $file");
571
 
572
	$section = '';
573
	while (!feof($fp)) {
574
		$line = fgets($fp);
575
 
576
		// Match the beginning of a section.
577
		if (@ereg('^--([A-Z]+)--',$line,$r)) {
578
			$section = $r[1];
579
			$section_text[$section] = '';
580
			continue;
581
		}
582
 
583
		// Add to the section text.
584
		$section_text[$section] .= $line;
585
	}
586
	fclose($fp);
587
 
588
	/* For GET/POST tests, check if cgi sapi is avaliable and if it is, use it. */
589
	if ((!empty($section_text['GET']) || !empty($section_text['POST']))) {
590
		if (file_exists("./sapi/cgi/php")) {
591
			$old_php = $php;
592
			$php = realpath("./sapi/cgi/php") . ' -C ';
593
		}
594
	}
595
 
596
	$shortname = str_replace($GLOBALS['cwd'].'/', '', $file);
597
	$tested = trim($section_text['TEST'])." [$shortname]";
598
 
599
	$tmp = realpath(dirname($file));
600
    if (!is_dir($tmp)) {
601
        $tmp = dirname($file);
602
    }
603
	$tmp_skipif = $tmp . uniqid('/phpt.');
604
	$tmp_file   = @ereg_replace('\.phpt$','.php',$file);
605
	$tmp_post   = $tmp . uniqid('/phpt.');
606
 
607
	@unlink($tmp_skipif);
608
	@unlink($tmp_file);
609
	@unlink($tmp_post);
610
 
611
	// unlink old test results
612
	@unlink(@ereg_replace('\.phpt$','.diff',$file));
613
	@unlink(@ereg_replace('\.phpt$','.log',$file));
614
	@unlink(@ereg_replace('\.phpt$','.exp',$file));
615
	@unlink(@ereg_replace('\.phpt$','.out',$file));
616
 
617
	// Reset environment from any previous test.
618
	putenv("REDIRECT_STATUS=");
619
	putenv("QUERY_STRING=");
620
	putenv("PATH_TRANSLATED=");
621
	putenv("SCRIPT_FILENAME=");
622
	putenv("REQUEST_METHOD=");
623
	putenv("CONTENT_TYPE=");
624
	putenv("CONTENT_LENGTH=");
625
 
626
	// Check if test should be skipped.
627
	$info = '';
628
	$warn = false;
629
	if (array_key_exists('SKIPIF', $section_text)) {
630
		if (trim($section_text['SKIPIF'])) {
631
			save_text($tmp_skipif, $section_text['SKIPIF']);
632
 
633
            $curdir = getcwd();
634
            chdir(dirname($tmp_skipif));
635
            $t_s = basename($tmp_skipif);
636
			$output = `"$php" $info_params -f $t_s`;
637
            chdir($curdir);
638
			@unlink($tmp_skipif);
639
			if (@eregi("^skip", trim($output))) {
640
				echo "SKIP $tested";
641
				$reason = (@eregi("^skip[[:space:]]*(.+)\$", trim($output))) ? @eregi_replace("^skip[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE;
642
				if ($reason) {
643
					echo " (reason: $reason)\n";
644
				} else {
645
					echo "\n";
646
				}
647
				if (isset($old_php)) {
648
					$php = $old_php;
649
				}
650
				return 'SKIPPED';
651
			}
652
			if (@eregi("^info", trim($output))) {
653
				$reason = (@ereg("^info[[:space:]]*(.+)\$", trim($output))) ? @ereg_replace("^info[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE;
654
				if ($reason) {
655
					$info = " (info: $reason)";
656
				}
657
			}
658
			if (@eregi("^warn", trim($output))) {
659
				$reason = (@ereg("^warn[[:space:]]*(.+)\$", trim($output))) ? @ereg_replace("^warn[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE;
660
				if ($reason) {
661
					$warn = true; /* only if there is a reason */
662
					$info = " (warn: $reason)";
663
				}
664
			}
665
		}
666
	}
667
 
668
	// Default ini settings
669
	$ini_settings = array();
670
	// additional ini overwrites
671
	//$ini_overwrites[] = 'setting=value';
672
	settings2array($ini_overwrites, $ini_settings);
673
 
674
	// Any special ini settings
675
	// these may overwrite the test defaults...
676
	if (array_key_exists('INI', $section_text)) {
677
		settings2array(preg_split( "/[\n\r]+/", $section_text['INI']), $ini_settings);
678
	}
679
	settings2paramsnoquotes($ini_settings);
680
 
681
	// We've satisfied the preconditions - run the test!
682
	save_text($tmp_file,$section_text['FILE']);
683
	if (array_key_exists('GET', $section_text)) {
684
		$query_string = trim($section_text['GET']);
685
	} else {
686
		$query_string = '';
687
	}
688
 
689
	putenv("REDIRECT_STATUS=1");
690
	putenv("QUERY_STRING=$query_string");
691
	putenv("PATH_TRANSLATED=$tmp_file");
692
	putenv("SCRIPT_FILENAME=$tmp_file");
693
 
694
	$args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : '';
695
 
696
	if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
697
 
698
		$post = trim($section_text['POST']);
699
		save_text($tmp_post,$post);
700
		$content_length = strlen($post);
701
 
702
		putenv("REQUEST_METHOD=POST");
703
		putenv("CONTENT_TYPE=application/x-www-form-urlencoded");
704
		putenv("CONTENT_LENGTH=$content_length");
705
 
706
		$cmd = "\"$php\"$ini_settings -f $tmp_file 2>&1 < \"$tmp_post\"";
707
 
708
	} else {
709
 
710
		putenv("REQUEST_METHOD=GET");
711
		putenv("CONTENT_TYPE=");
712
		putenv("CONTENT_LENGTH=");
713
 
714
		$cmd = "\"$php\"$ini_settings -f $tmp_file$args 2>&1";
715
	}
716
 
717
	if (DETAILED) echo "
718
CONTENT_LENGTH  = " . getenv("CONTENT_LENGTH") . "
719
CONTENT_TYPE    = " . getenv("CONTENT_TYPE") . "
720
PATH_TRANSLATED = " . getenv("PATH_TRANSLATED") . "
721
QUERY_STRING    = " . getenv("QUERY_STRING") . "
722
REDIRECT_STATUS = " . getenv("REDIRECT_STATUS") . "
723
REQUEST_METHOD  = " . getenv("REQUEST_METHOD") . "
724
SCRIPT_FILENAME = " . getenv("SCRIPT_FILENAME") . "
725
COMMAND $cmd
726
";
727
 
728
	$out = `$cmd`;
729
 
730
	@unlink($tmp_post);
731
 
732
	// Does the output match what is expected?
733
	$output = trim($out);
734
	$output = preg_replace('/\r\n/',"\n",$output);
735
 
736
	/* when using CGI, strip the headers from the output */
737
	if (isset($old_php) && ($pos = strpos($output, "\n\n")) !== FALSE) {
738
		$output = substr($output, ($pos + 2));
739
	}
740
 
741
	if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) {
742
		if (isset($section_text['EXPECTF'])) {
743
			$wanted = trim($section_text['EXPECTF']);
744
		} else {
745
			$wanted = trim($section_text['EXPECTREGEX']);
746
		}
747
		$wanted_re = preg_replace('/\r\n/',"\n",$wanted);
748
		if (isset($section_text['EXPECTF'])) {
749
			$wanted_re = preg_quote($wanted_re, '/');
750
			// Stick to basics
751
			$wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy
752
			$wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re);
753
			$wanted_re = str_replace("%d", "[0-9]+", $wanted_re);
754
			$wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re);
755
			$wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re);
756
			$wanted_re = str_replace("%c", ".", $wanted_re);
757
			// %f allows two points "-.0.0" but that is the best *simple* expression
758
		}
759
/* DEBUG YOUR REGEX HERE
760
		var_dump($wanted_re);
761
		print(str_repeat('=', 80) . "\n");
762
		var_dump($output);
763
*/
764
		if (preg_match("/^$wanted_re\$/s", $output)) {
765
			@unlink($tmp_file);
766
			echo "PASS $tested$info\n";
767
			if (isset($old_php)) {
768
				$php = $old_php;
769
			}
770
			return 'PASSED';
771
		}
772
 
773
	} else {
774
		$wanted = trim($section_text['EXPECT']);
775
		$wanted = preg_replace('/\r\n/',"\n",$wanted);
776
	// compare and leave on success
777
		$ok = (0 == strcmp($output,$wanted));
778
		if ($ok) {
779
			@unlink($tmp_file);
780
			echo "PASS $tested$info\n";
781
			if (isset($old_php)) {
782
				$php = $old_php;
783
			}
784
			return 'PASSED';
785
		}
786
	}
787
 
788
	// Test failed so we need to report details.
789
	if ($warn) {
790
		echo "WARN $tested$info\n";
791
	} else {
792
		echo "FAIL $tested$info\n";
793
	}
794
 
795
	$GLOBALS['__PHP_FAILED_TESTS__'][] = array(
796
						'name' => $file,
797
						'test_name' => $tested,
798
						'output' => @ereg_replace('\.phpt$','.log', $file),
799
						'diff'   => @ereg_replace('\.phpt$','.diff', $file),
800
						'info'   => $info
801
						);
802
 
803
	// write .exp
804
	if (strpos($log_format,'E') !== FALSE) {
805
		$logname = @ereg_replace('\.phpt$','.exp',$file);
806
		$log = fopen($logname,'w') or error("Cannot create test log - $logname");
807
		fwrite($log,$wanted);
808
		fclose($log);
809
	}
810
 
811
	// write .out
812
	if (strpos($log_format,'O') !== FALSE) {
813
		$logname = @ereg_replace('\.phpt$','.out',$file);
814
		$log = fopen($logname,'w') or error("Cannot create test log - $logname");
815
		fwrite($log,$output);
816
		fclose($log);
817
	}
818
 
819
	// write .diff
820
	if (strpos($log_format,'D') !== FALSE) {
821
		$logname = @ereg_replace('\.phpt$','.diff',$file);
822
		$log = fopen($logname,'w') or error("Cannot create test log - $logname");
823
		fwrite($log,generate_diff($wanted,$output));
824
		fclose($log);
825
	}
826
 
827
	// write .log
828
	if (strpos($log_format,'L') !== FALSE) {
829
		$logname = @ereg_replace('\.phpt$','.log',$file);
830
		$log = fopen($logname,'w') or error("Cannot create test log - $logname");
831
		fwrite($log,"
832
---- EXPECTED OUTPUT
833
$wanted
834
---- ACTUAL OUTPUT
835
$output
836
---- FAILED
837
");
838
		fclose($log);
839
		error_report($file,$logname,$tested);
840
	}
841
 
842
	if (isset($old_php)) {
843
		$php = $old_php;
844
	}
845
 
846
	return $warn ? 'WARNED' : 'FAILED';
847
}
848
 
849
function generate_diff($wanted,$output)
850
{
851
	$w = explode("\n", $wanted);
852
	$o = explode("\n", $output);
853
	$w1 = array_diff_assoc($w,$o);
854
	$o1 = array_diff_assoc($o,$w);
855
	$w2 = array();
856
	$o2 = array();
857
	foreach($w1 as $idx => $val) $w2[sprintf("%03d<",$idx)] = sprintf("%03d- ", $idx+1).$val;
858
	foreach($o1 as $idx => $val) $o2[sprintf("%03d>",$idx)] = sprintf("%03d+ ", $idx+1).$val;
859
	$diff = array_merge($w2, $o2);
860
	ksort($diff);
861
	return implode("\r\n", $diff);
862
}
863
 
864
function error($message)
865
{
866
	echo "ERROR: {$message}\n";
867
	exit(1);
868
}
869
 
870
function settings2array($settings, &$ini_settings)
871
{
872
	foreach($settings as $setting) {
873
		if (strpos($setting, '=')!==false) {
874
			$setting = explode("=", $setting, 2);
875
			$name = trim(strtolower($setting[0]));
876
			$value = trim($setting[1]);
877
			$ini_settings[$name] = $value;
878
		}
879
	}
880
}
881
 
882
function settings2params(&$ini_settings)
883
{
884
	if (count($ini_settings)) {
885
		$settings = '';
886
		foreach($ini_settings as $name => $value) {
887
			$value = addslashes($value);
888
			$settings .= " -d \"$name=$value\"";
889
		}
890
		$ini_settings = $settings;
891
	} else {
892
		$ini_settings = '';
893
	}
894
}
895
 
896
function settings2paramsnoquotes(&$ini_settings)
897
{
898
	if (count($ini_settings)) {
899
		$settings = '';
900
		foreach($ini_settings as $name => $value) {
901
			$value = addslashes($value);
902
			$settings .= " -d $name=$value";
903
		}
904
		$ini_settings = $settings;
905
	} else {
906
		$ini_settings = '';
907
	}
908
}
909
 
910
/*
911
 * Local variables:
912
 * tab-width: 4
913
 * c-basic-offset: 4
914
 * End:
915
 * vim600: fdm=marker
916
 * vim: noet sw=4 ts=4
917
 */
918
?>