From 8750460fce202808feb63d74e01e1181dd7262ab Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 22 Jul 2017 11:49:26 +0200 Subject: [PATCH] #135 rewrote `AnnotationRegistry` tests to prevent reflection reads --- .../Common/Annotations/AnnotationRegistry.php | 5 +- .../Annotations/AnnotationRegistryTest.php | 88 ++++++++++++++++--- 2 files changed, 75 insertions(+), 18 deletions(-) diff --git a/lib/Doctrine/Common/Annotations/AnnotationRegistry.php b/lib/Doctrine/Common/Annotations/AnnotationRegistry.php index ebfaf77dc..8ca951a02 100644 --- a/lib/Doctrine/Common/Annotations/AnnotationRegistry.php +++ b/lib/Doctrine/Common/Annotations/AnnotationRegistry.php @@ -113,11 +113,8 @@ static public function registerAutoloadNamespaces(array $namespaces) * * @throws \InvalidArgumentException */ - static public function registerLoader($callable) + static public function registerLoader(callable $callable) { - if (!is_callable($callable)) { - throw new \InvalidArgumentException("A callable is expected in AnnotationRegistry::registerLoader()."); - } // Reset our static cache now that we have a new loader to work with self::$failedToAutoload = array(); self::$loaders[] = $callable; diff --git a/tests/Doctrine/Tests/Common/Annotations/AnnotationRegistryTest.php b/tests/Doctrine/Tests/Common/Annotations/AnnotationRegistryTest.php index 7fb2bd0e8..a458872b4 100644 --- a/tests/Doctrine/Tests/Common/Annotations/AnnotationRegistryTest.php +++ b/tests/Doctrine/Tests/Common/Annotations/AnnotationRegistryTest.php @@ -25,8 +25,6 @@ public function testReset() self::assertEmpty($this->getStaticField($this->class, 'autoloadNamespaces')); self::assertEmpty($this->getStaticField($this->class, 'loaders')); - self::assertEmpty($this->getStaticField($this->class, 'loaded')); - self::assertEmpty($this->getStaticField($this->class, 'unloadable')); } /** @@ -68,7 +66,10 @@ protected function getStaticField($class, $field) return $reflection->getValue(); } - public function testStopCallingLoadersIfClassIsNotFound() + /** + * @runInSeparateProcess + */ + public function testStopCallingLoadersIfClassIsNotFound() : void { AnnotationRegistry::reset(); $i = 0; @@ -83,29 +84,88 @@ public function testStopCallingLoadersIfClassIsNotFound() $this->assertEquals(1, $i, 'Autoloader should only be called once'); } - public function testStopCallingLoadersAfterClassIsFound() + /** + * @runInSeparateProcess + */ + public function testStopCallingLoadersAfterClassIsFound() : void { + $className = 'autoloadedClass' . random_int(10, 100000); AnnotationRegistry::reset(); $i = 0; - $autoLoader = function($annotation) use (&$i) { + $autoLoader = function($annotation) use (&$i, $className) { + eval('class ' . $className . ' {}'); $i++; return true; }; AnnotationRegistry::registerLoader($autoLoader); - AnnotationRegistry::loadAnnotationClass(self::class); - AnnotationRegistry::loadAnnotationClass(self::class); - AnnotationRegistry::loadAnnotationClass(self::class); + AnnotationRegistry::loadAnnotationClass($className); + AnnotationRegistry::loadAnnotationClass($className); + AnnotationRegistry::loadAnnotationClass($className); $this->assertEquals(1, $i, 'Autoloader should only be called once'); } - public function testAddingANewLoaderClearsTheCache() + /** + * @runInSeparateProcess + */ + public function testAddingANewLoaderClearsTheCache() : void + { + $failures = 0; + $failingLoader = function (string $annotation) use (& $failures) : bool { + $failures += 1; + + return false; + }; + + AnnotationRegistry::reset(); + AnnotationRegistry::registerLoader($failingLoader); + + self::assertSame(0, $failures); + + AnnotationRegistry::loadAnnotationClass('unloadableClass'); + + self::assertSame(1, $failures); + + AnnotationRegistry::loadAnnotationClass('unloadableClass'); + + self::assertSame(1, $failures); + + AnnotationRegistry::registerLoader(function () { + return false; + }); + AnnotationRegistry::loadAnnotationClass('unloadableClass'); + + self::assertSame(2, $failures); + } + + /** + * @runInSeparateProcess + */ + public function testResetClearsRegisteredAutoloaderFailures() : void { + $failures = 0; + $failingLoader = function (string $annotation) use (& $failures) : bool { + $failures += 1; + + return false; + }; + AnnotationRegistry::reset(); - AnnotationRegistry::registerLoader('class_exists'); - AnnotationRegistry::loadAnnotationClass(self::class); + AnnotationRegistry::registerLoader($failingLoader); + + self::assertSame(0, $failures); + + AnnotationRegistry::loadAnnotationClass('unloadableClass'); + + self::assertSame(1, $failures); + AnnotationRegistry::loadAnnotationClass('unloadableClass'); - AnnotationRegistry::registerLoader('class_exists'); - self::assertEmpty($this->getStaticField($this->class, 'loaded')); - self::assertEmpty($this->getStaticField($this->class, 'unloadable')); + + self::assertSame(1, $failures); + + AnnotationRegistry::reset(); + AnnotationRegistry::registerLoader($failingLoader); + AnnotationRegistry::loadAnnotationClass('unloadableClass'); + + self::assertSame(2, $failures); } } \ No newline at end of file