mirror of
https://github.com/danog/amp.git
synced 2025-01-22 05:11:42 +01:00
add tests
This commit is contained in:
parent
dcab6907c0
commit
33fd20acb3
@ -224,7 +224,7 @@ function any(array $promises) {
|
||||
function first(array $promises) {
|
||||
if (empty($promises)) {
|
||||
return new Failure(new \LogicException(
|
||||
"No promises or values provided for first() resolution"
|
||||
"No promises or values provided"
|
||||
));
|
||||
}
|
||||
|
||||
@ -244,7 +244,7 @@ function first(array $promises) {
|
||||
}
|
||||
if (--$struct->remaining === 0) {
|
||||
$struct->promisor->fail(new \RuntimeException(
|
||||
"All promises passed for first() resolution failed"
|
||||
"All promises failed"
|
||||
));
|
||||
}
|
||||
};
|
||||
@ -295,7 +295,14 @@ function map(array $promises, callable $functor) {
|
||||
$struct->remaining--;
|
||||
try {
|
||||
$struct->results[$key] = \call_user_func($struct->functor, $result);
|
||||
} catch (\Throwable $e) {
|
||||
$struct->remaining = 0;
|
||||
$struct->promisor->fail($e);
|
||||
return;
|
||||
} catch (\Exception $e) {
|
||||
/**
|
||||
* @TODO This extra catch block is necessary for PHP5; remove once PHP7 is required
|
||||
*/
|
||||
$struct->remaining = 0;
|
||||
$struct->promisor->fail($e);
|
||||
return;
|
||||
@ -312,7 +319,13 @@ function map(array $promises, callable $functor) {
|
||||
$struct->remaining--;
|
||||
try {
|
||||
$struct->results[$key] = \call_user_func($struct->functor, $promise);
|
||||
} catch (\Throwable $e) {
|
||||
$struct->remaining = 0;
|
||||
$struct->promisor->fail($e);
|
||||
} catch (\Exception $e) {
|
||||
/**
|
||||
* @TODO This extra catch block is necessary for PHP5; remove once PHP7 is required
|
||||
*/
|
||||
$struct->remaining = 0;
|
||||
$struct->promisor->fail($e);
|
||||
}
|
||||
@ -363,7 +376,14 @@ function filter(array $promises, callable $functor) {
|
||||
if (\call_user_func($struct->functor, $result)) {
|
||||
$struct->results[$key] = $result;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$struct->remaining = 0;
|
||||
$struct->promisor->fail($e);
|
||||
return;
|
||||
} catch (\Exception $e) {
|
||||
/**
|
||||
* @TODO This extra catch block is necessary for PHP5; remove once PHP7 is required
|
||||
*/
|
||||
$struct->remaining = 0;
|
||||
$struct->promisor->fail($e);
|
||||
return;
|
||||
@ -382,7 +402,13 @@ function filter(array $promises, callable $functor) {
|
||||
if (\call_user_func($struct->functor, $promise)) {
|
||||
$struct->results[$key] = $promise;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$struct->remaining = 0;
|
||||
$struct->promisor->fail($e);
|
||||
} catch (\Exception $e) {
|
||||
/**
|
||||
* @TODO This extra catch block is necessary for PHP5; remove once PHP7 is required
|
||||
*/
|
||||
$struct->remaining = 0;
|
||||
$struct->promisor->fail($e);
|
||||
}
|
||||
@ -403,10 +429,15 @@ function filter(array $promises, callable $functor) {
|
||||
* @return \Amp\Promise
|
||||
*/
|
||||
function pipe($promise, callable $functor) {
|
||||
if (!($promise instanceof Promise)) {
|
||||
if (!$promise instanceof Promise) {
|
||||
try {
|
||||
return new Success(\call_user_func($functor, $promise));
|
||||
} catch (\Throwable $e) {
|
||||
return new Failure($e);
|
||||
} catch (\Exception $e) {
|
||||
/**
|
||||
* @TODO This extra catch block is necessary for PHP5; remove once PHP7 is required
|
||||
*/
|
||||
return new Failure($e);
|
||||
}
|
||||
}
|
||||
@ -419,7 +450,12 @@ function pipe($promise, callable $functor) {
|
||||
}
|
||||
try {
|
||||
$promisor->succeed(\call_user_func($functor, $result));
|
||||
} catch (\Throwable $error) {
|
||||
$promisor->fail($error);
|
||||
} catch (\Exception $error) {
|
||||
/**
|
||||
* @TODO This extra catch block is necessary for PHP5; remove once PHP7 is required
|
||||
*/
|
||||
$promisor->fail($error);
|
||||
}
|
||||
});
|
||||
@ -468,10 +504,11 @@ function timeout(Promise $promise, $msTimeout, Reactor $reactor = null) {
|
||||
"Promise resolution timed out"
|
||||
));
|
||||
}, $msTimeout);
|
||||
$promise->when(function($error = null, $result = null) use ($reactor, $promisor, $watcherId, $resolved) {
|
||||
$promise->when(function($error = null, $result = null) use ($reactor, $promisor, $watcherId, &$resolved) {
|
||||
if ($resolved) {
|
||||
return;
|
||||
}
|
||||
$resolved = true;
|
||||
$reactor->cancel($watcherId);
|
||||
if ($error) {
|
||||
$promisor->fail($error);
|
||||
|
@ -10,7 +10,7 @@ use Amp\PromiseStream;
|
||||
|
||||
class FunctionsTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
public function testPipe() {
|
||||
public function testPipeWrapsRawValue() {
|
||||
$invoked = 0;
|
||||
$promise = \Amp\pipe(21, function($r) { return $r * 2; });
|
||||
$promise->when(function($e, $r) use (&$invoked) {
|
||||
@ -20,6 +20,21 @@ class FunctionsTest extends \PHPUnit_Framework_TestCase {
|
||||
$this->assertSame(1, $invoked);
|
||||
}
|
||||
|
||||
public function testPipeTransformsEventualPromiseResult() {
|
||||
$result = 0;
|
||||
(new NativeReactor)->run(function ($reactor) use (&$result) {
|
||||
$promisor = new Deferred;
|
||||
$reactor->once(function () use ($promisor) {
|
||||
$promisor->succeed("woot");
|
||||
}, 10);
|
||||
|
||||
$promise = $promisor->promise();
|
||||
$result = (yield \Amp\pipe($promise, "strtoupper"));
|
||||
});
|
||||
|
||||
$this->assertSame("WOOT", $result);
|
||||
}
|
||||
|
||||
public function testPipeAbortsIfOriginalPromiseFails() {
|
||||
$invoked = 0;
|
||||
$failure = new Failure(new \RuntimeException);
|
||||
@ -31,7 +46,7 @@ class FunctionsTest extends \PHPUnit_Framework_TestCase {
|
||||
$this->assertSame(1, $invoked);
|
||||
}
|
||||
|
||||
public function testPipeAbortsIfFunctorThrows() {
|
||||
public function testPipeAbortsIfFunctorThrowsOnRawValue() {
|
||||
$invoked = 0;
|
||||
$promise = \Amp\pipe(42, function(){ throw new \RuntimeException; });
|
||||
$promise->when(function($e, $r) use (&$invoked) {
|
||||
@ -41,6 +56,16 @@ class FunctionsTest extends \PHPUnit_Framework_TestCase {
|
||||
$this->assertSame(1, $invoked);
|
||||
}
|
||||
|
||||
public function testPipeAbortsIfFunctorThrows() {
|
||||
$invoked = 0;
|
||||
$promise = \Amp\pipe(new Success(42), function(){ throw new \RuntimeException; });
|
||||
$promise->when(function($e, $r) use (&$invoked) {
|
||||
$invoked++;
|
||||
$this->assertInstanceOf("RuntimeException", $e);
|
||||
});
|
||||
$this->assertSame(1, $invoked);
|
||||
}
|
||||
|
||||
public function testAllResolutionWhenNoPromiseInstancesCombined() {
|
||||
$promises = [null, 1, 2, true];
|
||||
\Amp\all($promises)->when(function($e, $r) {
|
||||
@ -136,7 +161,7 @@ class FunctionsTest extends \PHPUnit_Framework_TestCase {
|
||||
$this->assertSame(['r1' => 42, 'r3' => 40], $results);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public function testSomeFailsImmediatelyOnEmptyPromiseArrayInput() {
|
||||
$promise = \Amp\some([]);
|
||||
$this->assertInstanceOf("Amp\Failure", $promise);
|
||||
@ -163,6 +188,76 @@ class FunctionsTest extends \PHPUnit_Framework_TestCase {
|
||||
});
|
||||
}
|
||||
|
||||
public function testFirstFailsImmediatelyOnEmptyPromiseArrayInput() {
|
||||
$promise = \Amp\first([]);
|
||||
$this->assertInstanceOf("Amp\Failure", $promise);
|
||||
$error = null;
|
||||
$result = null;
|
||||
$promise->when(function($e, $r) use (&$error, &$result) {
|
||||
$error = $e;
|
||||
$result = $r;
|
||||
});
|
||||
$this->assertNull($result);
|
||||
$this->assertInstanceOf("\LogicException", $error);
|
||||
$this->assertSame("No promises or values provided", $error->getMessage());
|
||||
}
|
||||
|
||||
public function testFirst() {
|
||||
$resolutionCount = 0;
|
||||
$result = 0;
|
||||
(new NativeReactor)->run(function ($reactor) use (&$resolutionCount, &$result) {
|
||||
$p1 = new Deferred;
|
||||
$reactor->once(function () use ($p1, &$resolutionCount) {
|
||||
$p1->succeed(1);
|
||||
$resolutionCount++;
|
||||
}, 10);
|
||||
|
||||
$p2 = new Deferred;
|
||||
$reactor->once(function () use ($p2, &$resolutionCount) {
|
||||
$p2->succeed(2);
|
||||
$resolutionCount++;
|
||||
}, 20);
|
||||
|
||||
$p3 = new Deferred;
|
||||
$reactor->once(function () use ($p3, &$resolutionCount) {
|
||||
$p3->succeed(3);
|
||||
$resolutionCount++;
|
||||
}, 30);
|
||||
|
||||
$promises = [$p1->promise(), $p2->promise(), $p3->promise()];
|
||||
$allPromise = \Amp\all($promises, $reactor);
|
||||
$allPromise->when([$reactor, "stop"]);
|
||||
|
||||
$result = (yield \Amp\first($promises, $reactor));
|
||||
});
|
||||
|
||||
$this->assertSame(3, $resolutionCount);
|
||||
$this->assertSame(1, $result);
|
||||
}
|
||||
|
||||
public function testNonPromiseValueImmediatelyResolvesFirstCombinator() {
|
||||
$result = 0;
|
||||
(new NativeReactor)->run(function ($reactor) use (&$result) {
|
||||
$p1 = 42;
|
||||
$p2 = (new Deferred)->promise();
|
||||
$result = (yield \Amp\first([$p1, $p2], $reactor));
|
||||
});
|
||||
$this->assertSame(42, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage All promises failed
|
||||
*/
|
||||
public function testFirstFailsIfAllPromisesFail() {
|
||||
(new NativeReactor)->run(function ($reactor) use (&$result) {
|
||||
$e1 = new \Exception("foo");
|
||||
$e2 = new \Exception("bar");
|
||||
$promises = [new Failure($e1), new Failure($e2)];
|
||||
yield \Amp\first($promises, $reactor);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage Promise resolution timed out
|
||||
@ -174,6 +269,58 @@ class FunctionsTest extends \PHPUnit_Framework_TestCase {
|
||||
});
|
||||
}
|
||||
|
||||
public function testTimeoutOnSuccess() {
|
||||
$invoked = false;
|
||||
(new NativeReactor)->run(function ($reactor) use (&$invoked) {
|
||||
$promisor = new Deferred;
|
||||
$reactor->once(function () use ($promisor) {
|
||||
$promisor->succeed(42);
|
||||
}, 10);
|
||||
|
||||
$result = (yield \Amp\timeout($promisor->promise(), 10000, $reactor));
|
||||
$this->assertSame(42, $result);
|
||||
$invoked = true;
|
||||
});
|
||||
|
||||
$this->assertTrue($invoked);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException RuntimeException
|
||||
* @expectedExceptionMessage nothing that is worth knowing can be taught
|
||||
*/
|
||||
public function testTimeoutOnFailure() {
|
||||
(new NativeReactor)->run(function ($reactor) {
|
||||
$promisor = new Deferred;
|
||||
$reactor->once(function () use ($promisor) {
|
||||
$promisor->fail(new \RuntimeException(
|
||||
"nothing that is worth knowing can be taught"
|
||||
));
|
||||
}, 10);
|
||||
|
||||
$result = (yield \Amp\timeout($promisor->promise(), 10000, $reactor));
|
||||
});
|
||||
}
|
||||
|
||||
public function testTimeoutIgnoresResultIfAlreadyComplete() {
|
||||
$invoked = false;
|
||||
(new NativeReactor)->run(function ($reactor) use (&$invoked) {
|
||||
$promisor = new Deferred;
|
||||
$reactor->once(function () use ($promisor) {
|
||||
$promisor->succeed(42);
|
||||
}, 100);
|
||||
try {
|
||||
$result = (yield \Amp\timeout($promisor->promise(), 10, $reactor));
|
||||
} catch (\RuntimeException $e) {
|
||||
// ignore this
|
||||
}
|
||||
yield $promisor->promise();
|
||||
$invoked = true;
|
||||
});
|
||||
|
||||
$this->assertTrue($invoked);
|
||||
}
|
||||
|
||||
public function testAllCombinatorResolution() {
|
||||
$invoked = 0;
|
||||
(new NativeReactor)->run(function($reactor) use (&$invoked) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user