[PHPUnitBridge] Fix deprecation type detection when trigger_deprecation is used

This commit is contained in:
Laurent VOULLEMIER 2020-08-30 22:52:51 +02:00 committed by Nicolas Grekas
parent 96151f391a
commit fd39961180
11 changed files with 230 additions and 13 deletions

View File

@ -52,13 +52,18 @@ class Deprecation
*/
public function __construct($message, array $trace, $file)
{
if (isset($trace[2]['function']) && 'trigger_deprecation' === $trace[2]['function']) {
$file = $trace[2]['file'];
array_splice($trace, 1, 1);
}
$this->trace = $trace;
$this->message = $message;
$i = \count($trace);
while (1 < $i && $this->lineShouldBeSkipped($trace[--$i])) {
$i = \count($this->trace);
while (1 < $i && $this->lineShouldBeSkipped($this->trace[--$i])) {
// No-op
}
$line = $trace[$i];
$line = $this->trace[$i];
$this->triggeringFile = $file;
if (isset($line['object']) || isset($line['class'])) {
if (isset($line['class']) && 0 === strpos($line['class'], SymfonyTestsListenerFor::class)) {

View File

@ -0,0 +1,41 @@
<?php
namespace App\Services;
use acme\lib\SomeService;
use foo\lib\SomeOtherService;
final class AppService
{
public function directDeprecationsTwoVendors()
{
$service1 = new SomeService();
$service1->deprecatedApi();
$service2 = new SomeOtherService();
$service2->deprecatedApi();
}
public function selfDeprecation(bool $useContracts = false)
{
$args = [__FUNCTION__, __FUNCTION__];
if ($useContracts) {
trigger_deprecation('App', '3.0', sprintf('%s is deprecated, use %s_new instead.', ...$args));
} else {
@trigger_error(sprintf('Since App 3.0: %s is deprecated, use %s_new instead.', ...$args), E_USER_DEPRECATED);
}
}
public function directDeprecation(bool $useContracts = false)
{
$service = new SomeService();
$service->deprecatedApi($useContracts);
}
public function indirectDeprecation(bool $useContracts = false)
{
$service = new SomeService();
$service->indirectDeprecatedApi($useContracts);
}
}

View File

@ -2,13 +2,22 @@
namespace acme\lib;
use bar\lib\AnotherService;
class SomeService
{
public function deprecatedApi()
public function deprecatedApi(bool $useContracts = false)
{
@trigger_error(
__FUNCTION__.' is deprecated! You should stop relying on it!',
E_USER_DEPRECATED
);
$args = [__FUNCTION__, __FUNCTION__];
if ($useContracts) {
trigger_deprecation('acme/lib', '3.0', sprintf('%s is deprecated, use %s_new instead.', ...$args));
} else {
@trigger_error(sprintf('Since acme/lib 3.0: %s is deprecated, use %s_new instead.', ...$args), E_USER_DEPRECATED);
}
}
public function indirectDeprecatedApi(bool $useContracts = false)
{
(new AnotherService())->deprecatedApi($useContracts);
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace bar\lib;
class AnotherService
{
public function deprecatedApi(bool $useContracts = false)
{
$args = [__FUNCTION__, __FUNCTION__];
if ($useContracts) {
trigger_deprecation('bar/lib', '3.0', sprintf('%s is deprecated, use %s_new instead.', ...$args));
} else {
@trigger_error(sprintf('Since bar/lib 3.0: %s is deprecated, use %s_new instead.', ...$args), E_USER_DEPRECATED);
}
}
}

View File

@ -9,14 +9,41 @@ class ComposerLoaderFake
public function getPrefixesPsr4()
{
return [];
return [
'App\\Services\\' => [__DIR__.'/../../fake_app/'],
'acme\\lib\\' => [__DIR__.'/../acme/lib/'],
'bar\\lib\\' => [__DIR__.'/../bar/lib/'],
];
}
public function loadClass($className)
{
foreach ($this->getPrefixesPsr4() as $prefix => $baseDirs) {
if (strpos($className, $prefix) !== 0) {
continue;
}
foreach ($baseDirs as $baseDir) {
$file = str_replace([$prefix, '\\'], [$baseDir, '/'], $className.'.php');
if (file_exists($file)) {
require $file;
}
}
}
}
}
class ComposerAutoloaderInitFake
{
private static $loader;
public static function getLoader()
{
return new ComposerLoaderFake();
if (null === self::$loader) {
self::$loader = new ComposerLoaderFake();
spl_autoload_register([self::$loader, 'loadClass']);
}
return self::$loader;
}
}

View File

@ -35,5 +35,5 @@ 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: Since acme/lib 3.0: deprecatedApi is deprecated, use deprecatedApi_new instead.
1x in SomeService::deprecatedApi from acme\lib

View File

@ -28,7 +28,7 @@ Remaining direct deprecation notices (1)
Remaining indirect deprecation notices (1)
1x: deprecatedApi is deprecated! You should stop relying on it!
1x: Since acme/lib 3.0: deprecatedApi is deprecated, use deprecatedApi_new instead.
1x in SomeService::deprecatedApi from acme\lib
Legacy deprecation notices (2)

View File

@ -35,5 +35,5 @@ 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: Since acme/lib 3.0: deprecatedApi is deprecated, use deprecatedApi_new instead.
1x in SomeService::deprecatedApi from acme\lib

View File

@ -0,0 +1,58 @@
--TEST--
Test deprecation types with trigger_deprecation
--FILE--
<?php
$k = 'SYMFONY_DEPRECATIONS_HELPER';
putenv($k.'='.$_SERVER[$k] = $_ENV[$k] = 'max[self]=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';
(new \App\Services\AppService())->selfDeprecation(true);
(new \App\Services\AppService())->directDeprecation(true);
(new \App\Services\AppService())->indirectDeprecation(true);
trigger_deprecation('foo/bar', '2.0', 'func is deprecated, use new instead.');
?>
--EXPECTF--
Remaining self deprecation notices (1)
1x: Since App 3.0: selfDeprecation is deprecated, use selfDeprecation_new instead.
1x in AppService::selfDeprecation from App\Services
Remaining direct deprecation notices (1)
1x: Since acme/lib 3.0: deprecatedApi is deprecated, use deprecatedApi_new instead.
1x in AppService::directDeprecation from App\Services
Remaining indirect deprecation notices (1)
1x: Since bar/lib 3.0: deprecatedApi is deprecated, use deprecatedApi_new instead.
1x in AppService::indirectDeprecation from App\Services
Other deprecation notices (1)
1x: Since foo/bar 2.0: func is deprecated, use new instead.

View File

@ -0,0 +1,58 @@
--TEST--
Test deprecation types with trigger_error
--FILE--
<?php
$k = 'SYMFONY_DEPRECATIONS_HELPER';
putenv($k.'='.$_SERVER[$k] = $_ENV[$k] = 'max[self]=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';
(new \App\Services\AppService())->selfDeprecation();
(new \App\Services\AppService())->directDeprecation();
(new \App\Services\AppService())->indirectDeprecation();
@trigger_error('Since foo/bar 2.0: func is deprecated, use new instead.', E_USER_DEPRECATED);
?>
--EXPECTF--
Remaining self deprecation notices (1)
1x: Since App 3.0: selfDeprecation is deprecated, use selfDeprecation_new instead.
1x in AppService::selfDeprecation from App\Services
Remaining direct deprecation notices (1)
1x: Since acme/lib 3.0: deprecatedApi is deprecated, use deprecatedApi_new instead.
1x in AppService::directDeprecation from App\Services
Remaining indirect deprecation notices (1)
1x: Since bar/lib 3.0: deprecatedApi is deprecated, use deprecatedApi_new instead.
1x in AppService::indirectDeprecation from App\Services
Other deprecation notices (1)
1x: Since foo/bar 2.0: func is deprecated, use new instead.

View File

@ -45,5 +45,8 @@
"name": "phpunit/phpunit",
"url": "https://github.com/sebastianbergmann/phpunit"
}
},
"require-dev": {
"symfony/deprecation-contracts": "^2.1"
}
}