feature #35271 [PHPUnitBridge] Improved deprecations display (greg0ire)

This PR was squashed before being merged into the 5.1-dev branch (closes #35271).

Discussion
----------

[PHPUnitBridge] Improved deprecations display

| Q             | A
| ------------- | ---
| Branch?       | master for features
| Bug fix?      | no
| New feature?  | yes <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets       | n/a
| License       | MIT
| Doc PR        | todo

- [x] Ignore verbose when the build fails because of deprecations
- [x] Add per-group verbosity : it is now possible to make the report a lot quieter, by specifying which groups should become quiet, like this: `quiet[]=indirect&quiet[]=direct`

Might add more improvements to that branch if people suggest some.

Commits
-------

c55a89e4ff [PHPUnitBridge] Improved deprecations display
This commit is contained in:
Fabien Potencier 2020-01-29 15:01:15 +01:00
commit 7ecb5aad8e
10 changed files with 517 additions and 166 deletions

View File

@ -1,6 +1,12 @@
CHANGELOG
=========
5.1.0
-----
* ignore verbosity settings when the build fails because of deprecations
* added per-group verbosity
5.0.0
-----

View File

@ -15,6 +15,7 @@ use PHPUnit\Framework\TestResult;
use PHPUnit\Util\ErrorHandler;
use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Configuration;
use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Deprecation;
use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\DeprecationGroup;
use Symfony\Component\ErrorHandler\DebugClassLoader;
/**
@ -30,24 +31,20 @@ class DeprecationErrorHandler
private $mode;
private $configuration;
private $deprecations = [
'unsilencedCount' => 0,
'remaining selfCount' => 0,
'legacyCount' => 0,
'otherCount' => 0,
'remaining directCount' => 0,
'remaining indirectCount' => 0,
'unsilenced' => [],
'remaining self' => [],
'legacy' => [],
'other' => [],
'remaining direct' => [],
'remaining indirect' => [],
];
/**
* @var DeprecationGroup[]
*/
private $deprecationGroups = [];
private static $isRegistered = false;
private static $isAtLeastPhpUnit83;
public function __construct()
{
$this->resetDeprecationGroups();
}
/**
* Registers and configures the deprecation handler.
*
@ -135,9 +132,9 @@ class DeprecationErrorHandler
$group = 'legacy';
} else {
$group = [
Deprecation::TYPE_SELF => 'remaining self',
Deprecation::TYPE_DIRECT => 'remaining direct',
Deprecation::TYPE_INDIRECT => 'remaining indirect',
Deprecation::TYPE_SELF => 'self',
Deprecation::TYPE_DIRECT => 'direct',
Deprecation::TYPE_INDIRECT => 'indirect',
Deprecation::TYPE_UNDETERMINED => 'other',
][$deprecation->getType()];
}
@ -148,18 +145,14 @@ class DeprecationErrorHandler
exit(1);
}
if ('legacy' !== $group) {
$ref = &$this->deprecations[$group][$msg]['count'];
++$ref;
$ref = &$this->deprecations[$group][$msg][$class.'::'.$method];
++$ref;
$this->deprecationGroups[$group]->addNoticeFromObject($msg, $class, $method);
} else {
$this->deprecationGroups[$group]->addNotice();
}
} else {
$ref = &$this->deprecations[$group][$msg]['count'];
++$ref;
$this->deprecationGroups[$group]->addNoticeFromProceduralCode($msg);
}
++$this->deprecations[$group.'Count'];
return null;
}
@ -184,34 +177,44 @@ class DeprecationErrorHandler
echo "\n", self::colorize('THE ERROR HANDLER HAS CHANGED!', true), "\n";
}
$groups = ['unsilenced', 'remaining self', 'remaining direct', 'remaining indirect', 'legacy', 'other'];
$this->displayDeprecations($groups, $configuration);
$groups = array_keys($this->deprecationGroups);
// store failing status
$isFailing = !$configuration->tolerates($this->deprecations);
$isFailing = !$configuration->tolerates($this->deprecationGroups);
// reset deprecations array
foreach ($this->deprecations as $group => $arrayOrInt) {
$this->deprecations[$group] = \is_int($arrayOrInt) ? 0 : [];
}
$this->displayDeprecations($groups, $configuration, $isFailing);
$this->resetDeprecationGroups();
register_shutdown_function(function () use ($isFailing, $groups, $configuration) {
foreach ($this->deprecations as $group => $arrayOrInt) {
if (0 < (\is_int($arrayOrInt) ? $arrayOrInt : \count($arrayOrInt))) {
foreach ($this->deprecationGroups as $group) {
if ($group->count() > 0) {
echo "Shutdown-time deprecations:\n";
break;
}
}
$this->displayDeprecations($groups, $configuration);
$isFailingAtShutdown = !$configuration->tolerates($this->deprecationGroups);
$this->displayDeprecations($groups, $configuration, $isFailingAtShutdown);
if ($isFailing || !$configuration->tolerates($this->deprecations)) {
if ($isFailing || $isFailingAtShutdown) {
exit(1);
}
});
}
private function resetDeprecationGroups()
{
$this->deprecationGroups = [
'unsilenced' => new DeprecationGroup(),
'self' => new DeprecationGroup(),
'direct' => new DeprecationGroup(),
'indirect' => new DeprecationGroup(),
'legacy' => new DeprecationGroup(),
'other' => new DeprecationGroup(),
];
}
private function getConfiguration()
{
if (null !== $this->configuration) {
@ -270,31 +273,38 @@ class DeprecationErrorHandler
/**
* @param string[] $groups
* @param Configuration $configuration
* @param bool $isFailing
*/
private function displayDeprecations($groups, $configuration)
private function displayDeprecations($groups, $configuration, $isFailing)
{
$cmp = function ($a, $b) {
return $b['count'] - $a['count'];
return $b->count() - $a->count();
};
foreach ($groups as $group) {
if ($this->deprecations[$group.'Count']) {
if ($this->deprecationGroups[$group]->count()) {
echo "\n", self::colorize(
sprintf('%s deprecation notices (%d)', ucfirst($group), $this->deprecations[$group.'Count']),
'legacy' !== $group && 'remaining indirect' !== $group
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";
if (!$configuration->verboseOutput()) {
if ('legacy' !== $group && !$configuration->verboseOutput($group) && !$isFailing) {
continue;
}
uasort($this->deprecations[$group], $cmp);
$notices = $this->deprecationGroups[$group]->notices();
uasort($notices, $cmp);
foreach ($this->deprecations[$group] as $msg => $notices) {
echo "\n ", $notices['count'], 'x: ', $msg, "\n";
foreach ($notices as $msg => $notice) {
echo "\n ", $notice->count(), 'x: ', $msg, "\n";
arsort($notices);
$countsByCaller = $notice->getCountsByCaller();
arsort($countsByCaller);
foreach ($notices as $method => $count) {
foreach ($countsByCaller as $method => $count) {
if ('count' !== $method) {
echo ' ', $count, 'x in ', preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method), "\n";
}

View File

@ -32,17 +32,17 @@ class Configuration
private $enabled = true;
/**
* @var bool
* @var bool[]
*/
private $verboseOutput = true;
private $verboseOutput;
/**
* @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
* @param bool[] $verboseOutput Keyed by groups
*/
private function __construct(array $thresholds = [], $regex = '', $verboseOutput = true)
private function __construct(array $thresholds = [], $regex = '', $verboseOutput = [])
{
$groups = ['total', 'indirect', 'direct', 'self'];
@ -72,7 +72,21 @@ class Configuration
}
}
$this->regex = $regex;
$this->verboseOutput = $verboseOutput;
$this->verboseOutput = [
'unsilenced' => true,
'direct' => true,
'indirect' => true,
'self' => true,
'other' => true,
];
foreach ($verboseOutput as $group => $status) {
if (!isset($this->verboseOutput[$group])) {
throw new \InvalidArgumentException(sprintf('Unsupported verbosity group "%s", expected one of "%s"', $group, implode('", "', array_keys($this->verboseOutput))));
}
$this->verboseOutput[$group] = (bool) $status;
}
}
/**
@ -84,24 +98,26 @@ class Configuration
}
/**
* @param mixed[] $deprecations
* @param DeprecationGroup[] $deprecationGroups
*
* @return bool
*/
public function tolerates(array $deprecations)
public function tolerates(array $deprecationGroups)
{
$deprecationCounts = [];
foreach ($deprecations as $key => $deprecation) {
if (false !== strpos($key, 'Count') && false === strpos($key, 'legacy')) {
$deprecationCounts[$key] = $deprecation;
$grandTotal = 0;
foreach ($deprecationGroups as $name => $group) {
if ('legacy' !== $name) {
$grandTotal += $group->count();
}
}
if (array_sum($deprecationCounts) > $this->thresholds['total']) {
if ($grandTotal > $this->thresholds['total']) {
return false;
}
foreach (['self', 'direct', 'indirect'] as $deprecationType) {
if ($deprecationCounts['remaining '.$deprecationType.'Count'] > $this->thresholds[$deprecationType]) {
if ($deprecationGroups[$deprecationType]->count() > $this->thresholds[$deprecationType]) {
return false;
}
}
@ -130,9 +146,9 @@ class Configuration
/**
* @return bool
*/
public function verboseOutput()
public function verboseOutput($group)
{
return $this->verboseOutput;
return $this->verboseOutput[$group];
}
/**
@ -145,7 +161,7 @@ class Configuration
{
parse_str($serializedConfiguration, $normalizedConfiguration);
foreach (array_keys($normalizedConfiguration) as $key) {
if (!\in_array($key, ['max', 'disabled', 'verbose'], true)) {
if (!\in_array($key, ['max', 'disabled', 'verbose', 'quiet'], true)) {
throw new \InvalidArgumentException(sprintf('Unknown configuration option "%s"', $key));
}
}
@ -154,9 +170,19 @@ class Configuration
return self::inDisabledMode();
}
$verboseOutput = true;
if (isset($normalizedConfiguration['verbose'])) {
$verboseOutput = (bool) $normalizedConfiguration['verbose'];
$verboseOutput = [];
if (!isset($normalizedConfiguration['verbose'])) {
$normalizedConfiguration['verbose'] = true;
}
foreach (['unsilenced', 'direct', 'indirect', 'self', 'other'] as $group) {
$verboseOutput[$group] = (bool) $normalizedConfiguration['verbose'];
}
if (isset($normalizedConfiguration['quiet']) && \is_array($normalizedConfiguration['quiet'])) {
foreach ($normalizedConfiguration['quiet'] as $shushedGroup) {
$verboseOutput[$shushedGroup] = false;
}
}
return new self(
@ -190,7 +216,12 @@ class Configuration
*/
public static function inWeakMode()
{
return new self([], '', false);
$verboseOutput = [];
foreach (['unsilenced', 'direct', 'indirect', 'self', 'other'] as $group) {
$verboseOutput[$group] = false;
}
return new self([], '', $verboseOutput);
}
/**

View File

@ -0,0 +1,74 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bridge\PhpUnit\DeprecationErrorHandler;
/**
* @internal
*/
final class DeprecationGroup
{
private $count = 0;
/**
* @var DeprecationNotice[] keys are messages
*/
private $deprecationNotices = [];
/**
* @param string $message
* @param string $class
* @param string $method
*/
public function addNoticeFromObject($message, $class, $method)
{
$this->deprecationNotice($message)->addObjectOccurence($class, $method);
$this->addNotice();
}
/**
* @param string $message
*/
public function addNoticeFromProceduralCode($message)
{
$this->deprecationNotice($message)->addProceduralOccurence();
$this->addNotice();
}
public function addNotice()
{
++$this->count;
}
/**
* @param string $message
*
* @return DeprecationNotice
*/
private function deprecationNotice($message)
{
if (!isset($this->deprecationNotices[$message])) {
$this->deprecationNotices[$message] = new DeprecationNotice();
}
return $this->deprecationNotices[$message];
}
public function count()
{
return $this->count;
}
public function notices()
{
return $this->deprecationNotices;
}
}

View File

@ -0,0 +1,49 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bridge\PhpUnit\DeprecationErrorHandler;
/**
* @internal
*/
final class DeprecationNotice
{
private $count = 0;
/**
* @var int[]
*/
private $countsByCaller = [];
public function addObjectOccurence($class, $method)
{
if (!isset($this->countsByCaller["$class::$method"])) {
$this->countsByCaller["$class::$method"] = 0;
}
++$this->countsByCaller["$class::$method"];
++$this->count;
}
public function addProceduralOccurence()
{
++$this->count;
}
public function getCountsByCaller()
{
return $this->countsByCaller;
}
public function count()
{
return $this->count;
}
}

View File

@ -13,6 +13,7 @@ namespace Symfony\Bridge\PhpUnit\Tests\DeprecationErrorHandler;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Configuration;
use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\DeprecationGroup;
class ConfigurationTest extends TestCase
{
@ -47,122 +48,122 @@ class ConfigurationTest extends TestCase
public function testItNoticesExceededTotalThreshold()
{
$configuration = Configuration::fromUrlEncodedString('max[total]=3');
$this->assertTrue($configuration->tolerates([
'unsilencedCount' => 1,
'remaining selfCount' => 0,
'legacyCount' => 1,
'otherCount' => 0,
'remaining directCount' => 1,
'remaining indirectCount' => 1,
]));
$this->assertFalse($configuration->tolerates([
'unsilencedCount' => 1,
'remaining selfCount' => 1,
'legacyCount' => 1,
'otherCount' => 0,
'remaining directCount' => 1,
'remaining indirectCount' => 1,
]));
$this->assertTrue($configuration->tolerates($this->buildGroups([
'unsilenced' => 1,
'self' => 0,
'legacy' => 1,
'other' => 0,
'direct' => 1,
'indirect' => 1,
])));
$this->assertFalse($configuration->tolerates($this->buildGroups([
'unsilenced' => 1,
'self' => 1,
'legacy' => 1,
'other' => 0,
'direct' => 1,
'indirect' => 1,
])));
}
public function testItNoticesExceededSelfThreshold()
{
$configuration = Configuration::fromUrlEncodedString('max[self]=1');
$this->assertTrue($configuration->tolerates([
'unsilencedCount' => 1234,
'remaining selfCount' => 1,
'legacyCount' => 23,
'otherCount' => 13,
'remaining directCount' => 124,
'remaining indirectCount' => 3244,
]));
$this->assertFalse($configuration->tolerates([
'unsilencedCount' => 1234,
'remaining selfCount' => 2,
'legacyCount' => 23,
'otherCount' => 13,
'remaining directCount' => 124,
'remaining indirectCount' => 3244,
]));
$this->assertTrue($configuration->tolerates($this->buildGroups([
'unsilenced' => 1234,
'self' => 1,
'legacy' => 23,
'other' => 13,
'direct' => 124,
'indirect' => 3244,
])));
$this->assertFalse($configuration->tolerates($this->buildGroups([
'unsilenced' => 1234,
'self' => 2,
'legacy' => 23,
'other' => 13,
'direct' => 124,
'indirect' => 3244,
])));
}
public function testItNoticesExceededDirectThreshold()
{
$configuration = Configuration::fromUrlEncodedString('max[direct]=1&max[self]=999999');
$this->assertTrue($configuration->tolerates([
'unsilencedCount' => 1234,
'remaining selfCount' => 123,
'legacyCount' => 23,
'otherCount' => 13,
'remaining directCount' => 1,
'remaining indirectCount' => 3244,
]));
$this->assertFalse($configuration->tolerates([
'unsilencedCount' => 1234,
'remaining selfCount' => 124,
'legacyCount' => 23,
'otherCount' => 13,
'remaining directCount' => 2,
'remaining indirectCount' => 3244,
]));
$this->assertTrue($configuration->tolerates($this->buildGroups([
'unsilenced' => 1234,
'self' => 123,
'legacy' => 23,
'other' => 13,
'direct' => 1,
'indirect' => 3244,
])));
$this->assertFalse($configuration->tolerates($this->buildGroups([
'unsilenced' => 1234,
'self' => 124,
'legacy' => 23,
'other' => 13,
'direct' => 2,
'indirect' => 3244,
])));
}
public function testItNoticesExceededIndirectThreshold()
{
$configuration = Configuration::fromUrlEncodedString('max[indirect]=1&max[direct]=999999&max[self]=999999');
$this->assertTrue($configuration->tolerates([
'unsilencedCount' => 1234,
'remaining selfCount' => 123,
'legacyCount' => 23,
'otherCount' => 13,
'remaining directCount' => 1234,
'remaining indirectCount' => 1,
]));
$this->assertFalse($configuration->tolerates([
'unsilencedCount' => 1234,
'remaining selfCount' => 124,
'legacyCount' => 23,
'otherCount' => 13,
'remaining directCount' => 2324,
'remaining indirectCount' => 2,
]));
$this->assertTrue($configuration->tolerates($this->buildGroups([
'unsilenced' => 1234,
'self' => 123,
'legacy' => 23,
'other' => 13,
'direct' => 1234,
'indirect' => 1,
])));
$this->assertFalse($configuration->tolerates($this->buildGroups([
'unsilenced' => 1234,
'self' => 124,
'legacy' => 23,
'other' => 13,
'direct' => 2324,
'indirect' => 2,
])));
}
public function testIndirectThresholdIsUsedAsADefaultForDirectAndSelfThreshold()
{
$configuration = Configuration::fromUrlEncodedString('max[indirect]=1');
$this->assertTrue($configuration->tolerates([
'unsilencedCount' => 0,
'remaining selfCount' => 1,
'legacyCount' => 0,
'otherCount' => 0,
'remaining directCount' => 0,
'remaining indirectCount' => 0,
]));
$this->assertFalse($configuration->tolerates([
'unsilencedCount' => 0,
'remaining selfCount' => 2,
'legacyCount' => 0,
'otherCount' => 0,
'remaining directCount' => 0,
'remaining indirectCount' => 0,
]));
$this->assertTrue($configuration->tolerates([
'unsilencedCount' => 0,
'remaining selfCount' => 0,
'legacyCount' => 0,
'otherCount' => 0,
'remaining directCount' => 1,
'remaining indirectCount' => 0,
]));
$this->assertFalse($configuration->tolerates([
'unsilencedCount' => 0,
'remaining selfCount' => 0,
'legacyCount' => 0,
'otherCount' => 0,
'remaining directCount' => 2,
'remaining indirectCount' => 0,
]));
$this->assertTrue($configuration->tolerates($this->buildGroups([
'unsilenced' => 0,
'self' => 1,
'legacy' => 0,
'other' => 0,
'direct' => 0,
'indirect' => 0,
])));
$this->assertFalse($configuration->tolerates($this->buildGroups([
'unsilenced' => 0,
'self' => 2,
'legacy' => 0,
'other' => 0,
'direct' => 0,
'indirect' => 0,
])));
$this->assertTrue($configuration->tolerates($this->buildGroups([
'unsilenced' => 0,
'self' => 0,
'legacy' => 0,
'other' => 0,
'direct' => 1,
'indirect' => 0,
])));
$this->assertFalse($configuration->tolerates($this->buildGroups([
'unsilenced' => 0,
'self' => 0,
'legacy' => 0,
'other' => 0,
'direct' => 2,
'indirect' => 0,
])));
}
public function testItCanTellWhetherToDisplayAStackTrace()
@ -184,12 +185,51 @@ class ConfigurationTest extends TestCase
public function testItCanBeShushed()
{
$configuration = Configuration::fromUrlEncodedString('verbose');
$this->assertFalse($configuration->verboseOutput());
$this->assertFalse($configuration->verboseOutput('unsilenced'));
$this->assertFalse($configuration->verboseOutput('direct'));
$this->assertFalse($configuration->verboseOutput('indirect'));
$this->assertFalse($configuration->verboseOutput('self'));
$this->assertFalse($configuration->verboseOutput('other'));
}
public function testItCanBePartiallyShushed()
{
$configuration = Configuration::fromUrlEncodedString('quiet[]=unsilenced&quiet[]=indirect&quiet[]=other');
$this->assertFalse($configuration->verboseOutput('unsilenced'));
$this->assertTrue($configuration->verboseOutput('direct'));
$this->assertFalse($configuration->verboseOutput('indirect'));
$this->assertTrue($configuration->verboseOutput('self'));
$this->assertFalse($configuration->verboseOutput('other'));
}
public function testItThrowsOnUnknownVerbosityGroup()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('made-up');
Configuration::fromUrlEncodedString('quiet[]=made-up');
}
public function testOutputIsNotVerboseInWeakMode()
{
$configuration = Configuration::inWeakMode();
$this->assertFalse($configuration->verboseOutput());
$this->assertFalse($configuration->verboseOutput('unsilenced'));
$this->assertFalse($configuration->verboseOutput('direct'));
$this->assertFalse($configuration->verboseOutput('indirect'));
$this->assertFalse($configuration->verboseOutput('self'));
$this->assertFalse($configuration->verboseOutput('other'));
}
private function buildGroups($counts)
{
$groups = [];
foreach ($counts as $name => $count) {
$groups[$name] = new DeprecationGroup();
$i = 0;
while ($i++ < $count) {
$groups[$name]->addNotice();
}
}
return $groups;
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace Symfony\Bridge\PhpUnit\Tests\DeprecationErrorHandler;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\DeprecationGroup;
final class DeprecationGroupTest extends TestCase
{
public function testItGroupsByMessage()
{
$group = new DeprecationGroup();
$group->addNoticeFromObject(
'Calling sfContext::getInstance() is deprecated',
'MonsterController',
'get5klocMethod'
);
$group->addNoticeFromProceduralCode('Calling sfContext::getInstance() is deprecated');
$this->assertCount(1, $group->notices());
$this->assertSame(2, $group->count());
}
public function testItAllowsAddingANoticeWithoutClutteringTheMemory()
{
// this is useful for notices in the legacy group
$group = new DeprecationGroup();
$group->addNotice();
$this->assertSame(1, $group->count());
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace Symfony\Bridge\PhpUnit\Tests\DeprecationErrorHandler;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\DeprecationNotice;
final class DeprecationNoticeTest extends TestCase
{
public function testItGroupsByCaller()
{
$notice = new DeprecationNotice();
$notice->addObjectOccurence('MyAction', '__invoke');
$notice->addObjectOccurence('MyAction', '__invoke');
$notice->addObjectOccurence('MyOtherAction', '__invoke');
$countsByCaller = $notice->getCountsByCaller();
$this->assertCount(2, $countsByCaller);
$this->assertArrayHasKey('MyAction::__invoke', $countsByCaller);
$this->assertArrayHasKey('MyOtherAction::__invoke', $countsByCaller);
$this->assertSame(2, $countsByCaller['MyAction::__invoke']);
$this->assertSame(1, $countsByCaller['MyOtherAction::__invoke']);
}
public function testItCountsBothTypesOfOccurences()
{
$notice = new DeprecationNotice();
$notice->addObjectOccurence('MyAction', '__invoke');
$this->assertSame(1, $notice->count());
$notice->addProceduralOccurence();
$this->assertSame(2, $notice->count());
}
}

View File

@ -0,0 +1,37 @@
--TEST--
Test DeprecationErrorHandler quiet on everything but indirect deprecations
--FILE--
<?php
$k = 'SYMFONY_DEPRECATIONS_HELPER';
putenv($k.'='.$_SERVER[$k] = $_ENV[$k] = 'max[self]=0&quiet[]=unsilenced&quiet[]=direct&quiet[]=other');
putenv('ANSICON');
putenv('ConEmuANSI');
putenv('TERM');
$vendor = __DIR__;
while (!file_exists($vendor.'/vendor')) {
$vendor = dirname($vendor);
}
define('PHPUNIT_COMPOSER_INSTALL', $vendor.'/vendor/autoload.php');
require PHPUNIT_COMPOSER_INSTALL;
require_once __DIR__.'/../../bootstrap.php';
require __DIR__.'/fake_vendor/autoload.php';
require __DIR__.'/fake_vendor/acme/lib/deprecation_riddled.php';
require __DIR__.'/fake_vendor/acme/outdated-lib/outdated_file.php';
?>
--EXPECTF--
Unsilenced deprecation notices (3)
Remaining direct deprecation notices (1)
Remaining indirect deprecation notices (1)
1x: deprecatedApi is deprecated! You should stop relying on it!
1x in SomeService::deprecatedApi from acme\lib
Legacy deprecation notices (2)
Other deprecation notices (1)

View File

@ -0,0 +1,39 @@
--TEST--
Test DeprecationErrorHandler when failing and not verbose
--FILE--
<?php
$k = 'SYMFONY_DEPRECATIONS_HELPER';
putenv($k.'='.$_SERVER[$k] = $_ENV[$k] = 'max[total]=0&verbose=0');
putenv('ANSICON');
putenv('ConEmuANSI');
putenv('TERM');
$vendor = __DIR__;
while (!file_exists($vendor.'/vendor')) {
$vendor = dirname($vendor);
}
define('PHPUNIT_COMPOSER_INSTALL', $vendor.'/vendor/autoload.php');
require PHPUNIT_COMPOSER_INSTALL;
require_once __DIR__.'/../../bootstrap.php';
eval(<<<'EOPHP'
namespace PHPUnit\Util;
class Test
{
public static function getGroups()
{
return array();
}
}
EOPHP
);
require __DIR__.'/fake_vendor/autoload.php';
require __DIR__.'/fake_vendor/acme/outdated-lib/outdated_file.php';
?>
--EXPECTF--
Remaining indirect deprecation notices (1)
1x: deprecatedApi is deprecated! You should stop relying on it!
1x in SomeService::deprecatedApi from acme\lib