Merge branch '4.3' into 4.4

* 4.3:
  Mute deprecations triggered from phpunit
This commit is contained in:
Nicolas Grekas 2019-07-18 16:16:21 +02:00
commit 1d3db3dd8b
4 changed files with 92 additions and 13 deletions

View File

@ -128,6 +128,9 @@ class DeprecationErrorHandler
}
$deprecation = new Deprecation($msg, debug_backtrace(), $file);
if ($deprecation->isMuted()) {
return;
}
$group = 'other';
if ($deprecation->originatesFromAnObject()) {

View File

@ -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;

View File

@ -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

View File

@ -70,8 +70,8 @@ class ErrorHandlerTest extends TestCase
public function testErrorGetLast()
{
$handler = ErrorHandler::register();
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$handler = ErrorHandler::register();
$handler->setDefaultLogger($logger);
$handler->screamAt(E_ALL);
@ -143,9 +143,8 @@ class ErrorHandlerTest extends TestCase
public function testDefaultLogger()
{
try {
$handler = ErrorHandler::register();
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$handler = ErrorHandler::register();
$handler->setDefaultLogger($logger, E_NOTICE);
$handler->setDefaultLogger($logger, [E_USER_NOTICE => LogLevel::CRITICAL]);
@ -331,12 +330,11 @@ class ErrorHandlerTest extends TestCase
public function testHandleException()
{
try {
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$handler = ErrorHandler::register();
$exception = new \Exception('foo');
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$logArgCheck = function ($level, $message, $context) {
$this->assertSame('Uncaught Exception: foo', $message);
$this->assertArrayHasKey('exception', $context);
@ -442,6 +440,7 @@ class ErrorHandlerTest extends TestCase
public function testHandleFatalError()
{
try {
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$handler = ErrorHandler::register();
$error = [
@ -451,8 +450,6 @@ class ErrorHandlerTest extends TestCase
'line' => 123,
];
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$logArgCheck = function ($level, $message, $context) {
$this->assertEquals('Fatal Parse Error: foo', $message);
$this->assertArrayHasKey('exception', $context);