Subversion Repositories Applications.gtt

Rev

Rev 94 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 94 Rev 187
Line 2... Line 2...
2
/**
2
/**
3
 * PEAR_RunTest
3
 * PEAR_RunTest
4
 *
4
 *
5
 * PHP versions 4 and 5
5
 * PHP versions 4 and 5
6
 *
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
7
 * @category   pear
14
 * @package    PEAR
8
 * @package    PEAR
15
 * @author     Tomas V.V.Cox <cox@idecnet.com>
9
 * @author     Tomas V.V.Cox <cox@idecnet.com>
16
 * @author     Greg Beaver <cellog@php.net>
10
 * @author     Greg Beaver <cellog@php.net>
17
 * @copyright  1997-2006 The PHP Group
11
 * @copyright  1997-2009 The Authors
18
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
12
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
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
13
 * @link       http://pear.php.net/package/PEAR
21
 * @since      File available since Release 1.3.3
14
 * @since      File available since Release 1.3.3
22
 */
15
 */
Line 23... Line 16...
23
 
16
 
Line 40... Line 33...
40
 *
33
 *
41
 * @category   pear
34
 * @category   pear
42
 * @package    PEAR
35
 * @package    PEAR
43
 * @author     Tomas V.V.Cox <cox@idecnet.com>
36
 * @author     Tomas V.V.Cox <cox@idecnet.com>
44
 * @author     Greg Beaver <cellog@php.net>
37
 * @author     Greg Beaver <cellog@php.net>
45
 * @copyright  1997-2006 The PHP Group
38
 * @copyright  1997-2009 The Authors
46
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
39
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
47
 * @version    Release: 1.5.1
40
 * @version    Release: 1.10.1
48
 * @link       http://pear.php.net/package/PEAR
41
 * @link       http://pear.php.net/package/PEAR
49
 * @since      Class available since Release 1.3.3
42
 * @since      Class available since Release 1.3.3
50
 */
43
 */
51
class PEAR_RunTest
44
class PEAR_RunTest
52
{
45
{
-
 
46
    var $_headers = array();
53
    var $_logger;
47
    var $_logger;
54
    var $_options;
48
    var $_options;
-
 
49
    var $_php;
-
 
50
    var $tests_count;
-
 
51
    var $xdebug_loaded;
-
 
52
    /**
-
 
53
     * Saved value of php executable, used to reset $_php when we
-
 
54
     * have a test that uses cgi
-
 
55
     *
-
 
56
     * @var unknown_type
-
 
57
     */
-
 
58
    var $_savephp;
55
    var $ini_overwrites = array(
59
    var $ini_overwrites = array(
56
        'output_handler=',
60
        'output_handler=',
57
        'open_basedir=',
61
        'open_basedir=',
58
        'safe_mode=0',
-
 
59
        'disable_functions=',
62
        'disable_functions=',
60
        'output_buffering=Off',
63
        'output_buffering=Off',
61
        'error_reporting=E_ALL',
-
 
62
        'display_errors=1',
64
        'display_errors=1',
63
        'log_errors=0',
65
        'log_errors=0',
64
        'html_errors=0',
66
        'html_errors=0',
65
        'track_errors=1',
67
        'track_errors=1',
66
        'report_memleaks=1',
68
        'report_memleaks=0',
67
        'report_zend_debug=0',
69
        'report_zend_debug=0',
68
        'docref_root=',
70
        'docref_root=',
69
        'docref_ext=.html',
71
        'docref_ext=.html',
70
        'error_prepend_string=',
72
        'error_prepend_string=',
71
        'error_append_string=',
73
        'error_append_string=',
72
        'auto_prepend_file=',
74
        'auto_prepend_file=',
73
        'auto_append_file=',
75
        'auto_append_file=',
74
        'magic_quotes_runtime=0',
76
        'xdebug.default_enable=0',
-
 
77
        'allow_url_fopen=1',
75
    );
78
    );
Line 76... Line -...
76
 
-
 
77
 
79
 
78
    /**
80
    /**
79
     * An object that supports the PEAR_Common->log() signature, or null
81
     * An object that supports the PEAR_Common->log() signature, or null
80
     * @param PEAR_Common|null
82
     * @param PEAR_Common|null
81
     */
83
     */
82
    function PEAR_RunTest($logger = null, $options = array())
84
    function __construct($logger = null, $options = array())
-
 
85
    {
-
 
86
        if (!defined('E_DEPRECATED')) {
-
 
87
            define('E_DEPRECATED', 0);
-
 
88
        }
-
 
89
        if (!defined('E_STRICT')) {
-
 
90
            define('E_STRICT', 0);
-
 
91
        }
83
    {
92
        $this->ini_overwrites[] = 'error_reporting=' . (E_ALL & ~(E_DEPRECATED | E_STRICT));
84
        if (is_null($logger)) {
93
        if (is_null($logger)) {
85
            require_once 'PEAR/Common.php';
94
            require_once 'PEAR/Common.php';
86
            $logger = new PEAR_Common;
95
            $logger = new PEAR_Common;
87
        }
96
        }
88
        $this->_logger = $logger;
97
        $this->_logger  = $logger;
-
 
98
        $this->_options = $options;
-
 
99
 
-
 
100
        $conf = &PEAR_Config::singleton();
89
        $this->_options = $options;
101
        $this->_php = $conf->get('php_bin');
Line 90... Line 102...
90
    }
102
    }
91
 
103
 
92
    /**
104
    /**
Line 98... Line 110...
98
     * @return unknown
110
     * @return unknown
99
     */
111
     */
100
    function system_with_timeout($commandline, $env = null, $stdin = null)
112
    function system_with_timeout($commandline, $env = null, $stdin = null)
101
    {
113
    {
102
        $data = '';
114
        $data = '';
-
 
115
        $proc = proc_open($commandline, array(
-
 
116
            0 => array('pipe', 'r'),
-
 
117
            1 => array('pipe', 'w'),
-
 
118
            2 => array('pipe', 'w')
-
 
119
        ), $pipes, null, $env, array('suppress_errors' => true));
Line 103... Line -...
103
 
-
 
104
        if (version_compare(phpversion(), '5.0.0', '<')) {
-
 
105
            $proc = proc_open($commandline, array(
-
 
106
                0 => array('pipe', 'r'),
-
 
107
                1 => array('pipe', 'w'),
-
 
108
                2 => array('pipe', 'w')
-
 
109
                ), $pipes);
-
 
110
        } else {
-
 
111
            $proc = proc_open($commandline, array(
-
 
112
                0 => array('pipe', 'r'),
-
 
113
                1 => array('pipe', 'w'),
-
 
114
                2 => array('pipe', 'w')
-
 
115
                ), $pipes, null, $env, array("suppress_errors" => true));
-
 
116
        }
-
 
117
    
120
 
118
        if (!$proc) {
121
        if (!$proc) {
119
            return false;
122
            return false;
120
        }
123
        }
121
    
124
 
122
        if (is_string($stdin)) {
125
        if (is_string($stdin)) {
123
            fwrite($pipes[0], $stdin);
126
            fwrite($pipes[0], $stdin);
124
        }
127
        }
125
        fclose($pipes[0]);
128
        fclose($pipes[0]);
126
    
129
 
127
        while (true) {
130
        while (true) {
128
            /* hide errors from interrupted syscalls */
131
            /* hide errors from interrupted syscalls */
129
            $r = $pipes;
-
 
130
            $w = null;
132
            $r = $pipes;
131
            $e = null;
133
            $e = $w = null;
132
            $n = @stream_select($r, $w, $e, 60);
134
            $n = @stream_select($r, $w, $e, 60);
133
    
135
 
134
            if ($n === 0) {
136
            if ($n === 0) {
135
                /* timed out */
137
                /* timed out */
136
                $data .= "\n ** ERROR: process timed out **\n";
138
                $data .= "\n ** ERROR: process timed out **\n";
137
                proc_terminate($proc);
139
                proc_terminate($proc);
Line 156... Line 158...
156
            $code = $stat['exitcode'];
158
            $code = $stat['exitcode'];
157
        }
159
        }
158
        return array($code, $data);
160
        return array($code, $data);
159
    }
161
    }
Line -... Line 162...
-
 
162
 
-
 
163
    /**
-
 
164
     * Turns a PHP INI string into an array
-
 
165
     *
-
 
166
     * Turns -d "include_path=/foo/bar" into this:
-
 
167
     * array(
-
 
168
     *   'include_path' => array(
-
 
169
     *          'operator' => '-d',
-
 
170
     *          'value'    => '/foo/bar',
-
 
171
     *   )
-
 
172
     * )
-
 
173
     * Works both with quotes and without
-
 
174
     *
-
 
175
     * @param string an PHP INI string, -d "include_path=/foo/bar"
-
 
176
     * @return array
-
 
177
     */
-
 
178
    function iniString2array($ini_string)
-
 
179
    {
-
 
180
        if (!$ini_string) {
-
 
181
            return array();
-
 
182
        }
-
 
183
        $split = preg_split('/[\s]|=/', $ini_string, -1, PREG_SPLIT_NO_EMPTY);
-
 
184
        $key   = $split[1][0] == '"'                     ? substr($split[1], 1)     : $split[1];
-
 
185
        $value = $split[2][strlen($split[2]) - 1] == '"' ? substr($split[2], 0, -1) : $split[2];
-
 
186
        // FIXME review if this is really the struct to go with
-
 
187
        $array = array($key => array('operator' => $split[0], 'value' => $value));
-
 
188
        return $array;
-
 
189
    }
160
 
190
 
161
    function settings2array($settings, $ini_settings)
191
    function settings2array($settings, $ini_settings)
162
    {
192
    {
163
        foreach ($settings as $setting) {
193
        foreach ($settings as $setting) {
164
            if (strpos($setting, '=')!==false) {
194
            if (strpos($setting, '=') !== false) {
165
                $setting = explode("=", $setting, 2);
195
                $setting = explode('=', $setting, 2);
166
                $name = trim(strtolower($setting[0]));
196
                $name  = trim(strtolower($setting[0]));
167
                $value = trim($setting[1]);
197
                $value = trim($setting[1]);
168
                $ini_settings[$name] = $value;
198
                $ini_settings[$name] = $value;
169
            }
199
            }
170
        }
200
        }
171
        return $ini_settings;
201
        return $ini_settings;
172
    }
202
    }
173
    
203
 
174
    function settings2params($ini_settings)
204
    function settings2params($ini_settings)
175
    {
205
    {
176
        $settings = '';
206
        $settings = '';
-
 
207
        foreach ($ini_settings as $name => $value) {
-
 
208
            if (is_array($value)) {
-
 
209
                $operator = $value['operator'];
-
 
210
                $value    = $value['value'];
-
 
211
            } else {
-
 
212
                $operator = '-d';
177
        foreach ($ini_settings as $name => $value) {
213
            }
178
            $value = addslashes($value);
214
            $value = addslashes($value);
179
            $settings .= " -d \"$name=$value\"";
215
            $settings .= " $operator \"$name=$value\"";
180
        }
216
        }
181
        return $settings;
217
        return $settings;
Line -... Line 218...
-
 
218
    }
182
    }
219
 
183
 
220
    function _preparePhpBin($php, $file, $ini_settings)
-
 
221
    {
-
 
222
        $file = escapeshellarg($file);
-
 
223
        $cmd = $php . $ini_settings . ' -f ' . $file;
184
    //
224
 
Line 185... Line 225...
185
    //  Run an individual test case.
225
        return $cmd;
186
    //
226
    }
187
 
-
 
188
    function run($file, $ini_settings = '')
-
 
189
    {
-
 
190
        $cwd = getcwd();
227
 
191
        $conf = &PEAR_Config::singleton();
228
    function runPHPUnit($file, $ini_settings = '')
192
        $php = $conf->get('php_bin');
229
    {
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
            }
230
        if (!file_exists($file) && file_exists(getcwd() . DIRECTORY_SEPARATOR . $file)) {
198
    
-
 
199
            $savedir = getcwd(); // in case the test moves us around
-
 
200
            chdir(dirname($file));
-
 
201
            echo `$cmd`;
231
            $file = realpath(getcwd() . DIRECTORY_SEPARATOR . $file);
-
 
232
        } elseif (file_exists($file)) {
202
            chdir($savedir);
233
            $file = realpath($file);
203
            return 'PASSED'; // we have no way of knowing this information so assume passing
234
        }
204
        }
235
 
205
        $pass_options = '';
236
        $cmd = $this->_preparePhpBin($this->_php, $file, $ini_settings);
Line -... Line 237...
-
 
237
        if (isset($this->_logger)) {
-
 
238
            $this->_logger->log(2, 'Running command "' . $cmd . '"');
206
        if (!empty($this->_options['ini'])) {
239
        }
207
            $pass_options = $this->_options['ini'];
240
 
-
 
241
        $savedir = getcwd(); // in case the test moves us around
-
 
242
        chdir(dirname($file));
Line -... Line 243...
-
 
243
        echo `$cmd`;
208
        }
244
        chdir($savedir);
-
 
245
        return 'PASSED'; // we have no way of knowing this information so assume passing
209
 
246
    }
-
 
247
 
-
 
248
    /**
-
 
249
     * Runs an individual test case.
-
 
250
     *
-
 
251
     * @param string       The filename of the test
210
        $info_params = '';
252
     * @param array|string INI settings to be applied to the test run
-
 
253
     * @param integer      Number what the current running test is of the
-
 
254
     *                     whole test suite being runned.
-
 
255
     *
-
 
256
     * @return string|object Returns PASSED, WARNED, FAILED depending on how the
211
        $log_format = 'LEOD';
257
     *                       test came out.
-
 
258
     *                       PEAR Error when the tester it self fails
-
 
259
     */
212
 
260
    function run($file, $ini_settings = array(), $test_number = 1)
-
 
261
    {
-
 
262
        $this->_restorePHPBinary();
213
        // Load the sections of the test file.
263
 
214
        $section_text = array(
264
        if (empty($this->_options['cgi'])) {
-
 
265
            // try to see if php-cgi is in the path
215
            'TEST'    => '(unnamed test)',
266
            $res = $this->system_with_timeout('php-cgi -v');
-
 
267
            if (false !== $res && !(is_array($res) && in_array($res[0], array(-1, 127)))) {
-
 
268
                $this->_options['cgi'] = 'php-cgi';
216
            'SKIPIF'  => '',
269
            }
217
            'GET'    => '',
270
        }
218
            'COOKIE' => '',
271
        if (1 < $len = strlen($this->tests_count)) {
Line 219... Line 272...
219
            'POST'   => '',
272
            $test_number = str_pad($test_number, $len, ' ', STR_PAD_LEFT);
220
            'ARGS'    => '',
273
            $test_nr = "[$test_number/$this->tests_count] ";
221
            'INI'     => '',
274
        } else {
-
 
275
            $test_nr = '';
222
            'CLEAN'   => '',
276
        }
Line 223... Line 277...
223
        );
277
 
224
 
278
        $file = realpath($file);
225
        $file = realpath($file);
279
        $section_text = $this->_readFile($file);
Line 226... Line -...
226
        if (!is_file($file) || !$fp = fopen($file, "r")) {
-
 
227
            return PEAR::raiseError("Cannot open test file: $file");
-
 
228
        }
-
 
229
 
-
 
230
        $section = '';
280
        if (PEAR::isError($section_text)) {
231
        while (!feof($fp)) {
-
 
232
            $line = fgets($fp);
-
 
233
 
-
 
234
            // Match the beginning of a section.
-
 
Line -... Line 281...
-
 
281
            return $section_text;
235
            if (preg_match('/^--([_A-Z]+)--/', $line, $r)) {
282
        }
236
                $section = $r[1];
283
 
237
                $section_text[$section] = '';
284
        if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) {
238
                continue;
-
 
Line 239... Line 285...
239
            } elseif (empty($section)) {
285
            return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file");
240
                fclose($fp);
286
        }
241
                return PEAR::raiseError("Invalid sections formats in test file: $file");
287
 
242
            }
-
 
-
 
288
        $cwd = getcwd();
243
 
289
 
244
            // Add to the section text.
290
        $pass_options = '';
245
            $section_text[$section] .= $line;
291
        if (!empty($this->_options['ini'])) {
246
        }
292
            $pass_options = $this->_options['ini'];
247
        fclose($fp);
293
        }
248
 
294
 
249
        if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) {
295
        if (is_string($ini_settings)) {
250
            return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file");
296
            $ini_settings = $this->iniString2array($ini_settings);
251
        }
297
        }
252
        $ini_settings = array();
298
 
253
        $ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings);
-
 
-
 
299
        $ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings);
254
        if ($section_text['INI']) {
300
        if ($section_text['INI']) {
255
            if (strpos($section_text['INI'], '{PWD}') !== false) {
-
 
256
                $section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']);
301
            if (strpos($section_text['INI'], '{PWD}') !== false) {
257
            }
302
                $section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']);
258
            $ini_settings = $this->settings2array(preg_split( "/[\n\r]+/",
303
            }
259
                $section_text['INI']), $ini_settings);
304
            $ini = preg_split( "/[\n\r]+/", $section_text['INI']);
260
        }
305
            $ini_settings = $this->settings2array($ini, $ini_settings);
261
        $ini_settings = $this->settings2params($ini_settings);
306
        }
262
        $shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file);
307
        $ini_settings = $this->settings2params($ini_settings);
263
        if (!isset($this->_options['simple'])) {
308
        $shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file);
264
            $tested = trim($section_text['TEST']) . "[$shortname]";
309
 
265
        } else {
310
        $tested = trim($section_text['TEST']);
266
            $tested = trim($section_text['TEST']) . ' ';
311
        $tested.= !isset($this->_options['simple']) ? "[$shortname]" : ' ';
267
        }
312
 
268
        if (!empty($section_text['GET']) || !empty($section_text['POST']) ||
313
        if (!empty($section_text['POST']) || !empty($section_text['POST_RAW']) ||
269
              !empty($section_text['POST_RAW']) || !empty($section_text['COOKIE']) ||
314
              !empty($section_text['UPLOAD']) || !empty($section_text['GET']) ||
-
 
315
              !empty($section_text['COOKIE']) || !empty($section_text['EXPECTHEADERS'])) {
270
              !empty($section_text['UPLOAD'])) {
316
            if (empty($this->_options['cgi'])) {
271
            if (empty($this->_options['cgi'])) {
317
                if (!isset($this->_options['quiet'])) {
Line 272... Line 318...
272
                if (!isset($this->_options['quiet'])) {
318
                    $this->_logger->log(0, "SKIP $test_nr$tested (reason: --cgi option needed for this test, type 'pear help run-tests')");
273
                    $this->_logger->log(0, "SKIP $tested (reason: --cgi option needed for this test, type 'pear help run-tests')");
319
                }
274
                }
320
                if (isset($this->_options['tapoutput'])) {
275
                if (isset($this->_options['tapoutput'])) {
321
                    return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info');
276
                    return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info');
322
                }
277
                }
323
                return 'SKIPPED';
278
                return 'SKIPPED';
324
            }
279
            }
325
            $this->_savePHPBinary();
280
            $php = $this->_options['cgi'];
-
 
281
        }
326
            $this->_php = $this->_options['cgi'];
282
 
-
 
283
        $temp_dir = $test_dir = realpath(dirname($file));
327
        }
284
    	$main_file_name = basename($file,'phpt');
-
 
285
    	$diff_filename     = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff';
328
 
286
    	$log_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log';
329
        $temp_dir = realpath(dirname($file));
287
    	$exp_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp';
330
        $main_file_name = basename($file, 'phpt');
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';
331
        $diff_filename     = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff';
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);
-
 
Line 300... Line 332...
300
    	@unlink($log_filename);
332
        $log_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log';
301
    	@unlink($exp_filename);
-
 
302
    	@unlink($output_filename);
-
 
303
    	@unlink($memcheck_filename);
-
 
304
    	@unlink($temp_file);
-
 
305
    	@unlink($test_file);
333
        $exp_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp';
306
    	@unlink($temp_skipif);
-
 
307
    	@unlink($test_skipif);
-
 
308
    	@unlink($tmp_post);
334
        $output_filename   = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'out';
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
                    }
335
        $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'mem';
332
                    return 'SKIPPED';
-
 
333
                }
-
 
334
                if (!strncasecmp('info', ltrim($output), 4)) {
336
        $temp_file         = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'php';
-
 
337
        $temp_skipif       = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php';
-
 
338
        $temp_clean        = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php';
Line 335... Line 339...
335
                    if (preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) {
339
        $tmp_post          = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
-
 
340
 
-
 
341
        // unlink old test results
-
 
342
        $this->_cleanupOldFiles($file);
-
 
343
 
336
                        $info = " (info: $m[1])";
344
        // Check if test should be skipped.
-
 
345
        $res  = $this->_runSkipIf($section_text, $temp_skipif, $tested, $ini_settings);
-
 
346
        if (count($res) != 2) {
-
 
347
            return $res;
-
 
348
        }
-
 
349
        $info = $res['info'];
-
 
350
        $warn = $res['warn'];
-
 
351
 
-
 
352
        // We've satisfied the preconditions - run the test!
Line -... Line 353...
-
 
353
        if (isset($this->_options['coverage']) && $this->xdebug_loaded) {
337
                    }
354
            $xdebug_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'xdebug';
-
 
355
            $text = "\n" . 'function coverage_shutdown() {' .
-
 
356
                    "\n" . '    $xdebug = var_export(xdebug_get_code_coverage(), true);';
-
 
357
            if (!function_exists('file_put_contents')) {
Line -... Line 358...
-
 
358
                $text .= "\n" . '    $fh = fopen(\'' . $xdebug_file . '\', "wb");' .
338
                }
359
                        "\n" . '    if ($fh !== false) {' .
339
                if (!strncasecmp('warn', ltrim($output), 4)) {
360
                        "\n" . '        fwrite($fh, $xdebug);' .
-
 
361
                        "\n" . '        fclose($fh);' .
340
                    if (preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) {
362
                        "\n" . '    }';
341
                        $warn = true; /* only if there is a reason */
363
            } else {
Line -... Line 364...
-
 
364
                $text .= "\n" . '    file_put_contents(\'' . $xdebug_file . '\', $xdebug);';
342
                        $info = " (warn: $m[1])";
365
            }
343
                    }
366
 
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
 
367
            // Workaround for http://pear.php.net/bugs/bug.php?id=17292
353
        $cmd = "$php$ini_settings -f $temp_file$args 2>&1";
368
            $lines             = explode("\n", $section_text['FILE']);
354
        if (isset($this->_logger)) {
369
            $numLines          = count($lines);
-
 
370
            $namespace         = '';
355
            $this->_logger->log(2, 'Running command "' . $cmd . '"');
371
            $coverage_shutdown = 'coverage_shutdown';
356
        }
372
 
357
 
373
            if (
358
        $savedir = getcwd(); // in case the test moves us around
374
                substr($lines[0], 0, 2) == '<?' ||
359
        // Reset environment from any previous test.
375
                substr($lines[0], 0, 5) == '<?php'
360
        $env = $_ENV;
376
            ) {
361
        $env['REDIRECT_STATUS']='';
377
                unset($lines[0]);
-
 
378
            }
-
 
379
 
-
 
380
 
-
 
381
            for ($i = 0; $i < $numLines; $i++) {
362
        $env['QUERY_STRING']='';
382
                if (isset($lines[$i]) && substr($lines[$i], 0, 9) == 'namespace') {
363
        $env['PATH_TRANSLATED']='';
383
                    $namespace         = substr($lines[$i], 10, -1);
364
        $env['SCRIPT_FILENAME']='';
384
                    $coverage_shutdown = $namespace . '\\coverage_shutdown';
-
 
385
                    $namespace         = "namespace " . $namespace . ";\n";
365
        $env['REQUEST_METHOD']='';
386
 
366
        $env['CONTENT_TYPE']='';
387
                    unset($lines[$i]);
367
        $env['CONTENT_LENGTH']='';
388
                    break;
368
        if (!empty($section_text['ENV'])) {
389
                }
-
 
390
            }
369
            foreach(explode("\n", trim($section_text['ENV'])) as $e) {
391
 
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)) {
-
 
Line 377... Line -...
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);
392
            $text .= "\n    xdebug_stop_code_coverage();" .
393
 
-
 
394
            $request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" .
-
 
395
                       "-----------------------------20896060251896012921717172737\n";
-
 
396
            foreach ($upload_files as $fileinfo) {
-
 
397
                $fileinfo = explode('=', $fileinfo);
393
                "\n" . '} // end coverage_shutdown()' .
398
                if (count($fileinfo) != 2) {
-
 
399
                    return PEAR::raiseError("Invalid UPLOAD section in test file: $file");
-
 
-
 
394
                "\n\n" . 'register_shutdown_function("' . $coverage_shutdown . '");';
400
                }
395
            $text .= "\n" . 'xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);' . "\n";
401
                if (!realpath(dirname($file) . '/' . $fileinfo[1])) {
396
 
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
397
            $this->save_text($temp_file, "<?php\n" . $namespace . $text  . "\n" . implode("\n", $lines));
414
                $post = trim($section_text['POST']);
-
 
415
                $post = explode('&', $post);
-
 
416
                foreach ($post as $i => $post_info) {
398
        } else {
-
 
399
            $this->save_text($temp_file, $section_text['FILE']);
417
                    $post_info = explode('=', $post_info);
400
        }
418
                    if (count($post_info) != 2) {
401
 
419
                        return PEAR::raiseError("Invalid POST data in test file: $file");
402
        $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : '';
420
                    }
403
        $cmd = $this->_preparePhpBin($this->_php, $temp_file, $ini_settings);
421
                    $post_info[0] = rawurldecode($post_info[0]);
404
        $cmd.= "$args 2>&1";
422
                    $post_info[1] = rawurldecode($post_info[1]);
405
        if (isset($this->_logger)) {
423
                    $post[$i] = $post_info;
406
            $this->_logger->log(2, 'Running command "' . $cmd . '"');
424
                }
407
        }
425
                foreach ($post as $post_info) {
408
 
426
                    $request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n";
409
        // Reset environment from any previous test.
427
                    $request .= $post_info[1] . "\n" .
410
        $env = $this->_resetEnv($section_text, $temp_file);
428
                        "-----------------------------20896060251896012921717172737\n";
411
 
429
                }
412
        $section_text = $this->_processUpload($section_text, $file);
430
                unset($section_text['POST']);
413
        if (PEAR::isError($section_text)) {
431
            }
414
            return $section_text;
432
            $section_text['POST_RAW'] = $request;
415
        }
433
        }
416
 
434
        if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) {
417
        if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) {
435
            $post = trim($section_text['POST_RAW']);
418
            $post = trim($section_text['POST_RAW']);
436
            $raw_lines = explode("\n", $post);
419
            $raw_lines = explode("\n", $post);
437
    
420
 
Line 438... Line 421...
438
            $request = '';
421
            $request = '';
439
            $started = false;
422
            $started = false;
440
            foreach ($raw_lines as $i => $line) {
423
            foreach ($raw_lines as $i => $line) {
441
                if (empty($env['CONTENT_TYPE']) &&
-
 
442
                      preg_match('/^Content-Type:(.*)/i', $line, $res)) {
424
                if (empty($env['CONTENT_TYPE']) &&
443
                    $env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1]));
425
                    preg_match('/^Content-Type:(.*)/i', $line, $res)) {
444
                    continue;
426
                    $env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1]));
445
                }
427
                    continue;
446
                if ($started) {
428
                }
447
                    $request .= "\n";
429
                if ($started) {
448
                }
430
                    $request .= "\n";
449
                $started = true;
431
                }
450
                $request .= $line;
432
                $started = true;
451
            }
-
 
452
    
433
                $request .= $line;
453
            $env['CONTENT_LENGTH'] = strlen($request);
-
 
454
            $env['REQUEST_METHOD'] = 'POST';
434
            }
455
 
435
 
456
            $this->save_text($tmp_post, $request);
436
            $env['CONTENT_LENGTH'] = strlen($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
    
437
            $env['REQUEST_METHOD'] = 'POST';
-
 
438
 
460
            $post = trim($section_text['POST']);
439
            $this->save_text($tmp_post, $request);
461
            $this->save_text($tmp_post, $post);
440
            $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
462
            $content_length = strlen($post);
441
        } elseif (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
463
    
442
            $post = trim($section_text['POST']);
464
            $env['REQUEST_METHOD'] = 'POST';
443
            $this->save_text($tmp_post, $post);
465
            $env['CONTENT_TYPE']   = 'application/x-www-form-urlencoded';
444
            $content_length = strlen($post);
466
            $env['CONTENT_LENGTH'] = $content_length;
445
 
467
    
446
            $env['REQUEST_METHOD'] = 'POST';
468
            $cmd = "$php$pass_options$ini_settings -f \"$test_file\" 2>&1 < $tmp_post";
447
            $env['CONTENT_TYPE']   = 'application/x-www-form-urlencoded';
469
    
448
            $env['CONTENT_LENGTH'] = $content_length;
470
        } else {
449
 
471
    
450
            $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
472
            $env['REQUEST_METHOD'] = 'GET';
451
        } else {
473
            $env['CONTENT_TYPE']   = '';
452
            $env['REQUEST_METHOD'] = 'GET';
474
            $env['CONTENT_LENGTH'] = '';
-
 
475
    
-
 
476
            $cmd = "$php$pass_options$ini_settings -f \"$test_file\" $args 2>&1";
-
 
477
        }
-
 
Line 478... Line -...
478
        if (OS_WINDOWS && isset($section_text['RETURNS'])) {
-
 
479
            ob_start();
-
 
480
            system($cmd, $return_value);
-
 
481
            $out = ob_get_contents();
453
            $env['CONTENT_TYPE']   = '';
-
 
454
            $env['CONTENT_LENGTH'] = '';
482
            ob_end_clean();
455
        }
483
            $section_text['RETURNS'] = (int) trim($section_text['RETURNS']);
456
 
484
            $returnfail = ($return_value != $section_text['RETURNS']);
-
 
485
        } else {
457
        if (OS_WINDOWS && isset($section_text['RETURNS'])) {
486
            $returnfail = false;
458
            ob_start();
487
            $out = $this->system_with_timeout($cmd, $env,
-
 
488
                isset($section_text['STDIN']) ? $section_text['STDIN'] : null);
-
 
Line 489... Line 459...
489
            $return_value = $out[0];
459
            system($cmd, $return_value);
490
            $out = $out[1];
460
            $out = ob_get_contents();
-
 
461
            ob_end_clean();
491
        }
462
            $section_text['RETURNS'] = (int) trim($section_text['RETURNS']);
-
 
463
            $returnfail = ($return_value != $section_text['RETURNS']);
492
        if (isset($tmp_post) && realpath($tmp_post)) {
464
        } else {
493
            unlink(realpath($tmp_post));
465
            $returnfail = false;
494
        }
466
            $stdin = isset($section_text['STDIN']) ? $section_text['STDIN'] : null;
495
        chdir($savedir);
467
            $out = $this->system_with_timeout($cmd, $env, $stdin);
496
 
468
            $return_value = $out[0];
497
        if ($section_text['CLEAN']) {
469
            $out = $out[1];
498
            // perform test cleanup
470
        }
499
            $this->save_text($temp_clean, $section_text['CLEAN']);
471
 
500
            $this->system_with_timeout("$php $temp_clean");
472
        $output = preg_replace('/\r\n/', "\n", trim($out));
501
            if (file_exists($temp_clean)) {
473
 
-
 
474
        if (isset($tmp_post) && realpath($tmp_post) && file_exists($tmp_post)) {
-
 
475
            @unlink(realpath($tmp_post));
-
 
476
        }
-
 
477
        chdir($cwd); // in case the test moves us around
502
                unlink($temp_clean);
478
 
Line -... Line 479...
-
 
479
        /* when using CGI, strip the headers from the output */
-
 
480
        $output = $this->_stripHeadersCGI($output);
-
 
481
 
503
            }
482
        if (isset($section_text['EXPECTHEADERS'])) {
504
        }
483
            $testheaders = $this->_processHeaders($section_text['EXPECTHEADERS']);
505
        // Does the output match what is expected?
484
            $missing = array_diff_assoc($testheaders, $this->_headers);
506
        $output = trim($out);
485
            $changed = '';
507
        $output = preg_replace('/\r\n/', "\n", $output);
486
            foreach ($missing as $header => $value) {
508
 
487
                if (isset($this->_headers[$header])) {
509
        /* when using CGI, strip the headers from the output */
488
                    $changed .= "-$header: $value\n+$header: ";
510
        $headers = "";
489
                    $changed .= $this->_headers[$header];
511
        if (!empty($this->_options['cgi']) &&
490
                } else {
512
              preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $out, $match)) {
491
                    $changed .= "-$header: $value\n";
513
            $output = trim($match[2]);
492
                }
514
            $rh = preg_split("/[\n\r]+/",$match[1]);
493
            }
515
            $headers = array();
494
            if ($missing) {
Line 538... Line 517...
538
                    $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re);
517
                    $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);
518
                    $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re);
540
                    $wanted_re = str_replace("%c", ".", $wanted_re);
519
                    $wanted_re = str_replace("%c", ".", $wanted_re);
541
                    // %f allows two points "-.0.0" but that is the best *simple* expression
520
                    // %f allows two points "-.0.0" but that is the best *simple* expression
542
                }
521
                }
-
 
522
 
543
    /* DEBUG YOUR REGEX HERE
523
    /* DEBUG YOUR REGEX HERE
544
            var_dump($wanted_re);
524
            var_dump($wanted_re);
545
            print(str_repeat('=', 80) . "\n");
525
            print(str_repeat('=', 80) . "\n");
546
            var_dump($output);
526
            var_dump($output);
547
    */
527
    */
548
                if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) {
528
                if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) {
549
                    if (file_exists($temp_file)) {
529
                    if (file_exists($temp_file)) {
550
                        unlink($temp_file);
530
                        unlink($temp_file);
551
                    }
531
                    }
552
 
-
 
553
                    if (array_key_exists('FAIL', $section_text)) {
532
                    if (array_key_exists('FAIL', $section_text)) {
554
                        break;
533
                        break;
555
                    }
534
                    }
556
                    if (!isset($this->_options['quiet'])) {
535
                    if (!isset($this->_options['quiet'])) {
557
                        $this->_logger->log(0, "PASS $tested$info");
536
                        $this->_logger->log(0, "PASS $test_nr$tested$info");
558
                    }
-
 
559
                    if (isset($old_php)) {
-
 
560
                        $php = $old_php;
-
 
561
                    }
537
                    }
562
                    if (isset($this->_options['tapoutput'])) {
538
                    if (isset($this->_options['tapoutput'])) {
563
                        return array('ok', ' - ' . $tested);
539
                        return array('ok', ' - ' . $tested);
564
                    }
540
                    }
565
                    return 'PASSED';
541
                    return 'PASSED';
566
                }
542
                }
567
 
-
 
568
            } else {
543
            } else {
-
 
544
                if (isset($section_text['EXPECTFILE'])) {
-
 
545
                    $f = $temp_dir . '/' . trim($section_text['EXPECTFILE']);
-
 
546
                    if (!($fp = @fopen($f, 'rb'))) {
-
 
547
                        return PEAR::raiseError('--EXPECTFILE-- section file ' .
-
 
548
                            $f . ' not found');
-
 
549
                    }
-
 
550
                    fclose($fp);
-
 
551
                    $section_text['EXPECT'] = file_get_contents($f);
-
 
552
                }
-
 
553
 
569
                $wanted = trim($section_text['EXPECT']);
554
                if (isset($section_text['EXPECT'])) {
570
                $wanted = preg_replace('/\r\n/',"\n",$wanted);
555
                    $wanted = preg_replace('/\r\n/', "\n", trim($section_text['EXPECT']));
-
 
556
                } else {
571
            // compare and leave on success
557
                    $wanted = '';
-
 
558
                }
-
 
559
 
572
                $ok = (0 == strcmp($output,$wanted));
560
                // compare and leave on success
573
                if (!$returnfail && $ok) {
561
                if (!$returnfail && 0 == strcmp($output, $wanted)) {
574
                    if (file_exists($temp_file)) {
562
                    if (file_exists($temp_file)) {
575
                        unlink($temp_file);
563
                        unlink($temp_file);
576
                    }
564
                    }
577
                    if (array_key_exists('FAIL', $section_text)) {
565
                    if (array_key_exists('FAIL', $section_text)) {
578
                        break;
566
                        break;
579
                    }
567
                    }
580
                    if (!isset($this->_options['quiet'])) {
568
                    if (!isset($this->_options['quiet'])) {
581
                        $this->_logger->log(0, "PASS $tested$info");
569
                        $this->_logger->log(0, "PASS $test_nr$tested$info");
582
                    }
-
 
583
                    if (isset($old_php)) {
-
 
584
                        $php = $old_php;
-
 
585
                    }
570
                    }
586
                    if (isset($this->_options['tapoutput'])) {
571
                    if (isset($this->_options['tapoutput'])) {
587
                        return array('ok', ' - ' . $tested);
572
                        return array('ok', ' - ' . $tested);
588
                    }
573
                    }
589
                    return 'PASSED';
574
                    return 'PASSED';
Line 592... Line 577...
592
        } while (false);
577
        } while (false);
Line 593... Line 578...
593
 
578
 
594
        if (array_key_exists('FAIL', $section_text)) {
579
        if (array_key_exists('FAIL', $section_text)) {
595
            // we expect a particular failure
580
            // 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,
581
            // this is only used for testing PEAR_RunTest
601
                      isset($section_text['EXPECTF']) ? $wanted_re : null);
582
            $expectf  = isset($section_text['EXPECTF']) ? $wanted_re : null;
602
            $wanted = preg_replace('/\r/', '', trim($section_text['FAIL']));
583
            $faildiff = $this->generate_diff($wanted, $output, null, $expectf);
-
 
584
            $faildiff = preg_replace('/\r/', '', $faildiff);
603
            $faildiff = preg_replace('/\r/', '', $faildiff);
585
            $wanted   = preg_replace('/\r/', '', trim($section_text['FAIL']));
604
            if ($faildiff == $wanted) {
586
            if ($faildiff == $wanted) {
605
                if (!isset($this->_options['quiet'])) {
587
                if (!isset($this->_options['quiet'])) {
606
                    $this->_logger->log(0, "PASS $tested$info");
-
 
607
                }
-
 
608
                if (isset($old_php)) {
-
 
609
                    $php = $old_php;
588
                    $this->_logger->log(0, "PASS $test_nr$tested$info");
610
                }
589
                }
611
                if (isset($this->_options['tapoutput'])) {
590
                if (isset($this->_options['tapoutput'])) {
612
                    return array('ok', ' - ' . $tested);
591
                    return array('ok', ' - ' . $tested);
613
                }
592
                }
Line 620... Line 599...
620
                    $file);
599
                    $file);
621
            }
600
            }
622
        }
601
        }
Line 623... Line 602...
623
 
602
 
624
        // Test failed so we need to report details.
-
 
625
        if ($warn) {
603
        // Test failed so we need to report details.
626
            $this->_logger->log(0, "WARN $tested$info");
-
 
627
        } else {
604
        $txt = $warn ? 'WARN ' : 'FAIL ';
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
                            );
-
 
Line 648... Line 605...
648
        }
605
        $this->_logger->log(0, $txt . $test_nr . $tested . $info);
649
 
-
 
650
        // write .exp
606
 
651
        if (strpos($log_format,'E') !== FALSE) {
607
        // write .exp
652
            $logname = $exp_filename;
-
 
653
            if (!$log = fopen($logname,'w')) {
-
 
654
                return PEAR::raiseError("Cannot create test log - $logname");
-
 
655
            }
608
        $res = $this->_writeLog($exp_filename, $wanted);
656
            fwrite($log,$wanted);
609
        if (PEAR::isError($res)) {
Line 657... Line 610...
657
            fclose($log);
610
            return $res;
658
        }
-
 
659
 
611
        }
660
        // write .out
612
 
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");
613
        // write .out
665
            }
614
        $res = $this->_writeLog($output_filename, $output);
Line 666... Line 615...
666
            fwrite($log,$output);
615
        if (PEAR::isError($res)) {
667
            fclose($log);
616
            return $res;
668
        }
617
        }
669
 
618
 
670
        // write .diff
619
        // write .diff
671
        if (strpos($log_format,'D') !== FALSE) {
-
 
672
            $logname = $diff_filename;
620
        $returns = isset($section_text['RETURNS']) ?
673
            if (!$log = fopen($logname,'w')) {
-
 
674
                return PEAR::raiseError("Cannot create test log - $logname");
621
                        array(trim($section_text['RETURNS']), $return_value) : null;
675
            }
622
        $expectf = isset($section_text['EXPECTF']) ? $wanted_re : null;
676
            fwrite($log, $this->generate_diff(
623
        $data = $this->generate_diff($wanted, $output, $returns, $expectf);
677
                      $wanted,
624
        $res  = $this->_writeLog($diff_filename, $data);
678
                      $output,
625
        if (isset($this->_options['showdiff'])) {
-
 
626
            $this->_logger->log(0, "========DIFF========");
679
                      isset($section_text['RETURNS']) ?
627
            $this->_logger->log(0, $data);
680
                        array(trim($section_text['RETURNS']), $return_value) : null,
628
            $this->_logger->log(0, "========DONE========");
Line 681... Line 629...
681
                      isset($section_text['EXPECTF']) ? $wanted_re : null)
629
        }
682
                  );
-
 
683
            fclose($log);
-
 
684
        }
-
 
685
 
-
 
686
        // write .log
630
        if (PEAR::isError($res)) {
687
        if (strpos($log_format,'L') !== FALSE) {
-
 
688
            $logname = $log_filename;
631
            return $res;
689
            if (!$log = fopen($logname,'w')) {
632
        }
690
                return PEAR::raiseError("Cannot create test log - $logname");
633
 
691
            }
634
        // write .log
692
            fwrite($log,"
635
        $data = "
693
---- EXPECTED OUTPUT
636
---- EXPECTED OUTPUT
-
 
637
$wanted
694
$wanted
638
---- ACTUAL OUTPUT
695
---- ACTUAL OUTPUT
639
$output
696
$output
640
---- FAILED
697
---- FAILED
641
";
698
");
642
 
699
            if ($returnfail) {
643
        if ($returnfail) {
700
                fwrite($log,"
644
            $data .= "
701
---- EXPECTED RETURN
-
 
702
$section_text[RETURNS]
-
 
703
---- ACTUAL RETURN
-
 
704
$return_value
645
---- EXPECTED RETURN
Line -... Line 646...
-
 
646
$section_text[RETURNS]
705
");
647
---- ACTUAL RETURN
706
            }
648
$return_value
707
            fclose($log);
649
";
Line 708... Line 650...
708
            //error_report($file,$logname,$tested);
650
        }
709
        }
651
 
710
 
652
        $res = $this->_writeLog($log_filename, $data);
Line 720... Line 662...
720
            return array($wanted . $output . 'not ok', ' - ' . $tested);
662
            return array($wanted . $output . 'not ok', ' - ' . $tested);
721
        }
663
        }
722
        return $warn ? 'WARNED' : 'FAILED';
664
        return $warn ? 'WARNED' : 'FAILED';
723
    }
665
    }
Line 724... Line 666...
724
 
666
 
725
    function generate_diff($wanted, $output, $return_value, $wanted_re)
667
    function generate_diff($wanted, $output, $rvalue, $wanted_re)
726
    {
668
    {
727
        $w = explode("\n", $wanted);
669
        $w  = explode("\n", $wanted);
728
        $o = explode("\n", $output);
670
        $o  = explode("\n", $output);
729
        $wr = explode("\n", $wanted_re);
671
        $wr = explode("\n", $wanted_re);
730
        $w1 = array_diff_assoc($w,$o);
672
        $w1 = array_diff_assoc($w, $o);
731
        $o1 = array_diff_assoc($o,$w);
-
 
732
        $w2 = array();
673
        $o1 = array_diff_assoc($o, $w);
733
        $o2 = array();
674
        $o2 = $w2 = array();
734
        foreach($w1 as $idx => $val) {
675
        foreach ($w1 as $idx => $val) {
735
            if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) ||
676
            if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) ||
736
                  !preg_match('/^' . $wr[$idx] . '$/', $o1[$idx])) {
677
                  !preg_match('/^' . $wr[$idx] . '\\z/', $o1[$idx])) {
737
                $w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val;
678
                $w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val;
738
            }
679
            }
739
        }
680
        }
740
        foreach($o1 as $idx => $val) {
681
        foreach ($o1 as $idx => $val) {
741
            if (!$wanted_re || !isset($wr[$idx]) ||
682
            if (!$wanted_re || !isset($wr[$idx]) ||
742
                  !preg_match('/^' . $wr[$idx] . '$/', $val)) {
683
                  !preg_match('/^' . $wr[$idx] . '\\z/', $val)) {
743
                $o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val;
684
                $o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val;
744
            }
685
            }
745
        }
686
        }
746
        $diff = array_merge($w2, $o2);
687
        $diff = array_merge($w2, $o2);
747
        ksort($diff);
-
 
748
        if ($return_value) {
688
        ksort($diff);
749
            $extra = "##EXPECTED: $return_value[0]\r\n##RETURNED: $return_value[1]";
-
 
750
        } else {
-
 
751
            $extra = '';
-
 
752
        }
689
        $extra = $rvalue ? "##EXPECTED: $rvalue[0]\r\n##RETURNED: $rvalue[1]" : '';
753
        return implode("\r\n", $diff) . $extra;
690
        return implode("\r\n", $diff) . $extra;
Line 754... Line -...
754
    }
-
 
755
 
691
    }
756
    //
-
 
757
    //  Write the given text to a temporary file, and return the filename.
-
 
758
    //
692
 
759
 
693
    //  Write the given text to a temporary file, and return the filename.
760
    function save_text($filename, $text)
694
    function save_text($filename, $text)
761
    {
695
    {
762
        if (!$fp = fopen($filename, 'w')) {
696
        if (!$fp = fopen($filename, 'w')) {
763
            return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)");
697
            return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)");
764
        }
698
        }
765
        fwrite($fp,$text);
699
        fwrite($fp, $text);
766
        fclose($fp);
700
        fclose($fp);
767
    if (1 < DETAILED) echo "
701
    if (1 < DETAILED) echo "
768
FILE $filename {{{
702
FILE $filename {{{
769
$text
703
$text
770
}}}
704
}}}
Line -... Line 705...
-
 
705
";
-
 
706
    }
-
 
707
 
-
 
708
    function _cleanupOldFiles($file)
-
 
709
    {
-
 
710
        $temp_dir = realpath(dirname($file));
-
 
711
        $mainFileName = basename($file, 'phpt');
-
 
712
        $diff_filename     = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'diff';
-
 
713
        $log_filename      = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'log';
-
 
714
        $exp_filename      = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'exp';
-
 
715
        $output_filename   = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'out';
-
 
716
        $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'mem';
-
 
717
        $temp_file         = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'php';
-
 
718
        $temp_skipif       = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'skip.php';
-
 
719
        $temp_clean        = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'clean.php';
-
 
720
        $tmp_post          = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
-
 
721
 
-
 
722
        // unlink old test results
-
 
723
        @unlink($diff_filename);
-
 
724
        @unlink($log_filename);
-
 
725
        @unlink($exp_filename);
-
 
726
        @unlink($output_filename);
-
 
727
        @unlink($memcheck_filename);
-
 
728
        @unlink($temp_file);
-
 
729
        @unlink($temp_skipif);
-
 
730
        @unlink($tmp_post);
-
 
731
        @unlink($temp_clean);
-
 
732
    }
-
 
733
 
-
 
734
    function _runSkipIf($section_text, $temp_skipif, $tested, $ini_settings)
-
 
735
    {
-
 
736
        $info = '';
-
 
737
        $warn = false;
-
 
738
        if (array_key_exists('SKIPIF', $section_text) && trim($section_text['SKIPIF'])) {
-
 
739
            $this->save_text($temp_skipif, $section_text['SKIPIF']);
-
 
740
            $output = $this->system_with_timeout("$this->_php$ini_settings -f \"$temp_skipif\"");
-
 
741
            $output = $output[1];
-
 
742
            $loutput = ltrim($output);
-
 
743
            unlink($temp_skipif);
-
 
744
            if (!strncasecmp('skip', $loutput, 4)) {
-
 
745
                $skipreason = "SKIP $tested";
-
 
746
                if (preg_match('/^\s*skip\s*(.+)\s*/i', $output, $m)) {
-
 
747
                    $skipreason .= '(reason: ' . $m[1] . ')';
-
 
748
                }
-
 
749
                if (!isset($this->_options['quiet'])) {
-
 
750
                    $this->_logger->log(0, $skipreason);
-
 
751
                }
-
 
752
                if (isset($this->_options['tapoutput'])) {
-
 
753
                    return array('ok', ' # skip ' . $reason);
-
 
754
                }
-
 
755
                return 'SKIPPED';
-
 
756
            }
-
 
757
 
-
 
758
            if (!strncasecmp('info', $loutput, 4)
-
 
759
                && preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) {
-
 
760
                $info = " (info: $m[1])";
-
 
761
            }
-
 
762
 
-
 
763
            if (!strncasecmp('warn', $loutput, 4)
-
 
764
                && preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) {
-
 
765
                $warn = true; /* only if there is a reason */
-
 
766
                $info = " (warn: $m[1])";
-
 
767
            }
-
 
768
        }
-
 
769
 
-
 
770
        return array('warn' => $warn, 'info' => $info);
-
 
771
    }
-
 
772
 
-
 
773
    function _stripHeadersCGI($output)
-
 
774
    {
-
 
775
        $this->headers = array();
-
 
776
        if (!empty($this->_options['cgi']) &&
-
 
777
              $this->_php == $this->_options['cgi'] &&
-
 
778
              preg_match("/^(.*?)(?:\n\n(.*)|\\z)/s", $output, $match)) {
-
 
779
            $output = isset($match[2]) ? trim($match[2]) : '';
-
 
780
            $this->_headers = $this->_processHeaders($match[1]);
-
 
781
        }
-
 
782
 
-
 
783
        return $output;
-
 
784
    }
-
 
785
 
-
 
786
    /**
-
 
787
     * Return an array that can be used with array_diff() to compare headers
-
 
788
     *
-
 
789
     * @param string $text
-
 
790
     */
-
 
791
    function _processHeaders($text)
-
 
792
    {
-
 
793
        $headers = array();
-
 
794
        $rh = preg_split("/[\n\r]+/", $text);
-
 
795
        foreach ($rh as $line) {
-
 
796
            if (strpos($line, ':')!== false) {
-
 
797
                $line = explode(':', $line, 2);
-
 
798
                $headers[trim($line[0])] = trim($line[1]);
-
 
799
            }
-
 
800
        }
-
 
801
        return $headers;
-
 
802
    }
-
 
803
 
-
 
804
    function _readFile($file)
-
 
805
    {
-
 
806
        // Load the sections of the test file.
-
 
807
        $section_text = array(
-
 
808
            'TEST'   => '(unnamed test)',
-
 
809
            'SKIPIF' => '',
-
 
810
            'GET'    => '',
-
 
811
            'COOKIE' => '',
-
 
812
            'POST'   => '',
-
 
813
            'ARGS'   => '',
-
 
814
            'INI'    => '',
-
 
815
            'CLEAN'  => '',
-
 
816
        );
-
 
817
 
-
 
818
        if (!is_file($file) || !$fp = fopen($file, "r")) {
-
 
819
            return PEAR::raiseError("Cannot open test file: $file");
-
 
820
        }
-
 
821
 
-
 
822
        $section = '';
-
 
823
        while (!feof($fp)) {
-
 
824
            $line = fgets($fp);
-
 
825
 
-
 
826
            // Match the beginning of a section.
-
 
827
            if (preg_match('/^--([_A-Z]+)--/', $line, $r)) {
-
 
828
                $section = $r[1];
-
 
829
                $section_text[$section] = '';
-
 
830
                continue;
-
 
831
            } elseif (empty($section)) {
-
 
832
                fclose($fp);
-
 
833
                return PEAR::raiseError("Invalid sections formats in test file: $file");
-
 
834
            }
-
 
835
 
-
 
836
            // Add to the section text.
-
 
837
            $section_text[$section] .= $line;
-
 
838
        }
-
 
839
        fclose($fp);
-
 
840
 
-
 
841
        return $section_text;
-
 
842
    }
-
 
843
 
-
 
844
    function _writeLog($logname, $data)
-
 
845
    {
-
 
846
        if (!$log = fopen($logname, 'w')) {
-
 
847
            return PEAR::raiseError("Cannot create test log - $logname");
-
 
848
        }
-
 
849
        fwrite($log, $data);
-
 
850
        fclose($log);
-
 
851
    }
-
 
852
 
-
 
853
    function _resetEnv($section_text, $temp_file)
-
 
854
    {
-
 
855
        $env = $_ENV;
-
 
856
        $env['REDIRECT_STATUS'] = '';
-
 
857
        $env['QUERY_STRING']    = '';
-
 
858
        $env['PATH_TRANSLATED'] = '';
-
 
859
        $env['SCRIPT_FILENAME'] = '';
-
 
860
        $env['REQUEST_METHOD']  = '';
-
 
861
        $env['CONTENT_TYPE']    = '';
-
 
862
        $env['CONTENT_LENGTH']  = '';
-
 
863
        if (!empty($section_text['ENV'])) {
-
 
864
            if (strpos($section_text['ENV'], '{PWD}') !== false) {
-
 
865
                $section_text['ENV'] = str_replace('{PWD}', dirname($temp_file), $section_text['ENV']);
-
 
866
            }
-
 
867
            foreach (explode("\n", trim($section_text['ENV'])) as $e) {
-
 
868
                $e = explode('=', trim($e), 2);
-
 
869
                if (!empty($e[0]) && isset($e[1])) {
-
 
870
                    $env[$e[0]] = $e[1];
-
 
871
                }
-
 
872
            }
-
 
873
        }
-
 
874
        if (array_key_exists('GET', $section_text)) {
-
 
875
            $env['QUERY_STRING'] = trim($section_text['GET']);
-
 
876
        } else {
-
 
877
            $env['QUERY_STRING'] = '';
-
 
878
        }
-
 
879
        if (array_key_exists('COOKIE', $section_text)) {
-
 
880
            $env['HTTP_COOKIE'] = trim($section_text['COOKIE']);
-
 
881
        } else {
-
 
882
            $env['HTTP_COOKIE'] = '';
-
 
883
        }
-
 
884
        $env['REDIRECT_STATUS'] = '1';
-
 
885
        $env['PATH_TRANSLATED'] = $temp_file;
-
 
886
        $env['SCRIPT_FILENAME'] = $temp_file;
-
 
887
 
-
 
888
        return $env;
-
 
889
    }
-
 
890
 
-
 
891
    function _processUpload($section_text, $file)
-
 
892
    {
-
 
893
        if (array_key_exists('UPLOAD', $section_text) && !empty($section_text['UPLOAD'])) {
-
 
894
            $upload_files = trim($section_text['UPLOAD']);
-
 
895
            $upload_files = explode("\n", $upload_files);
-
 
896
 
-
 
897
            $request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" .
-
 
898
                       "-----------------------------20896060251896012921717172737\n";
-
 
899
            foreach ($upload_files as $fileinfo) {
-
 
900
                $fileinfo = explode('=', $fileinfo);
-
 
901
                if (count($fileinfo) != 2) {
-
 
902
                    return PEAR::raiseError("Invalid UPLOAD section in test file: $file");
-
 
903
                }
-
 
904
                if (!realpath(dirname($file) . '/' . $fileinfo[1])) {
-
 
905
                    return PEAR::raiseError("File for upload does not exist: $fileinfo[1] " .
-
 
906
                        "in test file: $file");
-
 
907
                }
-
 
908
                $file_contents = file_get_contents(dirname($file) . '/' . $fileinfo[1]);
-
 
909
                $fileinfo[1] = basename($fileinfo[1]);
-
 
910
                $request .= "Content-Disposition: form-data; name=\"$fileinfo[0]\"; filename=\"$fileinfo[1]\"\n";
-
 
911
                $request .= "Content-Type: text/plain\n\n";
-
 
912
                $request .= $file_contents . "\n" .
-
 
913
                    "-----------------------------20896060251896012921717172737\n";
-
 
914
            }
-
 
915
 
-
 
916
            if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
-
 
917
                // encode POST raw
-
 
918
                $post = trim($section_text['POST']);
-
 
919
                $post = explode('&', $post);
-
 
920
                foreach ($post as $i => $post_info) {
-
 
921
                    $post_info = explode('=', $post_info);
-
 
922
                    if (count($post_info) != 2) {
-
 
923
                        return PEAR::raiseError("Invalid POST data in test file: $file");
-
 
924
                    }
-
 
925
                    $post_info[0] = rawurldecode($post_info[0]);
-
 
926
                    $post_info[1] = rawurldecode($post_info[1]);
-
 
927
                    $post[$i] = $post_info;
-
 
928
                }
-
 
929
                foreach ($post as $post_info) {
-
 
930
                    $request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n";
-
 
931
                    $request .= $post_info[1] . "\n" .
-
 
932
                        "-----------------------------20896060251896012921717172737\n";
-
 
933
                }
-
 
934
                unset($section_text['POST']);
-
 
935
            }
-
 
936
            $section_text['POST_RAW'] = $request;
-
 
937
        }
-
 
938
 
-
 
939
        return $section_text;
-
 
940
    }
-
 
941
 
-
 
942
    function _testCleanup($section_text, $temp_clean)
-
 
943
    {
-
 
944
        if ($section_text['CLEAN']) {
-
 
945
            $this->_restorePHPBinary();
-
 
946
 
-
 
947
            // perform test cleanup
-
 
948
            $this->save_text($temp_clean, $section_text['CLEAN']);
-
 
949
            $output = $this->system_with_timeout("$this->_php $temp_clean  2>&1");
-
 
950
            if (strlen($output[1])) {
-
 
951
                echo "BORKED --CLEAN-- section! output:\n", $output[1];
-
 
952
            }
-
 
953
            if (file_exists($temp_clean)) {
-
 
954
                unlink($temp_clean);
-
 
955
            }
-
 
956
        }
-
 
957
    }
-
 
958
 
-
 
959
    function _savePHPBinary()
-
 
960
    {
-
 
961
        $this->_savephp = $this->_php;
-
 
962
    }
-
 
963
 
-
 
964
    function _restorePHPBinary()
-
 
965
    {
-
 
966
        if (isset($this->_savephp))
-
 
967
        {
-
 
968
            $this->_php = $this->_savephp;
771
";
969
            unset($this->_savephp);
772
    }
-