gmarche/vendor/symfony/config/Tests/Resource/ReflectionClassResourceTest...

212 lines
7.0 KiB
PHP

<?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\Component\Config\Tests\Resource;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\Resource\ReflectionClassResource;
use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ReflectionClassResourceTest extends TestCase
{
public function testToString()
{
$res = new ReflectionClassResource(new \ReflectionClass('ErrorException'));
$this->assertSame('reflection.ErrorException', (string) $res);
}
public function testSerializeUnserialize()
{
$res = new ReflectionClassResource(new \ReflectionClass(DummyInterface::class));
$ser = unserialize(serialize($res));
$this->assertTrue($res->isFresh(0));
$this->assertTrue($ser->isFresh(0));
$this->assertSame((string) $res, (string) $ser);
}
public function testIsFresh()
{
$res = new ReflectionClassResource(new \ReflectionClass(__CLASS__));
$mtime = filemtime(__FILE__);
$this->assertTrue($res->isFresh($mtime), '->isFresh() returns true if the resource has not changed in same second');
$this->assertTrue($res->isFresh($mtime + 10), '->isFresh() returns true if the resource has not changed');
$this->assertTrue($res->isFresh($mtime - 86400), '->isFresh() returns true if the resource has not changed');
}
public function testIsFreshForDeletedResources()
{
$now = time();
$tmp = sys_get_temp_dir().'/tmp.php';
file_put_contents($tmp, '<?php class ReflectionClassResourceTestClass {}');
require $tmp;
$res = new ReflectionClassResource(new \ReflectionClass('ReflectionClassResourceTestClass'));
$this->assertTrue($res->isFresh($now));
unlink($tmp);
$this->assertFalse($res->isFresh($now), '->isFresh() returns false if the resource does not exist');
}
/**
* @dataProvider provideHashedSignature
*/
public function testHashedSignature($changeExpected, $changedLine, $changedCode)
{
$code = <<<'EOPHP'
/* 0*/
/* 1*/ class %s extends ErrorException
/* 2*/ {
/* 3*/ const FOO = 123;
/* 4*/
/* 5*/ public $pub = [];
/* 6*/
/* 7*/ protected $prot;
/* 8*/
/* 9*/ private $priv;
/*10*/
/*11*/ public function pub($arg = null) {}
/*12*/
/*13*/ protected function prot($a = []) {}
/*14*/
/*15*/ private function priv() {}
/*16*/ }
EOPHP;
static $expectedSignature, $generateSignature;
if (null === $expectedSignature) {
eval(sprintf($code, $class = 'Foo'.str_replace('.', '_', uniqid('', true))));
$r = new \ReflectionClass(ReflectionClassResource::class);
$generateSignature = $r->getMethod('generateSignature');
$generateSignature->setAccessible(true);
$generateSignature = $generateSignature->getClosure($r->newInstanceWithoutConstructor());
$expectedSignature = implode("\n", iterator_to_array($generateSignature(new \ReflectionClass($class))));
}
$code = explode("\n", $code);
$code[$changedLine] = $changedCode;
eval(sprintf(implode("\n", $code), $class = 'Foo'.str_replace('.', '_', uniqid('', true))));
$signature = implode("\n", iterator_to_array($generateSignature(new \ReflectionClass($class))));
if ($changeExpected) {
$this->assertNotSame($expectedSignature, $signature);
} else {
$this->assertSame($expectedSignature, $signature);
}
}
public function provideHashedSignature()
{
yield [0, 0, "// line change\n\n"];
yield [1, 0, '/** class docblock */'];
yield [1, 1, 'abstract class %s'];
yield [1, 1, 'final class %s'];
yield [1, 1, 'class %s extends Exception'];
yield [1, 1, 'class %s implements '.DummyInterface::class];
yield [1, 3, 'const FOO = 456;'];
yield [1, 3, 'const BAR = 123;'];
yield [1, 4, '/** pub docblock */'];
yield [1, 5, 'protected $pub = [];'];
yield [1, 5, 'public $pub = [123];'];
yield [1, 6, '/** prot docblock */'];
yield [1, 7, 'private $prot;'];
yield [0, 8, '/** priv docblock */'];
yield [0, 9, 'private $priv = 123;'];
yield [1, 10, '/** pub docblock */'];
if (\PHP_VERSION_ID >= 50600) {
yield [1, 11, 'public function pub(...$arg) {}'];
}
if (\PHP_VERSION_ID >= 70000) {
yield [1, 11, 'public function pub($arg = null): Foo {}'];
}
yield [0, 11, "public function pub(\$arg = null) {\nreturn 123;\n}"];
yield [1, 12, '/** prot docblock */'];
yield [1, 13, 'protected function prot($a = [123]) {}'];
yield [0, 14, '/** priv docblock */'];
yield [0, 15, ''];
if (\PHP_VERSION_ID >= 70400) {
// PHP7.4 typed properties without default value are
// undefined, make sure this doesn't throw an error
yield [1, 5, 'public array $pub;'];
yield [0, 7, 'protected int $prot;'];
yield [0, 9, 'private string $priv;'];
}
}
public function testEventSubscriber()
{
$res = new ReflectionClassResource(new \ReflectionClass(TestEventSubscriber::class));
$this->assertTrue($res->isFresh(0));
TestEventSubscriber::$subscribedEvents = [123];
$this->assertFalse($res->isFresh(0));
$res = new ReflectionClassResource(new \ReflectionClass(TestEventSubscriber::class));
$this->assertTrue($res->isFresh(0));
}
public function testServiceSubscriber()
{
$res = new ReflectionClassResource(new \ReflectionClass(TestServiceSubscriber::class));
$this->assertTrue($res->isFresh(0));
TestServiceSubscriber::$subscribedServices = [123];
$this->assertFalse($res->isFresh(0));
$res = new ReflectionClassResource(new \ReflectionClass(TestServiceSubscriber::class));
$this->assertTrue($res->isFresh(0));
}
public function testIgnoresObjectsInSignature()
{
$res = new ReflectionClassResource(new \ReflectionClass(TestServiceWithStaticProperty::class));
$this->assertTrue($res->isFresh(0));
TestServiceWithStaticProperty::$initializedObject = new TestServiceWithStaticProperty();
$this->assertTrue($res->isFresh(0));
}
}
interface DummyInterface
{
}
class TestEventSubscriber implements EventSubscriberInterface
{
public static $subscribedEvents = [];
public static function getSubscribedEvents()
{
return self::$subscribedEvents;
}
}
class TestServiceSubscriber implements ServiceSubscriberInterface
{
public static $subscribedServices = [];
public static function getSubscribedServices()
{
return self::$subscribedServices;
}
}
class TestServiceWithStaticProperty
{
public static $initializedObject;
}