AnnotationRegistryTest.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. <?php
  2. namespace EasySwoole\DoctrineAnnotation\Tests;
  3. use EasySwoole\DoctrineAnnotation\AnnotationRegistry;
  4. use EasySwoole\DoctrineAnnotation\Tests\Fixtures\Annotation\CanBeAutoLoaded;
  5. use EasySwoole\DoctrineAnnotation\Tests\Fixtures\Annotation\LoadedUsingRegisterFile;
  6. use EasySwoole\DoctrineAnnotation\Tests\Fixtures\Annotation\ShouldNeverBeLoaded;
  7. use PHPUnit\Framework\TestCase;
  8. use ReflectionProperty;
  9. use TypeError;
  10. use function random_int;
  11. class AnnotationRegistryTest extends TestCase
  12. {
  13. /** @var string */
  14. protected $class = AnnotationRegistry::class;
  15. /**
  16. * @runInSeparateProcess
  17. */
  18. public function testReset(): void
  19. {
  20. $data = ['foo' => 'bar'];
  21. $this->setStaticField($this->class, 'autoloadNamespaces', $data);
  22. $this->setStaticField($this->class, 'loaders', $data);
  23. self::assertSame($data, $this->getStaticField($this->class, 'autoloadNamespaces'));
  24. self::assertSame($data, $this->getStaticField($this->class, 'loaders'));
  25. AnnotationRegistry::reset();
  26. self::assertEmpty($this->getStaticField($this->class, 'autoloadNamespaces'));
  27. self::assertEmpty($this->getStaticField($this->class, 'loaders'));
  28. }
  29. /**
  30. * @runInSeparateProcess
  31. */
  32. public function testRegisterAutoloadNamespaces(): void
  33. {
  34. $this->setStaticField($this->class, 'autoloadNamespaces', ['foo' => 'bar']);
  35. AnnotationRegistry::registerAutoloadNamespaces(['test' => 'bar']);
  36. self::assertSame(['foo' => 'bar', 'test' => 'bar'], $this->getStaticField($this->class, 'autoloadNamespaces'));
  37. }
  38. /**
  39. * @runInSeparateProcess
  40. */
  41. public function testRegisterLoaderNoCallable(): void
  42. {
  43. $this->expectException(TypeError::class);
  44. AnnotationRegistry::registerLoader('test' . random_int(10, 10000));
  45. }
  46. /**
  47. * @param mixed[] $value
  48. */
  49. protected function setStaticField(string $class, string $field, array $value): void
  50. {
  51. $reflection = new ReflectionProperty($class, $field);
  52. $reflection->setAccessible(true);
  53. $reflection->setValue(null, $value);
  54. }
  55. /**
  56. * @return mixed
  57. */
  58. protected function getStaticField(string $class, string $field)
  59. {
  60. $reflection = new ReflectionProperty($class, $field);
  61. $reflection->setAccessible(true);
  62. return $reflection->getValue();
  63. }
  64. /**
  65. * @runInSeparateProcess
  66. */
  67. public function testStopCallingLoadersIfClassIsNotFound(): void
  68. {
  69. AnnotationRegistry::reset();
  70. $i = 0;
  71. $autoLoader = static function () use (&$i): bool {
  72. $i += 1;
  73. return false;
  74. };
  75. AnnotationRegistry::registerLoader($autoLoader);
  76. AnnotationRegistry::loadAnnotationClass('unloadableClass');
  77. AnnotationRegistry::loadAnnotationClass('unloadableClass');
  78. AnnotationRegistry::loadAnnotationClass('unloadableClass');
  79. self::assertSame(1, $i, 'Autoloader should only be called once');
  80. }
  81. /**
  82. * @runInSeparateProcess
  83. */
  84. public function testStopCallingLoadersAfterClassIsFound(): void
  85. {
  86. $className = 'autoloadedClass' . random_int(10, 100000);
  87. AnnotationRegistry::reset();
  88. $i = 0;
  89. $autoLoader = static function () use (&$i, $className): bool {
  90. eval('class ' . $className . ' {}');
  91. $i += 1;
  92. return true;
  93. };
  94. AnnotationRegistry::registerLoader($autoLoader);
  95. AnnotationRegistry::loadAnnotationClass($className);
  96. AnnotationRegistry::loadAnnotationClass($className);
  97. AnnotationRegistry::loadAnnotationClass($className);
  98. self::assertSame(1, $i, 'Autoloader should only be called once');
  99. }
  100. /**
  101. * @runInSeparateProcess
  102. */
  103. public function testAddingANewLoaderClearsTheCache(): void
  104. {
  105. $failures = 0;
  106. $failingLoader = static function () use (&$failures): bool {
  107. $failures += 1;
  108. return false;
  109. };
  110. AnnotationRegistry::reset();
  111. AnnotationRegistry::registerLoader($failingLoader);
  112. self::assertSame(0, $failures);
  113. AnnotationRegistry::loadAnnotationClass('unloadableClass');
  114. self::assertSame(1, $failures);
  115. AnnotationRegistry::loadAnnotationClass('unloadableClass');
  116. self::assertSame(1, $failures);
  117. AnnotationRegistry::registerLoader(static function (): bool {
  118. return false;
  119. });
  120. AnnotationRegistry::loadAnnotationClass('unloadableClass');
  121. self::assertSame(2, $failures);
  122. }
  123. /**
  124. * @runInSeparateProcess
  125. */
  126. public function testResetClearsRegisteredAutoloaderFailures(): void
  127. {
  128. $failures = 0;
  129. $failingLoader = static function () use (&$failures): bool {
  130. $failures += 1;
  131. return false;
  132. };
  133. AnnotationRegistry::reset();
  134. AnnotationRegistry::registerLoader($failingLoader);
  135. self::assertSame(0, $failures);
  136. AnnotationRegistry::loadAnnotationClass('unloadableClass');
  137. self::assertSame(1, $failures);
  138. AnnotationRegistry::loadAnnotationClass('unloadableClass');
  139. self::assertSame(1, $failures);
  140. AnnotationRegistry::reset();
  141. AnnotationRegistry::registerLoader($failingLoader);
  142. AnnotationRegistry::loadAnnotationClass('unloadableClass');
  143. self::assertSame(2, $failures);
  144. }
  145. /**
  146. * @runInSeparateProcess
  147. */
  148. public function testRegisterLoaderIfNotExistsOnlyRegisteresSameLoaderOnce(): void
  149. {
  150. $className = 'autoloadedClassThatDoesNotExist';
  151. AnnotationRegistry::reset();
  152. $autoLoader = self::createPartialMock(Autoloader::class, ['__invoke']);
  153. $autoLoader->expects($this->once())->method('__invoke');
  154. AnnotationRegistry::registerUniqueLoader($autoLoader);
  155. AnnotationRegistry::registerUniqueLoader($autoLoader);
  156. AnnotationRegistry::loadAnnotationClass($className);
  157. AnnotationRegistry::loadAnnotationClass($className);
  158. }
  159. /**
  160. * @runInSeparateProcess
  161. */
  162. public function testClassExistsFallback(): void
  163. {
  164. AnnotationRegistry::reset();
  165. self::assertTrue(AnnotationRegistry::loadAnnotationClass(CanBeAutoLoaded::class));
  166. }
  167. /**
  168. * @runInSeparateProcess
  169. */
  170. public function testClassExistsFallbackNotUsedWhenRegisterFileUsed(): void
  171. {
  172. AnnotationRegistry::reset();
  173. AnnotationRegistry::registerFile(__DIR__ . '/Fixtures/Annotation/LoadedUsingRegisterFile.php');
  174. self::assertTrue(AnnotationRegistry::loadAnnotationClass(LoadedUsingRegisterFile::class));
  175. self::assertFalse(AnnotationRegistry::loadAnnotationClass(ShouldNeverBeLoaded::class));
  176. }
  177. }
  178. class Autoloader
  179. {
  180. public function __invoke(): void
  181. {
  182. }
  183. }