DeferredTest.php 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. <?php
  2. namespace React\Promise;
  3. use React\Promise\PromiseAdapter\CallbackPromiseAdapter;
  4. /**
  5. * @template T
  6. */
  7. class DeferredTest extends TestCase
  8. {
  9. use PromiseTest\FullTestTrait;
  10. /**
  11. * @return CallbackPromiseAdapter<T>
  12. */
  13. public function getPromiseTestAdapter(callable $canceller = null): CallbackPromiseAdapter
  14. {
  15. $d = new Deferred($canceller);
  16. return new CallbackPromiseAdapter([
  17. 'promise' => [$d, 'promise'],
  18. 'resolve' => [$d, 'resolve'],
  19. 'reject' => [$d, 'reject'],
  20. 'settle' => [$d, 'resolve'],
  21. ]);
  22. }
  23. /** @test */
  24. public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithException(): void
  25. {
  26. gc_collect_cycles();
  27. $deferred = new Deferred(function ($resolve, $reject) {
  28. $reject(new \Exception('foo'));
  29. });
  30. $deferred->promise()->cancel();
  31. unset($deferred);
  32. $this->assertSame(0, gc_collect_cycles());
  33. }
  34. /** @test */
  35. public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejectsWithException(): void
  36. {
  37. gc_collect_cycles();
  38. gc_collect_cycles(); // clear twice to avoid leftovers in PHP 7.4 with ext-xdebug and code coverage turned on
  39. $deferred = new Deferred(function ($resolve, $reject) {
  40. $reject(new \Exception('foo'));
  41. });
  42. $deferred->promise()->then()->cancel();
  43. unset($deferred);
  44. $this->assertSame(0, gc_collect_cycles());
  45. }
  46. /** @test */
  47. public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerHoldsReferenceAndExplicitlyRejectWithException(): void
  48. {
  49. gc_collect_cycles();
  50. gc_collect_cycles(); // clear twice to avoid leftovers in PHP 7.4 with ext-xdebug and code coverage turned on
  51. /** @var Deferred<never> $deferred */
  52. $deferred = new Deferred(function () use (&$deferred) {
  53. assert($deferred instanceof Deferred);
  54. });
  55. $deferred->promise()->then(null, $this->expectCallableOnce()); // avoid reporting unhandled rejection
  56. $deferred->reject(new \Exception('foo'));
  57. unset($deferred);
  58. $this->assertSame(0, gc_collect_cycles());
  59. }
  60. }