Skip to content

Commit 951031e

Browse files
mondrakenicolas-grekas
authored andcommitted
[PhpUnitBridge] Add option ignoreFile to configure a file that lists deprecation messages to ignore
1 parent 2730b25 commit 951031e

File tree

5 files changed

+183
-2
lines changed

5 files changed

+183
-2
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
6.1
5+
---
6+
7+
* Add option `ignoreFile` to configure a file that lists deprecation messages to ignore
8+
49
6.0
510
---
611

DeprecationErrorHandler.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ public function handleError($type, $msg, $file, $line, $context = [])
136136
if ($deprecation->isMuted()) {
137137
return null;
138138
}
139+
if ($this->getConfiguration()->isIgnoredDeprecation($deprecation)) {
140+
return null;
141+
}
139142
if ($this->getConfiguration()->isBaselineDeprecation($deprecation)) {
140143
return null;
141144
}

DeprecationErrorHandler/Configuration.php

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ class Configuration
3636
*/
3737
private $verboseOutput;
3838

39+
/**
40+
* @var string[]
41+
*/
42+
private $ignoreDeprecationPatterns = [];
43+
3944
/**
4045
* @var bool
4146
*/
@@ -60,11 +65,12 @@ class Configuration
6065
* @param int[] $thresholds A hash associating groups to thresholds
6166
* @param string $regex Will be matched against messages, to decide whether to display a stack trace
6267
* @param bool[] $verboseOutput Keyed by groups
68+
* @param string $ignoreFile The path to the ignore deprecation patterns file
6369
* @param bool $generateBaseline Whether to generate or update the baseline file
6470
* @param string $baselineFile The path to the baseline file
6571
* @param string|null $logFile The path to the log file
6672
*/
67-
private function __construct(array $thresholds = [], $regex = '', $verboseOutput = [], $generateBaseline = false, $baselineFile = '', $logFile = null)
73+
private function __construct(array $thresholds = [], $regex = '', $verboseOutput = [], $ignoreFile = '', $generateBaseline = false, $baselineFile = '', $logFile = null)
6874
{
6975
$groups = ['total', 'indirect', 'direct', 'self'];
7076

@@ -110,6 +116,25 @@ private function __construct(array $thresholds = [], $regex = '', $verboseOutput
110116
$this->verboseOutput[$group] = $status;
111117
}
112118

119+
if ($ignoreFile) {
120+
if (!is_file($ignoreFile)) {
121+
throw new \InvalidArgumentException(sprintf('The ignoreFile "%s" does not exist.', $ignoreFile));
122+
}
123+
set_error_handler(static function ($t, $m) use ($ignoreFile, &$line) {
124+
throw new \RuntimeException(sprintf('Invalid pattern found in "%s" on line "%d"', $ignoreFile, 1 + $line).substr($m, 12));
125+
});
126+
try {
127+
foreach (file($ignoreFile) as $line => $pattern) {
128+
if ('#' !== trim($line)[0] ?? '#') {
129+
preg_match($pattern, '');
130+
$this->ignoreDeprecationPatterns[] = $pattern;
131+
}
132+
}
133+
} finally {
134+
restore_error_handler();
135+
}
136+
}
137+
113138
if ($generateBaseline && !$baselineFile) {
114139
throw new \InvalidArgumentException('You cannot use the "generateBaseline" configuration option without providing a "baselineFile" configuration option.');
115140
}
@@ -165,6 +190,19 @@ public function tolerates(array $deprecationGroups)
165190
return true;
166191
}
167192

193+
public function isIgnoredDeprecation(Deprecation $deprecation): bool
194+
{
195+
if (!$this->ignoreDeprecationPatterns) {
196+
return false;
197+
}
198+
$result = @preg_filter($this->ignoreDeprecationPatterns, '$0', $deprecation->getMessage());
199+
if (\PREG_NO_ERROR !== preg_last_error()) {
200+
throw new \RuntimeException(preg_last_error_msg());
201+
}
202+
203+
return (bool) $result;
204+
}
205+
168206
/**
169207
* @return bool
170208
*/
@@ -266,7 +304,7 @@ public static function fromUrlEncodedString($serializedConfiguration)
266304
{
267305
parse_str($serializedConfiguration, $normalizedConfiguration);
268306
foreach (array_keys($normalizedConfiguration) as $key) {
269-
if (!\in_array($key, ['max', 'disabled', 'verbose', 'quiet', 'generateBaseline', 'baselineFile', 'logFile'], true)) {
307+
if (!\in_array($key, ['max', 'disabled', 'verbose', 'quiet', 'ignoreFile', 'generateBaseline', 'baselineFile', 'logFile'], true)) {
270308
throw new \InvalidArgumentException(sprintf('Unknown configuration option "%s".', $key));
271309
}
272310
}
@@ -276,6 +314,7 @@ public static function fromUrlEncodedString($serializedConfiguration)
276314
'disabled' => false,
277315
'verbose' => true,
278316
'quiet' => [],
317+
'ignoreFile' => '',
279318
'generateBaseline' => false,
280319
'baselineFile' => '',
281320
'logFile' => null,
@@ -300,6 +339,7 @@ public static function fromUrlEncodedString($serializedConfiguration)
300339
$normalizedConfiguration['max'] ?? [],
301340
'',
302341
$verboseOutput,
342+
$normalizedConfiguration['ignoreFile'],
303343
filter_var($normalizedConfiguration['generateBaseline'], \FILTER_VALIDATE_BOOLEAN),
304344
$normalizedConfiguration['baselineFile'],
305345
$normalizedConfiguration['logFile']

Tests/DeprecationErrorHandler/ConfigurationTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,62 @@ public function testBaselineFileWriteError()
391391
$configuration->writeBaseline();
392392
}
393393

394+
public function testExistingIgnoreFile()
395+
{
396+
$filename = $this->createFile();
397+
$ignorePatterns = [
398+
'/Test message .*/',
399+
'/^\d* occurrences/',
400+
];
401+
file_put_contents($filename, implode("\n", $ignorePatterns));
402+
403+
$configuration = Configuration::fromUrlEncodedString('ignoreFile='.urlencode($filename));
404+
$trace = debug_backtrace();
405+
$this->assertTrue($configuration->isIgnoredDeprecation(new Deprecation('Test message 1', $trace, '')));
406+
$this->assertTrue($configuration->isIgnoredDeprecation(new Deprecation('Test message 2', $trace, '')));
407+
$this->assertFalse($configuration->isIgnoredDeprecation(new Deprecation('Test mexxage 3', $trace, '')));
408+
$this->assertTrue($configuration->isIgnoredDeprecation(new Deprecation('1 occurrences', $trace, '')));
409+
$this->assertTrue($configuration->isIgnoredDeprecation(new Deprecation('1200 occurrences and more', $trace, '')));
410+
$this->assertFalse($configuration->isIgnoredDeprecation(new Deprecation('Many occurrences', $trace, '')));
411+
}
412+
413+
public function testIgnoreFilePatternInvalid()
414+
{
415+
$filename = $this->createFile();
416+
$ignorePatterns = [
417+
'/Test message (.*/',
418+
];
419+
file_put_contents($filename, implode("\n", $ignorePatterns));
420+
421+
$this->expectException(\RuntimeException::class);
422+
$this->expectExceptionMessage('missing closing parenthesis');
423+
$configuration = Configuration::fromUrlEncodedString('ignoreFile='.urlencode($filename));
424+
}
425+
426+
public function testIgnoreFilePatternException()
427+
{
428+
$filename = $this->createFile();
429+
$ignorePatterns = [
430+
'/(?:\D+|<\d+>)*[!?]/',
431+
];
432+
file_put_contents($filename, implode("\n", $ignorePatterns));
433+
434+
$configuration = Configuration::fromUrlEncodedString('ignoreFile='.urlencode($filename));
435+
$trace = debug_backtrace();
436+
$this->expectException(\RuntimeException::class);
437+
$this->expectExceptionMessageMatches('/[Bb]acktrack limit exhausted/');
438+
$configuration->isIgnoredDeprecation(new Deprecation('foobar foobar foobar', $trace, ''));
439+
}
440+
441+
public function testIgnoreFileException()
442+
{
443+
$filename = $this->createFile();
444+
unlink($filename);
445+
$this->expectException(\InvalidArgumentException::class);
446+
$this->expectExceptionMessage(sprintf('The ignoreFile "%s" does not exist.', $filename));
447+
Configuration::fromUrlEncodedString('ignoreFile='.urlencode($filename));
448+
}
449+
394450
protected function setUp(): void
395451
{
396452
$this->files = [];
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
--TEST--
2+
Test DeprecationErrorHandler with an ignoreFile
3+
--FILE--
4+
<?php
5+
$filename = tempnam(sys_get_temp_dir(), 'sf-');
6+
$ignorePatterns = [
7+
'/^ignored .* deprecation/',
8+
];
9+
file_put_contents($filename, implode("\n", $ignorePatterns));
10+
11+
$k = 'SYMFONY_DEPRECATIONS_HELPER';
12+
unset($_SERVER[$k], $_ENV[$k]);
13+
putenv($k.'='.$_SERVER[$k] = $_ENV[$k] = 'ignoreFile=' . urlencode($filename));
14+
putenv('ANSICON');
15+
putenv('ConEmuANSI');
16+
putenv('TERM');
17+
18+
$vendor = __DIR__;
19+
while (!file_exists($vendor.'/vendor')) {
20+
$vendor = dirname($vendor);
21+
}
22+
define('PHPUNIT_COMPOSER_INSTALL', $vendor.'/vendor/autoload.php');
23+
require PHPUNIT_COMPOSER_INSTALL;
24+
require_once __DIR__.'/../../bootstrap.php';
25+
26+
@trigger_error('root deprecation', E_USER_DEPRECATED);
27+
@trigger_error('ignored root deprecation', E_USER_DEPRECATED);
28+
29+
eval(<<<'EOPHP'
30+
namespace PHPUnit\Util;
31+
32+
class Test
33+
{
34+
public static function getGroups()
35+
{
36+
return array();
37+
}
38+
}
39+
EOPHP
40+
);
41+
42+
class PHPUnit_Util_Test
43+
{
44+
public static function getGroups()
45+
{
46+
return array();
47+
}
48+
}
49+
50+
class FooTestCase
51+
{
52+
public function testLegacyFoo()
53+
{
54+
@trigger_error('ignored foo deprecation', E_USER_DEPRECATED);
55+
@trigger_error('not ignored foo deprecation', E_USER_DEPRECATED);
56+
}
57+
58+
public function testNonLegacyBar()
59+
{
60+
@trigger_error('ignored bar deprecation', E_USER_DEPRECATED);
61+
@trigger_error('not ignored bar deprecation', E_USER_DEPRECATED);
62+
}
63+
}
64+
65+
$foo = new FooTestCase();
66+
$foo->testLegacyFoo();
67+
$foo->testNonLegacyBar();
68+
?>
69+
--EXPECTF--
70+
Legacy deprecation notices (1)
71+
72+
Other deprecation notices (2)
73+
74+
1x: root deprecation
75+
76+
1x: not ignored bar deprecation
77+
1x in FooTestCase::testNonLegacyBar

0 commit comments

Comments
 (0)