FlattenExceptionTest.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <?php
  2. namespace yiiunit\debug;
  3. use yii\debug\FlattenException;
  4. use yii\web\NotFoundHttpException;
  5. /**
  6. * @author Dmitry Bashkarev <dmitry@bashkarev.com>
  7. */
  8. class FlattenExceptionTest extends TestCase
  9. {
  10. protected function setUp()
  11. {
  12. ini_set('zend.exception_ignore_args', false);
  13. }
  14. public function testMessage()
  15. {
  16. $flattened = new FlattenException(new \Exception('test'));
  17. $this->assertEquals('test', $flattened->getMessage());
  18. }
  19. public function testCode()
  20. {
  21. $flattened = new FlattenException(new \Exception('test', 100));
  22. $this->assertEquals(100, $flattened->getCode());
  23. }
  24. public function testFile()
  25. {
  26. $flattened = new FlattenException(new \Exception('test', 100));
  27. $this->assertEquals(__FILE__, $flattened->getFile());
  28. }
  29. public function testLine()
  30. {
  31. $flattened = new FlattenException(new \Exception('test', 100));
  32. $this->assertEquals(__LINE__ - 1, $flattened->getLine());
  33. }
  34. public function testTrace()
  35. {
  36. $i = (new \Exception('test'));
  37. $flattened = new FlattenException($i);
  38. $trace = $flattened->getTrace();
  39. $this->assertEquals(__NAMESPACE__, $trace[0]['namespace']);
  40. $this->assertEquals(__CLASS__, $trace[0]['class']);
  41. $this->assertEquals('FlattenExceptionTest', $trace[0]['short_class']);
  42. $this->assertEquals(__FUNCTION__, $trace[0]['function']);
  43. }
  44. public function testPrevious()
  45. {
  46. $exception2 = new \Exception;
  47. $exception = new \Exception('test', 0, $exception2);
  48. $flattened = new FlattenException($exception);
  49. $flattened2 = new FlattenException($exception2);
  50. $this->assertSame($flattened2->getTrace(), $flattened->getPrevious()->getTrace());
  51. }
  52. public function testTraceAsString()
  53. {
  54. $exception = $this->createException('test');
  55. $this->assertEquals($exception->getTraceAsString(), (new FlattenException($exception))->getTraceAsString());
  56. }
  57. public function testToString()
  58. {
  59. $exception = new \Exception();
  60. $this->assertEquals($exception->__toString(), (new FlattenException($exception))->__toString(), 'empty');
  61. $exception = new \Exception('test');
  62. $this->assertEquals($exception->__toString(), (new FlattenException($exception))->__toString());
  63. }
  64. public function testClass()
  65. {
  66. $this->assertEquals((new FlattenException(new \Exception()))->getClass(), 'Exception');
  67. }
  68. public function testArguments()
  69. {
  70. if (defined('HHVM_VERSION')) {
  71. $this->markTestSkipped('HHVM skip');
  72. }
  73. $dh = opendir(__DIR__);
  74. $fh = tmpfile();
  75. $incomplete = unserialize('O:14:"BogusTestClass":0:{}');
  76. $exception = $this->createException([
  77. (object)['foo' => 1],
  78. new NotFoundHttpException(),
  79. $incomplete,
  80. $dh,
  81. $fh,
  82. function () {
  83. },
  84. [1, 2],
  85. ['foo' => 123],
  86. null,
  87. true,
  88. false,
  89. 0,
  90. 0.0,
  91. '0',
  92. '',
  93. INF,
  94. NAN,
  95. ]);
  96. $flattened = new FlattenException($exception);
  97. $trace = $flattened->getTrace();
  98. $args = $trace[0]['args'];
  99. $array = $args[0][1];
  100. closedir($dh);
  101. fclose($fh);
  102. $i = 0;
  103. $this->assertSame(['object', 'stdClass'], $array[$i++]);
  104. $this->assertSame(['object', 'yii\web\NotFoundHttpException'], $array[$i++]);
  105. $this->assertSame(['incomplete-object', 'BogusTestClass'], $array[$i++]);
  106. $this->assertSame(['resource', 'stream'], $array[$i++]);
  107. $this->assertSame(['resource', 'stream'], $array[$i++]);
  108. $args = $array[$i++];
  109. $this->assertSame($args[0], 'object');
  110. $this->assertTrue('Closure' === $args[1] || is_subclass_of($args[1], '\Closure'),
  111. 'Expect object class name to be Closure or a subclass of Closure.');
  112. $this->assertSame(['array', [['integer', 1], ['integer', 2]]], $array[$i++]);
  113. $this->assertSame(['array', ['foo' => ['integer', 123]]], $array[$i++]);
  114. $this->assertSame(['null', null], $array[$i++]);
  115. $this->assertSame(['boolean', true], $array[$i++]);
  116. $this->assertSame(['boolean', false], $array[$i++]);
  117. $this->assertSame(['integer', 0], $array[$i++]);
  118. $this->assertSame(['float', 0.0], $array[$i++]);
  119. $this->assertSame(['string', '0'], $array[$i++]);
  120. $this->assertSame(['string', ''], $array[$i++]);
  121. $this->assertSame(['float', INF], $array[$i++]);
  122. // assertEquals() does not like NAN values.
  123. $this->assertEquals($array[$i][0], 'float');
  124. $this->assertTrue(is_nan($array[$i++][1]));
  125. }
  126. public function testClosureSerialize()
  127. {
  128. $exception = $this->createException(function () {
  129. return 1 + 1;
  130. });
  131. $flattened = new FlattenException($exception);
  132. $this->assertContains('Closure', serialize($flattened));
  133. }
  134. public function testRecursionInArguments()
  135. {
  136. $a = ['foo'];
  137. $a[] = [2, &$a];
  138. $exception = $this->createException($a);
  139. $flattened = new FlattenException($exception);
  140. $trace = $flattened->getTrace();
  141. $this->assertContains('*DEEP NESTED ARRAY*', serialize($trace));
  142. }
  143. public function testTooBigArray()
  144. {
  145. $a = [];
  146. for ($i = 0; $i < 20; ++$i) {
  147. for ($j = 0; $j < 50; ++$j) {
  148. for ($k = 0; $k < 10; ++$k) {
  149. $a[$i][$j][$k] = 'value';
  150. }
  151. }
  152. }
  153. $a[20] = 'value';
  154. $a[21] = 'value1';
  155. $exception = $this->createException($a);
  156. $flattened = new FlattenException($exception);
  157. $trace = $flattened->getTrace();
  158. $this->assertSame($trace[0]['args'][0], ['array', ['array', '*SKIPPED over 10000 entries*']]);
  159. $serializeTrace = serialize($trace);
  160. $this->assertContains('*SKIPPED over 10000 entries*', $serializeTrace);
  161. $this->assertNotContains('*value1*', $serializeTrace);
  162. }
  163. private function createException($foo)
  164. {
  165. return new \Exception();
  166. }
  167. }