From 3ed22bea69ba7df03f0045b2998365d1c8e8adaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20K=C3=A4fer?= Date: Wed, 23 Dec 2020 20:13:44 +0100 Subject: [PATCH] [PhpUnitBridge] Add log file option for deprecations --- src/Symfony/Bridge/PhpUnit/CHANGELOG.md | 1 + .../PhpUnit/DeprecationErrorHandler.php | 34 +++++++---- .../DeprecationErrorHandler/Configuration.php | 36 +++++++++--- .../DeprecationErrorHandler/log_file.phpt | 58 +++++++++++++++++++ 4 files changed, 110 insertions(+), 19 deletions(-) create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/log_file.phpt diff --git a/src/Symfony/Bridge/PhpUnit/CHANGELOG.md b/src/Symfony/Bridge/PhpUnit/CHANGELOG.md index 35f65cd492..e5d4445fcb 100644 --- a/src/Symfony/Bridge/PhpUnit/CHANGELOG.md +++ b/src/Symfony/Bridge/PhpUnit/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * bumped the minimum PHP version to 7.1.3 * bumped the minimum PHPUnit version to 7.5 * deprecated the `SetUpTearDownTrait` trait, use original methods with "void" return typehint. + * added `logFile` option to write deprecations to a file instead of echoing them 5.1.0 ----- diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index 7b7b038fc5..bca9ddfe5f 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -285,6 +285,8 @@ class DeprecationErrorHandler * @param string[] $groups * @param Configuration $configuration * @param bool $isFailing + * + * @throws \InvalidArgumentException */ private function displayDeprecations($groups, $configuration, $isFailing) { @@ -292,16 +294,26 @@ class DeprecationErrorHandler return $b->count() - $a->count(); }; + if ($configuration->shouldWriteToLogFile()) { + if (false === $handle = @fopen($file = $configuration->getLogFile(), 'a')) { + throw new \InvalidArgumentException(sprintf('The configured log file "%s" is not writeable.', $file)); + } + } else { + $handle = fopen('php://output', 'w'); + } + foreach ($groups as $group) { if ($this->deprecationGroups[$group]->count()) { - echo "\n", self::colorize( - sprintf( - '%s deprecation notices (%d)', - \in_array($group, ['direct', 'indirect', 'self'], true) ? "Remaining $group" : ucfirst($group), - $this->deprecationGroups[$group]->count() - ), - 'legacy' !== $group && 'indirect' !== $group - ), "\n"; + $deprecationGroupMessage = sprintf( + '%s deprecation notices (%d)', + \in_array($group, ['direct', 'indirect', 'self'], true) ? "Remaining $group" : ucfirst($group), + $this->deprecationGroups[$group]->count() + ); + if ($configuration->shouldWriteToLogFile()) { + fwrite($handle, "\n$deprecationGroupMessage\n"); + } else { + fwrite($handle, "\n".self::colorize($deprecationGroupMessage, 'legacy' !== $group && 'indirect' !== $group)."\n"); + } if ('legacy' !== $group && !$configuration->verboseOutput($group) && !$isFailing) { continue; @@ -310,14 +322,14 @@ class DeprecationErrorHandler uasort($notices, $cmp); foreach ($notices as $msg => $notice) { - echo "\n ", $notice->count(), 'x: ', $msg, "\n"; + fwrite($handle, sprintf("\n %sx: %s\n", $notice->count(), $msg)); $countsByCaller = $notice->getCountsByCaller(); arsort($countsByCaller); foreach ($countsByCaller as $method => $count) { if ('count' !== $method) { - echo ' ', $count, 'x in ', preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method), "\n"; + fwrite($handle, sprintf(" %dx in %s\n", $count, preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method))); } } } @@ -325,7 +337,7 @@ class DeprecationErrorHandler } if (!empty($notices)) { - echo "\n"; + fwrite($handle, "\n"); } } diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Configuration.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Configuration.php index 95b6436971..99248c508c 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Configuration.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Configuration.php @@ -52,13 +52,19 @@ class Configuration private $baselineDeprecations = []; /** - * @param int[] $thresholds A hash associating groups to thresholds - * @param string $regex Will be matched against messages, to decide whether to display a stack trace - * @param bool[] $verboseOutput Keyed by groups - * @param bool $generateBaseline Whether to generate or update the baseline file - * @param string $baselineFile The path to the baseline file + * @var string|null */ - private function __construct(array $thresholds = [], $regex = '', $verboseOutput = [], $generateBaseline = false, $baselineFile = '') + private $logFile = null; + + /** + * @param int[] $thresholds A hash associating groups to thresholds + * @param string $regex Will be matched against messages, to decide whether to display a stack trace + * @param bool[] $verboseOutput Keyed by groups + * @param bool $generateBaseline Whether to generate or update the baseline file + * @param string $baselineFile The path to the baseline file + * @param string|null $logFile The path to the log file + */ + private function __construct(array $thresholds = [], $regex = '', $verboseOutput = [], $generateBaseline = false, $baselineFile = '', $logFile = null) { $groups = ['total', 'indirect', 'direct', 'self']; @@ -119,6 +125,8 @@ class Configuration throw new \InvalidArgumentException(sprintf('The baselineFile "%s" does not exist.', $this->baselineFile)); } } + + $this->logFile = $logFile; } /** @@ -238,6 +246,16 @@ class Configuration return $this->verboseOutput[$group]; } + public function shouldWriteToLogFile() + { + return null !== $this->logFile; + } + + public function getLogFile() + { + return $this->logFile; + } + /** * @param string $serializedConfiguration an encoded string, for instance * max[total]=1234&max[indirect]=42 @@ -248,7 +266,7 @@ class Configuration { parse_str($serializedConfiguration, $normalizedConfiguration); foreach (array_keys($normalizedConfiguration) as $key) { - if (!\in_array($key, ['max', 'disabled', 'verbose', 'quiet', 'generateBaseline', 'baselineFile'], true)) { + if (!\in_array($key, ['max', 'disabled', 'verbose', 'quiet', 'generateBaseline', 'baselineFile', 'logFile'], true)) { throw new \InvalidArgumentException(sprintf('Unknown configuration option "%s".', $key)); } } @@ -260,6 +278,7 @@ class Configuration 'quiet' => [], 'generateBaseline' => false, 'baselineFile' => '', + 'logFile' => null, ]; if ('' === $normalizedConfiguration['disabled'] || filter_var($normalizedConfiguration['disabled'], \FILTER_VALIDATE_BOOLEAN)) { @@ -282,7 +301,8 @@ class Configuration '', $verboseOutput, filter_var($normalizedConfiguration['generateBaseline'], \FILTER_VALIDATE_BOOLEAN), - $normalizedConfiguration['baselineFile'] + $normalizedConfiguration['baselineFile'], + $normalizedConfiguration['logFile'] ); } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/log_file.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/log_file.phpt new file mode 100644 index 0000000000..7f114ab5e2 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/log_file.phpt @@ -0,0 +1,58 @@ +--TEST-- +Test DeprecationErrorHandler with log file +--FILE-- +testLegacyFoo(); +$foo->testLegacyBar(); + +register_shutdown_function(function () use ($filename) { + var_dump(file_get_contents($filename)); +}); +?> +--EXPECTF-- +string(234) " +Unsilenced deprecation notices (3) + + 2x: unsilenced foo deprecation + 2x in FooTestCase::testLegacyFoo + + 1x: unsilenced bar deprecation + 1x in FooTestCase::testLegacyBar + +Other deprecation notices (1) + + 1x: root deprecation + +"