4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Config\Tests\Resource;
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\Config\Resource\ReflectionClassResource;
16 use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
17 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
19 class ReflectionClassResourceTest extends TestCase
21 public function testToString()
23 $res = new ReflectionClassResource(new \ReflectionClass('ErrorException'));
25 $this->assertSame('reflection.ErrorException', (string) $res);
28 public function testSerializeUnserialize()
30 $res = new ReflectionClassResource(new \ReflectionClass(DummyInterface::class));
31 $ser = unserialize(serialize($res));
33 $this->assertTrue($res->isFresh(0));
34 $this->assertTrue($ser->isFresh(0));
36 $this->assertSame((string) $res, (string) $ser);
39 public function testIsFresh()
41 $res = new ReflectionClassResource(new \ReflectionClass(__CLASS__));
42 $mtime = filemtime(__FILE__);
44 $this->assertTrue($res->isFresh($mtime), '->isFresh() returns true if the resource has not changed in same second');
45 $this->assertTrue($res->isFresh($mtime + 10), '->isFresh() returns true if the resource has not changed');
46 $this->assertTrue($res->isFresh($mtime - 86400), '->isFresh() returns true if the resource has not changed');
49 public function testIsFreshForDeletedResources()
52 $tmp = sys_get_temp_dir().'/tmp.php';
53 file_put_contents($tmp, '<?php class ReflectionClassResourceTestClass {}');
56 $res = new ReflectionClassResource(new \ReflectionClass('ReflectionClassResourceTestClass'));
57 $this->assertTrue($res->isFresh($now));
60 $this->assertFalse($res->isFresh($now), '->isFresh() returns false if the resource does not exist');
64 * @dataProvider provideHashedSignature
66 public function testHashedSignature($changeExpected, $changedLine, $changedCode)
70 /* 1*/ class %s extends ErrorException
72 /* 3*/ const FOO = 123;
74 /* 5*/ public $pub = array();
76 /* 7*/ protected $prot;
80 /*11*/ public function pub($arg = null) {}
82 /*13*/ protected function prot($a = array()) {}
84 /*15*/ private function priv() {}
88 static $expectedSignature, $generateSignature;
90 if (null === $expectedSignature) {
91 eval(sprintf($code, $class = 'Foo'.str_replace('.', '_', uniqid('', true))));
92 $r = new \ReflectionClass(ReflectionClassResource::class);
93 $generateSignature = $r->getMethod('generateSignature');
94 $generateSignature->setAccessible(true);
95 $generateSignature = $generateSignature->getClosure($r->newInstanceWithoutConstructor());
96 $expectedSignature = implode("\n", iterator_to_array($generateSignature(new \ReflectionClass($class))));
99 $code = explode("\n", $code);
100 $code[$changedLine] = $changedCode;
101 eval(sprintf(implode("\n", $code), $class = 'Foo'.str_replace('.', '_', uniqid('', true))));
102 $signature = implode("\n", iterator_to_array($generateSignature(new \ReflectionClass($class))));
104 if ($changeExpected) {
105 $this->assertNotSame($expectedSignature, $signature);
107 $this->assertSame($expectedSignature, $signature);
111 public function provideHashedSignature()
113 yield array(0, 0, "// line change\n\n");
114 yield array(1, 0, '/** class docblock */');
115 yield array(1, 1, 'abstract class %s');
116 yield array(1, 1, 'final class %s');
117 yield array(1, 1, 'class %s extends Exception');
118 yield array(1, 1, 'class %s implements '.DummyInterface::class);
119 yield array(1, 3, 'const FOO = 456;');
120 yield array(1, 3, 'const BAR = 123;');
121 yield array(1, 4, '/** pub docblock */');
122 yield array(1, 5, 'protected $pub = array();');
123 yield array(1, 5, 'public $pub = array(123);');
124 yield array(1, 6, '/** prot docblock */');
125 yield array(1, 7, 'private $prot;');
126 yield array(0, 8, '/** priv docblock */');
127 yield array(0, 9, 'private $priv = 123;');
128 yield array(1, 10, '/** pub docblock */');
129 if (\PHP_VERSION_ID >= 50600) {
130 yield array(1, 11, 'public function pub(...$arg) {}');
132 if (\PHP_VERSION_ID >= 70000) {
133 yield array(1, 11, 'public function pub($arg = null): Foo {}');
135 yield array(0, 11, "public function pub(\$arg = null) {\nreturn 123;\n}");
136 yield array(1, 12, '/** prot docblock */');
137 yield array(1, 13, 'protected function prot($a = array(123)) {}');
138 yield array(0, 14, '/** priv docblock */');
139 yield array(0, 15, '');
142 public function testEventSubscriber()
144 $res = new ReflectionClassResource(new \ReflectionClass(TestEventSubscriber::class));
145 $this->assertTrue($res->isFresh(0));
147 TestEventSubscriber::$subscribedEvents = array(123);
148 $this->assertFalse($res->isFresh(0));
150 $res = new ReflectionClassResource(new \ReflectionClass(TestEventSubscriber::class));
151 $this->assertTrue($res->isFresh(0));
154 public function testServiceSubscriber()
156 $res = new ReflectionClassResource(new \ReflectionClass(TestServiceSubscriber::class));
157 $this->assertTrue($res->isFresh(0));
159 TestServiceSubscriber::$subscribedServices = array(123);
160 $this->assertFalse($res->isFresh(0));
162 $res = new ReflectionClassResource(new \ReflectionClass(TestServiceSubscriber::class));
163 $this->assertTrue($res->isFresh(0));
167 interface DummyInterface
171 class TestEventSubscriber implements EventSubscriberInterface
173 public static $subscribedEvents = array();
175 public static function getSubscribedEvents()
177 return self::$subscribedEvents;
181 class TestServiceSubscriber implements ServiceSubscriberInterface
183 public static $subscribedServices = array();
185 public static function getSubscribedServices()
187 return self::$subscribedServices;