LoggerDataCollectorTest.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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\HttpKernel\Tests\DataCollector;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext;
  13. use Symfony\Component\HttpFoundation\Request;
  14. use Symfony\Component\HttpFoundation\RequestStack;
  15. use Symfony\Component\HttpFoundation\Response;
  16. use Symfony\Component\HttpKernel\DataCollector\LoggerDataCollector;
  17. use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
  18. use Symfony\Component\VarDumper\Cloner\Data;
  19. class LoggerDataCollectorTest extends TestCase
  20. {
  21. public function testCollectWithUnexpectedFormat()
  22. {
  23. $logger = $this
  24. ->getMockBuilder(DebugLoggerInterface::class)
  25. ->onlyMethods(['countErrors', 'getLogs', 'clear'])
  26. ->getMock();
  27. $logger->expects($this->once())->method('countErrors')->willReturn(123);
  28. $logger->expects($this->exactly(2))->method('getLogs')->willReturn([]);
  29. $c = new LoggerDataCollector($logger, __DIR__.'/');
  30. $c->lateCollect();
  31. $compilerLogs = $c->getCompilerLogs()->getValue('message');
  32. $this->assertSame([
  33. ['message' => 'Removed service "Psr\Container\ContainerInterface"; reason: private alias.'],
  34. ['message' => 'Removed service "Symfony\Component\DependencyInjection\ContainerInterface"; reason: private alias.'],
  35. ], $compilerLogs['Symfony\Component\DependencyInjection\Compiler\RemovePrivateAliasesPass']);
  36. $this->assertSame([
  37. ['message' => 'Some custom logging message'],
  38. ['message' => 'With ending :'],
  39. ], $compilerLogs['Unknown Compiler Pass']);
  40. }
  41. public function testCollectFromDeprecationsLog()
  42. {
  43. $containerPathPrefix = __DIR__.'/';
  44. $path = $containerPathPrefix.'Deprecations.log';
  45. touch($path);
  46. file_put_contents($path, serialize([[
  47. 'type' => 16384,
  48. 'message' => 'The "Symfony\Bundle\FrameworkBundle\Controller\Controller" class is deprecated since Symfony 4.2, use Symfony\Bundle\FrameworkBundle\Controller\AbstractController instead.',
  49. 'file' => '/home/hamza/projet/contrib/sf/vendor/symfony/framework-bundle/Controller/Controller.php',
  50. 'line' => 17,
  51. 'trace' => [[
  52. 'file' => '/home/hamza/projet/contrib/sf/src/Controller/DefaultController.php',
  53. 'line' => 9,
  54. 'function' => 'spl_autoload_call',
  55. ]],
  56. 'count' => 1,
  57. ]]));
  58. $logger = $this
  59. ->getMockBuilder(DebugLoggerInterface::class)
  60. ->onlyMethods(['countErrors', 'getLogs', 'clear'])
  61. ->getMock();
  62. $logger->expects($this->once())->method('countErrors')->willReturn(0);
  63. $logger->expects($this->exactly(2))->method('getLogs')->willReturn([]);
  64. $c = new LoggerDataCollector($logger, $containerPathPrefix);
  65. $c->lateCollect();
  66. $processedLogs = $c->getProcessedLogs();
  67. $this->assertCount(1, $processedLogs);
  68. $this->assertEquals($processedLogs[0]['type'], 'deprecation');
  69. $this->assertEquals($processedLogs[0]['errorCount'], 1);
  70. $this->assertEquals($processedLogs[0]['timestamp'], (new \DateTimeImmutable())->setTimestamp(filemtime($path))->format(\DateTimeInterface::RFC3339_EXTENDED));
  71. $this->assertEquals($processedLogs[0]['priority'], 100);
  72. $this->assertEquals($processedLogs[0]['priorityName'], 'DEBUG');
  73. $this->assertNull($processedLogs[0]['channel']);
  74. $this->assertInstanceOf(Data::class, $processedLogs[0]['message']);
  75. $this->assertInstanceOf(Data::class, $processedLogs[0]['context']);
  76. @unlink($path);
  77. }
  78. public function testWithMainRequest()
  79. {
  80. $mainRequest = new Request();
  81. $stack = new RequestStack();
  82. $stack->push($mainRequest);
  83. $logger = $this
  84. ->getMockBuilder(DebugLoggerInterface::class)
  85. ->onlyMethods(['countErrors', 'getLogs', 'clear'])
  86. ->getMock();
  87. $logger->expects($this->once())->method('countErrors')->with(null);
  88. $logger->expects($this->exactly(2))->method('getLogs')->with(null)->willReturn([]);
  89. $c = new LoggerDataCollector($logger, __DIR__.'/', $stack);
  90. $c->collect($mainRequest, new Response());
  91. $c->lateCollect();
  92. }
  93. public function testWithSubRequest()
  94. {
  95. $mainRequest = new Request();
  96. $subRequest = new Request();
  97. $stack = new RequestStack();
  98. $stack->push($mainRequest);
  99. $stack->push($subRequest);
  100. $logger = $this
  101. ->getMockBuilder(DebugLoggerInterface::class)
  102. ->onlyMethods(['countErrors', 'getLogs', 'clear'])
  103. ->getMock();
  104. $logger->expects($this->once())->method('countErrors')->with($subRequest);
  105. $logger->expects($this->exactly(2))->method('getLogs')->with($subRequest)->willReturn([]);
  106. $c = new LoggerDataCollector($logger, __DIR__.'/', $stack);
  107. $c->collect($subRequest, new Response());
  108. $c->lateCollect();
  109. }
  110. /**
  111. * @dataProvider getCollectTestData
  112. */
  113. public function testCollect($nb, $logs, $expectedLogs, $expectedDeprecationCount, $expectedScreamCount, $expectedPriorities = null)
  114. {
  115. $logger = $this
  116. ->getMockBuilder(DebugLoggerInterface::class)
  117. ->onlyMethods(['countErrors', 'getLogs', 'clear'])
  118. ->getMock();
  119. $logger->expects($this->once())->method('countErrors')->willReturn($nb);
  120. $logger->expects($this->exactly(2))->method('getLogs')->willReturn($logs);
  121. $c = new LoggerDataCollector($logger);
  122. $c->lateCollect();
  123. $this->assertEquals('logger', $c->getName());
  124. $this->assertEquals($nb, $c->countErrors());
  125. $logs = array_map(function ($v) {
  126. if (isset($v['context']['exception'])) {
  127. $e = &$v['context']['exception'];
  128. $e = isset($e["\0*\0message"]) ? [$e["\0*\0message"], $e["\0*\0severity"]] : [$e["\0Symfony\Component\ErrorHandler\Exception\SilencedErrorContext\0severity"]];
  129. }
  130. return $v;
  131. }, $c->getLogs()->getValue(true));
  132. $this->assertEquals($expectedLogs, $logs);
  133. $this->assertEquals($expectedDeprecationCount, $c->countDeprecations());
  134. $this->assertEquals($expectedScreamCount, $c->countScreams());
  135. if (isset($expectedPriorities)) {
  136. $this->assertSame($expectedPriorities, $c->getPriorities()->getValue(true));
  137. }
  138. }
  139. public function testReset()
  140. {
  141. $logger = $this
  142. ->getMockBuilder(DebugLoggerInterface::class)
  143. ->onlyMethods(['countErrors', 'getLogs', 'clear'])
  144. ->getMock();
  145. $logger->expects($this->once())->method('clear');
  146. $c = new LoggerDataCollector($logger);
  147. $c->reset();
  148. }
  149. public static function getCollectTestData()
  150. {
  151. yield 'simple log' => [
  152. 1,
  153. [['message' => 'foo', 'context' => [], 'priority' => 100, 'priorityName' => 'DEBUG']],
  154. [['message' => 'foo', 'context' => [], 'priority' => 100, 'priorityName' => 'DEBUG']],
  155. 0,
  156. 0,
  157. ];
  158. yield 'log with a context' => [
  159. 1,
  160. [['message' => 'foo', 'context' => ['foo' => 'bar'], 'priority' => 100, 'priorityName' => 'DEBUG']],
  161. [['message' => 'foo', 'context' => ['foo' => 'bar'], 'priority' => 100, 'priorityName' => 'DEBUG']],
  162. 0,
  163. 0,
  164. ];
  165. if (!class_exists(SilencedErrorContext::class)) {
  166. return;
  167. }
  168. yield 'logs with some deprecations' => [
  169. 1,
  170. [
  171. ['message' => 'foo3', 'context' => ['exception' => new \ErrorException('warning', 0, \E_USER_WARNING)], 'priority' => 100, 'priorityName' => 'DEBUG'],
  172. ['message' => 'foo', 'context' => ['exception' => new \ErrorException('deprecated', 0, \E_DEPRECATED)], 'priority' => 100, 'priorityName' => 'DEBUG'],
  173. ['message' => 'foo2', 'context' => ['exception' => new \ErrorException('deprecated', 0, \E_USER_DEPRECATED)], 'priority' => 100, 'priorityName' => 'DEBUG'],
  174. ],
  175. [
  176. ['message' => 'foo3', 'context' => ['exception' => ['warning', \E_USER_WARNING]], 'priority' => 100, 'priorityName' => 'DEBUG'],
  177. ['message' => 'foo', 'context' => ['exception' => ['deprecated', \E_DEPRECATED]], 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => false],
  178. ['message' => 'foo2', 'context' => ['exception' => ['deprecated', \E_USER_DEPRECATED]], 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => false],
  179. ],
  180. 2,
  181. 0,
  182. [100 => ['count' => 3, 'name' => 'DEBUG']],
  183. ];
  184. yield 'logs with some silent errors' => [
  185. 1,
  186. [
  187. ['message' => 'foo3', 'context' => ['exception' => new \ErrorException('warning', 0, \E_USER_WARNING)], 'priority' => 100, 'priorityName' => 'DEBUG'],
  188. ['message' => 'foo3', 'context' => ['exception' => new SilencedErrorContext(\E_USER_WARNING, __FILE__, __LINE__)], 'priority' => 100, 'priorityName' => 'DEBUG'],
  189. ['message' => '0', 'context' => ['exception' => new SilencedErrorContext(\E_USER_WARNING, __FILE__, __LINE__)], 'priority' => 100, 'priorityName' => 'DEBUG'],
  190. ],
  191. [
  192. ['message' => 'foo3', 'context' => ['exception' => ['warning', \E_USER_WARNING]], 'priority' => 100, 'priorityName' => 'DEBUG'],
  193. ['message' => 'foo3', 'context' => ['exception' => [\E_USER_WARNING]], 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => true],
  194. ['message' => '0', 'context' => ['exception' => [\E_USER_WARNING]], 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => true],
  195. ],
  196. 0,
  197. 2,
  198. ];
  199. }
  200. }