1
0
mirror of https://github.com/danog/amp.git synced 2024-12-11 00:49:48 +01:00
amp/test/PlaceholderTraitTest.php
Niklas Keller c12828081f Fix exceptions bubbling from Coroutine::__destruct
This has been an edge case potentially hiding some exceptions. The tests have been refactored to error if the loop has watchers leaking from one test to another test.
2019-05-31 11:38:02 -05:00

384 lines
9.6 KiB
PHP

<?php
namespace Amp\Test;
use Amp\Loop;
use Amp\Promise;
class Placeholder
{
use \Amp\Internal\Placeholder {
resolve as public;
fail as public;
}
}
class PlaceholderTraitTest extends BaseTest
{
/** @var Placeholder */
private $placeholder;
public function setUp()
{
$this->placeholder = new Placeholder;
}
public function testOnResolveOnSuccess()
{
$value = "Resolution value";
$invoked = 0;
$callback = function ($exception, $value) use (&$invoked, &$result) {
$result = $value;
++$invoked;
};
$this->placeholder->onResolve($callback);
$this->placeholder->resolve($value);
$this->assertSame(1, $invoked);
$this->assertSame($value, $result);
}
/**
* @depends testOnResolveOnSuccess
*/
public function testMultipleOnResolvesOnSuccess()
{
$value = "Resolution value";
$invoked = 0;
$callback = function ($exception, $value) use (&$invoked, &$result) {
$result = $value;
++$invoked;
};
$this->placeholder->onResolve($callback);
$this->placeholder->onResolve($callback);
$this->placeholder->onResolve($callback);
$this->placeholder->resolve($value);
$this->assertSame(3, $invoked);
$this->assertSame($value, $result);
}
/**
* @depends testOnResolveOnSuccess
*/
public function testOnResolveAfterSuccess()
{
$value = "Resolution value";
$invoked = 0;
$callback = function ($exception, $value) use (&$invoked, &$result) {
$result = $value;
++$invoked;
};
$this->placeholder->resolve($value);
$this->placeholder->onResolve($callback);
$this->assertSame(1, $invoked);
$this->assertSame($value, $result);
}
/**
* @depends testOnResolveAfterSuccess
*/
public function testMultipleOnResolveAfterSuccess()
{
$value = "Resolution value";
$invoked = 0;
$callback = function ($exception, $value) use (&$invoked, &$result) {
$result = $value;
++$invoked;
};
$this->placeholder->resolve($value);
$this->placeholder->onResolve($callback);
$this->placeholder->onResolve($callback);
$this->placeholder->onResolve($callback);
$this->assertSame(3, $invoked);
$this->assertSame($value, $result);
}
/**
* @depends testOnResolveOnSuccess
*/
public function testOnResolveThrowingForwardsToLoopHandlerOnSuccess()
{
Loop::run(function () use (&$invoked) {
$invoked = 0;
$expected = new \Exception;
Loop::setErrorHandler(function ($exception) use (&$invoked, $expected) {
$this->assertSame($expected, $exception);
++$invoked;
});
$callback = function () use ($expected) {
throw $expected;
};
$this->placeholder->onResolve($callback);
$this->placeholder->resolve($expected);
});
$this->assertSame(1, $invoked);
}
/**
* @depends testOnResolveAfterSuccess
*/
public function testOnResolveThrowingForwardsToLoopHandlerAfterSuccess()
{
Loop::run(function () use (&$invoked) {
$invoked = 0;
$expected = new \Exception;
Loop::setErrorHandler(function ($exception) use (&$invoked, $expected) {
$this->assertSame($expected, $exception);
++$invoked;
});
$callback = function () use ($expected) {
throw $expected;
};
$this->placeholder->resolve($expected);
$this->placeholder->onResolve($callback);
});
$this->assertSame(1, $invoked);
}
public function testOnResolveOnFail()
{
$exception = new \Exception;
$invoked = 0;
$callback = function ($exception, $value) use (&$invoked, &$result) {
$result = $exception;
++$invoked;
};
$this->placeholder->onResolve($callback);
$this->placeholder->fail($exception);
$this->assertSame(1, $invoked);
$this->assertSame($exception, $result);
}
/**
* @depends testOnResolveOnFail
*/
public function testMultipleOnResolvesOnFail()
{
$exception = new \Exception;
$invoked = 0;
$callback = function ($exception, $value) use (&$invoked, &$result) {
$result = $exception;
++$invoked;
};
$this->placeholder->onResolve($callback);
$this->placeholder->onResolve($callback);
$this->placeholder->onResolve($callback);
$this->placeholder->fail($exception);
$this->assertSame(3, $invoked);
$this->assertSame($exception, $result);
}
/**
* @depends testOnResolveOnFail
*/
public function testOnResolveAfterFail()
{
$exception = new \Exception;
$invoked = 0;
$callback = function ($exception, $value) use (&$invoked, &$result) {
$result = $exception;
++$invoked;
};
$this->placeholder->fail($exception);
$this->placeholder->onResolve($callback);
$this->assertSame(1, $invoked);
$this->assertSame($exception, $result);
}
/**
* @depends testOnResolveAfterFail
*/
public function testMultipleOnResolvesAfterFail()
{
$exception = new \Exception;
$invoked = 0;
$callback = function ($exception, $value) use (&$invoked, &$result) {
$result = $exception;
++$invoked;
};
$this->placeholder->fail($exception);
$this->placeholder->onResolve($callback);
$this->placeholder->onResolve($callback);
$this->placeholder->onResolve($callback);
$this->assertSame(3, $invoked);
$this->assertSame($exception, $result);
}
/**
* @depends testOnResolveOnSuccess
*/
public function testOnResolveThrowingForwardsToLoopHandlerOnFail()
{
Loop::run(function () use (&$invoked) {
$invoked = 0;
$expected = new \Exception;
Loop::setErrorHandler(function ($exception) use (&$invoked, $expected) {
$this->assertSame($expected, $exception);
++$invoked;
});
$callback = function () use ($expected) {
throw $expected;
};
$this->placeholder->onResolve($callback);
$this->placeholder->fail(new \Exception);
});
$this->assertSame(1, $invoked);
}
/**
* @depends testOnResolveOnSuccess
*/
public function testOnResolveThrowingForwardsToLoopHandlerAfterFail()
{
Loop::run(function () use (&$invoked) {
$invoked = 0;
$expected = new \Exception;
Loop::setErrorHandler(function ($exception) use (&$invoked, $expected) {
$this->assertSame($expected, $exception);
++$invoked;
});
$callback = function () use ($expected) {
throw $expected;
};
$this->placeholder->fail(new \Exception);
$this->placeholder->onResolve($callback);
});
$this->assertSame(1, $invoked);
}
public function testResolveWithPromiseBeforeOnResolve()
{
$promise = $this->getMockBuilder(Promise::class)->getMock();
$promise->expects($this->once())
->method("onResolve")
->with($this->callback("is_callable"));
$this->placeholder->resolve($promise);
$this->placeholder->onResolve(function () {
});
}
public function testResolveWithPromiseAfterOnResolve()
{
$promise = $this->getMockBuilder(Promise::class)->getMock();
$promise->expects($this->once())
->method("onResolve")
->with($this->callback("is_callable"));
$this->placeholder->onResolve(function () {
});
$this->placeholder->resolve($promise);
}
/**
* @expectedException \Error
* @expectedExceptionMessage Promise has already been resolved
*/
public function testDoubleResolve()
{
$this->placeholder->resolve();
$this->placeholder->resolve();
}
/**
* @expectedException \Error
* @expectedExceptionMessage Promise has already been resolved
*/
public function testResolveAgainWithinOnResolveCallback()
{
Loop::run(function () {
$this->placeholder->onResolve(function () {
$this->placeholder->resolve();
});
$this->placeholder->resolve();
});
}
public function testOnResolveWithGenerator()
{
$invoked = false;
$this->placeholder->onResolve(function ($exception, $value) use (&$invoked) {
$invoked = true;
return $value;
yield; // Unreachable, but makes function a generator.
});
$this->placeholder->resolve(1);
$this->assertTrue($invoked);
}
/**
* @depends testOnResolveWithGenerator
*/
public function testOnResolveWithGeneratorAfterResolve()
{
$this->placeholder->resolve(1);
$invoked = false;
$this->placeholder->onResolve(function ($exception, $value) use (&$invoked) {
$invoked = true;
return $value;
yield; // Unreachable, but makes function a generator.
});
$this->assertTrue($invoked);
}
}