PageRenderTime 52ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

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

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