DeprecationTest.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. <?php
  2. declare(strict_types=1);
  3. namespace Doctrine\Deprecations;
  4. use DeprecationTests\Foo;
  5. use DeprecationTests\RootDeprecation;
  6. use Doctrine\Deprecations\PHPUnit\VerifyDeprecations;
  7. use Doctrine\Foo\Baz;
  8. use PHPUnit\Framework\Error\Deprecated;
  9. use PHPUnit\Framework\MockObject\MockObject;
  10. use PHPUnit\Framework\TestCase;
  11. use Psr\Log\LoggerInterface;
  12. use ReflectionProperty;
  13. use Throwable;
  14. use function method_exists;
  15. use function set_error_handler;
  16. class DeprecationTest extends TestCase
  17. {
  18. use VerifyDeprecations;
  19. public function setUp(): void
  20. {
  21. // reset the global state of Deprecation class accross tests
  22. $reflectionProperty = new ReflectionProperty(Deprecation::class, 'ignoredPackages');
  23. $reflectionProperty->setAccessible(true);
  24. $reflectionProperty->setValue([]);
  25. $reflectionProperty = new ReflectionProperty(Deprecation::class, 'ignoredLinks');
  26. $reflectionProperty->setAccessible(true);
  27. $reflectionProperty->setValue([]);
  28. Deprecation::enableTrackingDeprecations();
  29. }
  30. public function expectDeprecation(): void
  31. {
  32. if (method_exists(TestCase::class, 'expectDeprecation')) {
  33. parent::expectDeprecation();
  34. } else {
  35. parent::expectException(Deprecated::class);
  36. }
  37. }
  38. public function expectDeprecationMessage(string $message): void
  39. {
  40. if (method_exists(TestCase::class, 'expectDeprecationMessage')) {
  41. parent::expectDeprecationMessage($message);
  42. } else {
  43. parent::expectExceptionMessage($message);
  44. }
  45. }
  46. public function expectErrorHandler(string $expectedMessage, string $identifier, int $times = 1): void
  47. {
  48. set_error_handler(function ($type, $message) use ($expectedMessage, $identifier, $times): void {
  49. $this->assertStringMatchesFormat(
  50. $expectedMessage,
  51. $message
  52. );
  53. $this->assertEquals([$identifier => $times], Deprecation::getTriggeredDeprecations());
  54. });
  55. }
  56. public function testDeprecation(): void
  57. {
  58. Deprecation::enableWithTriggerError();
  59. $this->expectDeprecationWithIdentifier('https://github.com/doctrine/deprecations/1234');
  60. $this->expectErrorHandler(
  61. 'this is deprecated foo 1234 (DeprecationTest.php:%d called by TestCase.php:%d, https://github.com/doctrine/deprecations/1234, package doctrine/orm)',
  62. 'https://github.com/doctrine/deprecations/1234'
  63. );
  64. Deprecation::trigger(
  65. 'doctrine/orm',
  66. 'https://github.com/doctrine/deprecations/1234',
  67. 'this is deprecated %s %d',
  68. 'foo',
  69. 1234
  70. );
  71. $this->assertEquals(1, Deprecation::getUniqueTriggeredDeprecationsCount());
  72. Deprecation::trigger(
  73. 'doctrine/orm',
  74. 'https://github.com/doctrine/deprecations/1234',
  75. 'this is deprecated %s %d',
  76. 'foo',
  77. 1234
  78. );
  79. $this->assertEquals(2, Deprecation::getUniqueTriggeredDeprecationsCount());
  80. }
  81. public function testDeprecationWithoutDeduplication(): void
  82. {
  83. Deprecation::enableWithTriggerError();
  84. Deprecation::withoutDeduplication();
  85. $this->expectErrorHandler(
  86. 'this is deprecated foo 2222 (DeprecationTest.php:%d called by TestCase.php:%d, https://github.com/doctrine/deprecations/2222, package doctrine/orm)',
  87. 'https://github.com/doctrine/deprecations/2222'
  88. );
  89. Deprecation::trigger(
  90. 'doctrine/orm',
  91. 'https://github.com/doctrine/deprecations/2222',
  92. 'this is deprecated %s %d',
  93. 'foo',
  94. 2222
  95. );
  96. $this->assertEquals(1, Deprecation::getUniqueTriggeredDeprecationsCount());
  97. $this->expectErrorHandler(
  98. 'this is deprecated foo 2222 (DeprecationTest.php:%d called by TestCase.php:%d, https://github.com/doctrine/deprecations/2222, package doctrine/orm)',
  99. 'https://github.com/doctrine/deprecations/2222',
  100. 2
  101. );
  102. Deprecation::trigger(
  103. 'doctrine/orm',
  104. 'https://github.com/doctrine/deprecations/2222',
  105. 'this is deprecated %s %d',
  106. 'foo',
  107. 2222
  108. );
  109. $this->assertEquals(2, Deprecation::getUniqueTriggeredDeprecationsCount());
  110. }
  111. public function testDeprecationResetsCounts(): void
  112. {
  113. try {
  114. Deprecation::trigger(
  115. 'doctrine/orm',
  116. 'https://github.com/doctrine/deprecations/1234',
  117. 'this is deprecated %s %d',
  118. 'foo',
  119. 1234
  120. );
  121. } catch (Throwable $e) {
  122. Deprecation::disable();
  123. $this->assertEquals(0, Deprecation::getUniqueTriggeredDeprecationsCount());
  124. $this->assertEquals(['https://github.com/doctrine/deprecations/1234' => 0], Deprecation::getTriggeredDeprecations());
  125. }
  126. }
  127. public function expectDeprecationMock(string $message, string $identifier, string $package): MockObject
  128. {
  129. $mock = $this->createMock(LoggerInterface::class);
  130. $mock->method('notice')->with($message, $this->callback(function ($context) use ($identifier, $package) {
  131. $this->assertEquals($package, $context['package']);
  132. $this->assertEquals($identifier, $context['link']);
  133. return true;
  134. }));
  135. return $mock;
  136. }
  137. public function testDeprecationWithPsrLogger(): void
  138. {
  139. $this->expectDeprecationWithIdentifier('https://github.com/doctrine/deprecations/2222');
  140. $mock = $this->expectDeprecationMock(
  141. 'this is deprecated foo 1234',
  142. 'https://github.com/doctrine/deprecations/2222',
  143. 'doctrine/orm'
  144. );
  145. Deprecation::enableWithPsrLogger($mock);
  146. Deprecation::trigger(
  147. 'doctrine/orm',
  148. 'https://github.com/doctrine/deprecations/2222',
  149. 'this is deprecated %s %d',
  150. 'foo',
  151. 1234
  152. );
  153. }
  154. public function testDeprecationWithIgnoredPackage(): void
  155. {
  156. Deprecation::enableWithTriggerError();
  157. Deprecation::ignorePackage('doctrine/orm');
  158. Deprecation::trigger(
  159. 'doctrine/orm',
  160. 'https://github.com/doctrine/orm/issue/1234',
  161. 'this is deprecated %s %d',
  162. 'foo',
  163. 1234
  164. );
  165. $this->assertEquals(1, Deprecation::getUniqueTriggeredDeprecationsCount());
  166. $this->assertEquals(['https://github.com/doctrine/orm/issue/1234' => 1], Deprecation::getTriggeredDeprecations());
  167. }
  168. public function testDeprecationIfCalledFromOutside(): void
  169. {
  170. Deprecation::enableWithTriggerError();
  171. $this->expectErrorHandler(
  172. 'Bar::oldFunc() is deprecated, use Bar::newFunc() instead. (Bar.php:16 called by Foo.php:14, https://github.com/doctrine/foo, package doctrine/foo)',
  173. 'https://github.com/doctrine/foo'
  174. );
  175. Foo::triggerDependencyWithDeprecation();
  176. }
  177. public function testDeprecationIfCalledFromOutsideNotTriggeringFromInside(): void
  178. {
  179. Deprecation::enableWithTriggerError();
  180. Foo::triggerDependencyWithDeprecationFromInside();
  181. $this->assertEquals(0, Deprecation::getUniqueTriggeredDeprecationsCount());
  182. }
  183. public function testDeprecationIfCalledFromOutsideNotTriggeringFromInsideClass(): void
  184. {
  185. Deprecation::enableWithTriggerError();
  186. $baz = new Baz();
  187. $baz->usingOldFunc();
  188. $this->assertEquals(0, Deprecation::getUniqueTriggeredDeprecationsCount());
  189. }
  190. public function testDeprecationCalledFromOutsideInRoot(): void
  191. {
  192. Deprecation::enableWithTriggerError();
  193. $this->expectDeprecationWithIdentifier('https://github.com/doctrine/deprecations/4444');
  194. $this->expectErrorHandler(
  195. 'this is deprecated foo 1234 (RootDeprecation.php:%d called by DeprecationTest.php:%d, https://github.com/doctrine/deprecations/4444, package doctrine/orm)',
  196. 'https://github.com/doctrine/deprecations/4444'
  197. );
  198. RootDeprecation::run();
  199. $this->assertEquals(1, Deprecation::getUniqueTriggeredDeprecationsCount());
  200. }
  201. }