PageRenderTime 27ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/phpunit/phpunit/PHPUnit/Util/PHP.php

https://gitlab.com/karora/awl
PHP | 333 lines | 236 code | 7 blank | 90 comment | 18 complexity | eff959a80282741968820e4005e2f49a MD5 | raw file
  1. <?php
  2. /**
  3. * PHPUnit
  4. *
  5. * Copyright (c) 2001-2012, 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 2001-2012 Sebastian Bergmann <sebastian@phpunit.de>
  41. * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License
  42. * @link http://www.phpunit.de/
  43. * @since File available since Release 3.4.0
  44. */
  45. /**
  46. * Utility methods for PHP sub-processes.
  47. *
  48. * @package PHPUnit
  49. * @subpackage Util
  50. * @author Sebastian Bergmann <sebastian@phpunit.de>
  51. * @copyright 2001-2012 Sebastian Bergmann <sebastian@phpunit.de>
  52. * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License
  53. * @version Release: @package_version@
  54. * @link http://www.phpunit.de/
  55. * @since Class available since Release 3.4.0
  56. */
  57. abstract class PHPUnit_Util_PHP
  58. {
  59. /**
  60. * @var string $phpBinary
  61. */
  62. protected $phpBinary;
  63. /**
  64. * Returns the path to a PHP interpreter.
  65. *
  66. * PHPUnit_Util_PHP::$phpBinary contains the path to the PHP
  67. * interpreter.
  68. *
  69. * When not set, the following assumptions will be made:
  70. *
  71. * 1. When PHPUnit is run using the CLI SAPI and the $_SERVER['_']
  72. * variable does not contain the string "PHPUnit", $_SERVER['_']
  73. * is assumed to contain the path to the current PHP interpreter
  74. * and that will be used.
  75. *
  76. * 2. When PHPUnit is run using the CLI SAPI and the $_SERVER['_']
  77. * variable contains the string "PHPUnit", the file that $_SERVER['_']
  78. * points to is assumed to be the PHPUnit TextUI CLI wrapper script
  79. * "phpunit" and the binary set up using #! on that file's first
  80. * line of code is assumed to contain the path to the current PHP
  81. * interpreter and that will be used.
  82. *
  83. * 3. When the PHP CLI/CGI binary configured with the PEAR Installer
  84. * (php_bin configuration value) is readable, it will be used.
  85. *
  86. * 4. The current PHP interpreter is assumed to be in the $PATH and
  87. * to be invokable through "php".
  88. *
  89. * @return string
  90. */
  91. protected function getPhpBinary()
  92. {
  93. if ($this->phpBinary === NULL) {
  94. if (defined("PHP_BINARY")) {
  95. $this->phpBinary = PHP_BINARY;
  96. } else if (PHP_SAPI == 'cli' && isset($_SERVER['_'])) {
  97. if (strpos($_SERVER['_'], 'phpunit') !== FALSE) {
  98. $file = file($_SERVER['_']);
  99. if (strpos($file[0], ' ') !== FALSE) {
  100. $tmp = explode(' ', $file[0]);
  101. $this->phpBinary = trim($tmp[1]);
  102. } else {
  103. $this->phpBinary = ltrim(trim($file[0]), '#!');
  104. }
  105. } else if (strpos(basename($_SERVER['_']), 'php') !== FALSE) {
  106. $this->phpBinary = $_SERVER['_'];
  107. }
  108. }
  109. if ($this->phpBinary === NULL) {
  110. $possibleBinaryLocations = array(
  111. PHP_BINDIR . '/php',
  112. PHP_BINDIR . '/php-cli.exe',
  113. PHP_BINDIR . '/php.exe',
  114. '@php_bin@',
  115. );
  116. foreach ($possibleBinaryLocations as $binary) {
  117. if (is_readable($binary)) {
  118. $this->phpBinary = $binary;
  119. break;
  120. }
  121. }
  122. }
  123. if (!is_readable($this->phpBinary)) {
  124. $this->phpBinary = 'php';
  125. } else {
  126. $this->phpBinary = escapeshellcmd($this->phpBinary);
  127. }
  128. }
  129. return $this->phpBinary;
  130. }
  131. /**
  132. * @return PHPUnit_Util_PHP
  133. * @since Method available since Release 3.5.12
  134. */
  135. public static function factory()
  136. {
  137. if (DIRECTORY_SEPARATOR == '\\') {
  138. return new PHPUnit_Util_PHP_Windows;
  139. }
  140. return new PHPUnit_Util_PHP_Default;
  141. }
  142. /**
  143. * Runs a single job (PHP code) using a separate PHP process.
  144. *
  145. * @param string $job
  146. * @param PHPUnit_Framework_TestCase $test
  147. * @param PHPUnit_Framework_TestResult $result
  148. * @return array|null
  149. * @throws PHPUnit_Framework_Exception
  150. */
  151. public function runJob($job, PHPUnit_Framework_Test $test = NULL, PHPUnit_Framework_TestResult $result = NULL)
  152. {
  153. $process = proc_open(
  154. $this->getPhpBinary(),
  155. array(
  156. 0 => array('pipe', 'r'),
  157. 1 => array('pipe', 'w'),
  158. 2 => array('pipe', 'w')
  159. ),
  160. $pipes
  161. );
  162. if (!is_resource($process)) {
  163. throw new PHPUnit_Framework_Exception(
  164. 'Unable to create process for process isolation.'
  165. );
  166. }
  167. if ($result !== NULL) {
  168. $result->startTest($test);
  169. }
  170. $this->process($pipes[0], $job);
  171. fclose($pipes[0]);
  172. $stdout = stream_get_contents($pipes[1]);
  173. fclose($pipes[1]);
  174. $stderr = stream_get_contents($pipes[2]);
  175. fclose($pipes[2]);
  176. proc_close($process);
  177. $this->cleanup();
  178. if ($result !== NULL) {
  179. $this->processChildResult($test, $result, $stdout, $stderr);
  180. } else {
  181. return array('stdout' => $stdout, 'stderr' => $stderr);
  182. }
  183. }
  184. /**
  185. * @param resource $pipe
  186. * @param string $job
  187. * @since Method available since Release 3.5.12
  188. */
  189. abstract protected function process($pipe, $job);
  190. /**
  191. * @since Method available since Release 3.5.12
  192. */
  193. protected function cleanup()
  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 PHPUnit_Framework_Exception(trim($stderr)), $time
  212. );
  213. } else {
  214. set_error_handler(function($errno, $errstr, $errfile, $errline) {
  215. throw new ErrorException($errstr, $errno, $errno, $errfile, $errline);
  216. });
  217. try {
  218. $childResult = unserialize($stdout);
  219. restore_error_handler();
  220. } catch (ErrorException $e) {
  221. restore_error_handler();
  222. $childResult = FALSE;
  223. $time = 0;
  224. $result->addError(
  225. $test, new PHPUnit_Framework_Exception(trim($stdout), 0, $e), $time
  226. );
  227. }
  228. if ($childResult !== FALSE) {
  229. if (!empty($childResult['output'])) {
  230. print $childResult['output'];
  231. }
  232. $test->setResult($childResult['testResult']);
  233. $test->addToAssertionCount($childResult['numAssertions']);
  234. $childResult = $childResult['result'];
  235. if ($result->getCollectCodeCoverageInformation()) {
  236. $result->getCodeCoverage()->merge(
  237. $childResult->getCodeCoverage()
  238. );
  239. }
  240. $time = $childResult->time();
  241. $notImplemented = $childResult->notImplemented();
  242. $skipped = $childResult->skipped();
  243. $errors = $childResult->errors();
  244. $failures = $childResult->failures();
  245. if (!empty($notImplemented)) {
  246. $result->addError(
  247. $test, $this->getException($notImplemented[0]), $time
  248. );
  249. }
  250. else if (!empty($skipped)) {
  251. $result->addError(
  252. $test, $this->getException($skipped[0]), $time
  253. );
  254. }
  255. else if (!empty($errors)) {
  256. $result->addError(
  257. $test, $this->getException($errors[0]), $time
  258. );
  259. }
  260. else if (!empty($failures)) {
  261. $result->addFailure(
  262. $test, $this->getException($failures[0]), $time
  263. );
  264. }
  265. }
  266. }
  267. $result->endTest($test, $time);
  268. }
  269. /**
  270. * Gets the thrown exception from a PHPUnit_Framework_TestFailure.
  271. *
  272. * @param PHPUnit_Framework_TestFailure $error
  273. * @since Method available since Release 3.6.0
  274. * @see https://github.com/sebastianbergmann/phpunit/issues/74
  275. */
  276. protected function getException(PHPUnit_Framework_TestFailure $error)
  277. {
  278. $exception = $error->thrownException();
  279. if ($exception instanceof __PHP_Incomplete_Class) {
  280. $exceptionArray = array();
  281. foreach ((array)$exception as $key => $value) {
  282. $key = substr($key, strrpos($key, "\0") + 1);
  283. $exceptionArray[$key] = $value;
  284. }
  285. $exception = new PHPUnit_Framework_SyntheticError(
  286. sprintf(
  287. '%s: %s',
  288. $exceptionArray['_PHP_Incomplete_Class_Name'],
  289. $exceptionArray['message']
  290. ),
  291. $exceptionArray['code'],
  292. $exceptionArray['file'],
  293. $exceptionArray['line'],
  294. $exceptionArray['trace']
  295. );
  296. }
  297. return $exception;
  298. }
  299. }