summaryrefslogtreecommitdiff
path: root/server/vendor/guzzlehttp/promises/tests
diff options
context:
space:
mode:
authorLoic GUEGAN <loic@Manzerbredes>2016-01-23 14:37:24 +0100
committerLoic GUEGAN <loic@Manzerbredes>2016-01-23 14:37:24 +0100
commit189f7a9ef4c6265dbac232e5c5685aebbbfc7c53 (patch)
treed397facc1e45cee4713ea95b0eaa4ffa9cbf0921 /server/vendor/guzzlehttp/promises/tests
parent2984adf171c49940e683fa997e8cdc60fcf1d60b (diff)
parenta44cc1d2e3c0f147e91a5c052ac7fd879e34e706 (diff)
Merge branch 'develop' of github.com:manzerbredes/istic-openstack into develop
Diffstat (limited to 'server/vendor/guzzlehttp/promises/tests')
-rw-r--r--server/vendor/guzzlehttp/promises/tests/AggregateExceptionTest.php14
-rw-r--r--server/vendor/guzzlehttp/promises/tests/EachPromiseTest.php294
-rw-r--r--server/vendor/guzzlehttp/promises/tests/FulfilledPromiseTest.php108
-rw-r--r--server/vendor/guzzlehttp/promises/tests/NotPromiseInstance.php50
-rw-r--r--server/vendor/guzzlehttp/promises/tests/PromiseTest.php579
-rw-r--r--server/vendor/guzzlehttp/promises/tests/RejectedPromiseTest.php143
-rw-r--r--server/vendor/guzzlehttp/promises/tests/RejectionExceptionTest.php47
-rw-r--r--server/vendor/guzzlehttp/promises/tests/TaskQueueTest.php31
-rw-r--r--server/vendor/guzzlehttp/promises/tests/Thennable.php24
-rw-r--r--server/vendor/guzzlehttp/promises/tests/bootstrap.php4
-rw-r--r--server/vendor/guzzlehttp/promises/tests/functionsTest.php694
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());
+ }
+}