FlattenExceptionTest.php 6.1 KB

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