123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- <?php
- namespace React\Promise;
- use React\Promise\PromiseAdapter\CallbackPromiseAdapter;
- class PromiseTest extends TestCase
- {
- use PromiseTest\FullTestTrait;
- public function getPromiseTestAdapter(callable $canceller = null)
- {
- $resolveCallback = $rejectCallback = $progressCallback = null;
- $promise = new Promise(function ($resolve, $reject, $progress) use (&$resolveCallback, &$rejectCallback, &$progressCallback) {
- $resolveCallback = $resolve;
- $rejectCallback = $reject;
- $progressCallback = $progress;
- }, $canceller);
- return new CallbackPromiseAdapter([
- 'promise' => function () use ($promise) {
- return $promise;
- },
- 'resolve' => $resolveCallback,
- 'reject' => $rejectCallback,
- 'notify' => $progressCallback,
- 'settle' => $resolveCallback,
- ]);
- }
- /** @test */
- public function shouldRejectIfResolverThrowsException()
- {
- $exception = new \Exception('foo');
- $promise = new Promise(function () use ($exception) {
- throw $exception;
- });
- $mock = $this->createCallableMock();
- $mock
- ->expects($this->once())
- ->method('__invoke')
- ->with($this->identicalTo($exception));
- $promise
- ->then($this->expectCallableNever(), $mock);
- }
- /** @test */
- public function shouldResolveWithoutCreatingGarbageCyclesIfResolverResolvesWithException()
- {
- gc_collect_cycles();
- $promise = new Promise(function ($resolve) {
- $resolve(new \Exception('foo'));
- });
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /** @test */
- public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsExceptionWithoutResolver()
- {
- gc_collect_cycles();
- $promise = new Promise(function () {
- throw new \Exception('foo');
- });
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /** @test */
- public function shouldRejectWithoutCreatingGarbageCyclesIfResolverRejectsWithException()
- {
- gc_collect_cycles();
- $promise = new Promise(function ($resolve, $reject) {
- $reject(new \Exception('foo'));
- });
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /** @test */
- public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerRejectsWithException()
- {
- gc_collect_cycles();
- $promise = new Promise(function ($resolve, $reject) { }, function ($resolve, $reject) {
- $reject(new \Exception('foo'));
- });
- $promise->cancel();
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /** @test */
- public function shouldRejectWithoutCreatingGarbageCyclesIfParentCancellerRejectsWithException()
- {
- gc_collect_cycles();
- $promise = new Promise(function ($resolve, $reject) { }, function ($resolve, $reject) {
- $reject(new \Exception('foo'));
- });
- $promise->then()->then()->then()->cancel();
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /** @test */
- public function shouldRejectWithoutCreatingGarbageCyclesIfResolverThrowsException()
- {
- gc_collect_cycles();
- $promise = new Promise(function ($resolve, $reject) {
- throw new \Exception('foo');
- });
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /**
- * Test that checks number of garbage cycles after throwing from a canceller
- * that explicitly uses a reference to the promise. This is rather synthetic,
- * actual use cases often have implicit (hidden) references which ought not
- * to be stored in the stack trace.
- *
- * Reassigned arguments only show up in the stack trace in PHP 7, so we can't
- * avoid this on legacy PHP. As an alternative, consider explicitly unsetting
- * any references before throwing.
- *
- * @test
- * @requires PHP 7
- */
- public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerWithReferenceThrowsException()
- {
- gc_collect_cycles();
- $promise = new Promise(function () {}, function () use (&$promise) {
- throw new \Exception('foo');
- });
- $promise->cancel();
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /**
- * @test
- * @requires PHP 7
- * @see self::shouldRejectWithoutCreatingGarbageCyclesIfCancellerWithReferenceThrowsException
- */
- public function shouldRejectWithoutCreatingGarbageCyclesIfResolverWithReferenceThrowsException()
- {
- gc_collect_cycles();
- $promise = new Promise(function () use (&$promise) {
- throw new \Exception('foo');
- });
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /**
- * @test
- * @requires PHP 7
- * @see self::shouldRejectWithoutCreatingGarbageCyclesIfCancellerWithReferenceThrowsException
- */
- public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerHoldsReferenceAndResolverThrowsException()
- {
- gc_collect_cycles();
- $promise = new Promise(function () {
- throw new \Exception('foo');
- }, function () use (&$promise) { });
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /** @test */
- public function shouldIgnoreNotifyAfterReject()
- {
- $promise = new Promise(function () { }, function ($resolve, $reject, $notify) {
- $reject(new \Exception('foo'));
- $notify(42);
- });
- $promise->then(null, null, $this->expectCallableNever());
- $promise->cancel();
- }
- /** @test */
- public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromise()
- {
- gc_collect_cycles();
- $promise = new Promise(function () { });
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /** @test */
- public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithThenFollowers()
- {
- gc_collect_cycles();
- $promise = new Promise(function () { });
- $promise->then()->then()->then();
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /** @test */
- public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithDoneFollowers()
- {
- gc_collect_cycles();
- $promise = new Promise(function () { });
- $promise->done();
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /** @test */
- public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithOtherwiseFollowers()
- {
- gc_collect_cycles();
- $promise = new Promise(function () { });
- $promise->otherwise(function () { });
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /** @test */
- public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithAlwaysFollowers()
- {
- gc_collect_cycles();
- $promise = new Promise(function () { });
- $promise->always(function () { });
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /** @test */
- public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithProgressFollowers()
- {
- gc_collect_cycles();
- $promise = new Promise(function () { });
- $promise->then(null, null, function () { });
- unset($promise);
- $this->assertSame(0, gc_collect_cycles());
- }
- /** @test */
- public function shouldFulfillIfFullfilledWithSimplePromise()
- {
- $adapter = $this->getPromiseTestAdapter();
- $mock = $this->createCallableMock();
- $mock
- ->expects($this->once())
- ->method('__invoke')
- ->with($this->identicalTo('foo'));
- $adapter->promise()
- ->then($mock);
- $adapter->resolve(new SimpleFulfilledTestPromise());
- }
- /** @test */
- public function shouldRejectIfRejectedWithSimplePromise()
- {
- $adapter = $this->getPromiseTestAdapter();
- $mock = $this->createCallableMock();
- $mock
- ->expects($this->once())
- ->method('__invoke')
- ->with($this->identicalTo('foo'));
- $adapter->promise()
- ->then($this->expectCallableNever(), $mock);
- $adapter->resolve(new SimpleRejectedTestPromise());
- }
- }
|