PageRenderTime 36ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/phpspec/phpspec/src/PhpSpec/Matcher/ThrowMatcher.php

https://gitlab.com/dzakiafif/cokelatklasik
PHP | 275 lines | 164 code | 32 blank | 79 comment | 20 complexity | 20c398ef19f28952359134eb31fc6b37 MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of PhpSpec, A php toolset to drive emergent
  4. * design by specification.
  5. *
  6. * (c) Marcello Duarte <marcello.duarte@gmail.com>
  7. * (c) Konstantin Kudryashov <ever.zet@gmail.com>
  8. *
  9. * For the full copyright and license information, please view the LICENSE
  10. * file that was distributed with this source code.
  11. */
  12. namespace PhpSpec\Matcher;
  13. use PhpSpec\Formatter\Presenter\PresenterInterface;
  14. use PhpSpec\Wrapper\Unwrapper;
  15. use PhpSpec\Wrapper\DelayedCall;
  16. use PhpSpec\Factory\ReflectionFactory;
  17. use PhpSpec\Exception\Example\MatcherException;
  18. use PhpSpec\Exception\Example\FailureException;
  19. use PhpSpec\Exception\Example\NotEqualException;
  20. use PhpSpec\Exception\Fracture\MethodNotFoundException;
  21. class ThrowMatcher implements MatcherInterface
  22. {
  23. /**
  24. * @var array
  25. */
  26. private static $ignoredProperties = array('file', 'line', 'string', 'trace', 'previous');
  27. /**
  28. * @var \PhpSpec\Wrapper\Unwrapper
  29. */
  30. private $unwrapper;
  31. /**
  32. * @var \PhpSpec\Formatter\Presenter\PresenterInterface
  33. */
  34. private $presenter;
  35. /**
  36. * @var ReflectionFactory
  37. */
  38. private $factory;
  39. /**
  40. * @param Unwrapper $unwrapper
  41. * @param PresenterInterface $presenter
  42. * @param ReflectionFactory $factory
  43. */
  44. public function __construct(Unwrapper $unwrapper, PresenterInterface $presenter, ReflectionFactory $factory = null)
  45. {
  46. $this->unwrapper = $unwrapper;
  47. $this->presenter = $presenter;
  48. $this->factory = $factory ?: new ReflectionFactory();
  49. }
  50. /**
  51. * @param string $name
  52. * @param mixed $subject
  53. * @param array $arguments
  54. *
  55. * @return bool
  56. */
  57. public function supports($name, $subject, array $arguments)
  58. {
  59. return 'throw' === $name;
  60. }
  61. /**
  62. * @param string $name
  63. * @param mixed $subject
  64. * @param array $arguments
  65. *
  66. * @return DelayedCall
  67. */
  68. public function positiveMatch($name, $subject, array $arguments)
  69. {
  70. return $this->getDelayedCall(array($this, 'verifyPositive'), $subject, $arguments);
  71. }
  72. /**
  73. * @param string $name
  74. * @param mixed $subject
  75. * @param array $arguments
  76. *
  77. * @return DelayedCall
  78. */
  79. public function negativeMatch($name, $subject, array $arguments)
  80. {
  81. return $this->getDelayedCall(array($this, 'verifyNegative'), $subject, $arguments);
  82. }
  83. /**
  84. * @param callable $callable
  85. * @param array $arguments
  86. * @param null $exception
  87. *
  88. * @throws \PhpSpec\Exception\Example\FailureException
  89. * @throws \PhpSpec\Exception\Example\NotEqualException
  90. */
  91. public function verifyPositive($callable, array $arguments, $exception = null)
  92. {
  93. try {
  94. call_user_func_array($callable, $arguments);
  95. } catch (\Exception $e) {
  96. if (null === $exception) {
  97. return;
  98. }
  99. if (!$e instanceof $exception) {
  100. throw new FailureException(sprintf(
  101. 'Expected exception of class %s, but got %s.',
  102. $this->presenter->presentValue($exception),
  103. $this->presenter->presentValue($e)
  104. ));
  105. }
  106. if (is_object($exception)) {
  107. $exceptionRefl = $this->factory->create($exception);
  108. foreach ($exceptionRefl->getProperties() as $property) {
  109. if (in_array($property->getName(), self::$ignoredProperties)) {
  110. continue;
  111. }
  112. $property->setAccessible(true);
  113. $expected = $property->getValue($exception);
  114. $actual = $property->getValue($e);
  115. if (null !== $expected && $actual !== $expected) {
  116. throw new NotEqualException(sprintf(
  117. 'Expected exception `%s` to be %s, but it is %s.',
  118. $property->getName(),
  119. $this->presenter->presentValue($expected),
  120. $this->presenter->presentValue($actual)
  121. ), $expected, $actual);
  122. }
  123. }
  124. }
  125. return;
  126. }
  127. throw new FailureException('Expected to get exception, none got.');
  128. }
  129. /**
  130. * @param callable $callable
  131. * @param array $arguments
  132. * @param string|null $exception
  133. *
  134. * @throws \PhpSpec\Exception\Example\FailureException
  135. */
  136. public function verifyNegative($callable, array $arguments, $exception = null)
  137. {
  138. try {
  139. call_user_func_array($callable, $arguments);
  140. } catch (\Exception $e) {
  141. if (null === $exception) {
  142. throw new FailureException(sprintf(
  143. 'Expected to not throw any exceptions, but got %s.',
  144. $this->presenter->presentValue($e)
  145. ));
  146. }
  147. if ($e instanceof $exception) {
  148. $invalidProperties = array();
  149. if (is_object($exception)) {
  150. $exceptionRefl = $this->factory->create($exception);
  151. foreach ($exceptionRefl->getProperties() as $property) {
  152. if (in_array($property->getName(), self::$ignoredProperties)) {
  153. continue;
  154. }
  155. $property->setAccessible(true);
  156. $expected = $property->getValue($exception);
  157. $actual = $property->getValue($e);
  158. if (null !== $expected && $actual === $expected) {
  159. $invalidProperties[] = sprintf(
  160. ' `%s`=%s',
  161. $property->getName(),
  162. $this->presenter->presentValue($expected)
  163. );
  164. }
  165. }
  166. }
  167. $withProperties = '';
  168. if (count($invalidProperties) > 0) {
  169. $withProperties = sprintf(
  170. ' with'.PHP_EOL.'%s,'.PHP_EOL,
  171. implode(",\n", $invalidProperties)
  172. );
  173. }
  174. throw new FailureException(sprintf(
  175. 'Expected to not throw %s exception%s but got it.',
  176. $this->presenter->presentValue($exception),
  177. $withProperties
  178. ));
  179. }
  180. }
  181. }
  182. /**
  183. * @return int
  184. */
  185. public function getPriority()
  186. {
  187. return 1;
  188. }
  189. /**
  190. * @param callable $check
  191. * @param mixed $subject
  192. * @param array $arguments
  193. *
  194. * @return DelayedCall
  195. */
  196. private function getDelayedCall($check, $subject, array $arguments)
  197. {
  198. $exception = $this->getException($arguments);
  199. $unwrapper = $this->unwrapper;
  200. return new DelayedCall(
  201. function ($method, $arguments) use ($check, $subject, $exception, $unwrapper) {
  202. $arguments = $unwrapper->unwrapAll($arguments);
  203. $methodName = $arguments[0];
  204. $arguments = isset($arguments[1]) ? $arguments[1] : array();
  205. $callable = array($subject, $methodName);
  206. list($class, $methodName) = array($subject, $methodName);
  207. if (!method_exists($class, $methodName) && !method_exists($class, '__call')) {
  208. throw new MethodNotFoundException(
  209. sprintf('Method %s::%s not found.', get_class($class), $methodName),
  210. $class,
  211. $methodName,
  212. $arguments
  213. );
  214. }
  215. return call_user_func($check, $callable, $arguments, $exception);
  216. }
  217. );
  218. }
  219. /**
  220. * @param array $arguments
  221. *
  222. * @return null|string
  223. * @throws \PhpSpec\Exception\Example\MatcherException
  224. */
  225. private function getException(array $arguments)
  226. {
  227. if (0 == count($arguments)) {
  228. return null;
  229. }
  230. if (is_string($arguments[0])) {
  231. return $arguments[0];
  232. }
  233. if (is_object($arguments[0]) && $arguments[0] instanceof \Exception) {
  234. return $arguments[0];
  235. }
  236. throw new MatcherException(sprintf(
  237. "Wrong argument provided in throw matcher.\n".
  238. "Fully qualified classname or exception instance expected,\n".
  239. "Got %s.",
  240. $this->presenter->presentValue($arguments[0])
  241. ));
  242. }
  243. }