From 61fd043dd5a2a305d68f0ea32beb8ab32d849fa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Sun, 5 Feb 2017 18:06:12 +0100 Subject: [PATCH] Introduce weak vendors mode A new mode is introduced, in which deprecations coming from the vendors are not taken into account when deciding to exit with an error code. In this mode, deprecations coming from the vendors are segregated from other deprecations. --- .../PhpUnit/DeprecationErrorHandler.php | 57 ++++++++++++-- .../acme/lib/deprecation_riddled.php | 35 +++++++++ .../fake_vendor/autoload.php | 3 + .../fake_vendor/composer/autoload_real.php | 5 ++ .../fake_vendor/composer/installed.json | 1 + .../weak_vendors_on_non_vendor.phpt | 74 +++++++++++++++++++ .../weak_vendors_on_vendor.phpt | 27 +++++++ 7 files changed, 196 insertions(+), 6 deletions(-) create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/autoload.php create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/composer/autoload_real.php create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/composer/installed.json create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_non_vendor.phpt create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_vendor.phpt diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index ff5d94c217d08..6a7ad1fa98828 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -19,6 +19,7 @@ class DeprecationErrorHandler { const MODE_WEAK = 'weak'; + const MODE_WEAK_VENDORS = 'weak_vendors'; const MODE_DISABLED = 'disabled'; private static $isRegistered = false; @@ -28,6 +29,7 @@ class DeprecationErrorHandler * * The following reporting modes are supported: * - use "weak" to hide the deprecation report but keep a global count; + * - use "weak_vendors" to act as "weak" but only for vendors; * - use "/some-regexp/" to stop the test suite whenever a deprecation * message matches the given regular expression; * - use a number to define the upper bound of allowed deprecations, @@ -52,13 +54,37 @@ public static function register($mode = 0) if (false === $mode) { $mode = getenv('SYMFONY_DEPRECATIONS_HELPER'); } - if (DeprecationErrorHandler::MODE_WEAK !== $mode && (!isset($mode[0]) || '/' !== $mode[0])) { + if (DeprecationErrorHandler::MODE_WEAK !== $mode && DeprecationErrorHandler::MODE_WEAK_VENDORS !== $mode && (!isset($mode[0]) || '/' !== $mode[0])) { $mode = preg_match('/^[1-9][0-9]*$/', $mode) ? (int) $mode : 0; } return $memoizedMode = $mode; }; + $inVendors = function ($path) { + /** @var string[] absolute paths to vendor directories */ + static $vendors; + if (null === $vendors) { + foreach (get_declared_classes() as $class) { + if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) { + $r = new \ReflectionClass($class); + $v = dirname(dirname($r->getFileName())); + if (file_exists($v.'/composer/installed.json')) { + $vendors[] = $v; + } + } + } + } + $path = realpath($path) ?: $path; + foreach ($vendors as $vendor) { + if (0 === strpos($path, $vendor) && false !== strpbrk(substr($path, strlen($vendor), 1), '/'.DIRECTORY_SEPARATOR)) { + return true; + } + } + + return false; + }; + $deprecations = array( 'unsilencedCount' => 0, 'remainingCount' => 0, @@ -69,7 +95,13 @@ public static function register($mode = 0) 'legacy' => array(), 'other' => array(), ); - $deprecationHandler = function ($type, $msg, $file, $line, $context) use (&$deprecations, $getMode, $UtilPrefix) { + if (self::MODE_WEAK_VENDORS === $mode) { + $deprecations += array( + 'remaining vendorCount' => 0, + 'remaining vendor' => array(), + ); + } + $deprecationHandler = function ($type, $msg, $file, $line, $context) use (&$deprecations, $getMode, $UtilPrefix, $inVendors) { $mode = $getMode(); if ((E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) || DeprecationErrorHandler::MODE_DISABLED === $mode) { $ErrorHandler = $UtilPrefix.'ErrorHandler'; @@ -80,6 +112,8 @@ public static function register($mode = 0) $trace = debug_backtrace(true); $group = 'other'; + $isWeak = DeprecationErrorHandler::MODE_WEAK === $mode || (DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode && $isVendor = $inVendors($file)); + $i = count($trace); while (1 < $i && (!isset($trace[--$i]['class']) || ('ReflectionMethod' === $trace[$i]['class'] || 0 === strpos($trace[$i]['class'], 'PHPUnit_') || 0 === strpos($trace[$i]['class'], 'PHPUnit\\')))) { // No-op @@ -99,6 +133,8 @@ public static function register($mode = 0) || in_array('legacy', $Test::getGroups($class, $method), true) ) { $group = 'legacy'; + } elseif (DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode && $isVendor) { + $group = 'remaining vendor'; } else { $group = 'remaining'; } @@ -117,13 +153,13 @@ public static function register($mode = 0) exit(1); } - if ('legacy' !== $group && DeprecationErrorHandler::MODE_WEAK !== $mode) { + if ('legacy' !== $group && !$isWeak) { $ref = &$deprecations[$group][$msg]['count']; ++$ref; $ref = &$deprecations[$group][$msg][$class.'::'.$method]; ++$ref; } - } elseif (DeprecationErrorHandler::MODE_WEAK !== $mode) { + } elseif (!$isWeak) { $ref = &$deprecations[$group][$msg]['count']; ++$ref; } @@ -167,9 +203,18 @@ public static function register($mode = 0) return $b['count'] - $a['count']; }; - foreach (array('unsilenced', 'remaining', 'legacy', 'other') as $group) { + $groups = array('unsilenced', 'remaining'); + if (DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode) { + $groups[] = 'remaining vendor'; + } + array_push($groups, 'legacy', 'other'); + + foreach ($groups as $group) { if ($deprecations[$group.'Count']) { - echo "\n", $colorize(sprintf('%s deprecation notices (%d)', ucfirst($group), $deprecations[$group.'Count']), 'legacy' !== $group), "\n"; + echo "\n", $colorize( + sprintf('%s deprecation notices (%d)', ucfirst($group), $deprecations[$group.'Count']), + 'legacy' !== $group && 'remaining vendor' !== $group + ), "\n"; uasort($deprecations[$group], $cmp); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php new file mode 100644 index 0000000000000..6f5123d4feb0c --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/acme/lib/deprecation_riddled.php @@ -0,0 +1,35 @@ +testLegacyFoo(); +$foo->testNonLegacyBar(); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/autoload.php b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/autoload.php new file mode 100644 index 0000000000000..bf315f2eaa312 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/fake_vendor/autoload.php @@ -0,0 +1,3 @@ +testLegacyFoo(); +$foo->testNonLegacyBar(); + +?> +--EXPECTF-- +Unsilenced deprecation notices (3) + +unsilenced foo deprecation: 2x + 2x in FooTestCase::testLegacyFoo + +unsilenced bar deprecation: 1x + 1x in FooTestCase::testNonLegacyBar + +Remaining deprecation notices (1) + +silenced bar deprecation: 1x + 1x in FooTestCase::testNonLegacyBar + +Legacy deprecation notices (1) + +Other deprecation notices (1) + +root deprecation: 1x + diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_vendor.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_vendor.phpt new file mode 100644 index 0000000000000..7bbda8775d6d5 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_vendor.phpt @@ -0,0 +1,27 @@ +--TEST-- +Test DeprecationErrorHandler in weak vendors mode on vendor file +--FILE-- +