mirror of
https://github.com/danog/amp.git
synced 2025-01-22 05:11:42 +01:00
Expose boolean AMP_DEBUG for performance tuning
Amp Future instances double both as Promisor and Promise implementations when AMP_DEBUG is defined and set to false. This switch allows private Promise resolution safety by default at the expense of performance. Amp applications should set AMP_DEBUG to false in production environments to maximize performance.
This commit is contained in:
parent
0973bba5ef
commit
3af013d418
112
lib/Future.php
112
lib/Future.php
@ -2,112 +2,8 @@
|
||||
|
||||
namespace Amp;
|
||||
|
||||
class Future implements Promisor, Promise {
|
||||
private $isResolved = false;
|
||||
private $watchers = [];
|
||||
private $whens = [];
|
||||
private $error;
|
||||
private $result;
|
||||
|
||||
/**
|
||||
* Retrieve the Promise placeholder for this deferred value
|
||||
*
|
||||
* This implementation acts as both Promisor and Promise so we simply return the
|
||||
* current instance. If users require a Promisor that can only be resolved by code
|
||||
* holding a reference to the Promisor they may instead use Amp\PrivateFuture.
|
||||
*
|
||||
* @return \Amp\Promise
|
||||
*/
|
||||
public function promise() {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function when(callable $func) {
|
||||
if ($this->isResolved) {
|
||||
$func($this->error, $this->result);
|
||||
} else {
|
||||
$this->whens[] = $func;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function watch(callable $func) {
|
||||
if (!$this->isResolved) {
|
||||
$this->watchers[] = $func;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws \LogicException if the promise has already resolved
|
||||
*/
|
||||
public function update($progress) {
|
||||
if ($this->isResolved) {
|
||||
throw new \LogicException(
|
||||
'Cannot update resolved promise'
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($this->watchers as $watcher) {
|
||||
$watcher($progress);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws \LogicException if the promise has already resolved or the result is the current instance
|
||||
*/
|
||||
public function succeed($result = null) {
|
||||
if ($this->isResolved) {
|
||||
throw new \LogicException(
|
||||
'Promise already resolved'
|
||||
);
|
||||
} elseif ($result === $this) {
|
||||
throw new \LogicException(
|
||||
'A Promise cannot act as its own resolution result'
|
||||
);
|
||||
} elseif ($result instanceof Promise) {
|
||||
$result->when(function(\Exception $error = null, $result = null) {
|
||||
if ($error) {
|
||||
$this->fail($error);
|
||||
} else {
|
||||
$this->succeed($result);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$this->isResolved = true;
|
||||
$this->result = $result;
|
||||
$error = null;
|
||||
foreach ($this->whens as $when) {
|
||||
$when($error, $result);
|
||||
}
|
||||
$this->whens = $this->watchers = [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws \LogicException if the promise has already resolved
|
||||
*/
|
||||
public function fail(\Exception $error) {
|
||||
if ($this->isResolved) {
|
||||
throw new \LogicException(
|
||||
'Promise already resolved'
|
||||
);
|
||||
}
|
||||
|
||||
$this->isResolved = true;
|
||||
$this->error = $error;
|
||||
$result = null;
|
||||
|
||||
foreach ($this->whens as $when) {
|
||||
$when($error, $result);
|
||||
}
|
||||
$this->whens = $this->watchers = [];
|
||||
}
|
||||
if (!defined("AMP_DEBUG") || \AMP_DEBUG) {
|
||||
final class Future implements Promisor { use PrivatePromisor; }
|
||||
} else {
|
||||
final class Future implements Promisor, Promise { use PublicPromisor; }
|
||||
}
|
||||
|
81
lib/Placeholder.php
Normal file
81
lib/Placeholder.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Amp;
|
||||
|
||||
/**
|
||||
* A placeholder value that will be resolved at some point in the future by
|
||||
* the Promisor that created it.
|
||||
*/
|
||||
trait Placeholder {
|
||||
private $isResolved = false;
|
||||
private $watchers = [];
|
||||
private $whens = [];
|
||||
private $error;
|
||||
private $result;
|
||||
|
||||
/**
|
||||
* Notify the $func callback when the promise resolves (whether successful or not)
|
||||
*
|
||||
* @param callable $func
|
||||
* @return self
|
||||
*/
|
||||
public function when(callable $func) {
|
||||
if ($this->isResolved) {
|
||||
call_user_func($func, $this->error, $this->result);
|
||||
} else {
|
||||
$this->whens[] = $func;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the $func callback when resolution progress events are emitted
|
||||
*
|
||||
* @param callable $func
|
||||
* @return self
|
||||
*/
|
||||
public function watch(callable $func) {
|
||||
if (!$this->isResolved) {
|
||||
$this->watchers[] = $func;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function update($progress) {
|
||||
if ($this->isResolved) {
|
||||
throw new \LogicException(
|
||||
"Cannot update resolved promise"
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($this->watchers as $watcher) {
|
||||
call_user_func($watcher, $progress);
|
||||
}
|
||||
}
|
||||
|
||||
private function resolve(\Exception $error = null, $result = null) {
|
||||
if ($this->isResolved) {
|
||||
throw new \LogicException(
|
||||
"Promise already resolved"
|
||||
);
|
||||
} elseif ($result === $this) {
|
||||
throw new \LogicException(
|
||||
"A Promise cannot act as its own resolution result"
|
||||
);
|
||||
} elseif ($result instanceof Promise) {
|
||||
$result->when(function($error, $result) {
|
||||
$this->resolve($error, $result);
|
||||
});
|
||||
} else {
|
||||
$this->isResolved = true;
|
||||
$this->error = $error;
|
||||
$this->result = $result;
|
||||
foreach ($this->whens as $when) {
|
||||
call_user_func($when, $error, $result);
|
||||
}
|
||||
$this->whens = $this->watchers = [];
|
||||
}
|
||||
}
|
||||
}
|
@ -3,12 +3,11 @@
|
||||
namespace Amp;
|
||||
|
||||
/**
|
||||
* A PrivateFuture creates a read-only Promise that may *only* be fulfilled by holders of the
|
||||
* actual PrivateFuture instance. This provides an additional layer of API protection over
|
||||
* the standard Future Promisor implementation whose Promise can be resolved by any code
|
||||
* holding a reference to the Future instance.
|
||||
* A PrivatePromisor creates read-only Promise instances that can only be
|
||||
* resolved by holders of the PrivatePromisor instance. This creates an
|
||||
* additional layer of API protection beyond the PublicPromisor.
|
||||
*/
|
||||
class PrivateFuture implements Promisor {
|
||||
trait PrivatePromisor {
|
||||
private $resolver;
|
||||
private $updater;
|
||||
private $promise;
|
||||
@ -27,7 +26,7 @@ class PrivateFuture implements Promisor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Promise future fulfillment via a temporary placeholder value
|
||||
* Promise future fulfillment of the returned placeholder value
|
||||
*
|
||||
* @return \Amp\Promise
|
||||
*/
|
||||
@ -46,7 +45,7 @@ class PrivateFuture implements Promisor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the promised value as a success
|
||||
* Resolve the associated promise placeholder as a success
|
||||
*
|
||||
* @param mixed $result
|
||||
* @return void
|
||||
@ -56,7 +55,7 @@ class PrivateFuture implements Promisor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the promised value as a failure
|
||||
* Resolve the associated promise placeholder as a failure
|
||||
*
|
||||
* @param \Exception $error
|
||||
* @return void
|
@ -16,10 +16,10 @@ class PromiseStream {
|
||||
*/
|
||||
public function __construct(Promise $watchedPromise) {
|
||||
$this->state = self::WAIT;
|
||||
$this->promisors[] = new PrivateFuture;
|
||||
$this->promisors[] = new Future;
|
||||
$watchedPromise->watch(function($data) {
|
||||
$this->state = self::NOTIFY;
|
||||
$this->promisors[$this->index + 1] = new PrivateFuture;
|
||||
$this->promisors[$this->index + 1] = new Future;
|
||||
$this->promisors[$this->index++]->succeed($data);
|
||||
});
|
||||
$watchedPromise->when(function($error, $result) {
|
||||
|
56
lib/PublicPromisor.php
Normal file
56
lib/PublicPromisor.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Amp;
|
||||
|
||||
trait PublicPromisor {
|
||||
use Placeholder;
|
||||
|
||||
/**
|
||||
* Promise future fulfillment via a temporary placeholder value
|
||||
*
|
||||
* This implementation acts as both Promisor and Promise so we simply return the
|
||||
* current instance.
|
||||
*
|
||||
* @return \Amp\Promise
|
||||
*/
|
||||
public function promise() {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update watchers of progress resolving the promised value
|
||||
*
|
||||
* @param mixed $progress
|
||||
* @return void
|
||||
*/
|
||||
public function update($progress) {
|
||||
if ($this->isResolved) {
|
||||
throw new \LogicException(
|
||||
'Cannot update resolved promise'
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($this->watchers as $watcher) {
|
||||
$watcher($progress);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the promised value as a success
|
||||
*
|
||||
* @param mixed $result
|
||||
* @return void
|
||||
*/
|
||||
public function succeed($result = null) {
|
||||
return $this->resolve($error = null, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the promised value as a failure
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fail(\Exception $error) {
|
||||
return $this->resolve($error, $result = null);
|
||||
}
|
||||
}
|
@ -7,75 +7,5 @@ namespace Amp;
|
||||
* the Promisor that created it.
|
||||
*/
|
||||
class Unresolved implements Promise {
|
||||
private $isResolved = false;
|
||||
private $watchers = [];
|
||||
private $whens = [];
|
||||
private $error;
|
||||
private $result;
|
||||
|
||||
/**
|
||||
* Notify the $func callback when the promise resolves (whether successful or not)
|
||||
*
|
||||
* @param callable $func
|
||||
* @return self
|
||||
*/
|
||||
public function when(callable $func) {
|
||||
if ($this->isResolved) {
|
||||
call_user_func($func, $this->error, $this->result);
|
||||
} else {
|
||||
$this->whens[] = $func;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the $func callback when resolution progress events are emitted
|
||||
*
|
||||
* @param callable $func
|
||||
* @return self
|
||||
*/
|
||||
public function watch(callable $func) {
|
||||
if (!$this->isResolved) {
|
||||
$this->watchers[] = $func;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function resolve(\Exception $error = null, $result = null) {
|
||||
if ($this->isResolved) {
|
||||
throw new \LogicException(
|
||||
"Promise already resolved"
|
||||
);
|
||||
} elseif ($result === $this) {
|
||||
throw new \LogicException(
|
||||
"A Promise cannot act as its own resolution result"
|
||||
);
|
||||
} elseif ($result instanceof Promise) {
|
||||
$result->when(function($error, $result) {
|
||||
$this->resolve($error, $result);
|
||||
});
|
||||
} else {
|
||||
$this->isResolved = true;
|
||||
$this->error = $error;
|
||||
$this->result = $result;
|
||||
foreach ($this->whens as $when) {
|
||||
call_user_func($when, $error, $result);
|
||||
}
|
||||
$this->whens = $this->watchers = [];
|
||||
}
|
||||
}
|
||||
|
||||
private function update($progress) {
|
||||
if ($this->isResolved) {
|
||||
throw new \LogicException(
|
||||
"Cannot update resolved promise"
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($this->watchers as $watcher) {
|
||||
call_user_func($watcher, $progress);
|
||||
}
|
||||
}
|
||||
use Placeholder;
|
||||
}
|
||||
|
@ -189,9 +189,7 @@ function all(array $promises) {
|
||||
});
|
||||
}
|
||||
|
||||
// We can return $promisor directly because the Future Promisor implementation
|
||||
// also implements Promise for convenience
|
||||
return $promisor;
|
||||
return $promisor->promise();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -243,9 +241,7 @@ function some(array $promises) {
|
||||
});
|
||||
}
|
||||
|
||||
// We can return $promisor directly because the Future Promisor implementation
|
||||
// also implements Promise for convenience
|
||||
return $promisor;
|
||||
return $promisor->promise();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -282,9 +278,7 @@ function any(array $promises) {
|
||||
});
|
||||
}
|
||||
|
||||
// We can return $promisor directly because the Future Promisor implementation
|
||||
// also implements Promise for convenience
|
||||
return $promisor;
|
||||
return $promisor->promise();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -323,9 +317,7 @@ function first(array $promises) {
|
||||
});
|
||||
}
|
||||
|
||||
// We can return $promisor directly because the Future Promisor implementation
|
||||
// also implements Promise for convenience
|
||||
return $promisor;
|
||||
return $promisor->promise();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -365,9 +357,7 @@ function map(array $promises, callable $functor) {
|
||||
});
|
||||
}
|
||||
|
||||
// We can return $promisor directly because the Future Promisor implementation
|
||||
// also implements Promise for convenience
|
||||
return $promisor;
|
||||
return $promisor->promise();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -410,9 +400,7 @@ function filter(array $promises, callable $functor) {
|
||||
});
|
||||
}
|
||||
|
||||
// We can return $promisor directly because the Future Promisor implementation
|
||||
// also implements Promise for convenience
|
||||
return $promisor;
|
||||
return $promisor->promise();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,4 +1,4 @@
|
||||
<phpunit bootstrap="./vendor/autoload.php" colors="true">
|
||||
<phpunit bootstrap="./test/bootstrap.php" colors="true">
|
||||
<testsuites>
|
||||
<testsuite name="Tests">
|
||||
<directory>./test</directory>
|
||||
|
@ -5,7 +5,7 @@ namespace Amp\Test;
|
||||
use Amp\NativeReactor;
|
||||
use Amp\Success;
|
||||
use Amp\Failure;
|
||||
use Amp\PrivateFuture;
|
||||
use Amp\Future;
|
||||
use Amp\PromiseStream;
|
||||
|
||||
class FunctionsTest extends \PHPUnit_Framework_TestCase {
|
||||
@ -210,7 +210,7 @@ class FunctionsTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
public function testCoroutineResolutionBuffersYieldedPromiseStream() {
|
||||
(new NativeReactor)->run(function($reactor) {
|
||||
$promisor = new PrivateFuture;
|
||||
$promisor = new Future;
|
||||
$reactor->repeat(function($reactor, $watcherId) use (&$i, $promisor) {
|
||||
$i++;
|
||||
$promisor->update($i);
|
||||
@ -231,7 +231,7 @@ class FunctionsTest extends \PHPUnit_Framework_TestCase {
|
||||
*/
|
||||
public function testCoroutineResolutionThrowsOnPromiseStreamBufferFailure() {
|
||||
(new NativeReactor)->run(function($reactor) {
|
||||
$promisor = new PrivateFuture;
|
||||
$promisor = new Future;
|
||||
$reactor->repeat(function($reactor, $watcherId) use (&$i, $promisor) {
|
||||
$promisor->fail(new \Exception("test"));
|
||||
}, 10);
|
||||
|
9
test/PlaceholderPrivateTest.php
Normal file
9
test/PlaceholderPrivateTest.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Amp\Test;
|
||||
|
||||
class PlaceholderPrivateTest extends PlaceholderTest {
|
||||
protected function getPromisor() {
|
||||
return new PromisorPrivateImpl;
|
||||
}
|
||||
}
|
9
test/PlaceholderPublicTest.php
Normal file
9
test/PlaceholderPublicTest.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Amp\Test;
|
||||
|
||||
class PlaceholderPublicTest extends PlaceholderTest {
|
||||
protected function getPromisor() {
|
||||
return new PromisorPublicImpl;
|
||||
}
|
||||
}
|
@ -2,13 +2,13 @@
|
||||
|
||||
namespace Amp\Test;
|
||||
|
||||
use Amp\PrivateFuture;
|
||||
use Amp\Future;
|
||||
use Amp\NativeReactor;
|
||||
|
||||
class UnresolvedTest extends \PHPUnit_Framework_TestCase {
|
||||
abstract class PlaceholderTest {
|
||||
abstract protected function getPromisor();
|
||||
|
||||
public function testWatchInvokesCallbackWithResultIfAlreadySucceeded() {
|
||||
$promisor = new PrivateFuture;
|
||||
$promisor = $this->getPromisor();
|
||||
$promise = $promisor->promise();
|
||||
$promisor->succeed(42);
|
||||
$promise->watch(function($p, $e, $r) {
|
||||
@ -19,7 +19,7 @@ class UnresolvedTest extends \PHPUnit_Framework_TestCase {
|
||||
}
|
||||
|
||||
public function testWatchInvokesCallbackWithErrorIfAlreadyFailed() {
|
||||
$promisor = new PrivateFuture;
|
||||
$promisor = $this->getPromisor();
|
||||
$promise = $promisor->promise();
|
||||
$exception = new \Exception('test');
|
||||
$promisor->fail($exception);
|
||||
@ -35,7 +35,7 @@ class UnresolvedTest extends \PHPUnit_Framework_TestCase {
|
||||
* @expectedExceptionMessage Promise already resolved
|
||||
*/
|
||||
public function testSucceedThrowsIfAlreadyResolved() {
|
||||
$promisor = new PrivateFuture;
|
||||
$promisor = $this->getPromisor();
|
||||
$promisor->succeed(42);
|
||||
$promisor->succeed('zanzibar');
|
||||
}
|
||||
@ -45,7 +45,7 @@ class UnresolvedTest extends \PHPUnit_Framework_TestCase {
|
||||
* @expectedExceptionMessage A Promise cannot act as its own resolution result
|
||||
*/
|
||||
public function testSucceedThrowsIfPromiseIsTheResolutionValue() {
|
||||
$promisor = new PrivateFuture;
|
||||
$promisor = $this->getPromisor();
|
||||
$promise = $promisor->promise();
|
||||
$promisor->succeed($promise);
|
||||
}
|
||||
@ -55,15 +55,15 @@ class UnresolvedTest extends \PHPUnit_Framework_TestCase {
|
||||
* @expectedExceptionMessage Promise already resolved
|
||||
*/
|
||||
public function testFailThrowsIfAlreadyResolved() {
|
||||
$promisor = new PrivateFuture;
|
||||
$promisor = $this->getPromisor();
|
||||
$promisor->succeed(42);
|
||||
$promisor->fail(new \Exception);
|
||||
}
|
||||
|
||||
public function testSucceedingWithPromisePipelinesResult() {
|
||||
(new NativeReactor)->run(function($reactor) {
|
||||
$promisor = new PrivateFuture;
|
||||
$next = new Future;
|
||||
$promisor = $this->getPromisor();
|
||||
$next = $this->getPromisor();
|
||||
|
||||
$reactor->once(function() use ($next) {
|
||||
$next->succeed(42);
|
||||
@ -81,8 +81,8 @@ class UnresolvedTest extends \PHPUnit_Framework_TestCase {
|
||||
*/
|
||||
public function testFailingWithPromisePipelinesResult() {
|
||||
(new NativeReactor)->run(function($reactor) {
|
||||
$promisor = new PrivateFuture;
|
||||
$next = new Future;
|
||||
$promisor = $this->getPromisor();
|
||||
$next = $this->getPromisor();
|
||||
|
||||
$reactor->once(function() use ($next) {
|
||||
$next->fail(new \RuntimeException('fugazi'));
|
||||
@ -92,4 +92,5 @@ class UnresolvedTest extends \PHPUnit_Framework_TestCase {
|
||||
yield $promisor->promise();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Amp\Test;
|
||||
|
||||
use Amp\PrivateFuture;
|
||||
|
||||
class PrivateFutureTest extends PromisorTest {
|
||||
protected function getPromisor() {
|
||||
return new PrivateFuture;
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@ namespace Amp\Test;
|
||||
|
||||
use Amp\PromiseStream;
|
||||
use Amp\NativeReactor;
|
||||
use Amp\PrivateFuture;
|
||||
|
||||
class PromiseStreamTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
@ -14,7 +13,7 @@ class PromiseStreamTest extends \PHPUnit_Framework_TestCase {
|
||||
*/
|
||||
public function testStreamThrowsIfPromiseFails() {
|
||||
(new NativeReactor)->run(function($reactor) {
|
||||
$promisor = new PrivateFuture;
|
||||
$promisor = new PromisorPrivateImpl;
|
||||
$reactor->repeat(function($reactor, $watcherId) use (&$i, $promisor) {
|
||||
$i++;
|
||||
$promisor->update($i);
|
||||
@ -35,7 +34,7 @@ class PromiseStreamTest extends \PHPUnit_Framework_TestCase {
|
||||
* @expectedExceptionMessage Cannot advance stream: previous Promise not yet resolved
|
||||
*/
|
||||
public function testStreamThrowsIfPrematurelyIterated() {
|
||||
$promisor = new PrivateFuture;
|
||||
$promisor = new PromisorPrivateImpl;
|
||||
$stream = (new PromiseStream($promisor->promise()))->stream();
|
||||
$stream->next();
|
||||
}
|
||||
@ -45,7 +44,7 @@ class PromiseStreamTest extends \PHPUnit_Framework_TestCase {
|
||||
* @expectedExceptionMessage Cannot advance stream: subject Promise failed
|
||||
*/
|
||||
public function testStreamThrowsIfIteratedAfterFailure() {
|
||||
$promisor = new PrivateFuture;
|
||||
$promisor = new PromisorPrivateImpl;
|
||||
$promisor->fail(new \Exception("test"));
|
||||
$stream = (new PromiseStream($promisor->promise()))->stream();
|
||||
$stream->next();
|
||||
|
12
test/PromisorPrivateTest.php
Normal file
12
test/PromisorPrivateTest.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Amp\Test;
|
||||
|
||||
use Amp\Promisor;
|
||||
use Amp\Test\PromisorPrivateImpl;
|
||||
|
||||
class PromisorPrivateTest extends PromisorTest {
|
||||
protected function getPromisor() {
|
||||
return new PromisorPrivateImpl;
|
||||
}
|
||||
}
|
@ -2,14 +2,16 @@
|
||||
|
||||
namespace Amp\Test;
|
||||
|
||||
use Amp\Future;
|
||||
use Amp\Promisor;
|
||||
use Amp\Test\PromisorPublicImpl;
|
||||
|
||||
class FutureTest extends PromisorTest {
|
||||
class PromisorPublicTest extends PromisorTest {
|
||||
protected function getPromisor() {
|
||||
return new Future;
|
||||
return new PromisorPublicImpl;
|
||||
}
|
||||
|
||||
public function testPromiseReturnsSelf() {
|
||||
$promisor = new Future;
|
||||
$promisor = new PromisorPublicImpl;
|
||||
$this->assertSame($promisor, $promisor->promise());
|
||||
}
|
||||
}
|
12
test/bootstrap.php
Normal file
12
test/bootstrap.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Amp\Test;
|
||||
|
||||
require __DIR__ . "/../vendor/autoload.php";
|
||||
|
||||
class PromisorPrivateImpl implements \Amp\Promisor {
|
||||
use \Amp\PrivatePromisor;
|
||||
}
|
||||
class PromisorPublicImpl implements \Amp\Promisor, \Amp\Promise {
|
||||
use \Amp\PublicPromisor;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user