FlattenExceptionTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Debug\Tests\Exception;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\Debug\Exception\FlattenException;
  13. use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  14. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  15. use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
  16. use Symfony\Component\HttpKernel\Exception\GoneHttpException;
  17. use Symfony\Component\HttpKernel\Exception\LengthRequiredHttpException;
  18. use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
  19. use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
  20. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  21. use Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException;
  22. use Symfony\Component\HttpKernel\Exception\PreconditionRequiredHttpException;
  23. use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
  24. use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
  25. use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
  26. use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
  27. class FlattenExceptionTest extends TestCase
  28. {
  29. public function testStatusCode()
  30. {
  31. $flattened = FlattenException::create(new \RuntimeException(), 403);
  32. $this->assertEquals('403', $flattened->getStatusCode());
  33. $flattened = FlattenException::create(new \RuntimeException());
  34. $this->assertEquals('500', $flattened->getStatusCode());
  35. $flattened = FlattenException::create(new NotFoundHttpException());
  36. $this->assertEquals('404', $flattened->getStatusCode());
  37. $flattened = FlattenException::create(new UnauthorizedHttpException('Basic realm="My Realm"'));
  38. $this->assertEquals('401', $flattened->getStatusCode());
  39. $flattened = FlattenException::create(new BadRequestHttpException());
  40. $this->assertEquals('400', $flattened->getStatusCode());
  41. $flattened = FlattenException::create(new NotAcceptableHttpException());
  42. $this->assertEquals('406', $flattened->getStatusCode());
  43. $flattened = FlattenException::create(new ConflictHttpException());
  44. $this->assertEquals('409', $flattened->getStatusCode());
  45. $flattened = FlattenException::create(new MethodNotAllowedHttpException(array('POST')));
  46. $this->assertEquals('405', $flattened->getStatusCode());
  47. $flattened = FlattenException::create(new AccessDeniedHttpException());
  48. $this->assertEquals('403', $flattened->getStatusCode());
  49. $flattened = FlattenException::create(new GoneHttpException());
  50. $this->assertEquals('410', $flattened->getStatusCode());
  51. $flattened = FlattenException::create(new LengthRequiredHttpException());
  52. $this->assertEquals('411', $flattened->getStatusCode());
  53. $flattened = FlattenException::create(new PreconditionFailedHttpException());
  54. $this->assertEquals('412', $flattened->getStatusCode());
  55. $flattened = FlattenException::create(new PreconditionRequiredHttpException());
  56. $this->assertEquals('428', $flattened->getStatusCode());
  57. $flattened = FlattenException::create(new ServiceUnavailableHttpException());
  58. $this->assertEquals('503', $flattened->getStatusCode());
  59. $flattened = FlattenException::create(new TooManyRequestsHttpException());
  60. $this->assertEquals('429', $flattened->getStatusCode());
  61. $flattened = FlattenException::create(new UnsupportedMediaTypeHttpException());
  62. $this->assertEquals('415', $flattened->getStatusCode());
  63. }
  64. public function testHeadersForHttpException()
  65. {
  66. $flattened = FlattenException::create(new MethodNotAllowedHttpException(array('POST')));
  67. $this->assertEquals(array('Allow' => 'POST'), $flattened->getHeaders());
  68. $flattened = FlattenException::create(new UnauthorizedHttpException('Basic realm="My Realm"'));
  69. $this->assertEquals(array('WWW-Authenticate' => 'Basic realm="My Realm"'), $flattened->getHeaders());
  70. $flattened = FlattenException::create(new ServiceUnavailableHttpException('Fri, 31 Dec 1999 23:59:59 GMT'));
  71. $this->assertEquals(array('Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'), $flattened->getHeaders());
  72. $flattened = FlattenException::create(new ServiceUnavailableHttpException(120));
  73. $this->assertEquals(array('Retry-After' => 120), $flattened->getHeaders());
  74. $flattened = FlattenException::create(new TooManyRequestsHttpException('Fri, 31 Dec 1999 23:59:59 GMT'));
  75. $this->assertEquals(array('Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'), $flattened->getHeaders());
  76. $flattened = FlattenException::create(new TooManyRequestsHttpException(120));
  77. $this->assertEquals(array('Retry-After' => 120), $flattened->getHeaders());
  78. }
  79. /**
  80. * @dataProvider flattenDataProvider
  81. */
  82. public function testFlattenHttpException(\Exception $exception)
  83. {
  84. $flattened = FlattenException::create($exception);
  85. $flattened2 = FlattenException::create($exception);
  86. $flattened->setPrevious($flattened2);
  87. $this->assertEquals($exception->getMessage(), $flattened->getMessage(), 'The message is copied from the original exception.');
  88. $this->assertEquals($exception->getCode(), $flattened->getCode(), 'The code is copied from the original exception.');
  89. $this->assertInstanceOf($flattened->getClass(), $exception, 'The class is set to the class of the original exception');
  90. }
  91. /**
  92. * @dataProvider flattenDataProvider
  93. */
  94. public function testPrevious(\Exception $exception)
  95. {
  96. $flattened = FlattenException::create($exception);
  97. $flattened2 = FlattenException::create($exception);
  98. $flattened->setPrevious($flattened2);
  99. $this->assertSame($flattened2, $flattened->getPrevious());
  100. $this->assertSame(array($flattened2), $flattened->getAllPrevious());
  101. }
  102. /**
  103. * @requires PHP 7.0
  104. */
  105. public function testPreviousError()
  106. {
  107. $exception = new \Exception('test', 123, new \ParseError('Oh noes!', 42));
  108. $flattened = FlattenException::create($exception)->getPrevious();
  109. $this->assertEquals($flattened->getMessage(), 'Parse error: Oh noes!', 'The message is copied from the original exception.');
  110. $this->assertEquals($flattened->getCode(), 42, 'The code is copied from the original exception.');
  111. $this->assertEquals($flattened->getClass(), 'Symfony\Component\Debug\Exception\FatalThrowableError', 'The class is set to the class of the original exception');
  112. }
  113. /**
  114. * @dataProvider flattenDataProvider
  115. */
  116. public function testLine(\Exception $exception)
  117. {
  118. $flattened = FlattenException::create($exception);
  119. $this->assertSame($exception->getLine(), $flattened->getLine());
  120. }
  121. /**
  122. * @dataProvider flattenDataProvider
  123. */
  124. public function testFile(\Exception $exception)
  125. {
  126. $flattened = FlattenException::create($exception);
  127. $this->assertSame($exception->getFile(), $flattened->getFile());
  128. }
  129. /**
  130. * @dataProvider flattenDataProvider
  131. */
  132. public function testToArray(\Exception $exception)
  133. {
  134. $flattened = FlattenException::create($exception);
  135. $flattened->setTrace(array(), 'foo.php', 123);
  136. $this->assertEquals(array(
  137. array(
  138. 'message' => 'test',
  139. 'class' => 'Exception',
  140. 'trace' => array(array(
  141. 'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '', 'file' => 'foo.php', 'line' => 123,
  142. 'args' => array(),
  143. )),
  144. ),
  145. ), $flattened->toArray());
  146. }
  147. public function flattenDataProvider()
  148. {
  149. return array(
  150. array(new \Exception('test', 123)),
  151. );
  152. }
  153. public function testRecursionInArguments()
  154. {
  155. $a = null;
  156. $a = array('foo', array(2, &$a));
  157. $exception = $this->createException($a);
  158. $flattened = FlattenException::create($exception);
  159. $trace = $flattened->getTrace();
  160. $this->assertContains('*DEEP NESTED ARRAY*', serialize($trace));
  161. }
  162. public function testTooBigArray()
  163. {
  164. $a = array();
  165. for ($i = 0; $i < 20; ++$i) {
  166. for ($j = 0; $j < 50; ++$j) {
  167. for ($k = 0; $k < 10; ++$k) {
  168. $a[$i][$j][$k] = 'value';
  169. }
  170. }
  171. }
  172. $a[20] = 'value';
  173. $a[21] = 'value1';
  174. $exception = $this->createException($a);
  175. $flattened = FlattenException::create($exception);
  176. $trace = $flattened->getTrace();
  177. $serializeTrace = serialize($trace);
  178. $this->assertContains('*SKIPPED over 10000 entries*', $serializeTrace);
  179. $this->assertNotContains('*value1*', $serializeTrace);
  180. }
  181. private function createException($foo)
  182. {
  183. return new \Exception();
  184. }
  185. public function testSetTraceIncompleteClass()
  186. {
  187. $flattened = FlattenException::create(new \Exception('test', 123));
  188. $flattened->setTrace(
  189. array(
  190. array(
  191. 'file' => __FILE__,
  192. 'line' => 123,
  193. 'function' => 'test',
  194. 'args' => array(
  195. unserialize('O:14:"BogusTestClass":0:{}'),
  196. ),
  197. ),
  198. ),
  199. 'foo.php', 123
  200. );
  201. $this->assertEquals(array(
  202. array(
  203. 'message' => 'test',
  204. 'class' => 'Exception',
  205. 'trace' => array(
  206. array(
  207. 'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '',
  208. 'file' => 'foo.php', 'line' => 123,
  209. 'args' => array(),
  210. ),
  211. array(
  212. 'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => 'test',
  213. 'file' => __FILE__, 'line' => 123,
  214. 'args' => array(
  215. array(
  216. 'incomplete-object', 'BogusTestClass',
  217. ),
  218. ),
  219. ),
  220. ),
  221. ),
  222. ), $flattened->toArray());
  223. }
  224. }