8000 Introduce weak_lagging_vendors mode · symfony/symfony@9ef2619 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9ef2619

Browse files
greg0ireGrégoire Paris
authored andcommitted
Introduce weak_lagging_vendors mode
In this mode, failures coming from vendors that call other vendors in a deprecated way are not taken into account when deciding to make the build fail. They also appear in a separate group.
1 parent e2cc16a commit 9ef2619

File tree

5 files changed

+166
-7
lines changed

5 files changed

+166
-7
lines changed

src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class DeprecationErrorHandler
2020
{
2121
const MODE_WEAK = 'weak';
2222
const MODE_WEAK_VENDORS = 'weak_vendors';
23+
const MODE_WEAK_LAGGING_VENDORS = 'weak_lagging_vendors';
2324
const MODE_DISABLED = 'disabled';
2425

2526
private static $isRegistered = false;
@@ -30,6 +31,8 @@ class DeprecationErrorHandler
3031
* The following reporting modes are supported:
3132
* - use "weak" to hide the deprecation report but keep a global count;
3233
* - use "weak_vendors" to act as "weak" but only for vendors;
34+
* - use "weak_lagging_vendors" to act as "weak" but only for vendors that
35+
* failed to keep up with their upstream dependencies deprecations;
3336
* - use "/some-regexp/" to stop the test suite whenever a deprecation
3437
* message matches the given regular expression;
3538
* - use a number to define the upper bound of allowed deprecations,
@@ -54,24 +57,29 @@ public static function register($mode = 0)
5457
if (false === $mode) {
5558
$mode = getenv('SYMFONY_DEPRECATIONS_HELPER');
5659
}
57-
if (DeprecationErrorHandler::MODE_WEAK !== $mode && DeprecationErrorHandler::MODE_WEAK_VENDORS !== $mode && (!isset($mode[0]) || '/' !== $mode[0])) {
60+
if (!in_array($mode, array(
61+
DeprecationErrorHandler::MODE_WEAK,
62+
DeprecationErrorHandler::MODE_WEAK_VENDORS,
63+
DeprecationErrorHandler::MODE_WEAK_LAGGING_VENDORS,
64+
), true) && (!isset($mode[0]) || '/' !== $mode[0])) {
5865
$mode = preg_match('/^[1-9][0-9]*$/', $mode) ? (int) $mode : 0;
5966
}
6067

6168
return $memoizedMode = $mode;
6269
};
6370

64-
6571
$deprecations = array(
6672
'unsilencedCount' => 0,
6773
'remainingCount' => 0,
6874
'legacyCount' => 0,
6975
'otherCount' => 0,
76+
'lagging vendorCount' => 0,
7077
'remaining vendorCount' => 0,
7178
'unsilenced' => array(),
7279
'remaining' => array(),
7380
'legacy' => array(),
7481
'other' => array(),
82+
'lagging vendor' => array(),
7583
'remaining vendor' => array(),
7684
);
7785
$deprecationHandler = function ($type, $msg, $file, $line, $context = array()) use (&$deprecations, $getMode, $UtilPrefix) {
@@ -85,8 +93,9 @@ public static function register($mode = 0)
8593
$trace = debug_backtrace(true);
8694
$group = 'other';
8795

88-
$isWeak = DeprecationErrorHandler::MODE_WEAK === $mode || (DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode && $isVendor = self::inVendors($file));
89-
96+
$isWeak = DeprecationErrorHandler::MODE_WEAK === $mode ||
97+
(DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode && $isVendor = self::inVendors($file)) ||
98+
(DeprecationErrorHandler::MODE_WEAK_LAGGING_VENDORS === $mode && $isLaggingVendor = self::isLaggingVendor($trace));
9099
$i = count($trace);
91100
while (1 < $i && (!isset($trace[--$i]['class']) || ('ReflectionMethod' === $trace[$i]['class'] || 0 === strpos($trace[$i]['class'], 'PHPUnit_') || 0 === strpos($trace[$i]['class'], 'PHPUnit\\')))) {
92101
// No-op
@@ -114,6 +123,8 @@ public static function register($mode = 0)
114123
|| in_array('legacy', $Test::getGroups($class, $method), true)
115124
) {
116125
$group = 'legacy';
126+
} elseif (DeprecationErrorHandler::MODE_WEAK_LAGGING_VENDORS === $mode && $isLaggingVendor) {
127+
$group = 'lagging vendor';
117128
} elseif (DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode && $isVendor) {
118129
$group = 'remaining vendor';
119130
} else {
@@ -188,13 +199,16 @@ public static function register($mode = 0)
188199
if (DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode) {
189200
$groups[] = 'remaining vendor';
190201
}
202+
if (DeprecationErrorHandler::MODE_WEAK_LAGGING_VENDORS === $mode) {
203+
$groups[] = 'lagging vendor';
204+
}
191205
array_push($groups, 'legacy', 'other');
192206

193207
foreach ($groups as $group) {
194208
if ($deprecations[$group.'Count']) {
195209
echo "\n", $colorize(
196210
sprintf('%s deprecation notices (%d)', ucfirst($group), $deprecations[$group.'Count']),
197-
'legacy' !== $group && 'remaining vendor' !== $group
211+
!in_array($group, array('legacy', 'remaining vendor', 'lagging vendor'), true)
198212
), "\n";
199213

200214
uasort($deprecations[$group], $cmp);
@@ -223,10 +237,52 @@ public static function register($mode = 0)
223237
}
224238
}
225239

226-
private static function inVendors(string $path): bool
240+
private static function isLaggingVendor(array $trace): bool
241+
{
242+
foreach ($trace as $line) {
243+
if (isset($line['file'])) {
244+
$file = $line['file'];
245+
if ('-' === $file) {
246+
continue;
247+
}
248+
if (!self::inVendors($file)) {
249+
return false;
250+
}
251+
if (isset($erroringFile, $erroringPackage)) {
252+
if (self::getPackage($file) !== $erroringPackage) {
253+
return true;
254+
}
255+
} else {
256+
$erroringFile = $file;
257+
$erroringPackage = self::getPackage($file);
258+
}
259+
}
260+
}
261+
262+
return false;
263+
}
264+
265+
/**
266+
* inVendors() should always be called prior to calling this method.
267+
*/
268+
private static function getPackage(string $path): string
269+
{
270+
$path = realpath($path) ?: $path;
271+
foreach (self::getVendors() as $vendorRoot) {
272+
if (0 === strpos($path, $vendorRoot)) {
273+
$relativePath = substr($path, strlen($vendorRoot) + 1);
274+
$vendor = strstr($relativePath, DIRECTORY_SEPARATOR, true);
275+
276+
return $vendor.'/'.strstr(substr($relativePath, strlen($vendor) + 1), DIRECTORY_SEPARATOR, true);
277+
}
278+
}
279+
}
280+
281+
private static function getVendors(): ?array
227282
{
228283
/** @var string[] absolute paths to vendor directories */
229284
static $vendors;
285+
230286
if (null === $vendors) {
231287
foreach (get_declared_classes() as $class) {
232288
if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) {
@@ -238,8 +294,14 @@ private static function inVendors(string $path): bool
238294
}
239295
}
240296
}
297+
298+
return $vendors;
299+
}
300+
301+
private static function inVendors(string $path): bool
302+
{
241303
$path = realpath($path) ?: $path;
242-
foreach ($vendors as $vendor) {
304+
foreach (self::getVendors() as $vendor) {
243305
if (0 === strpos($path, $vendor) && false !== strpbrk(substr($path, strlen($vendor), 1), '/'.DIRECTORY_SEPARATOR)) {
244306
return true;
245307
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
/* We have not caught up on the deprecations yet and still call the other lib
3+
in a deprecated way. */
4+
5+
include __DIR__.'/../lib/deprecated_api.php';
6+
$defraculator = new \Acme\Lib\SomeService();
7+
$defraculator->deprecatedApi();
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
namespace Acme\Lib;
3+
4+
class SomeService
5+
{
6+
public function deprecatedApi()
7+
{
8+
@trigger_error(
9+
__FUNCTION__.' is deprecated! You should stop relying on it!',
10+
E_USER_DEPRECATED
11+
);
12+
}
13+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
--TEST--
2+
Test DeprecationErrorHandler in weak vendors mode when calling deprecated api
3+
--FILE--
4+
<?php
5+
6+
putenv('SYMFONY_DEPRECATIONS_HELPER=weak_lagging_vendors');
7+
putenv('ANSICON');
8+
putenv('ConEmuANSI');
9+
putenv('TERM');
10+
11+
$vendor = __DIR__;
12+
while (!file_exists($vendor.'/vendor')) {
13+
$vendor = dirname($vendor);
14+
}
15+
define('PHPUNIT_COMPOSER_INSTALL', $vendor.'/vendor/autoload.php');
16+
require PHPUNIT_COMPOSER_INSTALL;
17+
require_once __DIR__.'/../../bootstrap.php';
18+
eval(<<<'EOPHP'
19+
namespace PHPUnit\Util;
20+
21+
class Test
22+
{
23+
public static function getGroups()
24+
{
25+
return array();
26+
}
27+
}
28+
EOPHP
29+
);
30+
require __DIR__.'/fake_vendor/autoload.php';
31+
require __DIR__.'/fake_vendor/acme/lib/deprecated_api.php';
32+
$defraculator = new \Acme\Lib\SomeService();
33+
$defraculator->deprecatedApi();
34+
35+
36+
?>
37+
--EXPECTF--
38+
Remaining deprecation notices (1)
39+
40+
deprecatedApi is deprecated! You should stop relying on it!: 1x
41+
1x in SomeService::deprecatedApi from Acme\Lib
42+
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
Test DeprecationErrorHandler in weak vendors mode on vendor file
3+
--FILE--
4+
<?php
5+
6+
putenv('SYMFONY_DEPRECATIONS_HELPER=weak_lagging_vendors');
7+
putenv('ANSICON');
8+
putenv('ConEmuANSI');
9+
putenv('TERM');
10+
11+
$vendor = __DIR__;
12+
while (!file_exists($vendor.'/vendor')) {
13+
$vendor = dirname($vendor);
14+
}
15+
define('PHPUNIT_COMPOSER_INSTALL', $vendor.'/vendor/autoload.php');
16+
require PHPUNIT_COMPOSER_INSTALL;
17+
require_once __DIR__.'/../../bootstrap.php';
18+
eval(<<<'EOPHP'
19+
namespace PHPUnit\Util;
20+
21+
class Test
22+
{
23+
public static function getGroups()
24+
{
25+
return array();
26+
}
27+
}
28+
EOPHP
29+
);
30+
require __DIR__.'/fake_vendor/autoload.php';
31+
require __DIR__.'/fake_vendor/acme/lagging-lib/lagging_file.php';
32+
33+
?>
34+
--EXPECTF--
35+
Lagging vendor deprecation notices (1)

0 commit comments

Comments
 (0)
0