diff options
| author | Eole <josselin.35@live.fr> | 2016-01-21 10:29:26 +0100 |
|---|---|---|
| committer | Eole <josselin.35@live.fr> | 2016-01-21 10:29:26 +0100 |
| commit | a44cc1d2e3c0f147e91a5c052ac7fd879e34e706 (patch) | |
| tree | bdd6f72e0ba732c4fcc0479d1cfcf4d0baa5885d /server/vendor/guzzlehttp/promises/tests | |
| parent | 35db27b0e62b4cdcb03b0d21bceb4efc769e6161 (diff) | |
Init Server Composer Components
Diffstat (limited to 'server/vendor/guzzlehttp/promises/tests')
11 files changed, 1988 insertions, 0 deletions
diff --git a/server/vendor/guzzlehttp/promises/tests/AggregateExceptionTest.php b/server/vendor/guzzlehttp/promises/tests/AggregateExceptionTest.php new file mode 100644 index 0000000..eaa7703 --- /dev/null +++ b/server/vendor/guzzlehttp/promises/tests/AggregateExceptionTest.php @@ -0,0 +1,14 @@ +<?php +namespace GuzzleHttp\Promise\Tests; + +use GuzzleHttp\Promise\AggregateException; + +class AggregateExceptionTest extends \PHPUnit_Framework_TestCase +{ + public function testHasReason() + { + $e = new AggregateException('foo', ['baz', 'bar']); + $this->assertContains('foo', $e->getMessage()); + $this->assertEquals(['baz', 'bar'], $e->getReason()); + } +} diff --git a/server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php b/server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php new file mode 100644 index 0000000..0a0a851 --- /dev/null +++ b/server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php @@ -0,0 +1,294 @@ +<?php +namespace GuzzleHttp\Promise\Tests; + +use GuzzleHttp\Promise\RejectedPromise; +use GuzzleHttp\Promise\FulfilledPromise; +use GuzzleHttp\Promise\Promise; +use GuzzleHttp\Promise\PromiseInterface; +use GuzzleHttp\Promise\EachPromise; +use GuzzleHttp\Promise as P; + +/** + * @covers GuzzleHttp\Promise\EachPromise + */ +class EachPromiseTest extends \PHPUnit_Framework_TestCase +{ + public function testReturnsSameInstance() + { + $each = new EachPromise([], ['concurrency' => 100]); + $this->assertSame($each->promise(), $each->promise()); + } + + public function testInvokesAllPromises() + { + $promises = [new Promise(), new Promise(), new Promise()]; + $called = []; + $each = new EachPromise($promises, [ + 'fulfilled' => function ($value) use (&$called) { + $called[] = $value; + } + ]); + $p = $each->promise(); + $promises[0]->resolve('a'); + $promises[1]->resolve('c'); + $promises[2]->resolve('b'); + P\queue()->run(); + $this->assertEquals(['a', 'c', 'b'], $called); + $this->assertEquals(PromiseInterface::FULFILLED, $p->getState()); + } + + public function testIsWaitable() + { + $a = new Promise(function () use (&$a) { $a->resolve('a'); }); + $b = new Promise(function () use (&$b) { $b->resolve('b'); }); + $called = []; + $each = new EachPromise([$a, $b], [ + 'fulfilled' => function ($value) use (&$called) { $called[] = $value; } + ]); + $p = $each->promise(); + $this->assertNull($p->wait()); + $this->assertEquals(PromiseInterface::FULFILLED, $p->getState()); + $this->assertEquals(['a', 'b'], $called); + } + + public function testCanResolveBeforeConsumingAll() + { + $called = 0; + $a = new Promise(function () use (&$a) { $a->resolve('a'); }); + $b = new Promise(function () { $this->fail(); }); + $each = new EachPromise([$a, $b], [ + 'fulfilled' => function ($value, $idx, Promise $aggregate) use (&$called) { + $this->assertSame($idx, 0); + $this->assertEquals('a', $value); + $aggregate->resolve(null); + $called++; + }, + 'rejected' => function (\Exception $reason) { + $this->fail($reason->getMessage()); + } + ]); + $p = $each->promise(); + $p->wait(); + $this->assertNull($p->wait()); + $this->assertEquals(1, $called); + $this->assertEquals(PromiseInterface::FULFILLED, $a->getState()); + $this->assertEquals(PromiseInterface::PENDING, $b->getState()); + // Resolving $b has no effect on the aggregate promise. + $b->resolve('foo'); + $this->assertEquals(1, $called); + } + + public function testLimitsPendingPromises() + { + $pending = [new Promise(), new Promise(), new Promise(), new Promise()]; + $promises = new \ArrayIterator($pending); + $each = new EachPromise($promises, ['concurrency' => 2]); + $p = $each->promise(); + $this->assertCount(2, $this->readAttribute($each, 'pending')); + $pending[0]->resolve('a'); + $this->assertCount(2, $this->readAttribute($each, 'pending')); + $this->assertTrue($promises->valid()); + $pending[1]->resolve('b'); + P\queue()->run(); + $this->assertCount(2, $this->readAttribute($each, 'pending')); + $this->assertTrue($promises->valid()); + $promises[2]->resolve('c'); + P\queue()->run(); + $this->assertCount(1, $this->readAttribute($each, 'pending')); + $this->assertEquals(PromiseInterface::PENDING, $p->getState()); + $promises[3]->resolve('d'); + P\queue()->run(); + $this->assertNull($this->readAttribute($each, 'pending')); + $this->assertEquals(PromiseInterface::FULFILLED, $p->getState()); + $this->assertFalse($promises->valid()); + } + + public function testDynamicallyLimitsPendingPromises() + { + $calls = []; + $pendingFn = function ($count) use (&$calls) { + $calls[] = $count; + return 2; + }; + $pending = [new Promise(), new Promise(), new Promise(), new Promise()]; + $promises = new \ArrayIterator($pending); + $each = new EachPromise($promises, ['concurrency' => $pendingFn]); + $p = $each->promise(); + $this->assertCount(2, $this->readAttribute($each, 'pending')); + $pending[0]->resolve('a'); + $this->assertCount(2, $this->readAttribute($each, 'pending')); + $this->assertTrue($promises->valid()); + $pending[1]->resolve('b'); + $this->assertCount(2, $this->readAttribute($each, 'pending')); + P\queue()->run(); + $this->assertTrue($promises->valid()); + $promises[2]->resolve('c'); + P\queue()->run(); + $this->assertCount(1, $this->readAttribute($each, 'pending')); + $this->assertEquals(PromiseInterface::PENDING, $p->getState()); + $promises[3]->resolve('d'); + P\queue()->run(); + $this->assertNull($this->readAttribute($each, 'pending')); + $this->assertEquals(PromiseInterface::FULFILLED, $p->getState()); + $this->assertEquals([0, 1, 1, 1], $calls); + $this->assertFalse($promises->valid()); + } + + public function testClearsReferencesWhenResolved() + { + $called = false; + $a = new Promise(function () use (&$a, &$called) { + $a->resolve('a'); + $called = true; + }); + $each = new EachPromise([$a], [ + 'concurrency' => function () { return 1; }, + 'fulfilled' => function () {}, + 'rejected' => function () {} + ]); + $each->promise()->wait(); + $this->assertNull($this->readAttribute($each, 'onFulfilled')); + $this->assertNull($this->readAttribute($each, 'onRejected')); + $this->assertNull($this->readAttribute($each, 'iterable')); + $this->assertNull($this->readAttribute($each, 'pending')); + $this->assertNull($this->readAttribute($each, 'concurrency')); + $this->assertTrue($called); + } + + public function testCanBeCancelled() + { + $this->markTestIncomplete(); + } + + public function testFulfillsImmediatelyWhenGivenAnEmptyIterator() + { + $each = new EachPromise(new \ArrayIterator([])); + $result = $each->promise()->wait(); + } + + public function testDoesNotBlowStackWithFulfilledPromises() + { + $pending = []; + for ($i = 0; $i < 100; $i++) { + $pending[] = new FulfilledPromise($i); + } + $values = []; + $each = new EachPromise($pending, [ + 'fulfilled' => function ($value) use (&$values) { + $values[] = $value; + } + ]); + $called = false; + $each->promise()->then(function () use (&$called) { + $called = true; + }); + $this->assertFalse($called); + P\queue()->run(); + $this->assertTrue($called); + $this->assertEquals(range(0, 99), $values); + } + + public function testDoesNotBlowStackWithRejectedPromises() + { + $pending = []; + for ($i = 0; $i < 100; $i++) { + $pending[] = new RejectedPromise($i); + } + $values = []; + $each = new EachPromise($pending, [ + 'rejected' => function ($value) use (&$values) { + $values[] = $value; + } + ]); + $called = false; + $each->promise()->then( + function () use (&$called) { $called = true; }, + function () { $this->fail('Should not have rejected.'); } + ); + $this->assertFalse($called); + P\queue()->run(); + $this->assertTrue($called); + $this->assertEquals(range(0, 99), $values); + } + + public function testReturnsPromiseForWhatever() + { + $called = []; + $arr = ['a', 'b']; + $each = new EachPromise($arr, [ + 'fulfilled' => function ($v) use (&$called) { $called[] = $v; } + ]); + $p = $each->promise(); + $this->assertNull($p->wait()); + $this->assertEquals(['a', 'b'], $called); + } + + public function testRejectsAggregateWhenNextThrows() + { + $iter = function () { + yield 'a'; + throw new \Exception('Failure'); + }; + $each = new EachPromise($iter()); + $p = $each->promise(); + $e = null; + $received = null; + $p->then(null, function ($reason) use (&$e) { $e = $reason; }); + P\queue()->run(); + $this->assertInstanceOf('Exception', $e); + $this->assertEquals('Failure', $e->getMessage()); + } + + public function testDoesNotCallNextOnIteratorUntilNeededWhenWaiting() + { + $results = []; + $values = [10]; + $remaining = 9; + $iter = function () use (&$values) { + while ($value = array_pop($values)) { + yield $value; + } + }; + $each = new EachPromise($iter(), [ + 'concurrency' => 1, + 'fulfilled' => function ($r) use (&$results, &$values, &$remaining) { + $results[] = $r; + if ($remaining > 0) { + $values[] = $remaining--; + } + } + ]); + $each->promise()->wait(); + $this->assertEquals(range(10, 1), $results); + } + + public function testDoesNotCallNextOnIteratorUntilNeededWhenAsync() + { + $firstPromise = new Promise(); + $pending = [$firstPromise]; + $values = [$firstPromise]; + $results = []; + $remaining = 9; + $iter = function () use (&$values) { + while ($value = array_pop($values)) { + yield $value; + } + }; + $each = new EachPromise($iter(), [ + 'concurrency' => 1, + 'fulfilled' => function ($r) use (&$results, &$values, &$remaining, &$pending) { + $results[] = $r; + if ($remaining-- > 0) { + $pending[] = $values[] = new Promise(); + } + } + ]); + $i = 0; + $each->promise(); + while ($promise = array_pop($pending)) { + $promise->resolve($i++); + P\queue()->run(); + } + $this->assertEquals(range(0, 9), $results); + } +} diff --git a/server/vendor/guzzlehttp/promises/tests/FulfilledPromiseTest.php b/server/vendor/guzzlehttp/promises/tests/FulfilledPromiseTest.php new file mode 100644 index 0000000..554c150 --- /dev/null +++ b/server/vendor/guzzlehttp/promises/tests/FulfilledPromiseTest.php @@ -0,0 +1,108 @@ +<?php +namespace GuzzleHttp\Tests\Promise; + +use GuzzleHttp\Promise\Promise; +use GuzzleHttp\Promise\FulfilledPromise; + +/** + * @covers GuzzleHttp\Promise\FulfilledPromise + */ +class FulfilledPromiseTest extends \PHPUnit_Framework_TestCase +{ + public function testReturnsValueWhenWaitedUpon() + { + $p = new FulfilledPromise('foo'); + $this->assertEquals('fulfilled', $p->getState()); + $this->assertEquals('foo', $p->wait(true)); + } + + public function testCannotCancel() + { + $p = new FulfilledPromise('foo'); + $this->assertEquals('fulfilled', $p->getState()); + $p->cancel(); + $this->assertEquals('foo', $p->wait()); + } + + /** + * @expectedException \LogicException + * @exepctedExceptionMessage Cannot resolve a fulfilled promise + */ + public function testCannotResolve() + { + $p = new FulfilledPromise('foo'); + $p->resolve('bar'); + } + + /** + * @expectedException \LogicException + * @exepctedExceptionMessage Cannot reject a fulfilled promise + */ + public function testCannotReject() + { + $p = new FulfilledPromise('foo'); + $p->reject('bar'); + } + + public function testCanResolveWithSameValue() + { + $p = new FulfilledPromise('foo'); + $p->resolve('foo'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testCannotResolveWithPromise() + { + new FulfilledPromise(new Promise()); + } + + public function testReturnsSelfWhenNoOnFulfilled() + { + $p = new FulfilledPromise('a'); + $this->assertSame($p, $p->then()); + } + + public function testAsynchronouslyInvokesOnFulfilled() + { + $p = new FulfilledPromise('a'); + $r = null; + $f = function ($d) use (&$r) { $r = $d; }; + $p2 = $p->then($f); + $this->assertNotSame($p, $p2); + $this->assertNull($r); + \GuzzleHttp\Promise\queue()->run(); + $this->assertEquals('a', $r); + } + + public function testReturnsNewRejectedWhenOnFulfilledFails() + { + $p = new FulfilledPromise('a'); + $f = function () { throw new \Exception('b'); }; + $p2 = $p->then($f); + $this->assertNotSame($p, $p2); + try { + $p2->wait(); + $this->fail(); + } catch (\Exception $e) { + $this->assertEquals('b', $e->getMessage()); + } + } + + public function testOtherwiseIsSugarForRejections() + { + $c = null; + $p = new FulfilledPromise('foo'); + $p->otherwise(function ($v) use (&$c) { $c = $v; }); + $this->assertNull($c); + } + + public function testDoesNotTryToFulfillTwiceDuringTrampoline() + { + $fp = new FulfilledPromise('a'); + $t1 = $fp->then(function ($v) { return $v . ' b'; }); + $t1->resolve('why!'); + $this->assertEquals('why!', $t1->wait()); + } +} diff --git a/server/vendor/guzzlehttp/promises/tests/NotPromiseInstance.php b/server/vendor/guzzlehttp/promises/tests/NotPromiseInstance.php new file mode 100644 index 0000000..6288aa8 --- /dev/null +++ b/server/vendor/guzzlehttp/promises/tests/NotPromiseInstance.php @@ -0,0 +1,50 @@ +<?php +namespace GuzzleHttp\Promise\Tests; + +use GuzzleHttp\Promise\Promise; +use GuzzleHttp\Promise\PromiseInterface; + +class NotPromiseInstance extends Thennable implements PromiseInterface +{ + private $nextPromise = null; + + public function __construct() + { + $this->nextPromise = new Promise(); + } + + public function then(callable $res = null, callable $rej = null) + { + return $this->nextPromise->then($res, $rej); + } + + public function otherwise(callable $onRejected) + { + return $this->then($onRejected); + } + + public function resolve($value) + { + $this->nextPromise->resolve($value); + } + + public function reject($reason) + { + $this->nextPromise->reject($reason); + } + + public function wait($unwrap = true, $defaultResolution = null) + { + + } + + public function cancel() + { + + } + + public function getState() + { + return $this->nextPromise->getState(); + } +} diff --git a/server/vendor/guzzlehttp/promises/tests/PromiseTest.php b/server/vendor/guzzlehttp/promises/tests/PromiseTest.php new file mode 100644 index 0000000..946c627 --- /dev/null +++ b/server/vendor/guzzlehttp/promises/tests/PromiseTest.php @@ -0,0 +1,579 @@ +<?php +namespace GuzzleHttp\Promise\Tests; + +use GuzzleHttp\Promise\CancellationException; +use GuzzleHttp\Promise as P; +use GuzzleHttp\Promise\Promise; +use GuzzleHttp\Promise\RejectedPromise; +use GuzzleHttp\Promise\RejectionException; + +/** + * @covers GuzzleHttp\Promise\Promise + */ +class PromiseTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException \LogicException + * @expectedExceptionMessage The promise is already fulfilled + */ + public function testCannotResolveNonPendingPromise() + { + $p = new Promise(); + $p->resolve('foo'); + $p->resolve('bar'); + $this->assertEquals('foo', $p->wait()); + } + + public function testCanResolveWithSameValue() + { + $p = new Promise(); + $p->resolve('foo'); + $p->resolve('foo'); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Cannot change a fulfilled promise to rejected + */ + public function testCannotRejectNonPendingPromise() + { + $p = new Promise(); + $p->resolve('foo'); + $p->reject('bar'); + $this->assertEquals('foo', $p->wait()); + } + + public function testCanRejectWithSameValue() + { + $p = new Promise(); + $p->reject('foo'); + $p->reject('foo'); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Cannot change a fulfilled promise to rejected + */ + public function testCannotRejectResolveWithSameValue() + { + $p = new Promise(); + $p->resolve('foo'); + $p->reject('foo'); + } + + public function testInvokesWaitFunction() + { + $p = new Promise(function () use (&$p) { $p->resolve('10'); }); + $this->assertEquals('10', $p->wait()); + } + + /** + * @expectedException \GuzzleHttp\Promise\RejectionException + */ + public function testRejectsAndThrowsWhenWaitFailsToResolve() + { + $p = new Promise(function () {}); + $p->wait(); + } + + /** + * @expectedException \GuzzleHttp\Promise\RejectionException + * @expectedExceptionMessage The promise was rejected with reason: foo + */ + public function testThrowsWhenUnwrapIsRejectedWithNonException() + { + $p = new Promise(function () use (&$p) { $p->reject('foo'); }); + $p->wait(); + } + + /** + * @expectedException \UnexpectedValueException + * @expectedExceptionMessage foo + */ + public function testThrowsWhenUnwrapIsRejectedWithException() + { + $e = new \UnexpectedValueException('foo'); + $p = new Promise(function () use (&$p, $e) { $p->reject($e); }); + $p->wait(); + } + + public function testDoesNotUnwrapExceptionsWhenDisabled() + { + $p = new Promise(function () use (&$p) { $p->reject('foo'); }); + $this->assertEquals('pending', $p->getState()); + $p->wait(false); + $this->assertEquals('rejected', $p->getState()); + } + + public function testRejectsSelfWhenWaitThrows() + { + $e = new \UnexpectedValueException('foo'); + $p = new Promise(function () use ($e) { throw $e; }); + try { + $p->wait(); + $this->fail(); + } catch (\UnexpectedValueException $e) { + $this->assertEquals('rejected', $p->getState()); + } + } + + public function testWaitsOnNestedPromises() + { + $p = new Promise(function () use (&$p) { $p->resolve('_'); }); + $p2 = new Promise(function () use (&$p2) { $p2->resolve('foo'); }); + $p3 = $p->then(function () use ($p2) { return $p2; }); + $this->assertSame('foo', $p3->wait()); + } + + /** + * @expectedException \GuzzleHttp\Promise\RejectionException + */ + public function testThrowsWhenWaitingOnPromiseWithNoWaitFunction() + { + $p = new Promise(); + $p->wait(); + } + + public function testThrowsWaitExceptionAfterPromiseIsResolved() + { + $p = new Promise(function () use (&$p) { + $p->reject('Foo!'); + throw new \Exception('Bar?'); + }); + + try { + $p->wait(); + $this->fail(); + } catch (\Exception $e) { + $this->assertEquals('Bar?', $e->getMessage()); + } + } + + public function testGetsActualWaitValueFromThen() + { + $p = new Promise(function () use (&$p) { $p->reject('Foo!'); }); + $p2 = $p->then(null, function ($reason) { + return new RejectedPromise([$reason]); + }); + + try { + $p2->wait(); + $this->fail('Should have thrown'); + } catch (RejectionException $e) { + $this->assertEquals(['Foo!'], $e->getReason()); + } + } + + public function testWaitBehaviorIsBasedOnLastPromiseInChain() + { + $p3 = new Promise(function () use (&$p3) { $p3->resolve('Whoop'); }); + $p2 = new Promise(function () use (&$p2, $p3) { $p2->reject($p3); }); + $p = new Promise(function () use (&$p, $p2) { $p->reject($p2); }); + $this->assertEquals('Whoop', $p->wait()); + } + + public function testCannotCancelNonPending() + { + $p = new Promise(); + $p->resolve('foo'); + $p->cancel(); + $this->assertEquals('fulfilled', $p->getState()); + } + + /** + * @expectedException \GuzzleHttp\Promise\CancellationException + */ + public function testCancelsPromiseWhenNoCancelFunction() + { + $p = new Promise(); + $p->cancel(); + $this->assertEquals('rejected', $p->getState()); + $p->wait(); + } + + public function testCancelsPromiseWithCancelFunction() + { + $called = false; + $p = new Promise(null, function () use (&$called) { $called = true; }); + $p->cancel(); + $this->assertEquals('rejected', $p->getState()); + $this->assertTrue($called); + } + + public function testCancelsUppermostPendingPromise() + { + $called = false; + $p1 = new Promise(null, function () use (&$called) { $called = true; }); + $p2 = $p1->then(function () {}); + $p3 = $p2->then(function () {}); + $p4 = $p3->then(function () {}); + $p3->cancel(); + $this->assertEquals('rejected', $p1->getState()); + $this->assertEquals('rejected', $p2->getState()); + $this->assertEquals('rejected', $p3->getState()); + $this->assertEquals('pending', $p4->getState()); + $this->assertTrue($called); + + try { + $p3->wait(); + $this->fail(); + } catch (CancellationException $e) { + $this->assertContains('cancelled', $e->getMessage()); + } + + try { + $p4->wait(); + $this->fail(); + } catch (CancellationException $e) { + $this->assertContains('cancelled', $e->getMessage()); + } + + $this->assertEquals('rejected', $p4->getState()); + } + + public function testCancelsChildPromises() + { + $called1 = $called2 = $called3 = false; + $p1 = new Promise(null, function () use (&$called1) { $called1 = true; }); + $p2 = new Promise(null, function () use (&$called2) { $called2 = true; }); + $p3 = new Promise(null, function () use (&$called3) { $called3 = true; }); + $p4 = $p2->then(function () use ($p3) { return $p3; }); + $p5 = $p4->then(function () { $this->fail(); }); + $p4->cancel(); + $this->assertEquals('pending', $p1->getState()); + $this->assertEquals('rejected', $p2->getState()); + $this->assertEquals('rejected', $p4->getState()); + $this->assertEquals('pending', $p5->getState()); + $this->assertFalse($called1); + $this->assertTrue($called2); + $this->assertFalse($called3); + } + + public function testRejectsPromiseWhenCancelFails() + { + $called = false; + $p = new Promise(null, function () use (&$called) { + $called = true; + throw new \Exception('e'); + }); + $p->cancel(); + $this->assertEquals('rejected', $p->getState()); + $this->assertTrue($called); + try { + $p->wait(); + $this->fail(); + } catch (\Exception $e) { + $this->assertEquals('e', $e->getMessage()); + } + } + + public function testCreatesPromiseWhenFulfilledAfterThen() + { + $p = new Promise(); + $carry = null; + $p2 = $p->then(function ($v) use (&$carry) { $carry = $v; }); + $this->assertNotSame($p, $p2); + $p->resolve('foo'); + P\queue()->run(); + + $this->assertEquals('foo', $carry); + } + + public function testCreatesPromiseWhenFulfilledBeforeThen() + { + $p = new Promise(); + $p->resolve('foo'); + $carry = null; + $p2 = $p->then(function ($v) use (&$carry) { $carry = $v; }); + $this->assertNotSame($p, $p2); + $this->assertNull($carry); + \GuzzleHttp\Promise\queue()->run(); + $this->assertEquals('foo', $carry); + } + + public function testCreatesPromiseWhenFulfilledWithNoCallback() + { + $p = new Promise(); + $p->resolve('foo'); + $p2 = $p->then(); + $this->assertNotSame($p, $p2); + $this->assertInstanceOf('GuzzleHttp\Promise\FulfilledPromise', $p2); + } + + public function testCreatesPromiseWhenRejectedAfterThen() + { + $p = new Promise(); + $carry = null; + $p2 = $p->then(null, function ($v) use (&$carry) { $carry = $v; }); + $this->assertNotSame($p, $p2); + $p->reject('foo'); + P\queue()->run(); + $this->assertEquals('foo', $carry); + } + + public function testCreatesPromiseWhenRejectedBeforeThen() + { + $p = new Promise(); + $p->reject('foo'); + $carry = null; + $p2 = $p->then(null, function ($v) use (&$carry) { $carry = $v; }); + $this->assertNotSame($p, $p2); + $this->assertNull($carry); + P\queue()->run(); + $this->assertEquals('foo', $carry); + } + + public function testCreatesPromiseWhenRejectedWithNoCallback() + { + $p = new Promise(); + $p->reject('foo'); + $p2 = $p->then(); + $this->assertNotSame($p, $p2); + $this->assertInstanceOf('GuzzleHttp\Promise\RejectedPromise', $p2); + } + + public function testInvokesWaitFnsForThens() + { + $p = new Promise(function () use (&$p) { $p->resolve('a'); }); + $p2 = $p + ->then(function ($v) { return $v . '-1-'; }) + ->then(function ($v) { return $v . '2'; }); + $this->assertEquals('a-1-2', $p2->wait()); + } + + public function testStacksThenWaitFunctions() + { + $p1 = new Promise(function () use (&$p1) { $p1->resolve('a'); }); + $p2 = new Promise(function () use (&$p2) { $p2->resolve('b'); }); + $p3 = new Promise(function () use (&$p3) { $p3->resolve('c'); }); + $p4 = $p1 + ->then(function () use ($p2) { return $p2; }) + ->then(function () use ($p3) { return $p3; }); + $this->assertEquals('c', $p4->wait()); + } + + public function testForwardsFulfilledDownChainBetweenGaps() + { + $p = new Promise(); + $r = $r2 = null; + $p->then(null, null) + ->then(function ($v) use (&$r) { $r = $v; return $v . '2'; }) + ->then(function ($v) use (&$r2) { $r2 = $v; }); + $p->resolve('foo'); + P\queue()->run(); + $this->assertEquals('foo', $r); + $this->assertEquals('foo2', $r2); + } + + public function testForwardsRejectedPromisesDownChainBetweenGaps() + { + $p = new Promise(); + $r = $r2 = null; + $p->then(null, null) + ->then(null, function ($v) use (&$r) { $r = $v; return $v . '2'; }) + ->then(function ($v) use (&$r2) { $r2 = $v; }); + $p->reject('foo'); + P\queue()->run(); + $this->assertEquals('foo', $r); + $this->assertEquals('foo2', $r2); + } + + public function testForwardsThrownPromisesDownChainBetweenGaps() + { + $e = new \Exception(); + $p = new Promise(); + $r = $r2 = null; + $p->then(null, null) + ->then(null, function ($v) use (&$r, $e) { + $r = $v; + throw $e; + }) + ->then( + null, + function ($v) use (&$r2) { $r2 = $v; } + ); + $p->reject('foo'); + P\queue()->run(); + $this->assertEquals('foo', $r); + $this->assertSame($e, $r2); + } + + public function testForwardsReturnedRejectedPromisesDownChainBetweenGaps() + { + $p = new Promise(); + $rejected = new RejectedPromise('bar'); + $r = $r2 = null; + $p->then(null, null) + ->then(null, function ($v) use (&$r, $rejected) { + $r = $v; + return $rejected; + }) + ->then( + null, + function ($v) use (&$r2) { $r2 = $v; } + ); + $p->reject('foo'); + P\queue()->run(); + $this->assertEquals('foo', $r); + $this->assertEquals('bar', $r2); + try { + $p->wait(); + } catch (RejectionException $e) { + $this->assertEquals('foo', $e->getReason()); + } + } + + public function testForwardsHandlersToNextPromise() + { + $p = new Promise(); + $p2 = new Promise(); + $resolved = null; + $p + ->then(function ($v) use ($p2) { return $p2; }) + ->then(function ($value) use (&$resolved) { $resolved = $value; }); + $p->resolve('a'); + $p2->resolve('b'); + P\queue()->run(); + $this->assertEquals('b', $resolved); + } + + public function testRemovesReferenceFromChildWhenParentWaitedUpon() + { + $r = null; + $p = new Promise(function () use (&$p) { $p->resolve('a'); }); + $p2 = new Promise(function () use (&$p2) { $p2->resolve('b'); }); + $pb = $p->then( + function ($v) use ($p2, &$r) { + $r = $v; + return $p2; + }) + ->then(function ($v) { return $v . '.'; }); + $this->assertEquals('a', $p->wait()); + $this->assertEquals('b', $p2->wait()); + $this->assertEquals('b.', $pb->wait()); + $this->assertEquals('a', $r); + } + + public function testForwardsHandlersWhenFulfilledPromiseIsReturned() + { + $res = []; + $p = new Promise(); + $p2 = new Promise(); + $p2->resolve('foo'); + $p2->then(function ($v) use (&$res) { $res[] = 'A:' . $v; }); + // $res is A:foo + $p + ->then(function () use ($p2, &$res) { $res[] = 'B'; return $p2; }) + ->then(function ($v) use (&$res) { $res[] = 'C:' . $v; }); + $p->resolve('a'); + $p->then(function ($v) use (&$res) { $res[] = 'D:' . $v; }); + P\queue()->run(); + $this->assertEquals(['A:foo', 'B', 'D:a', 'C:foo'], $res); + } + + public function testForwardsHandlersWhenRejectedPromiseIsReturned() + { + $res = []; + $p = new Promise(); + $p2 = new Promise(); + $p2->reject('foo'); + $p2->then(null, function ($v) use (&$res) { $res[] = 'A:' . $v; }); + $p->then(null, function () use ($p2, &$res) { $res[] = 'B'; return $p2; }) + ->then(null, function ($v) use (&$res) { $res[] = 'C:' . $v; }); + $p->reject('a'); + $p->then(null, function ($v) use (&$res) { $res[] = 'D:' . $v; }); + P\queue()->run(); + $this->assertEquals(['A:foo', 'B', 'D:a', 'C:foo'], $res); + } + + public function testDoesNotForwardRejectedPromise() + { + $res = []; + $p = new Promise(); + $p2 = new Promise(); + $p2->cancel(); + $p2->then(function ($v) use (&$res) { $res[] = "B:$v"; return $v; }); + $p->then(function ($v) use ($p2, &$res) { $res[] = "B:$v"; return $p2; }) + ->then(function ($v) use (&$res) { $res[] = 'C:' . $v; }); + $p->resolve('a'); + $p->then(function ($v) use (&$res) { $res[] = 'D:' . $v; }); + P\queue()->run(); + $this->assertEquals(['B:a', 'D:a'], $res); + } + + public function testRecursivelyForwardsWhenOnlyThennable() + { + $res = []; + $p = new Promise(); + $p2 = new Thennable(); + $p2->resolve('foo'); + $p2->then(function ($v) use (&$res) { $res[] = 'A:' . $v; }); + $p->then(function () use ($p2, &$res) { $res[] = 'B'; return $p2; }) + ->then(function ($v) use (&$res) { $res[] = 'C:' . $v; }); + $p->resolve('a'); + $p->then(function ($v) use (&$res) { $res[] = 'D:' . $v; }); + P\queue()->run(); + $this->assertEquals(['A:foo', 'B', 'D:a', 'C:foo'], $res); + } + + public function testRecursivelyForwardsWhenNotInstanceOfPromise() + { + $res = []; + $p = new Promise(); + $p2 = new NotPromiseInstance(); + $p2->then(function ($v) use (&$res) { $res[] = 'A:' . $v; }); + $p->then(function () use ($p2, &$res) { $res[] = 'B'; return $p2; }) + ->then(function ($v) use (&$res) { $res[] = 'C:' . $v; }); + $p->resolve('a'); + $p->then(function ($v) use (&$res) { $res[] = 'D:' . $v; }); + P\queue()->run(); + $this->assertEquals(['B', 'D:a'], $res); + $p2->resolve('foo'); + P\queue()->run(); + $this->assertEquals(['B', 'D:a', 'A:foo', 'C:foo'], $res); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Cannot fulfill or reject a promise with itself + */ + public function testCannotResolveWithSelf() + { + $p = new Promise(); + $p->resolve($p); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Cannot fulfill or reject a promise with itself + */ + public function testCannotRejectWithSelf() + { + $p = new Promise(); + $p->reject($p); + } + + public function testDoesNotBlowStackWhenWaitingOnNestedThens() + { + $inner = new Promise(function () use (&$inner) { $inner->resolve(0); }); + $prev = $inner; + for ($i = 1; $i < 100; $i++) { + $prev = $prev->then(function ($i) { return $i + 1; }); + } + + $parent = new Promise(function () use (&$parent, $prev) { + $parent->resolve($prev); + }); + + $this->assertEquals(99, $parent->wait()); + } + + public function testOtherwiseIsSugarForRejections() + { + $p = new Promise(); + $p->reject('foo'); + $p->otherwise(function ($v) use (&$c) { $c = $v; }); + P\queue()->run(); + $this->assertEquals($c, 'foo'); + } +} diff --git a/server/vendor/guzzlehttp/promises/tests/RejectedPromiseTest.php b/server/vendor/guzzlehttp/promises/tests/RejectedPromiseTest.php new file mode 100644 index 0000000..60f926e --- /dev/null +++ b/server/vendor/guzzlehttp/promises/tests/RejectedPromiseTest.php @@ -0,0 +1,143 @@ +<?php +namespace GuzzleHttp\Promise\Tests; + +use GuzzleHttp\Promise\Promise; +use GuzzleHttp\Promise\RejectedPromise; + +/** + * @covers GuzzleHttp\Promise\RejectedPromise + */ +class RejectedPromiseTest extends \PHPUnit_Framework_TestCase +{ + public function testThrowsReasonWhenWaitedUpon() + { + $p = new RejectedPromise('foo'); + $this->assertEquals('rejected', $p->getState()); + try { + $p->wait(true); + $this->fail(); + } catch (\Exception $e) { + $this->assertEquals('rejected', $p->getState()); + $this->assertContains('foo', $e->getMessage()); + } + } + + public function testCannotCancel() + { + $p = new RejectedPromise('foo'); + $p->cancel(); + $this->assertEquals('rejected', $p->getState()); + } + + /** + * @expectedException \LogicException + * @exepctedExceptionMessage Cannot resolve a rejected promise + */ + public function testCannotResolve() + { + $p = new RejectedPromise('foo'); + $p->resolve('bar'); + } + + /** + * @expectedException \LogicException + * @exepctedExceptionMessage Cannot reject a rejected promise + */ + public function testCannotReject() + { + $p = new RejectedPromise('foo'); + $p->reject('bar'); + } + + public function testCanRejectWithSameValue() + { + $p = new RejectedPromise('foo'); + $p->reject('foo'); + } + + public function testThrowsSpecificException() + { + $e = new \Exception(); + $p = new RejectedPromise($e); + try { + $p->wait(true); + $this->fail(); + } catch (\Exception $e2) { + $this->assertSame($e, $e2); + } + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testCannotResolveWithPromise() + { + new RejectedPromise(new Promise()); + } + + public function testReturnsSelfWhenNoOnReject() + { + $p = new RejectedPromise('a'); + $this->assertSame($p, $p->then()); + } + + public function testInvokesOnRejectedAsynchronously() + { + $p = new RejectedPromise('a'); + $r = null; + $f = function ($reason) use (&$r) { $r = $reason; }; + $p->then(null, $f); + $this->assertNull($r); + \GuzzleHttp\Promise\queue()->run(); + $this->assertEquals('a', $r); + } + + public function testReturnsNewRejectedWhenOnRejectedFails() + { + $p = new RejectedPromise('a'); + $f = function () { throw new \Exception('b'); }; + $p2 = $p->then(null, $f); + $this->assertNotSame($p, $p2); + try { + $p2->wait(); + $this->fail(); + } catch (\Exception $e) { + $this->assertEquals('b', $e->getMessage()); + } + } + + public function testWaitingIsNoOp() + { + $p = new RejectedPromise('a'); + $p->wait(false); + } + + public function testOtherwiseIsSugarForRejections() + { + $p = new RejectedPromise('foo'); + $p->otherwise(function ($v) use (&$c) { $c = $v; }); + \GuzzleHttp\Promise\queue()->run(); + $this->assertSame('foo', $c); + } + + public function testCanResolveThenWithSuccess() + { + $actual = null; + $p = new RejectedPromise('foo'); + $p->otherwise(function ($v) { + return $v . ' bar'; + })->then(function ($v) use (&$actual) { + $actual = $v; + }); + \GuzzleHttp\Promise\queue()->run(); + $this->assertEquals('foo bar', $actual); + } + + public function testDoesNotTryToRejectTwiceDuringTrampoline() + { + $fp = new RejectedPromise('a'); + $t1 = $fp->then(null, function ($v) { return $v . ' b'; }); + $t1->resolve('why!'); + $this->assertEquals('why!', $t1->wait()); + } +} diff --git a/server/vendor/guzzlehttp/promises/tests/RejectionExceptionTest.php b/server/vendor/guzzlehttp/promises/tests/RejectionExceptionTest.php new file mode 100644 index 0000000..36c6a88 --- /dev/null +++ b/server/vendor/guzzlehttp/promises/tests/RejectionExceptionTest.php @@ -0,0 +1,47 @@ +<?php +namespace GuzzleHttp\Promise\Tests; + +use GuzzleHttp\Promise\RejectionException; + +class Thing1 +{ + public function __construct($message) + { + $this->message = $message; + } + + public function __toString() + { + return $this->message; + } +} + +class Thing2 implements \JsonSerializable +{ + public function jsonSerialize() + { + return '{}'; + } +} + +/** + * @covers GuzzleHttp\Promise\RejectionException + */ +class RejectionExceptionTest extends \PHPUnit_Framework_TestCase +{ + public function testCanGetReasonFromException() + { + $thing = new Thing1('foo'); + $e = new RejectionException($thing); + + $this->assertSame($thing, $e->getReason()); + $this->assertEquals('The promise was rejected with reason: foo', $e->getMessage()); + } + + public function testCanGetReasonMessageFromJson() + { + $reason = new Thing2(); + $e = new RejectionException($reason); + $this->assertContains("{}", $e->getMessage()); + } +} diff --git a/server/vendor/guzzlehttp/promises/tests/TaskQueueTest.php b/server/vendor/guzzlehttp/promises/tests/TaskQueueTest.php new file mode 100644 index 0000000..845b263 --- /dev/null +++ b/server/vendor/guzzlehttp/promises/tests/TaskQueueTest.php @@ -0,0 +1,31 @@ +<?php +namespace GuzzleHttp\Promise\Test; + +use GuzzleHttp\Promise\TaskQueue; + +class TaskQueueTest extends \PHPUnit_Framework_TestCase +{ + public function testKnowsIfEmpty() + { + $tq = new TaskQueue(false); + $this->assertTrue($tq->isEmpty()); + } + + public function testKnowsIfFull() + { + $tq = new TaskQueue(false); + $tq->add(function () {}); + $this->assertFalse($tq->isEmpty()); + } + + public function testExecutesTasksInOrder() + { + $tq = new TaskQueue(false); + $called = []; + $tq->add(function () use (&$called) { $called[] = 'a'; }); + $tq->add(function () use (&$called) { $called[] = 'b'; }); + $tq->add(function () use (&$called) { $called[] = 'c'; }); + $tq->run(); + $this->assertEquals(['a', 'b', 'c'], $called); + } +} diff --git a/server/vendor/guzzlehttp/promises/tests/Thennable.php b/server/vendor/guzzlehttp/promises/tests/Thennable.php new file mode 100644 index 0000000..398954d --- /dev/null +++ b/server/vendor/guzzlehttp/promises/tests/Thennable.php @@ -0,0 +1,24 @@ +<?php +namespace GuzzleHttp\Promise\Tests; + +use GuzzleHttp\Promise\Promise; + +class Thennable +{ + private $nextPromise = null; + + public function __construct() + { + $this->nextPromise = new Promise(); + } + + public function then(callable $res = null, callable $rej = null) + { + return $this->nextPromise->then($res, $rej); + } + + public function resolve($value) + { + $this->nextPromise->resolve($value); + } +} diff --git a/server/vendor/guzzlehttp/promises/tests/bootstrap.php b/server/vendor/guzzlehttp/promises/tests/bootstrap.php new file mode 100644 index 0000000..a63d264 --- /dev/null +++ b/server/vendor/guzzlehttp/promises/tests/bootstrap.php @@ -0,0 +1,4 @@ +<?php +require __DIR__ . '/../vendor/autoload.php'; +require __DIR__ . '/Thennable.php'; +require __DIR__ . '/NotPromiseInstance.php'; diff --git a/server/vendor/guzzlehttp/promises/tests/functionsTest.php b/server/vendor/guzzlehttp/promises/tests/functionsTest.php new file mode 100644 index 0000000..8e6fcf4 --- /dev/null +++ b/server/vendor/guzzlehttp/promises/tests/functionsTest.php @@ -0,0 +1,694 @@ +<?php +namespace GuzzleHttp\Promise\Tests; + +use GuzzleHttp\Promise as P; +use GuzzleHttp\Promise\FulfilledPromise; +use GuzzleHttp\Promise\Promise; +use GuzzleHttp\Promise\RejectedPromise; + +class FunctionsTest extends \PHPUnit_Framework_TestCase +{ + public function testCreatesPromiseForValue() + { + $p = \GuzzleHttp\Promise\promise_for('foo'); + $this->assertInstanceOf('GuzzleHttp\Promise\FulfilledPromise', $p); + } + + public function testReturnsPromiseForPromise() + { + $p = new Promise(); + $this->assertSame($p, \GuzzleHttp\Promise\promise_for($p)); + } + + public function testReturnsPromiseForThennable() + { + $p = new Thennable(); + $wrapped = \GuzzleHttp\Promise\promise_for($p); + $this->assertNotSame($p, $wrapped); + $this->assertInstanceOf('GuzzleHttp\Promise\PromiseInterface', $wrapped); + $p->resolve('foo'); + P\queue()->run(); + $this->assertEquals('foo', $wrapped->wait()); + } + + public function testReturnsRejection() + { + $p = \GuzzleHttp\Promise\rejection_for('fail'); + $this->assertInstanceOf('GuzzleHttp\Promise\RejectedPromise', $p); + $this->assertEquals('fail', $this->readAttribute($p, 'reason')); + } + + public function testReturnsPromisesAsIsInRejectionFor() + { + $a = new Promise(); + $b = \GuzzleHttp\Promise\rejection_for($a); + $this->assertSame($a, $b); + } + + public function testWaitsOnAllPromisesIntoArray() + { + $e = new \Exception(); + $a = new Promise(function () use (&$a) { $a->resolve('a'); }); + $b = new Promise(function () use (&$b) { $b->reject('b'); }); + $c = new Promise(function () use (&$c, $e) { $c->reject($e); }); + $results = \GuzzleHttp\Promise\inspect_all([$a, $b, $c]); + $this->assertEquals([ + ['state' => 'fulfilled', 'value' => 'a'], + ['state' => 'rejected', 'reason' => 'b'], + ['state' => 'rejected', 'reason' => $e] + ], $results); + } + + /** + * @expectedException \GuzzleHttp\Promise\RejectionException + */ + public function testUnwrapsPromisesWithNoDefaultAndFailure() + { + $promises = [new FulfilledPromise('a'), new Promise()]; + \GuzzleHttp\Promise\unwrap($promises); + } + + public function testUnwrapsPromisesWithNoDefault() + { + $promises = [new FulfilledPromise('a')]; + $this->assertEquals(['a'], \GuzzleHttp\Promise\unwrap($promises)); + } + + public function testUnwrapsPromisesWithKeys() + { + $promises = [ + 'foo' => new FulfilledPromise('a'), + 'bar' => new FulfilledPromise('b'), + ]; + $this->assertEquals([ + 'foo' => 'a', + 'bar' => 'b' + ], \GuzzleHttp\Promise\unwrap($promises)); + } + + public function testAllAggregatesSortedArray() + { + $a = new Promise(); + $b = new Promise(); + $c = new Promise(); + $d = \GuzzleHttp\Promise\all([$a, $b, $c]); + $b->resolve('b'); + $a->resolve('a'); + $c->resolve('c'); + $d->then( + function ($value) use (&$result) { $result = $value; }, + function ($reason) use (&$result) { $result = $reason; } + ); + P\queue()->run(); + $this->assertEquals(['a', 'b', 'c'], $result); + } + + public function testAllThrowsWhenAnyRejected() + { + $a = new Promise(); + $b = new Promise(); + $c = new Promise(); + $d = \GuzzleHttp\Promise\all([$a, $b, $c]); + $b->resolve('b'); + $a->reject('fail'); + $c->resolve('c'); + $d->then( + function ($value) use (&$result) { $result = $value; }, + function ($reason) use (&$result) { $result = $reason; } + ); + P\queue()->run(); + $this->assertEquals('fail', $result); + } + + public function testSomeAggregatesSortedArrayWithMax() + { + $a = new Promise(); + $b = new Promise(); + $c = new Promise(); + $d = \GuzzleHttp\Promise\some(2, [$a, $b, $c]); + $b->resolve('b'); + $c->resolve('c'); + $a->resolve('a'); + $d->then(function ($value) use (&$result) { $result = $value; }); + P\queue()->run(); + $this->assertEquals(['b', 'c'], $result); + } + + public function testSomeRejectsWhenTooManyRejections() + { + $a = new Promise(); + $b = new Promise(); + $d = \GuzzleHttp\Promise\some(2, [$a, $b]); + $a->reject('bad'); + $b->resolve('good'); + P\queue()->run(); + $this->assertEquals($a::REJECTED, $d->getState()); + $d->then(null, function ($reason) use (&$called) { + $called = $reason; + }); + P\queue()->run(); + $this->assertInstanceOf('GuzzleHttp\Promise\AggregateException', $called); + $this->assertContains('bad', $called->getReason()); + } + + public function testCanWaitUntilSomeCountIsSatisfied() + { + $a = new Promise(function () use (&$a) { $a->resolve('a'); }); + $b = new Promise(function () use (&$b) { $b->resolve('b'); }); + $c = new Promise(function () use (&$c) { $c->resolve('c'); }); + $d = \GuzzleHttp\Promise\some(2, [$a, $b, $c]); + $this->assertEquals(['a', 'b'], $d->wait()); + } + + /** + * @expectedException \GuzzleHttp\Promise\AggregateException + * @expectedExceptionMessage Not enough promises to fulfill count + */ + public function testThrowsIfImpossibleToWaitForSomeCount() + { + $a = new Promise(function () use (&$a) { $a->resolve('a'); }); + $d = \GuzzleHttp\Promise\some(2, [$a]); + $d->wait(); + } + + /** + * @expectedException \GuzzleHttp\Promise\AggregateException + * @expectedExceptionMessage Not enough promises to fulfill count + */ + public function testThrowsIfResolvedWithoutCountTotalResults() + { + $a = new Promise(); + $b = new Promise(); + $d = \GuzzleHttp\Promise\some(3, [$a, $b]); + $a->resolve('a'); + $b->resolve('b'); + $d->wait(); + } + + public function testAnyReturnsFirstMatch() + { + $a = new Promise(); + $b = new Promise(); + $c = \GuzzleHttp\Promise\any([$a, $b]); + $b->resolve('b'); + $a->resolve('a'); + //P\queue()->run(); + //$this->assertEquals('fulfilled', $c->getState()); + $c->then(function ($value) use (&$result) { $result = $value; }); + P\queue()->run(); + $this->assertEquals('b', $result); + } + + public function testSettleFulfillsWithFulfilledAndRejected() + { + $a = new Promise(); + $b = new Promise(); + $c = new Promise(); + $d = \GuzzleHttp\Promise\settle([$a, $b, $c]); + $b->resolve('b'); + $c->resolve('c'); + $a->reject('a'); + P\queue()->run(); + $this->assertEquals('fulfilled', $d->getState()); + $d->then(function ($value) use (&$result) { $result = $value; }); + P\queue()->run(); + $this->assertEquals([ + ['state' => 'rejected', 'reason' => 'a'], + ['state' => 'fulfilled', 'value' => 'b'], + ['state' => 'fulfilled', 'value' => 'c'] + ], $result); + } + + public function testCanInspectFulfilledPromise() + { + $p = new FulfilledPromise('foo'); + $this->assertEquals([ + 'state' => 'fulfilled', + 'value' => 'foo' + ], \GuzzleHttp\Promise\inspect($p)); + } + + public function testCanInspectRejectedPromise() + { + $p = new RejectedPromise('foo'); + $this->assertEquals([ + 'state' => 'rejected', + 'reason' => 'foo' + ], \GuzzleHttp\Promise\inspect($p)); + } + + public function testCanInspectRejectedPromiseWithNormalException() + { + $e = new \Exception('foo'); + $p = new RejectedPromise($e); + $this->assertEquals([ + 'state' => 'rejected', + 'reason' => $e + ], \GuzzleHttp\Promise\inspect($p)); + } + + public function testCallsEachLimit() + { + $p = new Promise(); + $aggregate = \GuzzleHttp\Promise\each_limit($p, 2); + $p->resolve('a'); + P\queue()->run(); + $this->assertEquals($p::FULFILLED, $aggregate->getState()); + } + + public function testEachLimitAllRejectsOnFailure() + { + $p = [new FulfilledPromise('a'), new RejectedPromise('b')]; + $aggregate = \GuzzleHttp\Promise\each_limit_all($p, 2); + P\queue()->run(); + $this->assertEquals(P\PromiseInterface::REJECTED, $aggregate->getState()); + $result = \GuzzleHttp\Promise\inspect($aggregate); + $this->assertEquals('b', $result['reason']); + } + + public function testIterForReturnsIterator() + { + $iter = new \ArrayIterator(); + $this->assertSame($iter, \GuzzleHttp\Promise\iter_for($iter)); + } + + public function testKnowsIfFulfilled() + { + $p = new FulfilledPromise(null); + $this->assertTrue(P\is_fulfilled($p)); + $this->assertFalse(P\is_rejected($p)); + } + + public function testKnowsIfRejected() + { + $p = new RejectedPromise(null); + $this->assertTrue(P\is_rejected($p)); + $this->assertFalse(P\is_fulfilled($p)); + } + + public function testKnowsIfSettled() + { + $p = new RejectedPromise(null); + $this->assertTrue(P\is_settled($p)); + $p = new Promise(); + $this->assertFalse(P\is_settled($p)); + } + + public function testReturnsTrampoline() + { + $this->assertInstanceOf('GuzzleHttp\Promise\TaskQueue', P\queue()); + $this->assertSame(P\queue(), P\queue()); + } + + public function testCanScheduleThunk() + { + $tramp = P\queue(); + $promise = P\task(function () { return 'Hi!'; }); + $c = null; + $promise->then(function ($v) use (&$c) { $c = $v; }); + $this->assertNull($c); + $tramp->run(); + $this->assertEquals('Hi!', $c); + } + + public function testCanScheduleThunkWithRejection() + { + $tramp = P\queue(); + $promise = P\task(function () { throw new \Exception('Hi!'); }); + $c = null; + $promise->otherwise(function ($v) use (&$c) { $c = $v; }); + $this->assertNull($c); + $tramp->run(); + $this->assertEquals('Hi!', $c->getMessage()); + } + + public function testCanScheduleThunkWithWait() + { + $tramp = P\queue(); + $promise = P\task(function () { return 'a'; }); + $this->assertEquals('a', $promise->wait()); + $tramp->run(); + } + + public function testYieldsFromCoroutine() + { + $promise = P\coroutine(function () { + $value = (yield new P\FulfilledPromise('a')); + yield $value . 'b'; + }); + $promise->then(function ($value) use (&$result) { $result = $value; }); + P\queue()->run(); + $this->assertEquals('ab', $result); + } + + public function testCanCatchExceptionsInCoroutine() + { + $promise = P\coroutine(function () { + try { + yield new P\RejectedPromise('a'); + $this->fail('Should have thrown into the coroutine!'); + } catch (P\RejectionException $e) { + $value = (yield new P\FulfilledPromise($e->getReason())); + yield $value . 'b'; + } + }); + $promise->then(function ($value) use (&$result) { $result = $value; }); + P\queue()->run(); + $this->assertEquals(P\PromiseInterface::FULFILLED, $promise->getState()); + $this->assertEquals('ab', $result); + } + + public function testRejectsParentExceptionWhenException() + { + $promise = P\coroutine(function () { + yield new P\FulfilledPromise(0); + throw new \Exception('a'); + }); + $promise->then( + function () { $this->fail(); }, + function ($reason) use (&$result) { $result = $reason; } + ); + P\queue()->run(); + $this->assertInstanceOf('Exception', $result); + $this->assertEquals('a', $result->getMessage()); + } + + public function testCanRejectFromRejectionCallback() + { + $promise = P\coroutine(function () { + yield new P\FulfilledPromise(0); + yield new P\RejectedPromise('no!'); + }); + $promise->then( + function () { $this->fail(); }, + function ($reason) use (&$result) { $result = $reason; } + ); + P\queue()->run(); + $this->assertInstanceOf('GuzzleHttp\Promise\RejectionException', $result); + $this->assertEquals('no!', $result->getReason()); + } + + public function testCanAsyncReject() + { + $rej = new P\Promise(); + $promise = P\coroutine(function () use ($rej) { + yield new P\FulfilledPromise(0); + yield $rej; + }); + $promise->then( + function () { $this->fail(); }, + function ($reason) use (&$result) { $result = $reason; } + ); + $rej->reject('no!'); + P\queue()->run(); + $this->assertInstanceOf('GuzzleHttp\Promise\RejectionException', $result); + $this->assertEquals('no!', $result->getReason()); + } + + public function testCanCatchAndThrowOtherException() + { + $promise = P\coroutine(function () { + try { + yield new P\RejectedPromise('a'); + $this->fail('Should have thrown into the coroutine!'); + } catch (P\RejectionException $e) { + throw new \Exception('foo'); + } + }); + $promise->otherwise(function ($value) use (&$result) { $result = $value; }); + P\queue()->run(); + $this->assertEquals(P\PromiseInterface::REJECTED, $promise->getState()); + $this->assertContains('foo', $result->getMessage()); + } + + public function testCanCatchAndYieldOtherException() + { + $promise = P\coroutine(function () { + try { + yield new P\RejectedPromise('a'); + $this->fail('Should have thrown into the coroutine!'); + } catch (P\RejectionException $e) { + yield new P\RejectedPromise('foo'); + } + }); + $promise->otherwise(function ($value) use (&$result) { $result = $value; }); + P\queue()->run(); + $this->assertEquals(P\PromiseInterface::REJECTED, $promise->getState()); + $this->assertContains('foo', $result->getMessage()); + } + + public function createLotsOfSynchronousPromise() + { + return P\coroutine(function () { + $value = 0; + for ($i = 0; $i < 1000; $i++) { + $value = (yield new P\FulfilledPromise($i)); + } + yield $value; + }); + } + + public function testLotsOfSynchronousDoesNotBlowStack() + { + $promise = $this->createLotsOfSynchronousPromise(); + $promise->then(function ($v) use (&$r) { $r = $v; }); + P\queue()->run(); + $this->assertEquals(999, $r); + } + + public function testLotsOfSynchronousWaitDoesNotBlowStack() + { + $promise = $this->createLotsOfSynchronousPromise(); + $promise->then(function ($v) use (&$r) { $r = $v; }); + $this->assertEquals(999, $promise->wait()); + $this->assertEquals(999, $r); + } + + private function createLotsOfFlappingPromise() + { + return P\coroutine(function () { + $value = 0; + for ($i = 0; $i < 1000; $i++) { + try { + if ($i % 2) { + $value = (yield new P\FulfilledPromise($i)); + } else { + $value = (yield new P\RejectedPromise($i)); + } + } catch (\Exception $e) { + $value = (yield new P\FulfilledPromise($i)); + } + } + yield $value; + }); + } + + public function testLotsOfTryCatchingDoesNotBlowStack() + { + $promise = $this->createLotsOfFlappingPromise(); + $promise->then(function ($v) use (&$r) { $r = $v; }); + P\queue()->run(); + $this->assertEquals(999, $r); + } + + public function testLotsOfTryCatchingWaitingDoesNotBlowStack() + { + $promise = $this->createLotsOfFlappingPromise(); + $promise->then(function ($v) use (&$r) { $r = $v; }); + $this->assertEquals(999, $promise->wait()); + $this->assertEquals(999, $r); + } + + public function testAsyncPromisesWithCorrectlyYieldedValues() + { + $promises = [ + new P\Promise(), + new P\Promise(), + new P\Promise() + ]; + + $promise = P\coroutine(function () use ($promises) { + $value = null; + $this->assertEquals('skip', (yield new P\FulfilledPromise('skip'))); + foreach ($promises as $idx => $p) { + $value = (yield $p); + $this->assertEquals($value, $idx); + $this->assertEquals('skip', (yield new P\FulfilledPromise('skip'))); + } + $this->assertEquals('skip', (yield new P\FulfilledPromise('skip'))); + yield $value; + }); + + $promises[0]->resolve(0); + $promises[1]->resolve(1); + $promises[2]->resolve(2); + + $promise->then(function ($v) use (&$r) { $r = $v; }); + P\queue()->run(); + $this->assertEquals(2, $r); + } + + public function testYieldFinalWaitablePromise() + { + $p1 = new P\Promise(function () use (&$p1) { + $p1->resolve('skip me'); + }); + $p2 = new P\Promise(function () use (&$p2) { + $p2->resolve('hello!'); + }); + $co = P\coroutine(function() use ($p1, $p2) { + yield $p1; + yield $p2; + }); + P\queue()->run(); + $this->assertEquals('hello!', $co->wait()); + } + + public function testCanYieldFinalPendingPromise() + { + $p1 = new P\Promise(); + $p2 = new P\Promise(); + $co = P\coroutine(function() use ($p1, $p2) { + yield $p1; + yield $p2; + }); + $p1->resolve('a'); + $p2->resolve('b'); + $co->then(function ($value) use (&$result) { $result = $value; }); + P\queue()->run(); + $this->assertEquals('b', $result); + } + + public function testCanNestYieldsAndFailures() + { + $p1 = new P\Promise(); + $p2 = new P\Promise(); + $p3 = new P\Promise(); + $p4 = new P\Promise(); + $p5 = new P\Promise(); + $co = P\coroutine(function() use ($p1, $p2, $p3, $p4, $p5) { + try { + yield $p1; + } catch (\Exception $e) { + yield $p2; + try { + yield $p3; + yield $p4; + } catch (\Exception $e) { + yield $p5; + } + } + }); + $p1->reject('a'); + $p2->resolve('b'); + $p3->resolve('c'); + $p4->reject('d'); + $p5->resolve('e'); + $co->then(function ($value) use (&$result) { $result = $value; }); + P\queue()->run(); + $this->assertEquals('e', $result); + } + + public function testCanYieldErrorsAndSuccessesWithoutRecursion() + { + $promises = []; + for ($i = 0; $i < 20; $i++) { + $promises[] = new P\Promise(); + } + + $co = P\coroutine(function() use ($promises) { + for ($i = 0; $i < 20; $i += 4) { + try { + yield $promises[$i]; + yield $promises[$i + 1]; + } catch (\Exception $e) { + yield $promises[$i + 2]; + yield $promises[$i + 3]; + } + } + }); + + for ($i = 0; $i < 20; $i += 4) { + $promises[$i]->resolve($i); + $promises[$i + 1]->reject($i + 1); + $promises[$i + 2]->resolve($i + 2); + $promises[$i + 3]->resolve($i + 3); + } + + $co->then(function ($value) use (&$result) { $result = $value; }); + P\queue()->run(); + $this->assertEquals('19', $result); + } + + public function testCanWaitOnPromiseAfterFulfilled() + { + $f = function () { + static $i = 0; + $i++; + return $p = new P\Promise(function () use (&$p, $i) { + $p->resolve($i . '-bar'); + }); + }; + + $promises = []; + for ($i = 0; $i < 20; $i++) { + $promises[] = $f(); + } + + $p = P\coroutine(function () use ($promises) { + yield new P\FulfilledPromise('foo!'); + foreach ($promises as $promise) { + yield $promise; + } + }); + + $this->assertEquals('20-bar', $p->wait()); + } + + public function testCanWaitOnErroredPromises() + { + $p1 = new P\Promise(function () use (&$p1) { $p1->reject('a'); }); + $p2 = new P\Promise(function () use (&$p2) { $p2->resolve('b'); }); + $p3 = new P\Promise(function () use (&$p3) { $p3->resolve('c'); }); + $p4 = new P\Promise(function () use (&$p4) { $p4->reject('d'); }); + $p5 = new P\Promise(function () use (&$p5) { $p5->resolve('e'); }); + $p6 = new P\Promise(function () use (&$p6) { $p6->reject('f'); }); + + $co = P\coroutine(function() use ($p1, $p2, $p3, $p4, $p5, $p6) { + try { + yield $p1; + } catch (\Exception $e) { + yield $p2; + try { + yield $p3; + yield $p4; + } catch (\Exception $e) { + yield $p5; + yield $p6; + } + } + }); + + $res = P\inspect($co); + $this->assertEquals('f', $res['reason']); + } + + public function testCoroutineOtherwiseIntegrationTest() + { + $a = new P\Promise(); + $b = new P\Promise(); + $promise = P\coroutine(function () use ($a, $b) { + // Execute the pool of commands concurrently, and process errors. + yield $a; + yield $b; + })->otherwise(function (\Exception $e) { + // Throw errors from the operations as a specific Multipart error. + throw new \OutOfBoundsException('a', 0, $e); + }); + $a->resolve('a'); + $b->reject('b'); + $reason = P\inspect($promise)['reason']; + $this->assertInstanceOf('OutOfBoundsException', $reason); + $this->assertInstanceOf('GuzzleHttp\Promise\RejectionException', $reason->getPrevious()); + } +} |
