1<?php 2 3/* 4 * This file is part of the Symfony package. 5 * 6 * (c) Fabien Potencier <fabien@symfony.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Symfony\Component\Console\Tests\EventListener; 13 14use PHPUnit\Framework\TestCase; 15use Psr\Log\LoggerInterface; 16use Symfony\Component\Console\Command\Command; 17use Symfony\Component\Console\Event\ConsoleErrorEvent; 18use Symfony\Component\Console\Event\ConsoleTerminateEvent; 19use Symfony\Component\Console\EventListener\ErrorListener; 20use Symfony\Component\Console\Input\ArgvInput; 21use Symfony\Component\Console\Input\ArrayInput; 22use Symfony\Component\Console\Input\Input; 23use Symfony\Component\Console\Input\InputInterface; 24use Symfony\Component\Console\Input\StringInput; 25use Symfony\Component\Console\Output\OutputInterface; 26 27class ErrorListenerTest extends TestCase 28{ 29 public function testOnConsoleError() 30 { 31 $error = new \TypeError('An error occurred'); 32 33 $logger = $this->getLogger(); 34 $logger 35 ->expects($this->once()) 36 ->method('error') 37 ->with('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => 'test:run --foo=baz buzz', 'message' => 'An error occurred']) 38 ; 39 40 $listener = new ErrorListener($logger); 41 $listener->onConsoleError(new ConsoleErrorEvent(new ArgvInput(['console.php', 'test:run', '--foo=baz', 'buzz']), $this->getOutput(), $error, new Command('test:run'))); 42 } 43 44 public function testOnConsoleErrorWithNoCommandAndNoInputString() 45 { 46 $error = new \RuntimeException('An error occurred'); 47 48 $logger = $this->getLogger(); 49 $logger 50 ->expects($this->once()) 51 ->method('error') 52 ->with('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => 'An error occurred']) 53 ; 54 55 $listener = new ErrorListener($logger); 56 $listener->onConsoleError(new ConsoleErrorEvent(new NonStringInput(), $this->getOutput(), $error)); 57 } 58 59 public function testOnConsoleTerminateForNonZeroExitCodeWritesToLog() 60 { 61 $logger = $this->getLogger(); 62 $logger 63 ->expects($this->once()) 64 ->method('debug') 65 ->with('Command "{command}" exited with code "{code}"', ['command' => 'test:run', 'code' => 255]) 66 ; 67 68 $listener = new ErrorListener($logger); 69 $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArgvInput(['console.php', 'test:run']), 255)); 70 } 71 72 public function testOnConsoleTerminateForZeroExitCodeDoesNotWriteToLog() 73 { 74 $logger = $this->getLogger(); 75 $logger 76 ->expects($this->never()) 77 ->method('debug') 78 ; 79 80 $listener = new ErrorListener($logger); 81 $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArgvInput(['console.php', 'test:run']), 0)); 82 } 83 84 public function testGetSubscribedEvents() 85 { 86 $this->assertEquals( 87 [ 88 'console.error' => ['onConsoleError', -128], 89 'console.terminate' => ['onConsoleTerminate', -128], 90 ], 91 ErrorListener::getSubscribedEvents() 92 ); 93 } 94 95 public function testAllKindsOfInputCanBeLogged() 96 { 97 $logger = $this->getLogger(); 98 $logger 99 ->expects($this->exactly(3)) 100 ->method('debug') 101 ->with('Command "{command}" exited with code "{code}"', ['command' => 'test:run --foo=bar', 'code' => 255]) 102 ; 103 104 $listener = new ErrorListener($logger); 105 $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArgvInput(['console.php', 'test:run', '--foo=bar']), 255)); 106 $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArrayInput(['name' => 'test:run', '--foo' => 'bar']), 255)); 107 $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new StringInput('test:run --foo=bar'), 255)); 108 } 109 110 public function testCommandNameIsDisplayedForNonStringableInput() 111 { 112 $logger = $this->getLogger(); 113 $logger 114 ->expects($this->once()) 115 ->method('debug') 116 ->with('Command "{command}" exited with code "{code}"', ['command' => 'test:run', 'code' => 255]) 117 ; 118 119 $listener = new ErrorListener($logger); 120 $listener->onConsoleTerminate($this->getConsoleTerminateEvent($this->getMockBuilder(InputInterface::class)->getMock(), 255)); 121 } 122 123 private function getLogger() 124 { 125 return $this->getMockForAbstractClass(LoggerInterface::class); 126 } 127 128 private function getConsoleTerminateEvent(InputInterface $input, $exitCode) 129 { 130 return new ConsoleTerminateEvent(new Command('test:run'), $input, $this->getOutput(), $exitCode); 131 } 132 133 private function getOutput() 134 { 135 return $this->getMockBuilder(OutputInterface::class)->getMock(); 136 } 137} 138 139class NonStringInput extends Input 140{ 141 public function getFirstArgument() 142 { 143 } 144 145 public function hasParameterOption($values, $onlyParams = false) 146 { 147 } 148 149 public function getParameterOption($values, $default = false, $onlyParams = false) 150 { 151 } 152 153 public function parse() 154 { 155 } 156} 157