From a4ab13d567616fdfca6a2a875b0c6c3e3fa0a1e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Fri, 5 Jul 2019 20:02:04 +0200 Subject: [PATCH] Mute deprecations triggered from phpunit --- .../PhpUnit/DeprecationErrorHandler.php | 3 + .../DeprecationErrorHandler/Deprecation.php | 28 +++++++-- .../DeprecationTest.php | 63 +++++++++++++++++++ 3 files changed, 88 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index f9457c937d..e059fe2a9d 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -128,6 +128,9 @@ class DeprecationErrorHandler } $deprecation = new Deprecation($msg, debug_backtrace(), $file); + if ($deprecation->isMuted()) { + return; + } $group = 'other'; if ($deprecation->originatesFromAnObject()) { diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php index ea84256663..2d6aa29224 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php @@ -48,9 +48,9 @@ class Deprecation private $originMethod; /** - * @var string one of the PATH_TYPE_* constants + * @var string */ - private $triggeringFilePathType; + private $triggeringFile; /** @var string[] absolute paths to vendor directories */ private static $vendors; @@ -76,7 +76,7 @@ class Deprecation // No-op } $line = $trace[$i]; - $this->triggeringFilePathType = $this->getPathType($file); + $this->triggeringFile = $file; if (isset($line['object']) || isset($line['class'])) { if (isset($line['class']) && 0 === strpos($line['class'], SymfonyTestsListenerFor::class)) { $parsedMsg = unserialize($this->message); @@ -88,7 +88,7 @@ class Deprecation // then we need to use the serialized information to determine // if the error has been triggered from vendor code. if (isset($parsedMsg['triggering_file'])) { - $this->triggeringFilePathType = $this->getPathType($parsedMsg['triggering_file']); + $this->triggeringFile = $parsedMsg['triggering_file']; } return; @@ -169,6 +169,21 @@ class Deprecation || \in_array('legacy', $test::getGroups($class, $method), true); } + /** + * @return bool + */ + public function isMuted() + { + if ('Function ReflectionType::__toString() is deprecated' !== $this->message) { + return false; + } + if (isset($this->trace[1]['class'])) { + return 0 === strpos($this->trace[1]['class'], 'PHPUnit\\'); + } + + return false !== strpos($this->triggeringFile, \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR.'phpunit'.\DIRECTORY_SEPARATOR); + } + /** * Tells whether both the calling package and the called package are vendor * packages. @@ -177,10 +192,11 @@ class Deprecation */ public function getType() { - if (self::PATH_TYPE_SELF === $this->triggeringFilePathType) { + $triggeringFilePathType = $this->getPathType($this->triggeringFile); + if (self::PATH_TYPE_SELF === $triggeringFilePathType) { return self::TYPE_SELF; } - if (self::PATH_TYPE_UNDETERMINED === $this->triggeringFilePathType) { + if (self::PATH_TYPE_UNDETERMINED === $triggeringFilePathType) { return self::TYPE_UNDETERMINED; } $erroringFile = $erroringPackage = null; diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php index 0c8708bb35..60b1efdfa2 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\PhpUnit\Tests\DeprecationErrorHandler; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\DeprecationErrorHandler; use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Deprecation; class DeprecationTest extends TestCase @@ -55,6 +56,68 @@ class DeprecationTest extends TestCase $this->assertNotSame(Deprecation::TYPE_INDIRECT, $deprecation->getType()); } + /** + * @dataProvider mutedProvider + */ + public function testItMutesOnlySpecificErrorMessagesWhenTheCallingCodeIsInPhpunit($muted, $callingClass, $message) + { + $trace = $this->debugBacktrace(); + array_unshift($trace, ['class' => $callingClass]); + array_unshift($trace, ['class' => DeprecationErrorHandler::class]); + $deprecation = new Deprecation($message, $trace, 'should_not_matter.php'); + $this->assertSame($muted, $deprecation->isMuted()); + } + + public function mutedProvider() + { + yield 'not from phpunit, and not a whitelisted message' => [ + false, + \My\Source\Code::class, + 'Self deprecating humor is deprecated by itself' + ]; + yield 'from phpunit, but not a whitelisted message' => [ + false, + \PHPUnit\Random\Piece\Of\Code::class, + 'Self deprecating humor is deprecated by itself' + ]; + yield 'whitelisted message, but not from phpunit' => [ + false, + \My\Source\Code::class, + 'Function ReflectionType::__toString() is deprecated', + ]; + yield 'from phpunit and whitelisted message' => [ + true, + \PHPUnit\Random\Piece\Of\Code::class, + 'Function ReflectionType::__toString() is deprecated', + ]; + } + + public function testNotMutedIfNotCalledFromAClassButARandomFile() + { + $deprecation = new Deprecation( + 'Function ReflectionType::__toString() is deprecated', + [ + ['file' => 'should_not_matter.php'], + ['file' => 'should_not_matter_either.php'], + ], + 'my-procedural-controller.php' + ); + $this->assertFalse($deprecation->isMuted()); + } + + public function testItTakesMutesDeprecationFromPhpUnitFiles() + { + $deprecation = new Deprecation( + 'Function ReflectionType::__toString() is deprecated', + [ + ['file' => 'should_not_matter.php'], + ['file' => 'should_not_matter_either.php'], + ], + 'random_path' . \DIRECTORY_SEPARATOR . 'vendor' . \DIRECTORY_SEPARATOR . 'phpunit' . \DIRECTORY_SEPARATOR . 'whatever.php' + ); + $this->assertTrue($deprecation->isMuted()); + } + /** * This method is here to simulate the extra level from the piece of code * triggering an error to the error handler