]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/PHPUnit/Util/PHP.php
Release 6.2.0
[Github/sugarcrm.git] / tests / PHPUnit / PHPUnit / Util / PHP.php
1 <?php
2 /**
3  * PHPUnit
4  *
5  * Copyright (c) 2002-2011, Sebastian Bergmann <sebastian@phpunit.de>.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *
15  *   * Redistributions in binary form must reproduce the above copyright
16  *     notice, this list of conditions and the following disclaimer in
17  *     the documentation and/or other materials provided with the
18  *     distribution.
19  *
20  *   * Neither the name of Sebastian Bergmann nor the names of his
21  *     contributors may be used to endorse or promote products derived
22  *     from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  * @package    PHPUnit
38  * @subpackage Util
39  * @author     Sebastian Bergmann <sebastian@phpunit.de>
40  * @copyright  2002-2011 Sebastian Bergmann <sebastian@phpunit.de>
41  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
42  * @link       http://www.phpunit.de/
43  * @since      File available since Release 3.4.0
44  */
45
46 /**
47  * Utility methods for PHP sub-processes.
48  *
49  * @package    PHPUnit
50  * @subpackage Util
51  * @author     Sebastian Bergmann <sebastian@phpunit.de>
52  * @copyright  2002-2011 Sebastian Bergmann <sebastian@phpunit.de>
53  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
54  * @version    Release: @package_version@
55  * @link       http://www.phpunit.de/
56  * @since      Class available since Release 3.4.0
57  */
58 abstract class PHPUnit_Util_PHP
59 {
60     /**
61      * Path to the PHP interpreter that is to be used.
62      *
63      * @var    string $phpBinary
64      */
65     protected static $phpBinary = NULL;
66
67     /**
68      * Returns the path to a PHP interpreter.
69      *
70      * PHPUnit_Util_PHP::$phpBinary contains the path to the PHP
71      * interpreter.
72      *
73      * When not set, the following assumptions will be made:
74      *
75      *   1. When the PHP CLI/CGI binary configured with the PEAR Installer
76      *      (php_bin configuration value) is readable, it will be used.
77      *
78      *   2. When PHPUnit is run using the CLI SAPI and the $_SERVER['_']
79      *      variable does not contain the string "PHPUnit", $_SERVER['_']
80      *      is assumed to contain the path to the current PHP interpreter
81      *      and that will be used.
82      *
83      *   3. When PHPUnit is run using the CLI SAPI and the $_SERVER['_']
84      *      variable contains the string "PHPUnit", the file that $_SERVER['_']
85      *      points to is assumed to be the PHPUnit TextUI CLI wrapper script
86      *      "phpunit" and the binary set up using #! on that file's first
87      *      line of code is assumed to contain the path to the current PHP
88      *      interpreter and that will be used.
89      *
90      *   4. The current PHP interpreter is assumed to be in the $PATH and
91      *      to be invokable through "php".
92      *
93      * @return string
94      */
95     public static function getPhpBinary()
96     {
97         if (self::$phpBinary === NULL) {
98             if (is_readable('@php_bin@')) {
99                 self::$phpBinary = '@php_bin@';
100             }
101
102             else if (PHP_SAPI == 'cli' && isset($_SERVER['_']) &&
103                      strpos($_SERVER['_'], 'phpunit') !== FALSE) {
104                 $file            = file($_SERVER['_']);
105                 $tmp             = explode(' ', $file[0]);
106                 self::$phpBinary = trim($tmp[1]);
107             }
108
109             if (!is_readable(self::$phpBinary)) {
110                 self::$phpBinary = 'php';
111             } else {
112                 self::$phpBinary = escapeshellarg(self::$phpBinary);
113             }
114         }
115
116         return self::$phpBinary;
117     }
118
119     /**
120      * @return PHPUnit_Util_PHP
121      * @since  Method available since Release 3.5.12
122      */
123     public static function factory()
124     {
125         if (DIRECTORY_SEPARATOR == '\\') {
126             return new PHPUnit_Util_PHP_Windows;
127         }
128
129         return new PHPUnit_Util_PHP_Default;
130     }
131
132     /**
133      * Runs a single job (PHP code) using a separate PHP process.
134      *
135      * @param  string                       $job
136      * @param  PHPUnit_Framework_TestCase   $test
137      * @param  PHPUnit_Framework_TestResult $result
138      * @return array|null
139      * @throws PHPUnit_Framework_Exception
140      */
141     public function runJob($job, PHPUnit_Framework_Test $test = NULL, PHPUnit_Framework_TestResult $result = NULL)
142     {
143         $process = proc_open(
144           self::getPhpBinary(),
145           array(
146             0 => array('pipe', 'r'),
147             1 => array('pipe', 'w'),
148             2 => array('pipe', 'w')
149           ),
150           $pipes
151         );
152
153         if (!is_resource($process)) {
154             throw new PHPUnit_Framework_Exception(
155               'Unable to create process for process isolation.'
156             );
157         }
158
159         if ($result !== NULL) {
160             $result->startTest($test);
161         }
162
163         $this->process($pipes[0], $job);
164         fclose($pipes[0]);
165
166         $stdout = stream_get_contents($pipes[1]);
167         fclose($pipes[1]);
168
169         $stderr = stream_get_contents($pipes[2]);
170         fclose($pipes[2]);
171
172         proc_close($process);
173         $this->cleanup();
174
175         if ($result !== NULL) {
176             $this->processChildResult($test, $result, $stdout, $stderr);
177         } else {
178             return array('stdout' => $stdout, 'stderr' => $stderr);
179         }
180     }
181
182     /**
183      * @param resource $pipe
184      * @param string   $job
185      * @since Method available since Release 3.5.12
186      */
187     abstract protected function process($pipe, $job);
188
189     /**
190      * @since Method available since Release 3.5.12
191      */
192     protected function cleanup()
193     {
194     }
195
196     /**
197      * Processes the TestResult object from an isolated process.
198      *
199      * @param PHPUnit_Framework_TestCase   $test
200      * @param PHPUnit_Framework_TestResult $result
201      * @param string                       $stdout
202      * @param string                       $stderr
203      * @since Method available since Release 3.5.0
204      */
205     protected function processChildResult(PHPUnit_Framework_Test $test, PHPUnit_Framework_TestResult $result, $stdout, $stderr)
206     {
207         if (!empty($stderr)) {
208             $time = 0;
209             $result->addError(
210               $test,
211               new RuntimeException(trim($stderr)), $time
212             );
213         } else {
214             $childResult = @unserialize($stdout);
215
216             if ($childResult !== FALSE) {
217                 if (!empty($childResult['output'])) {
218                     print $childResult['output'];
219                 }
220
221                 $test->setResult($childResult['testResult']);
222                 $test->addToAssertionCount($childResult['numAssertions']);
223
224                 $childResult = $childResult['result'];
225
226                 if ($result->getCollectCodeCoverageInformation()) {
227                     $codeCoverageInformation = $childResult->getRawCodeCoverageInformation();
228
229                     if (isset($codeCoverageInformation[0]) &&
230                          is_array($codeCoverageInformation[0])) {
231                         $result->getCodeCoverage()->append(
232                           $codeCoverageInformation[0], $test
233                         );
234                     }
235                 }
236
237                 $time           = $childResult->time();
238                 $notImplemented = $childResult->notImplemented();
239                 $skipped        = $childResult->skipped();
240                 $errors         = $childResult->errors();
241                 $failures       = $childResult->failures();
242
243                 if (!empty($notImplemented)) {
244                     $result->addError(
245                       $test, $notImplemented[0]->thrownException(), $time
246                     );
247                 }
248
249                 else if (!empty($skipped)) {
250                     $result->addError(
251                       $test, $skipped[0]->thrownException(), $time
252                     );
253                 }
254
255                 else if (!empty($errors)) {
256                     $result->addError(
257                       $test, $errors[0]->thrownException(), $time
258                     );
259                 }
260
261                 else if (!empty($failures)) {
262                     $result->addFailure(
263                       $test, $failures[0]->thrownException(), $time
264                     );
265                 }
266             } else {
267                 $time = 0;
268
269                 $result->addError(
270                   $test, new RuntimeException(trim($stdout)), $time
271                 );
272             }
273         }
274
275         $result->endTest($test, $time);
276     }
277 }