mirror of
https://github.com/danog/amp.git
synced 2024-11-26 20:15:00 +01:00
Initial tests plus some fixes
This commit is contained in:
parent
4ed8e65468
commit
3f654cbd5b
@ -18,7 +18,8 @@
|
|||||||
"async-interop/event-loop-implementation": "dev-master"
|
"async-interop/event-loop-implementation": "dev-master"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"amphp/loop": "dev-master"
|
"amphp/loop": "dev-master",
|
||||||
|
"phpunit/phpunit": "^4|^5"
|
||||||
},
|
},
|
||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -4,6 +4,7 @@ namespace Amp;
|
|||||||
|
|
||||||
use Interop\Async\Awaitable;
|
use Interop\Async\Awaitable;
|
||||||
|
|
||||||
|
// @codeCoverageIgnoreStart
|
||||||
try {
|
try {
|
||||||
if (@assert(false)) {
|
if (@assert(false)) {
|
||||||
production: // PHP 7 production environment (zend.assertions=0)
|
production: // PHP 7 production environment (zend.assertions=0)
|
||||||
@ -75,4 +76,4 @@ try {
|
|||||||
}
|
}
|
||||||
} catch (\AssertionError $exception) {
|
} catch (\AssertionError $exception) {
|
||||||
goto development; // zend.assertions=1 and assert.exception=1, use development definition.
|
goto development; // zend.assertions=1 and assert.exception=1, use development definition.
|
||||||
}
|
} // @codeCoverageIgnoreEnd
|
||||||
|
@ -144,13 +144,23 @@ function capture(Awaitable $awaitable, $className, callable $functor) {
|
|||||||
*/
|
*/
|
||||||
function timeout(Awaitable $awaitable, $timeout) {
|
function timeout(Awaitable $awaitable, $timeout) {
|
||||||
$deferred = new Deferred;
|
$deferred = new Deferred;
|
||||||
|
$resolved = false;
|
||||||
|
|
||||||
$watcher = Loop::delay($timeout, function () use ($deferred) {
|
$watcher = Loop::delay($timeout, function () use (&$resolved, $deferred) {
|
||||||
$deferred->fail(new TimeoutException);
|
if (!$resolved) {
|
||||||
|
$resolved = true;
|
||||||
|
$deferred->fail(new TimeoutException);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$awaitable->when(function () use ($awaitable, $deferred, $watcher) {
|
$awaitable->when(function () use (&$resolved, $awaitable, $deferred, $watcher) {
|
||||||
Loop::cancel($watcher);
|
Loop::cancel($watcher);
|
||||||
|
|
||||||
|
if ($resolved) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$resolved = true;
|
||||||
$deferred->resolve($awaitable);
|
$deferred->resolve($awaitable);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
31
phpunit.xml.dist
Normal file
31
phpunit.xml.dist
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<phpunit
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
|
||||||
|
backupGlobals="false"
|
||||||
|
backupStaticAttributes="false"
|
||||||
|
bootstrap="vendor/autoload.php"
|
||||||
|
colors="true"
|
||||||
|
convertErrorsToExceptions="true"
|
||||||
|
convertNoticesToExceptions="true"
|
||||||
|
convertWarningsToExceptions="true"
|
||||||
|
processIsolation="false"
|
||||||
|
stopOnFailure="false"
|
||||||
|
>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="Amp">
|
||||||
|
<directory>test</directory>
|
||||||
|
<!-- Remove tags below once PHP 7.0 is required -->
|
||||||
|
<exclude>test/ExtendedCoroutineTest.php</exclude>
|
||||||
|
<file phpVersion="7.0.0">test/ExtendedCoroutineTest.php</file>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
<filter>
|
||||||
|
<whitelist>
|
||||||
|
<directory suffix=".php">lib</directory>
|
||||||
|
</whitelist>
|
||||||
|
</filter>
|
||||||
|
<logging>
|
||||||
|
<log type="coverage-html" target="build/coverage" title="Icicle" highlight="true"/>
|
||||||
|
</logging>
|
||||||
|
</phpunit>
|
105
test/AdaptTest.php
Normal file
105
test/AdaptTest.php
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Amp\Test;
|
||||||
|
|
||||||
|
use Amp;
|
||||||
|
use Amp\Failure;
|
||||||
|
use Amp\Success;
|
||||||
|
use Interop\Async\Awaitable;
|
||||||
|
|
||||||
|
class PromiseMock {
|
||||||
|
/**
|
||||||
|
* @var \Interop\Async\Awaitable
|
||||||
|
*/
|
||||||
|
private $awaitable;
|
||||||
|
|
||||||
|
public function __construct(Awaitable $awaitable) {
|
||||||
|
$this->awaitable = $awaitable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function then(callable $onFulfilled = null, callable $onRejected = null) {
|
||||||
|
$this->awaitable->when(function ($exception, $value) use ($onFulfilled, $onRejected) {
|
||||||
|
if ($exception) {
|
||||||
|
if ($onRejected) {
|
||||||
|
$onRejected($exception);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($onFulfilled) {
|
||||||
|
$onFulfilled($value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AdaptTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
public function testThenCalled() {
|
||||||
|
$mock = $this->getMockBuilder(PromiseMock::class)
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
$mock->expects($this->once())
|
||||||
|
->method("then")
|
||||||
|
->with(
|
||||||
|
$this->callback(function ($resolve) {
|
||||||
|
return is_callable($resolve);
|
||||||
|
}),
|
||||||
|
$this->callback(function ($reject) {
|
||||||
|
return is_callable($reject);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
$awaitable = Amp\adapt($mock);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(Awaitable::class, $awaitable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testThenCalled
|
||||||
|
*/
|
||||||
|
public function testAwaitableFulfilled() {
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
$promise = new PromiseMock(new Success($value));
|
||||||
|
|
||||||
|
$awaitable = Amp\adapt($promise);
|
||||||
|
|
||||||
|
$awaitable->when(function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testThenCalled
|
||||||
|
*/
|
||||||
|
public function testAwaitableRejected() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$promise = new PromiseMock(new Failure($exception));
|
||||||
|
|
||||||
|
$awaitable = Amp\adapt($promise);
|
||||||
|
|
||||||
|
$awaitable->when(function ($exception, $value) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testScalarValue() {
|
||||||
|
Amp\adapt(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testNonThenableObject() {
|
||||||
|
Amp\adapt(new \stdClass);
|
||||||
|
}
|
||||||
|
}
|
77
test/AllTest.php
Normal file
77
test/AllTest.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Amp\Test;
|
||||||
|
|
||||||
|
use Amp;
|
||||||
|
use Amp\Pause;
|
||||||
|
use Amp\Success;
|
||||||
|
use Interop\Async\Loop;
|
||||||
|
|
||||||
|
class AllTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
public function testEmptyArray() {
|
||||||
|
$callback = function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Amp\all([])->when($callback);
|
||||||
|
|
||||||
|
$this->assertSame([], $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSuccessfulAwaitablesArray() {
|
||||||
|
$awaitables = [new Success(1), new Success(2), new Success(3)];
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Amp\all($awaitables)->when($callback);
|
||||||
|
|
||||||
|
$this->assertSame([1, 2, 3], $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPendingAwatiablesArray() {
|
||||||
|
Loop::execute(function () use (&$result) {
|
||||||
|
$awaitables = [
|
||||||
|
new Pause(0.2, 1),
|
||||||
|
new Pause(0.3, 2),
|
||||||
|
new Pause(0.1, 3),
|
||||||
|
];
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Amp\all($awaitables)->when($callback);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertEquals([1, 2, 3], $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testArrayKeysPreserved() {
|
||||||
|
$expected = ['one' => 1, 'two' => 2, 'three' => 3];
|
||||||
|
|
||||||
|
Loop::execute(function () use (&$result) {
|
||||||
|
$awaitables = [
|
||||||
|
'one' => new Pause(0.2, 1),
|
||||||
|
'two' => new Pause(0.3, 2),
|
||||||
|
'three' => new Pause(0.1, 3),
|
||||||
|
];
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Amp\all($awaitables)->when($callback);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testNonAwaitable() {
|
||||||
|
Amp\all([1]);
|
||||||
|
}
|
||||||
|
}
|
113
test/CaptureTest.php
Normal file
113
test/CaptureTest.php
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Amp\Test;
|
||||||
|
|
||||||
|
use Amp;
|
||||||
|
use Amp\Failure;
|
||||||
|
use Amp\Success;
|
||||||
|
use Interop\Async\Awaitable;
|
||||||
|
|
||||||
|
class CaptureTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
public function testSuccessfulAwaitable() {
|
||||||
|
$invoked = false;
|
||||||
|
$callback = function ($exception) use (&$invoked) {
|
||||||
|
$invoked = true;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
$awaitable = new Success($value);
|
||||||
|
|
||||||
|
$awaitable = Amp\capture($awaitable, \Exception::class, $callback);
|
||||||
|
$this->assertInstanceOf(Awaitable::class, $awaitable);
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
$awaitable->when($callback);
|
||||||
|
|
||||||
|
$this->assertFalse($invoked);
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFailedAwaitable() {
|
||||||
|
$invoked = false;
|
||||||
|
$callback = function ($exception) use (&$invoked, &$reason) {
|
||||||
|
$invoked = true;
|
||||||
|
$reason = $exception;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$awaitable = new Failure($exception);
|
||||||
|
|
||||||
|
$awaitable = Amp\capture($awaitable, \Exception::class, $callback);
|
||||||
|
$this->assertInstanceOf(Awaitable::class, $awaitable);
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
$awaitable->when($callback);
|
||||||
|
|
||||||
|
$this->assertTrue($invoked);
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
$this->assertSame(-1, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testFailedAwaitable
|
||||||
|
*/
|
||||||
|
public function testCallbackThrowing() {
|
||||||
|
$invoked = false;
|
||||||
|
$callback = function ($exception) use (&$invoked) {
|
||||||
|
$invoked = true;
|
||||||
|
throw new \Exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$awaitable = new Failure($exception);
|
||||||
|
|
||||||
|
$awaitable = Amp\capture($awaitable, \Exception::class, $callback);
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
$awaitable->when($callback);
|
||||||
|
|
||||||
|
$this->assertTrue($invoked);
|
||||||
|
$this->assertNotSame($exception, $reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testFailedAwaitable
|
||||||
|
*/
|
||||||
|
public function testUnmatchedExceptionClass() {
|
||||||
|
$invoked = false;
|
||||||
|
$callback = function ($exception) use (&$invoked, &$reason) {
|
||||||
|
$invoked = true;
|
||||||
|
$reason = $exception;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
$exception = new \LogicException;
|
||||||
|
|
||||||
|
$awaitable = new Failure($exception);
|
||||||
|
|
||||||
|
$awaitable = Amp\capture($awaitable, \RuntimeException::class, $callback);
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
$awaitable->when($callback);
|
||||||
|
|
||||||
|
$this->assertFalse($invoked);
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
}
|
||||||
|
}
|
539
test/CoroutineTest.php
Normal file
539
test/CoroutineTest.php
Normal file
@ -0,0 +1,539 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Icicle\Tests\Coroutine;
|
||||||
|
|
||||||
|
use Amp;
|
||||||
|
use Amp\Coroutine;
|
||||||
|
use Amp\Failure;
|
||||||
|
use Amp\InvalidYieldException;
|
||||||
|
use Amp\Pause;
|
||||||
|
use Amp\Success;
|
||||||
|
use Interop\Async\Loop;
|
||||||
|
|
||||||
|
class CoroutineTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
const TIMEOUT = 0.1;
|
||||||
|
|
||||||
|
public function testYieldSuccessfulAwaitable() {
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
$generator = function () use (&$yielded, $value) {
|
||||||
|
$yielded = (yield new Success($value));
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$this->assertSame($value, $yielded);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testYieldFailedAwaitable() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$generator = function () use (&$yielded, $exception) {
|
||||||
|
$yielded = (yield new Failure($exception));
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$this->assertNull($yielded);
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testYieldSuccessfulAwaitable
|
||||||
|
*/
|
||||||
|
public function testYieldPendingAwaitable() {
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
Loop::execute(function () use (&$yielded, $value) {
|
||||||
|
$generator = function () use (&$yielded, $value) {
|
||||||
|
$yielded = (yield new Pause(self::TIMEOUT, $value));
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($value, $yielded);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testYieldFailedAwaitable
|
||||||
|
*/
|
||||||
|
public function testCatchingFailedAwaitableException() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$fail = false;
|
||||||
|
$generator = function () use (&$fail, &$result, $exception) {
|
||||||
|
try {
|
||||||
|
yield new Failure($exception);
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
$result = $exception;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$fail = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
if ($fail) {
|
||||||
|
$this->fail("Failed awaitable reason not thrown into generator");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo Remove once PHP 7 is required.
|
||||||
|
*/
|
||||||
|
public function testSucceedsWithCoroutineResult() {
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
$generator = function () use ($value) {
|
||||||
|
yield Coroutine::result($value);
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testSucceedsWithCoroutineResult
|
||||||
|
* @todo Remove once PHP 7 is required.
|
||||||
|
*/
|
||||||
|
public function testSucceedsWithCoroutineAfterSuccessfulAwaitable() {
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
$generator = function () use ($value) {
|
||||||
|
yield Coroutine::result(yield new Success($value));
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testSucceedsWithCoroutineResult
|
||||||
|
* @todo Remove once PHP 7 is required.
|
||||||
|
*/
|
||||||
|
public function testSucceedsWithCoroutineAfterFailedAwaitable() {
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
$generator = function () use ($value) {
|
||||||
|
try {
|
||||||
|
yield new Failure(new \Exception);
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
yield Coroutine::result($value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvalidYield() {
|
||||||
|
$generator = function () {
|
||||||
|
yield 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertInstanceOf(InvalidYieldException::class, $reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testInvalidYield
|
||||||
|
*/
|
||||||
|
public function testInvalidYieldAfterYieldAwaitable() {
|
||||||
|
$generator = function () {
|
||||||
|
yield new Success;
|
||||||
|
yield 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertInstanceOf(InvalidYieldException::class, $reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testInvalidYield
|
||||||
|
*/
|
||||||
|
public function testCatchesExceptionAfterInvalidYield() {
|
||||||
|
$generator = function () {
|
||||||
|
try {
|
||||||
|
yield 1;
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
yield Coroutine::result(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertInstanceOf(InvalidYieldException::class, $reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testSucceedsWithCoroutineResult
|
||||||
|
* @todo Remove once PHP 7 is required.
|
||||||
|
*/
|
||||||
|
public function testYieldsAfterCoroutineResult() {
|
||||||
|
$generator = function () {
|
||||||
|
yield Coroutine::result(1);
|
||||||
|
yield new Success;
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertInstanceOf(InvalidYieldException::class, $reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testYieldsAfterCoroutineResult
|
||||||
|
* @todo Remove once PHP 7 is required.
|
||||||
|
*/
|
||||||
|
public function testCatchesExceptionAfterInvalidResult() {
|
||||||
|
$generator = function () {
|
||||||
|
yield Coroutine::result(1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
yield new Success;
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
yield Coroutine::result(2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertInstanceOf(InvalidYieldException::class, $reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testInvalidYield
|
||||||
|
*/
|
||||||
|
public function testThrowAfterInvalidYield() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$generator = function () use ($exception) {
|
||||||
|
try {
|
||||||
|
yield 1;
|
||||||
|
} catch (\Exception $reason) {
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertInstanceOf(InvalidYieldException::class, $reason);
|
||||||
|
$this->assertSame($exception, $reason->getPrevious());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testYieldFailedAwaitable
|
||||||
|
*/
|
||||||
|
public function testCatchingFailedAwaitableExceptionWithNoFurtherYields() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$generator = function () use ($exception) {
|
||||||
|
try {
|
||||||
|
yield new Failure($exception);
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
// No further yields in generator.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertNull($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGeneratorThrowingExceptionFailsCoroutine() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$generator = function () use ($exception) {
|
||||||
|
throw $exception;
|
||||||
|
yield;
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testGeneratorThrowingExceptionFailsCoroutine
|
||||||
|
*/
|
||||||
|
public function testGeneratorThrowingExceptionWithFinallyFailsCoroutine() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$invoked = false;
|
||||||
|
$generator = function () use (&$invoked, $exception) {
|
||||||
|
try {
|
||||||
|
throw $exception;
|
||||||
|
yield;
|
||||||
|
} finally {
|
||||||
|
$invoked = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
$this->assertTrue($invoked);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testYieldFailedAwaitable
|
||||||
|
* @depends testGeneratorThrowingExceptionWithFinallyFailsCoroutine
|
||||||
|
*/
|
||||||
|
public function testGeneratorYieldingFailedAwaitableWithFinallyFailsCoroutine() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$invoked = false;
|
||||||
|
$generator = function () use (&$invoked, $exception) {
|
||||||
|
try {
|
||||||
|
yield new Failure($exception);
|
||||||
|
} finally {
|
||||||
|
$invoked = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
$this->assertTrue($invoked);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testGeneratorThrowingExceptionFailsCoroutine
|
||||||
|
*/
|
||||||
|
public function testGeneratorThrowingExceptionAfterPendingAwaitableWithFinallyFailsCoroutine() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
Loop::execute(function () use (&$yielded, &$invoked, &$reason, $exception, $value) {
|
||||||
|
$invoked = false;
|
||||||
|
$generator = function () use (&$yielded, &$invoked, $exception, $value) {
|
||||||
|
try {
|
||||||
|
$yielded = (yield new Pause(self::TIMEOUT, $value));
|
||||||
|
throw $exception;
|
||||||
|
} finally {
|
||||||
|
$invoked = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
$this->assertTrue($invoked);
|
||||||
|
$this->assertSame($value, $yielded);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that yielding in a finally block is not recommended.
|
||||||
|
*
|
||||||
|
* @depends testYieldPendingAwaitable
|
||||||
|
* @depends testGeneratorThrowingExceptionWithFinallyFailsCoroutine
|
||||||
|
*/
|
||||||
|
public function testGeneratorThrowingExceptionWithFinallyYieldingPendingAwaitable() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
Loop::execute(function () use (&$yielded, &$reason, $exception, $value) {
|
||||||
|
$generator = function () use (&$yielded, $exception, $value) {
|
||||||
|
try {
|
||||||
|
throw $exception;
|
||||||
|
} finally {
|
||||||
|
$yielded = (yield new Pause(self::TIMEOUT, $value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($value, $yielded);
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testYieldPendingAwaitable
|
||||||
|
* @depends testGeneratorThrowingExceptionWithFinallyFailsCoroutine
|
||||||
|
*/
|
||||||
|
public function testGeneratorThrowingExceptionWithFinallyBlockThrowing() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$generator = function () use ($exception) {
|
||||||
|
try {
|
||||||
|
throw new \Exception;
|
||||||
|
} finally {
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield; // Unreachable, but makes function a generator.
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testYieldSuccessfulAwaitable
|
||||||
|
*/
|
||||||
|
public function testYieldConsecutiveSucceeded() {
|
||||||
|
$invoked = false;
|
||||||
|
Loop::execute(function () use (&$invoked) {
|
||||||
|
$count = 1000;
|
||||||
|
$awaitable = new Success;
|
||||||
|
|
||||||
|
$generator = function () use ($count, $awaitable) {
|
||||||
|
for ($i = 0; $i < $count; ++$i) {
|
||||||
|
yield $awaitable;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$invoked) {
|
||||||
|
$invoked = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertTrue($invoked);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testYieldFailedAwaitable
|
||||||
|
*/
|
||||||
|
public function testYieldConsecutiveFailed() {
|
||||||
|
$invoked = false;
|
||||||
|
Loop::execute(function () use (&$invoked) {
|
||||||
|
$count = 1000;
|
||||||
|
$awaitable = new Failure(new \Exception);
|
||||||
|
|
||||||
|
$generator = function () use ($count, $awaitable) {
|
||||||
|
for ($i = 0; $i < $count; ++$i) {
|
||||||
|
try {
|
||||||
|
yield $awaitable;
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
// Ignore and continue.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$invoked) {
|
||||||
|
$invoked = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testYieldSuccessfulAwaitable
|
||||||
|
*/
|
||||||
|
public function testFastInvalidGenerator() {
|
||||||
|
$generator = function () {
|
||||||
|
if (false) {
|
||||||
|
yield new Success;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$invoked = false;
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$invoked) {
|
||||||
|
$invoked = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertTrue($invoked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCoroutineFunction() {
|
||||||
|
$callable = Amp\coroutine(function () {
|
||||||
|
yield;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertInstanceOf(Coroutine::class, $callable());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testCoroutineFunction
|
||||||
|
* @expectedException \LogicException
|
||||||
|
*/
|
||||||
|
public function testCoroutineFunctionWithNonGeneratorCallback() {
|
||||||
|
$callable = Amp\coroutine(function () {});
|
||||||
|
|
||||||
|
$this->assertInstanceOf(Coroutine::class, $callable());
|
||||||
|
}
|
||||||
|
}
|
60
test/DeferredTest.php
Normal file
60
test/DeferredTest.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Amp\Test;
|
||||||
|
|
||||||
|
use Amp\Deferred;
|
||||||
|
use Interop\Async\Awaitable;
|
||||||
|
|
||||||
|
class DeferredTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
/**
|
||||||
|
* @var \Amp\Deferred
|
||||||
|
*/
|
||||||
|
private $deferred;
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
$this->deferred = new Deferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetAwaitable() {
|
||||||
|
$awaitable = $this->deferred->getAwaitable();
|
||||||
|
$this->assertInstanceOf(Awaitable::class, $awaitable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testGetAwaitable
|
||||||
|
*/
|
||||||
|
public function testResolve() {
|
||||||
|
$value = "Resolution value";
|
||||||
|
$awaitable = $this->deferred->getAwaitable();
|
||||||
|
|
||||||
|
$invoked = false;
|
||||||
|
$awaitable->when(function ($exception, $value) use (&$invoked, &$result) {
|
||||||
|
$invoked = true;
|
||||||
|
$result = $value;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->deferred->resolve($value);
|
||||||
|
|
||||||
|
$this->assertTrue($invoked);
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testGetAwaitable
|
||||||
|
*/
|
||||||
|
public function testFail() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
$awaitable = $this->deferred->getAwaitable();
|
||||||
|
|
||||||
|
$invoked = false;
|
||||||
|
$awaitable->when(function ($exception, $value) use (&$invoked, &$result) {
|
||||||
|
$invoked = true;
|
||||||
|
$result = $exception;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->deferred->fail($exception);
|
||||||
|
|
||||||
|
$this->assertTrue($invoked);
|
||||||
|
$this->assertSame($exception, $result);
|
||||||
|
}
|
||||||
|
}
|
80
test/ExtendedCoroutineTest.php
Normal file
80
test/ExtendedCoroutineTest.php
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Amp\Test;
|
||||||
|
|
||||||
|
use Amp\Coroutine;
|
||||||
|
use Amp\Success;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo Combine with CoroutineTest once PHP 7 is required.
|
||||||
|
*/
|
||||||
|
class ExtendedCoroutineTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
public function testCoroutineResolvedWithReturn() {
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
$generator = function () use ($value) {
|
||||||
|
return $value;
|
||||||
|
yield; // Unreachable, but makes function a coroutine.
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testCoroutineResolvedWithReturn
|
||||||
|
*/
|
||||||
|
public function testYieldFromGenerator() {
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
$generator = function () use ($value) {
|
||||||
|
$generator = function () use ($value) {
|
||||||
|
return yield new Success($value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return yield from $generator();
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testCoroutineResolvedWithReturn
|
||||||
|
*/
|
||||||
|
public function testFastReturningGenerator()
|
||||||
|
{
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
$generator = function () use ($value) {
|
||||||
|
if (true) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield;
|
||||||
|
|
||||||
|
return -$value;
|
||||||
|
};
|
||||||
|
|
||||||
|
$coroutine = new Coroutine($generator());
|
||||||
|
|
||||||
|
$coroutine->when(function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
57
test/FailureTest.php
Normal file
57
test/FailureTest.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Amp\Test;
|
||||||
|
|
||||||
|
use Amp\Failure;
|
||||||
|
use Interop\Async\Loop;
|
||||||
|
|
||||||
|
class FailureTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
/**
|
||||||
|
* @expectedException \LogicException
|
||||||
|
*/
|
||||||
|
public function testConstructWithNonException() {
|
||||||
|
$failure = new Failure(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWhen() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$invoked = 0;
|
||||||
|
$callback = function ($exception, $value) use (&$invoked, &$reason) {
|
||||||
|
++$invoked;
|
||||||
|
$reason = $exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
$success = new Failure($exception);
|
||||||
|
|
||||||
|
$success->when($callback);
|
||||||
|
|
||||||
|
$this->assertSame(1, $invoked);
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testWhen
|
||||||
|
*/
|
||||||
|
public function testWhenThrowingForwardsToLoopHandlerOnSuccess() {
|
||||||
|
Loop::execute(function () use (&$invoked) {
|
||||||
|
$invoked = 0;
|
||||||
|
$expected = new \Exception;
|
||||||
|
|
||||||
|
Loop::setErrorHandler(function ($exception) use (&$invoked, $expected) {
|
||||||
|
++$invoked;
|
||||||
|
$this->assertSame($expected, $exception);
|
||||||
|
});
|
||||||
|
|
||||||
|
$callback = function () use ($expected) {
|
||||||
|
throw $expected;
|
||||||
|
};
|
||||||
|
|
||||||
|
$success = new Failure(new \Exception);
|
||||||
|
|
||||||
|
$success->when($callback);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame(1, $invoked);
|
||||||
|
}
|
||||||
|
}
|
312
test/FutureTest.php
Normal file
312
test/FutureTest.php
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Amp\Test;
|
||||||
|
|
||||||
|
use Amp\Future;
|
||||||
|
use Interop\Async\Awaitable;
|
||||||
|
use Interop\Async\Loop;
|
||||||
|
|
||||||
|
class FutureTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
/**
|
||||||
|
* @var \Amp\Future
|
||||||
|
*/
|
||||||
|
private $future;
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
$this->future = new Future;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWhenOnSuccess() {
|
||||||
|
$value = "Resolution value";
|
||||||
|
|
||||||
|
$invoked = 0;
|
||||||
|
$callback = function ($exception, $value) use (&$invoked, &$result) {
|
||||||
|
++$invoked;
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->future->when($callback);
|
||||||
|
|
||||||
|
$this->future->resolve($value);
|
||||||
|
|
||||||
|
$this->assertSame(1, $invoked);
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testWhenOnSuccess
|
||||||
|
*/
|
||||||
|
public function testMultipleWhensOnSuccess() {
|
||||||
|
$value = "Resolution value";
|
||||||
|
|
||||||
|
$invoked = 0;
|
||||||
|
$callback = function ($exception, $value) use (&$invoked, &$result) {
|
||||||
|
++$invoked;
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->future->when($callback);
|
||||||
|
$this->future->when($callback);
|
||||||
|
$this->future->when($callback);
|
||||||
|
|
||||||
|
$this->future->resolve($value);
|
||||||
|
|
||||||
|
$this->assertSame(3, $invoked);
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testWhenOnSuccess
|
||||||
|
*/
|
||||||
|
public function testWhenAfterSuccess() {
|
||||||
|
$value = "Resolution value";
|
||||||
|
|
||||||
|
$invoked = 0;
|
||||||
|
$callback = function ($exception, $value) use (&$invoked, &$result) {
|
||||||
|
++$invoked;
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->future->resolve($value);
|
||||||
|
|
||||||
|
$this->future->when($callback);
|
||||||
|
|
||||||
|
$this->assertSame(1, $invoked);
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testWhenAfterSuccess
|
||||||
|
*/
|
||||||
|
public function testMultipleWhenAfterSuccess() {
|
||||||
|
$value = "Resolution value";
|
||||||
|
|
||||||
|
$invoked = 0;
|
||||||
|
$callback = function ($exception, $value) use (&$invoked, &$result) {
|
||||||
|
++$invoked;
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->future->resolve($value);
|
||||||
|
|
||||||
|
$this->future->when($callback);
|
||||||
|
$this->future->when($callback);
|
||||||
|
$this->future->when($callback);
|
||||||
|
|
||||||
|
$this->assertSame(3, $invoked);
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testWhenOnSuccess
|
||||||
|
*/
|
||||||
|
public function testWhenThrowingForwardsToLoopHandlerOnSuccess() {
|
||||||
|
Loop::execute(function () use (&$invoked) {
|
||||||
|
$invoked = 0;
|
||||||
|
$expected = new \Exception;
|
||||||
|
|
||||||
|
Loop::setErrorHandler(function ($exception) use (&$invoked, $expected) {
|
||||||
|
++$invoked;
|
||||||
|
$this->assertSame($expected, $exception);
|
||||||
|
});
|
||||||
|
|
||||||
|
$callback = function () use ($expected) {
|
||||||
|
throw $expected;
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->future->when($callback);
|
||||||
|
|
||||||
|
$this->future->resolve($expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame(1, $invoked);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testWhenAfterSuccess
|
||||||
|
*/
|
||||||
|
public function testWhenThrowingForwardsToLoopHandlerAfterSuccess() {
|
||||||
|
Loop::execute(function () use (&$invoked) {
|
||||||
|
$invoked = 0;
|
||||||
|
$expected = new \Exception;
|
||||||
|
|
||||||
|
Loop::setErrorHandler(function ($exception) use (&$invoked, $expected) {
|
||||||
|
++$invoked;
|
||||||
|
$this->assertSame($expected, $exception);
|
||||||
|
});
|
||||||
|
|
||||||
|
$callback = function () use ($expected) {
|
||||||
|
throw $expected;
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->future->resolve($expected);
|
||||||
|
|
||||||
|
$this->future->when($callback);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame(1, $invoked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWhenOnFail() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$invoked = 0;
|
||||||
|
$callback = function ($exception, $value) use (&$invoked, &$result) {
|
||||||
|
++$invoked;
|
||||||
|
$result = $exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->future->when($callback);
|
||||||
|
|
||||||
|
$this->future->fail($exception);
|
||||||
|
|
||||||
|
$this->assertSame(1, $invoked);
|
||||||
|
$this->assertSame($exception, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testWhenOnFail
|
||||||
|
*/
|
||||||
|
public function testMultipleWhensOnFail() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$invoked = 0;
|
||||||
|
$callback = function ($exception, $value) use (&$invoked, &$result) {
|
||||||
|
++$invoked;
|
||||||
|
$result = $exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->future->when($callback);
|
||||||
|
$this->future->when($callback);
|
||||||
|
$this->future->when($callback);
|
||||||
|
|
||||||
|
$this->future->fail($exception);
|
||||||
|
|
||||||
|
$this->assertSame(3, $invoked);
|
||||||
|
$this->assertSame($exception, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testWhenOnFail
|
||||||
|
*/
|
||||||
|
public function testWhenAfterFail() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$invoked = 0;
|
||||||
|
$callback = function ($exception, $value) use (&$invoked, &$result) {
|
||||||
|
++$invoked;
|
||||||
|
$result = $exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->future->fail($exception);
|
||||||
|
|
||||||
|
$this->future->when($callback);
|
||||||
|
|
||||||
|
$this->assertSame(1, $invoked);
|
||||||
|
$this->assertSame($exception, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testWhenAfterFail
|
||||||
|
*/
|
||||||
|
public function testMultipleWhensAfterFail() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$invoked = 0;
|
||||||
|
$callback = function ($exception, $value) use (&$invoked, &$result) {
|
||||||
|
++$invoked;
|
||||||
|
$result = $exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->future->fail($exception);
|
||||||
|
|
||||||
|
$this->future->when($callback);
|
||||||
|
$this->future->when($callback);
|
||||||
|
$this->future->when($callback);
|
||||||
|
|
||||||
|
$this->assertSame(3, $invoked);
|
||||||
|
$this->assertSame($exception, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testWhenOnSuccess
|
||||||
|
*/
|
||||||
|
public function testWhenThrowingForwardsToLoopHandlerOnFail() {
|
||||||
|
Loop::execute(function () use (&$invoked) {
|
||||||
|
$invoked = 0;
|
||||||
|
$expected = new \Exception;
|
||||||
|
|
||||||
|
Loop::setErrorHandler(function ($exception) use (&$invoked, $expected) {
|
||||||
|
++$invoked;
|
||||||
|
$this->assertSame($expected, $exception);
|
||||||
|
});
|
||||||
|
|
||||||
|
$callback = function () use ($expected) {
|
||||||
|
throw $expected;
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->future->when($callback);
|
||||||
|
|
||||||
|
$this->future->fail(new \Exception);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame(1, $invoked);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testWhenOnSuccess
|
||||||
|
*/
|
||||||
|
public function testWhenThrowingForwardsToLoopHandlerAfterFail() {
|
||||||
|
Loop::execute(function () use (&$invoked) {
|
||||||
|
$invoked = 0;
|
||||||
|
$expected = new \Exception;
|
||||||
|
|
||||||
|
Loop::setErrorHandler(function ($exception) use (&$invoked, $expected) {
|
||||||
|
++$invoked;
|
||||||
|
$this->assertSame($expected, $exception);
|
||||||
|
});
|
||||||
|
|
||||||
|
$callback = function () use ($expected) {
|
||||||
|
throw $expected;
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->future->fail(new \Exception);
|
||||||
|
|
||||||
|
$this->future->when($callback);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame(1, $invoked);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testResolveWithAwaitableBeforeWhen() {
|
||||||
|
$awaitable = $this->getMockBuilder(Awaitable::class)->getMock();
|
||||||
|
|
||||||
|
$awaitable->expects($this->once())
|
||||||
|
->method("when")
|
||||||
|
->with($this->callback("is_callable"));
|
||||||
|
|
||||||
|
$this->future->resolve($awaitable);
|
||||||
|
|
||||||
|
$this->future->when(function () {});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testResolveWithAwaitableAfterWhen() {
|
||||||
|
$awaitable = $this->getMockBuilder(Awaitable::class)->getMock();
|
||||||
|
|
||||||
|
$awaitable->expects($this->once())
|
||||||
|
->method("when")
|
||||||
|
->with($this->callback("is_callable"));
|
||||||
|
|
||||||
|
$this->future->when(function () {});
|
||||||
|
|
||||||
|
$this->future->resolve($awaitable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \LogicException
|
||||||
|
*/
|
||||||
|
public function testDoubleResolve() {
|
||||||
|
$this->future->resolve();
|
||||||
|
$this->future->resolve();
|
||||||
|
}
|
||||||
|
}
|
84
test/PipeTest.php
Normal file
84
test/PipeTest.php
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Amp\Test;
|
||||||
|
|
||||||
|
use Amp;
|
||||||
|
use Amp\Failure;
|
||||||
|
use Amp\Success;
|
||||||
|
use Interop\Async\Awaitable;
|
||||||
|
|
||||||
|
class PipeTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
public function testSuccessfulAwaitable() {
|
||||||
|
$invoked = false;
|
||||||
|
$callback = function ($value) use (&$invoked) {
|
||||||
|
$invoked = true;
|
||||||
|
return $value + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
$awaitable = new Success($value);
|
||||||
|
|
||||||
|
$awaitable = Amp\pipe($awaitable, $callback);
|
||||||
|
$this->assertInstanceOf(Awaitable::class, $awaitable);
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
$awaitable->when($callback);
|
||||||
|
|
||||||
|
$this->assertTrue($invoked);
|
||||||
|
$this->assertSame($value + 1, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFailedAwaitable() {
|
||||||
|
$invoked = false;
|
||||||
|
$callback = function ($value) use (&$invoked) {
|
||||||
|
$invoked = true;
|
||||||
|
return $value + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$awaitable = new Failure($exception);
|
||||||
|
|
||||||
|
$awaitable = Amp\pipe($awaitable, $callback);
|
||||||
|
$this->assertInstanceOf(Awaitable::class, $awaitable);
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
$awaitable->when($callback);
|
||||||
|
|
||||||
|
$this->assertFalse($invoked);
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testSuccessfulAwaitable
|
||||||
|
*/
|
||||||
|
public function testCallbackThrowing() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
$callback = function ($value) use (&$invoked, $exception) {
|
||||||
|
$invoked = true;
|
||||||
|
throw $exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
$awaitable = new Success($value);
|
||||||
|
|
||||||
|
$awaitable = Amp\pipe($awaitable, $callback);
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
$awaitable->when($callback);
|
||||||
|
|
||||||
|
$this->assertTrue($invoked);
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
}
|
||||||
|
}
|
26
test/RethrowTest.php
Normal file
26
test/RethrowTest.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Amp\Test;
|
||||||
|
|
||||||
|
use Amp;
|
||||||
|
use Amp\Failure;
|
||||||
|
use Interop\Async\Loop;
|
||||||
|
|
||||||
|
class RethrowTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
public function testWaitOnPendingAwaitable() {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Loop::execute(function () use ($exception) {
|
||||||
|
$awaitable = new Failure($exception);
|
||||||
|
|
||||||
|
Amp\rethrow($awaitable);
|
||||||
|
});
|
||||||
|
} catch (\Exception $reason) {
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->fail('Failed awaitable reason should be thrown from loop');
|
||||||
|
}
|
||||||
|
}
|
106
test/SomeTest.php
Normal file
106
test/SomeTest.php
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Amp\Test;
|
||||||
|
|
||||||
|
use Amp;
|
||||||
|
use Amp\Failure;
|
||||||
|
use Amp\MultiReasonException;
|
||||||
|
use Amp\Pause;
|
||||||
|
use Amp\Success;
|
||||||
|
use Interop\Async\Loop;
|
||||||
|
|
||||||
|
class SomeTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
/**
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testEmptyArray() {
|
||||||
|
Amp\some([], 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSuccessfulAwaitablesArray() {
|
||||||
|
$awaitables = [new Success(1), new Success(2), new Success(3)];
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Amp\some($awaitables, 2)->when($callback);
|
||||||
|
|
||||||
|
$this->assertSame([1, 2], $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSuccessfulAndFailedAwaitablesArray() {
|
||||||
|
$awaitables = [new Failure(new \Exception), new Failure(new \Exception), new Success(3)];
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Amp\some($awaitables, 1)->when($callback);
|
||||||
|
|
||||||
|
$this->assertSame([2 => 3], $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTooManyFailedAwaitables() {
|
||||||
|
$awaitables = [new Failure(new \Exception), new Failure(new \Exception), new Success(3)];
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
Amp\some($awaitables, 2)->when($callback);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(MultiReasonException::class, $reason);
|
||||||
|
|
||||||
|
$reasons = $reason->getReasons();
|
||||||
|
|
||||||
|
foreach ($reasons as $reason) {
|
||||||
|
$this->assertInstanceOf(\Exception::class, $reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPendingAwatiablesArray() {
|
||||||
|
Loop::execute(function () use (&$result) {
|
||||||
|
$awaitables = [
|
||||||
|
new Pause(0.2, 1),
|
||||||
|
new Pause(0.3, 2),
|
||||||
|
new Pause(0.1, 3),
|
||||||
|
];
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Amp\some($awaitables, 2)->when($callback);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertEquals([0 => 1, 2 => 3], $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testArrayKeysPreserved() {
|
||||||
|
$expected = ['one' => 1, 'two' => 2, 'three' => 3];
|
||||||
|
|
||||||
|
Loop::execute(function () use (&$result) {
|
||||||
|
$awaitables = [
|
||||||
|
'one' => new Pause(0.2, 1),
|
||||||
|
'two' => new Pause(0.3, 2),
|
||||||
|
'three' => new Pause(0.1, 3),
|
||||||
|
];
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Amp\some($awaitables, 3)->when($callback);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testNonAwaitable() {
|
||||||
|
Amp\some([1], 1);
|
||||||
|
}
|
||||||
|
}
|
58
test/SuccessTest.php
Normal file
58
test/SuccessTest.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Amp\Test;
|
||||||
|
|
||||||
|
use Amp\Success;
|
||||||
|
use Interop\Async\Awaitable;
|
||||||
|
use Interop\Async\Loop;
|
||||||
|
|
||||||
|
class SuccessTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
/**
|
||||||
|
* @expectedException \LogicException
|
||||||
|
*/
|
||||||
|
public function testConstructWithNonException() {
|
||||||
|
$failure = new Success($this->getMockBuilder(Awaitable::class)->getMock());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWhen() {
|
||||||
|
$value = "Resolution value";
|
||||||
|
|
||||||
|
$invoked = 0;
|
||||||
|
$callback = function ($exception, $value) use (&$invoked, &$result) {
|
||||||
|
++$invoked;
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
$success = new Success($value);
|
||||||
|
|
||||||
|
$success->when($callback);
|
||||||
|
|
||||||
|
$this->assertSame(1, $invoked);
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testWhen
|
||||||
|
*/
|
||||||
|
public function testWhenThrowingForwardsToLoopHandlerOnSuccess() {
|
||||||
|
Loop::execute(function () use (&$invoked) {
|
||||||
|
$invoked = 0;
|
||||||
|
$expected = new \Exception;
|
||||||
|
|
||||||
|
Loop::setErrorHandler(function ($exception) use (&$invoked, $expected) {
|
||||||
|
++$invoked;
|
||||||
|
$this->assertSame($expected, $exception);
|
||||||
|
});
|
||||||
|
|
||||||
|
$callback = function () use ($expected) {
|
||||||
|
throw $expected;
|
||||||
|
};
|
||||||
|
|
||||||
|
$success = new Success;
|
||||||
|
|
||||||
|
$success->when($callback);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame(1, $invoked);
|
||||||
|
}
|
||||||
|
}
|
92
test/TimeoutTest.php
Normal file
92
test/TimeoutTest.php
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Amp\Test;
|
||||||
|
|
||||||
|
use Amp;
|
||||||
|
use Amp\Failure;
|
||||||
|
use Amp\Pause;
|
||||||
|
use Amp\Success;
|
||||||
|
use Interop\Async\Awaitable;
|
||||||
|
use Interop\Async\Loop;
|
||||||
|
|
||||||
|
class TimeoutTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
public function testSuccessfulAwaitable() {
|
||||||
|
Loop::execute(function () {
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
$awaitable = new Success($value);
|
||||||
|
|
||||||
|
$awaitable = Amp\timeout($awaitable, 100);
|
||||||
|
$this->assertInstanceOf(Awaitable::class, $awaitable);
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
$awaitable->when($callback);
|
||||||
|
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFailedAwaitable() {
|
||||||
|
Loop::execute(function () {
|
||||||
|
$exception = new \Exception;
|
||||||
|
|
||||||
|
$awaitable = new Failure($exception);
|
||||||
|
|
||||||
|
$awaitable = Amp\timeout($awaitable, 100);
|
||||||
|
$this->assertInstanceOf(Awaitable::class, $awaitable);
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
$awaitable->when($callback);
|
||||||
|
|
||||||
|
$this->assertSame($exception, $reason);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testSuccessfulAwaitable
|
||||||
|
*/
|
||||||
|
public function testFastPending() {
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
Loop::execute(function () use (&$result, $value) {
|
||||||
|
$awaitable = new Pause(50, $value);
|
||||||
|
|
||||||
|
$awaitable = Amp\timeout($awaitable, 100);
|
||||||
|
$this->assertInstanceOf(Awaitable::class, $awaitable);
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$result) {
|
||||||
|
$result = $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
$awaitable->when($callback);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testSuccessfulAwaitable
|
||||||
|
*/
|
||||||
|
public function testSlowPending() {
|
||||||
|
Loop::execute(function () use (&$reason) {
|
||||||
|
$awaitable = new Pause(200);
|
||||||
|
|
||||||
|
$awaitable = Amp\timeout($awaitable, 100);
|
||||||
|
$this->assertInstanceOf(Awaitable::class, $awaitable);
|
||||||
|
|
||||||
|
$callback = function ($exception, $value) use (&$reason) {
|
||||||
|
$reason = $exception;
|
||||||
|
};
|
||||||
|
|
||||||
|
$awaitable->when($callback);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->assertInstanceOf(Amp\TimeoutException::class, $reason);
|
||||||
|
}
|
||||||
|
}
|
65
test/WaitTest.php
Normal file
65
test/WaitTest.php
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Amp\Test;
|
||||||
|
|
||||||
|
use Amp;
|
||||||
|
use Amp\Failure;
|
||||||
|
use Amp\Future;
|
||||||
|
use Amp\Pause;
|
||||||
|
use Amp\Success;
|
||||||
|
use Interop\Async\Loop;
|
||||||
|
|
||||||
|
class WaitTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
public function testWaitOnSuccessfulAwaitable()
|
||||||
|
{
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
$awaitable = new Success($value);
|
||||||
|
|
||||||
|
$result = Amp\wait($awaitable);
|
||||||
|
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWaitOnFailedAwaitable()
|
||||||
|
{
|
||||||
|
$exception = new \Exception();
|
||||||
|
|
||||||
|
$awaitable = new Failure($exception);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = Amp\wait($awaitable);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->assertSame($exception, $e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->fail('Rejection exception should be thrown from wait().');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testWaitOnSuccessfulAwaitable
|
||||||
|
*/
|
||||||
|
public function testWaitOnPendingAwaitable()
|
||||||
|
{
|
||||||
|
Loop::execute(function () {
|
||||||
|
$value = 1;
|
||||||
|
|
||||||
|
$awaitable = new Pause(100, $value);
|
||||||
|
|
||||||
|
$result = Amp\wait($awaitable);
|
||||||
|
|
||||||
|
$this->assertSame($value, $result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \LogicException
|
||||||
|
*/
|
||||||
|
public function testAwaitableWithNoResolutionPathThrowsException()
|
||||||
|
{
|
||||||
|
$awaitable = new Future;
|
||||||
|
|
||||||
|
$result = Amp\wait($awaitable);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user