Subversion Repositories Applications.gtt

Rev

Rev 94 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
94 jpm 1
<?php
2
/**
3
 * PEAR_RunTest
4
 *
5
 * PHP versions 4 and 5
6
 *
7
 * LICENSE: This source file is subject to version 3.0 of the PHP license
8
 * that is available through the world-wide-web at the following URI:
9
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
10
 * the PHP License and are unable to obtain it through the web, please
11
 * send a note to license@php.net so we can mail you a copy immediately.
12
 *
13
 * @category   pear
14
 * @package    PEAR
15
 * @author     Tomas V.V.Cox <cox@idecnet.com>
16
 * @author     Greg Beaver <cellog@php.net>
17
 * @copyright  1997-2006 The PHP Group
18
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
19
 * @version    CVS: $Id: RunTest.php,v 1.34 2007/02/17 19:57:56 cellog Exp $
20
 * @link       http://pear.php.net/package/PEAR
21
 * @since      File available since Release 1.3.3
22
 */
23
 
24
/**
25
 * for error handling
26
 */
27
require_once 'PEAR.php';
28
require_once 'PEAR/Config.php';
29
 
30
define('DETAILED', 1);
31
putenv("PHP_PEAR_RUNTESTS=1");
32
 
33
/**
34
 * Simplified version of PHP's test suite
35
 *
36
 * Try it with:
37
 *
38
 * $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);'
39
 *
40
 *
41
 * @category   pear
42
 * @package    PEAR
43
 * @author     Tomas V.V.Cox <cox@idecnet.com>
44
 * @author     Greg Beaver <cellog@php.net>
45
 * @copyright  1997-2006 The PHP Group
46
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
47
 * @version    Release: 1.5.1
48
 * @link       http://pear.php.net/package/PEAR
49
 * @since      Class available since Release 1.3.3
50
 */
51
class PEAR_RunTest
52
{
53
    var $_logger;
54
    var $_options;
55
    var $ini_overwrites = array(
56
        'output_handler=',
57
        'open_basedir=',
58
        'safe_mode=0',
59
        'disable_functions=',
60
        'output_buffering=Off',
61
        'error_reporting=E_ALL',
62
        'display_errors=1',
63
        'log_errors=0',
64
        'html_errors=0',
65
        'track_errors=1',
66
        'report_memleaks=1',
67
        'report_zend_debug=0',
68
        'docref_root=',
69
        'docref_ext=.html',
70
        'error_prepend_string=',
71
        'error_append_string=',
72
        'auto_prepend_file=',
73
        'auto_append_file=',
74
        'magic_quotes_runtime=0',
75
    );
76
 
77
 
78
    /**
79
     * An object that supports the PEAR_Common->log() signature, or null
80
     * @param PEAR_Common|null
81
     */
82
    function PEAR_RunTest($logger = null, $options = array())
83
    {
84
        if (is_null($logger)) {
85
            require_once 'PEAR/Common.php';
86
            $logger = new PEAR_Common;
87
        }
88
        $this->_logger = $logger;
89
        $this->_options = $options;
90
    }
91
 
92
    /**
93
     * Taken from php-src/run-tests.php
94
     *
95
     * @param string $commandline command name
96
     * @param array $env
97
     * @param string $stdin standard input to pass to the command
98
     * @return unknown
99
     */
100
    function system_with_timeout($commandline, $env = null, $stdin = null)
101
    {
102
        $data = '';
103
 
104
        if (version_compare(phpversion(), '5.0.0', '<')) {
105
            $proc = proc_open($commandline, array(
106
 
107
                1 => array('pipe', 'w'),
108
                2 => array('pipe', 'w')
109
                ), $pipes);
110
        } else {
111
            $proc = proc_open($commandline, array(
112
 
113
                1 => array('pipe', 'w'),
114
                2 => array('pipe', 'w')
115
                ), $pipes, null, $env, array("suppress_errors" => true));
116
        }
117
 
118
        if (!$proc) {
119
            return false;
120
        }
121
 
122
        if (is_string($stdin)) {
123
            fwrite($pipes[0], $stdin);
124
        }
125
        fclose($pipes[0]);
126
 
127
        while (true) {
128
            /* hide errors from interrupted syscalls */
129
            $r = $pipes;
130
            $w = null;
131
            $e = null;
132
            $n = @stream_select($r, $w, $e, 60);
133
 
134
            if ($n === 0) {
135
                /* timed out */
136
                $data .= "\n ** ERROR: process timed out **\n";
137
                proc_terminate($proc);
138
                return array(1234567890, $data);
139
            } else if ($n > 0) {
140
                $line = fread($pipes[1], 8192);
141
                if (strlen($line) == 0) {
142
                    /* EOF */
143
                    break;
144
                }
145
                $data .= $line;
146
            }
147
        }
148
        if (function_exists('proc_get_status')) {
149
            $stat = proc_get_status($proc);
150
            if ($stat['signaled']) {
151
                $data .= "\nTermsig=".$stat['stopsig'];
152
            }
153
        }
154
        $code = proc_close($proc);
155
        if (function_exists('proc_get_status')) {
156
            $code = $stat['exitcode'];
157
        }
158
        return array($code, $data);
159
    }
160
 
161
    function settings2array($settings, $ini_settings)
162
    {
163
        foreach ($settings as $setting) {
164
            if (strpos($setting, '=')!==false) {
165
                $setting = explode("=", $setting, 2);
166
                $name = trim(strtolower($setting[0]));
167
                $value = trim($setting[1]);
168
                $ini_settings[$name] = $value;
169
            }
170
        }
171
        return $ini_settings;
172
    }
173
 
174
    function settings2params($ini_settings)
175
    {
176
        $settings = '';
177
        foreach ($ini_settings as $name => $value) {
178
            $value = addslashes($value);
179
            $settings .= " -d \"$name=$value\"";
180
        }
181
        return $settings;
182
    }
183
 
184
    //
185
    //  Run an individual test case.
186
    //
187
 
188
    function run($file, $ini_settings = '')
189
    {
190
        $cwd = getcwd();
191
        $conf = &PEAR_Config::singleton();
192
        $php = $conf->get('php_bin');
193
        if (isset($this->_options['phpunit'])) {
194
            $cmd = "$php$ini_settings -f $file";
195
            if (isset($this->_logger)) {
196
                $this->_logger->log(2, 'Running command "' . $cmd . '"');
197
            }
198
 
199
            $savedir = getcwd(); // in case the test moves us around
200
            chdir(dirname($file));
201
            echo `$cmd`;
202
            chdir($savedir);
203
            return 'PASSED'; // we have no way of knowing this information so assume passing
204
        }
205
        $pass_options = '';
206
        if (!empty($this->_options['ini'])) {
207
            $pass_options = $this->_options['ini'];
208
        }
209
 
210
        $info_params = '';
211
        $log_format = 'LEOD';
212
 
213
        // Load the sections of the test file.
214
        $section_text = array(
215
            'TEST'    => '(unnamed test)',
216
            'SKIPIF'  => '',
217
            'GET'    => '',
218
            'COOKIE' => '',
219
            'POST'   => '',
220
            'ARGS'    => '',
221
            'INI'     => '',
222
            'CLEAN'   => '',
223
        );
224
 
225
        $file = realpath($file);
226
        if (!is_file($file) || !$fp = fopen($file, "r")) {
227
            return PEAR::raiseError("Cannot open test file: $file");
228
        }
229
 
230
        $section = '';
231
        while (!feof($fp)) {
232
            $line = fgets($fp);
233
 
234
            // Match the beginning of a section.
235
            if (preg_match('/^--([_A-Z]+)--/', $line, $r)) {
236
                $section = $r[1];
237
                $section_text[$section] = '';
238
                continue;
239
            } elseif (empty($section)) {
240
                fclose($fp);
241
                return PEAR::raiseError("Invalid sections formats in test file: $file");
242
            }
243
 
244
            // Add to the section text.
245
            $section_text[$section] .= $line;
246
        }
247
        fclose($fp);
248
 
249
        if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) {
250
            return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file");
251
        }
252
        $ini_settings = array();
253
        $ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings);
254
        if ($section_text['INI']) {
255
            if (strpos($section_text['INI'], '{PWD}') !== false) {
256
                $section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']);
257
            }
258
            $ini_settings = $this->settings2array(preg_split( "/[\n\r]+/",
259
                $section_text['INI']), $ini_settings);
260
        }
261
        $ini_settings = $this->settings2params($ini_settings);
262
        $shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file);
263
        if (!isset($this->_options['simple'])) {
264
            $tested = trim($section_text['TEST']) . "[$shortname]";
265
        } else {
266
            $tested = trim($section_text['TEST']) . ' ';
267
        }
268
        if (!empty($section_text['GET']) || !empty($section_text['POST']) ||
269
              !empty($section_text['POST_RAW']) || !empty($section_text['COOKIE']) ||
270
              !empty($section_text['UPLOAD'])) {
271
            if (empty($this->_options['cgi'])) {
272
                if (!isset($this->_options['quiet'])) {
273
                    $this->_logger->log(0, "SKIP $tested (reason: --cgi option needed for this test, type 'pear help run-tests')");
274
                }
275
                if (isset($this->_options['tapoutput'])) {
276
                    return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info');
277
                }
278
                return 'SKIPPED';
279
            }
280
            $php = $this->_options['cgi'];
281
        }
282
 
283
        $temp_dir = $test_dir = realpath(dirname($file));
284
    	$main_file_name = basename($file,'phpt');
285
    	$diff_filename     = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff';
286
    	$log_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log';
287
    	$exp_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp';
288
    	$output_filename   = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'out';
289
    	$memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'mem';
290
    	$temp_file         = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'php';
291
    	$test_file         = $test_dir . DIRECTORY_SEPARATOR . $main_file_name.'php';
292
    	$temp_skipif       = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php';
293
    	$test_skipif       = $test_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php';
294
    	$temp_clean        = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php';
295
    	$test_clean        = $test_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php';
296
    	$tmp_post          = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
297
 
298
    	// unlink old test results
299
    	@unlink($diff_filename);
300
    	@unlink($log_filename);
301
    	@unlink($exp_filename);
302
    	@unlink($output_filename);
303
    	@unlink($memcheck_filename);
304
    	@unlink($temp_file);
305
    	@unlink($test_file);
306
    	@unlink($temp_skipif);
307
    	@unlink($test_skipif);
308
    	@unlink($tmp_post);
309
    	@unlink($temp_clean);
310
    	@unlink($test_clean);
311
 
312
        // Check if test should be skipped.
313
        $info = '';
314
        $warn = false;
315
        if (array_key_exists('SKIPIF', $section_text)) {
316
            if (trim($section_text['SKIPIF'])) {
317
                $this->save_text($temp_skipif, $section_text['SKIPIF']);
318
                $output = $this->system_with_timeout("$php $info_params -f $temp_skipif");
319
                $output = $output[1];
320
                unlink($temp_skipif);
321
                if (!strncasecmp('skip', ltrim($output), 4)) {
322
                    $skipreason = "SKIP $tested";
323
                    if (preg_match('/^\s*skip\s*(.+)\s*/i', $output, $m)) {
324
                        $skipreason .= '(reason: ' . $m[1] . ')';
325
                    }
326
                    if (!isset($this->_options['quiet'])) {
327
                        $this->_logger->log(0, $skipreason);
328
                    }
329
                    if (isset($this->_options['tapoutput'])) {
330
                        return array('ok', ' # skip ' . $reason);
331
                    }
332
                    return 'SKIPPED';
333
                }
334
                if (!strncasecmp('info', ltrim($output), 4)) {
335
                    if (preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) {
336
                        $info = " (info: $m[1])";
337
                    }
338
                }
339
                if (!strncasecmp('warn', ltrim($output), 4)) {
340
                    if (preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) {
341
                        $warn = true; /* only if there is a reason */
342
                        $info = " (warn: $m[1])";
343
                    }
344
                }
345
            }
346
        }
347
 
348
        // We've satisfied the preconditions - run the test!
349
        $this->save_text($temp_file,$section_text['FILE']);
350
 
351
        $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : '';
352
 
353
        $cmd = "$php$ini_settings -f $temp_file$args 2>&1";
354
        if (isset($this->_logger)) {
355
            $this->_logger->log(2, 'Running command "' . $cmd . '"');
356
        }
357
 
358
        $savedir = getcwd(); // in case the test moves us around
359
        // Reset environment from any previous test.
360
        $env = $_ENV;
361
        $env['REDIRECT_STATUS']='';
362
        $env['QUERY_STRING']='';
363
        $env['PATH_TRANSLATED']='';
364
        $env['SCRIPT_FILENAME']='';
365
        $env['REQUEST_METHOD']='';
366
        $env['CONTENT_TYPE']='';
367
        $env['CONTENT_LENGTH']='';
368
        if (!empty($section_text['ENV'])) {
369
            foreach(explode("\n", trim($section_text['ENV'])) as $e) {
370
                $e = explode('=',trim($e),2);
371
                if (!empty($e[0]) && isset($e[1])) {
372
                    $env[$e[0]] = $e[1];
373
                }
374
            }
375
        }
376
        if (array_key_exists('GET', $section_text)) {
377
            $query_string = trim($section_text['GET']);
378
        } else {
379
            $query_string = '';
380
        }
381
        if (array_key_exists('COOKIE', $section_text)) {
382
            $env['HTTP_COOKIE'] = trim($section_text['COOKIE']);
383
        } else {
384
            $env['HTTP_COOKIE'] = '';
385
        }
386
        $env['REDIRECT_STATUS'] = '1';
387
        $env['QUERY_STRING']    = $query_string;
388
        $env['PATH_TRANSLATED'] = $test_file;
389
        $env['SCRIPT_FILENAME'] = $test_file;
390
        if (array_key_exists('UPLOAD', $section_text) && !empty($section_text['UPLOAD'])) {
391
            $upload_files = trim($section_text['UPLOAD']);
392
            $upload_files = explode("\n", $upload_files);
393
 
394
            $request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" .
395
                       "-----------------------------20896060251896012921717172737\n";
396
            foreach ($upload_files as $fileinfo) {
397
                $fileinfo = explode('=', $fileinfo);
398
                if (count($fileinfo) != 2) {
399
                    return PEAR::raiseError("Invalid UPLOAD section in test file: $file");
400
                }
401
                if (!realpath(dirname($file) . '/' . $fileinfo[1])) {
402
                    return PEAR::raiseError("File for upload does not exist: $fileinfo[1] " .
403
                        "in test file: $file");
404
                }
405
                $file_contents = file_get_contents(dirname($file) . '/' . $fileinfo[1]);
406
                $fileinfo[1] = basename($fileinfo[1]);
407
                $request .= "Content-Disposition: form-data; name=\"$fileinfo[0]\"; filename=\"$fileinfo[1]\"\n";
408
                $request .= "Content-Type: text/plain\n\n";
409
                $request .= $file_contents . "\n" .
410
                    "-----------------------------20896060251896012921717172737\n";
411
            }
412
            if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
413
                // encode POST raw
414
                $post = trim($section_text['POST']);
415
                $post = explode('&', $post);
416
                foreach ($post as $i => $post_info) {
417
                    $post_info = explode('=', $post_info);
418
                    if (count($post_info) != 2) {
419
                        return PEAR::raiseError("Invalid POST data in test file: $file");
420
                    }
421
                    $post_info[0] = rawurldecode($post_info[0]);
422
                    $post_info[1] = rawurldecode($post_info[1]);
423
                    $post[$i] = $post_info;
424
                }
425
                foreach ($post as $post_info) {
426
                    $request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n";
427
                    $request .= $post_info[1] . "\n" .
428
                        "-----------------------------20896060251896012921717172737\n";
429
                }
430
                unset($section_text['POST']);
431
            }
432
            $section_text['POST_RAW'] = $request;
433
        }
434
        if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) {
435
            $post = trim($section_text['POST_RAW']);
436
            $raw_lines = explode("\n", $post);
437
 
438
            $request = '';
439
            $started = false;
440
            foreach ($raw_lines as $i => $line) {
441
                if (empty($env['CONTENT_TYPE']) &&
442
                      preg_match('/^Content-Type:(.*)/i', $line, $res)) {
443
                    $env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1]));
444
                    continue;
445
                }
446
                if ($started) {
447
                    $request .= "\n";
448
                }
449
                $started = true;
450
                $request .= $line;
451
            }
452
 
453
            $env['CONTENT_LENGTH'] = strlen($request);
454
            $env['REQUEST_METHOD'] = 'POST';
455
 
456
            $this->save_text($tmp_post, $request);
457
            $cmd = "$php$pass_options$ini_settings -f \"$test_file\" 2>&1 < $tmp_post";
458
        } elseif (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
459
 
460
            $post = trim($section_text['POST']);
461
            $this->save_text($tmp_post, $post);
462
            $content_length = strlen($post);
463
 
464
            $env['REQUEST_METHOD'] = 'POST';
465
            $env['CONTENT_TYPE']   = 'application/x-www-form-urlencoded';
466
            $env['CONTENT_LENGTH'] = $content_length;
467
 
468
            $cmd = "$php$pass_options$ini_settings -f \"$test_file\" 2>&1 < $tmp_post";
469
 
470
        } else {
471
 
472
            $env['REQUEST_METHOD'] = 'GET';
473
            $env['CONTENT_TYPE']   = '';
474
            $env['CONTENT_LENGTH'] = '';
475
 
476
            $cmd = "$php$pass_options$ini_settings -f \"$test_file\" $args 2>&1";
477
        }
478
        if (OS_WINDOWS && isset($section_text['RETURNS'])) {
479
            ob_start();
480
            system($cmd, $return_value);
481
            $out = ob_get_contents();
482
            ob_end_clean();
483
            $section_text['RETURNS'] = (int) trim($section_text['RETURNS']);
484
            $returnfail = ($return_value != $section_text['RETURNS']);
485
        } else {
486
            $returnfail = false;
487
            $out = $this->system_with_timeout($cmd, $env,
488
                isset($section_text['STDIN']) ? $section_text['STDIN'] : null);
489
            $return_value = $out[0];
490
            $out = $out[1];
491
        }
492
        if (isset($tmp_post) && realpath($tmp_post)) {
493
            unlink(realpath($tmp_post));
494
        }
495
        chdir($savedir);
496
 
497
        if ($section_text['CLEAN']) {
498
            // perform test cleanup
499
            $this->save_text($temp_clean, $section_text['CLEAN']);
500
            $this->system_with_timeout("$php $temp_clean");
501
            if (file_exists($temp_clean)) {
502
                unlink($temp_clean);
503
            }
504
        }
505
        // Does the output match what is expected?
506
        $output = trim($out);
507
        $output = preg_replace('/\r\n/', "\n", $output);
508
 
509
        /* when using CGI, strip the headers from the output */
510
        $headers = "";
511
        if (!empty($this->_options['cgi']) &&
512
              preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $out, $match)) {
513
            $output = trim($match[2]);
514
            $rh = preg_split("/[\n\r]+/",$match[1]);
515
            $headers = array();
516
            foreach ($rh as $line) {
517
                if (strpos($line, ':')!==false) {
518
                    $line = explode(':', $line, 2);
519
                    $headers[trim($line[0])] = trim($line[1]);
520
                }
521
            }
522
        }
523
 
524
        do {
525
            if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) {
526
                if (isset($section_text['EXPECTF'])) {
527
                    $wanted = trim($section_text['EXPECTF']);
528
                } else {
529
                    $wanted = trim($section_text['EXPECTREGEX']);
530
                }
531
                $wanted_re = preg_replace('/\r\n/',"\n",$wanted);
532
                if (isset($section_text['EXPECTF'])) {
533
                    $wanted_re = preg_quote($wanted_re, '/');
534
                    // Stick to basics
535
                    $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy
536
                    $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re);
537
                    $wanted_re = str_replace("%d", "[0-9]+", $wanted_re);
538
                    $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re);
539
                    $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re);
540
                    $wanted_re = str_replace("%c", ".", $wanted_re);
541
                    // %f allows two points "-.0.0" but that is the best *simple* expression
542
                }
543
    /* DEBUG YOUR REGEX HERE
544
            var_dump($wanted_re);
545
            print(str_repeat('=', 80) . "\n");
546
            var_dump($output);
547
    */
548
                if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) {
549
                    if (file_exists($temp_file)) {
550
                        unlink($temp_file);
551
                    }
552
 
553
                    if (array_key_exists('FAIL', $section_text)) {
554
                        break;
555
                    }
556
                    if (!isset($this->_options['quiet'])) {
557
                        $this->_logger->log(0, "PASS $tested$info");
558
                    }
559
                    if (isset($old_php)) {
560
                        $php = $old_php;
561
                    }
562
                    if (isset($this->_options['tapoutput'])) {
563
                        return array('ok', ' - ' . $tested);
564
                    }
565
                    return 'PASSED';
566
                }
567
 
568
            } else {
569
                $wanted = trim($section_text['EXPECT']);
570
                $wanted = preg_replace('/\r\n/',"\n",$wanted);
571
            // compare and leave on success
572
                $ok = (0 == strcmp($output,$wanted));
573
                if (!$returnfail && $ok) {
574
                    if (file_exists($temp_file)) {
575
                        unlink($temp_file);
576
                    }
577
                    if (array_key_exists('FAIL', $section_text)) {
578
                        break;
579
                    }
580
                    if (!isset($this->_options['quiet'])) {
581
                        $this->_logger->log(0, "PASS $tested$info");
582
                    }
583
                    if (isset($old_php)) {
584
                        $php = $old_php;
585
                    }
586
                    if (isset($this->_options['tapoutput'])) {
587
                        return array('ok', ' - ' . $tested);
588
                    }
589
                    return 'PASSED';
590
                }
591
            }
592
        } while (false);
593
 
594
        if (array_key_exists('FAIL', $section_text)) {
595
            // we expect a particular failure
596
            // this is only used for testing PEAR_RunTest
597
            $faildiff = $this->generate_diff(
598
                      $wanted,
599
                      $output,
600
                      null,
601
                      isset($section_text['EXPECTF']) ? $wanted_re : null);
602
            $wanted = preg_replace('/\r/', '', trim($section_text['FAIL']));
603
            $faildiff = preg_replace('/\r/', '', $faildiff);
604
            if ($faildiff == $wanted) {
605
                if (!isset($this->_options['quiet'])) {
606
                    $this->_logger->log(0, "PASS $tested$info");
607
                }
608
                if (isset($old_php)) {
609
                    $php = $old_php;
610
                }
611
                if (isset($this->_options['tapoutput'])) {
612
                    return array('ok', ' - ' . $tested);
613
                }
614
                return 'PASSED';
615
            }
616
            unset($section_text['EXPECTF']);
617
            $output = $faildiff;
618
            if (isset($section_text['RETURNS'])) {
619
                return PEAR::raiseError('Cannot have both RETURNS and FAIL in the same test: ' .
620
                    $file);
621
            }
622
        }
623
 
624
        // Test failed so we need to report details.
625
        if ($warn) {
626
            $this->_logger->log(0, "WARN $tested$info");
627
        } else {
628
            $this->_logger->log(0, "FAIL $tested$info");
629
        }
630
 
631
        if (isset($section_text['RETURNS'])) {
632
            $GLOBALS['__PHP_FAILED_TESTS__'][] = array(
633
                            'name' => $file,
634
                            'test_name' => $tested,
635
                            'output' => $log_filename,
636
                            'diff'   => $diff_filename,
637
                            'info'   => $info,
638
                            'return' => $return_value
639
                            );
640
        } else {
641
            $GLOBALS['__PHP_FAILED_TESTS__'][] = array(
642
                            'name' => $file,
643
                            'test_name' => $tested,
644
                            'output' => $output_filename,
645
                            'diff'   => $diff_filename,
646
                            'info'   => $info,
647
                            );
648
        }
649
 
650
        // write .exp
651
        if (strpos($log_format,'E') !== FALSE) {
652
            $logname = $exp_filename;
653
            if (!$log = fopen($logname,'w')) {
654
                return PEAR::raiseError("Cannot create test log - $logname");
655
            }
656
            fwrite($log,$wanted);
657
            fclose($log);
658
        }
659
 
660
        // write .out
661
        if (strpos($log_format,'O') !== FALSE) {
662
            $logname = $output_filename;
663
            if (!$log = fopen($logname,'w')) {
664
                return PEAR::raiseError("Cannot create test log - $logname");
665
            }
666
            fwrite($log,$output);
667
            fclose($log);
668
        }
669
 
670
        // write .diff
671
        if (strpos($log_format,'D') !== FALSE) {
672
            $logname = $diff_filename;
673
            if (!$log = fopen($logname,'w')) {
674
                return PEAR::raiseError("Cannot create test log - $logname");
675
            }
676
            fwrite($log, $this->generate_diff(
677
                      $wanted,
678
                      $output,
679
                      isset($section_text['RETURNS']) ?
680
                        array(trim($section_text['RETURNS']), $return_value) : null,
681
                      isset($section_text['EXPECTF']) ? $wanted_re : null)
682
                  );
683
            fclose($log);
684
        }
685
 
686
        // write .log
687
        if (strpos($log_format,'L') !== FALSE) {
688
            $logname = $log_filename;
689
            if (!$log = fopen($logname,'w')) {
690
                return PEAR::raiseError("Cannot create test log - $logname");
691
            }
692
            fwrite($log,"
693
---- EXPECTED OUTPUT
694
$wanted
695
---- ACTUAL OUTPUT
696
$output
697
---- FAILED
698
");
699
            if ($returnfail) {
700
                fwrite($log,"
701
---- EXPECTED RETURN
702
$section_text[RETURNS]
703
---- ACTUAL RETURN
704
$return_value
705
");
706
            }
707
            fclose($log);
708
            //error_report($file,$logname,$tested);
709
        }
710
 
711
        if (isset($old_php)) {
712
            $php = $old_php;
713
        }
714
 
715
        if (isset($this->_options['tapoutput'])) {
716
            $wanted = explode("\n", $wanted);
717
            $wanted = "# Expected output:\n#\n#" . implode("\n#", $wanted);
718
            $output = explode("\n", $output);
719
            $output = "#\n#\n# Actual output:\n#\n#" . implode("\n#", $output);
720
            return array($wanted . $output . 'not ok', ' - ' . $tested);
721
        }
722
        return $warn ? 'WARNED' : 'FAILED';
723
    }
724
 
725
    function generate_diff($wanted, $output, $return_value, $wanted_re)
726
    {
727
        $w = explode("\n", $wanted);
728
        $o = explode("\n", $output);
729
        $wr = explode("\n", $wanted_re);
730
        $w1 = array_diff_assoc($w,$o);
731
        $o1 = array_diff_assoc($o,$w);
732
        $w2 = array();
733
        $o2 = array();
734
        foreach($w1 as $idx => $val) {
735
            if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) ||
736
                  !preg_match('/^' . $wr[$idx] . '$/', $o1[$idx])) {
737
                $w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val;
738
            }
739
        }
740
        foreach($o1 as $idx => $val) {
741
            if (!$wanted_re || !isset($wr[$idx]) ||
742
                  !preg_match('/^' . $wr[$idx] . '$/', $val)) {
743
                $o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val;
744
            }
745
        }
746
        $diff = array_merge($w2, $o2);
747
        ksort($diff);
748
        if ($return_value) {
749
            $extra = "##EXPECTED: $return_value[0]\r\n##RETURNED: $return_value[1]";
750
        } else {
751
            $extra = '';
752
        }
753
        return implode("\r\n", $diff) . $extra;
754
    }
755
 
756
    //
757
    //  Write the given text to a temporary file, and return the filename.
758
    //
759
 
760
    function save_text($filename, $text)
761
    {
762
        if (!$fp = fopen($filename, 'w')) {
763
            return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)");
764
        }
765
        fwrite($fp,$text);
766
        fclose($fp);
767
    if (1 < DETAILED) echo "
768
FILE $filename {{{
769
$text
770
}}}
771
";
772
    }
773
 
774
}
775
?>