1
0
mirror of https://github.com/danog/amp.git synced 2024-11-26 20:15:00 +01:00
amp/src/Test.php

282 lines
8.2 KiB
PHP
Raw Normal View History

2016-10-24 17:08:08 +02:00
<?php
2017-01-07 11:47:58 +01:00
namespace AsyncInterop\Promise;
2016-10-24 17:08:08 +02:00
2017-01-07 11:47:58 +01:00
use AsyncInterop\Promise;
2016-10-24 17:08:08 +02:00
abstract class Test extends \PHPUnit_Framework_TestCase {
private $originalErrorHandler;
2016-10-24 17:08:08 +02:00
/**
2016-12-23 13:14:11 +01:00
* An Promise to use for a test with resolution methods.
* Note that the callables shall take care of the Promise being resolved in any case. Example: The actual implementation delays resolution to the next loop tick. The callables then must run one tick of the loop in order to ensure resolution.
2016-10-24 17:08:08 +02:00
*
2016-12-23 13:14:11 +01:00
* @return array(Promise, callable, callable) where the last two callables are resolving the Promise with a result or a Throwable/Exception respectively
2016-10-24 17:08:08 +02:00
*/
2016-12-23 13:14:11 +01:00
abstract function promise();
2016-10-24 17:08:08 +02:00
function setUp() {
$this->originalErrorHandler = Promise\ErrorHandler::set(function ($e) {
throw $e;
});
}
function tearDown() {
Promise\ErrorHandler::set($this->originalErrorHandler);
}
2016-10-24 17:08:08 +02:00
function provideSuccessValues() {
return [
["string"],
[0],
2016-12-30 21:29:21 +01:00
[~PHP_INT_MAX],
2016-10-24 17:08:08 +02:00
[-1.0],
[true],
[false],
[[]],
[null],
[new \StdClass],
];
}
/** @dataProvider provideSuccessValues */
2016-12-23 13:14:11 +01:00
function testPromiseSucceed($value)
2016-10-24 17:08:08 +02:00
{
2016-12-23 13:14:11 +01:00
list($promise, $succeeder) = $this->promise();
$promise->when(function($e, $v) use (&$invoked, $value) {
2016-10-24 17:08:08 +02:00
$this->assertSame(null, $e);
$this->assertSame($value, $v);
$invoked = true;
});
$succeeder($value);
$this->assertTrue($invoked);
}
/** @dataProvider provideSuccessValues */
2016-12-23 13:14:11 +01:00
function testWhenOnSucceededPromise($value) {
list($promise, $succeeder) = $this->promise();
2016-10-24 17:08:08 +02:00
$succeeder($value);
2016-12-23 13:14:11 +01:00
$promise->when(function($e, $v) use (&$invoked, $value) {
2016-10-24 17:08:08 +02:00
$this->assertSame(null, $e);
$this->assertSame($value, $v);
$invoked = true;
});
$this->assertTrue($invoked);
}
2017-01-07 11:47:58 +01:00
2016-10-24 17:08:08 +02:00
function testSuccessAllWhensExecuted() {
2016-12-23 13:14:11 +01:00
list($promise, $succeeder) = $this->promise();
2016-10-24 17:08:08 +02:00
$invoked = 0;
2017-01-07 11:47:58 +01:00
2016-12-23 13:14:11 +01:00
$promise->when(function($e, $v) use (&$invoked) {
2016-10-24 17:08:08 +02:00
$this->assertSame(null, $e);
$this->assertSame(true, $v);
$invoked++;
});
2016-12-23 13:14:11 +01:00
$promise->when(function($e, $v) use (&$invoked) {
2016-10-24 17:08:08 +02:00
$this->assertSame(null, $e);
$this->assertSame(true, $v);
$invoked++;
});
$succeeder(true);
2016-12-23 13:14:11 +01:00
$promise->when(function($e, $v) use (&$invoked) {
2016-10-24 17:08:08 +02:00
$this->assertSame(null, $e);
$this->assertSame(true, $v);
$invoked++;
});
2016-12-23 13:14:11 +01:00
$promise->when(function($e, $v) use (&$invoked) {
2016-10-24 17:08:08 +02:00
$this->assertSame(null, $e);
$this->assertSame(true, $v);
$invoked++;
});
2017-01-07 11:47:58 +01:00
2016-10-24 17:08:08 +02:00
$this->assertSame(4, $invoked);
}
2016-12-23 13:14:11 +01:00
function testPromiseExceptionFailure() {
list($promise, , $failer) = $this->promise();
$promise->when(function ($e) use (&$invoked) {
2016-10-24 17:08:08 +02:00
$this->assertSame(get_class($e), "RuntimeException");
$invoked = true;
});
$failer(new \RuntimeException);
$this->assertTrue($invoked);
}
2016-12-23 13:14:11 +01:00
function testWhenOnExceptionFailedPromise() {
list($promise, , $failer) = $this->promise();
2016-10-24 17:08:08 +02:00
$failer(new \RuntimeException);
2016-12-23 13:14:11 +01:00
$promise->when(function ($e) use (&$invoked) {
2016-10-24 17:08:08 +02:00
$this->assertSame(get_class($e), "RuntimeException");
$invoked = true;
});
$this->assertTrue($invoked);
}
2017-01-07 11:47:58 +01:00
2016-10-24 17:08:08 +02:00
function testFailureAllWhensExecuted() {
2016-12-23 13:14:11 +01:00
list($promise, , $failer) = $this->promise();
2016-10-24 17:08:08 +02:00
$invoked = 0;
2016-12-23 13:14:11 +01:00
$promise->when(function ($e) use (&$invoked) {
2016-10-24 17:08:08 +02:00
$this->assertSame(get_class($e), "RuntimeException");
$invoked++;
});
2016-12-23 13:14:11 +01:00
$promise->when(function ($e) use (&$invoked) {
2016-10-24 17:08:08 +02:00
$this->assertSame(get_class($e), "RuntimeException");
$invoked++;
});
$failer(new \RuntimeException);
2016-12-23 13:14:11 +01:00
$promise->when(function ($e) use (&$invoked) {
2016-10-24 17:08:08 +02:00
$this->assertSame(get_class($e), "RuntimeException");
$invoked++;
});
2016-12-23 13:14:11 +01:00
$promise->when(function ($e) use (&$invoked) {
2016-10-24 17:08:08 +02:00
$this->assertSame(get_class($e), "RuntimeException");
$invoked++;
});
$this->assertSame(4, $invoked);
}
2016-12-23 13:14:11 +01:00
function testPromiseErrorFailure() {
2016-10-24 17:08:08 +02:00
if (PHP_VERSION_ID < 70000) {
$this->markTestSkipped("Error only exists on PHP 7+");
}
2016-12-23 13:14:11 +01:00
list($promise, , $failer) = $this->promise();
$promise->when(function ($e) use (&$invoked) {
2016-10-24 17:08:08 +02:00
$this->assertSame(get_class($e), "Error");
$invoked = true;
});
$failer(new \Error);
$this->assertTrue($invoked);
}
2016-12-23 13:14:11 +01:00
function testWhenOnErrorFailedPromise() {
2016-10-24 17:08:08 +02:00
if (PHP_VERSION_ID < 70000) {
$this->markTestSkipped("Error only exists on PHP 7+");
}
2016-12-23 13:14:11 +01:00
list($promise, , $failer) = $this->promise();
2016-10-24 17:08:08 +02:00
$failer(new \Error);
2016-12-23 13:14:11 +01:00
$promise->when(function ($e) use (&$invoked) {
2016-10-24 17:08:08 +02:00
$this->assertSame(get_class($e), "Error");
$invoked = true;
});
$this->assertTrue($invoked);
}
2016-12-23 13:14:11 +01:00
/** Implementations MAY fail upon resolution with an Promise, but they definitely MUST NOT return an Promise */
function testPromiseResolutionWithPromise() {
list($success, $succeeder) = $this->promise();
2016-10-24 17:08:08 +02:00
$succeeder(true);
2016-12-23 13:14:11 +01:00
list($promise, $succeeder) = $this->promise();
2016-10-24 17:08:08 +02:00
$ex = false;
try {
$succeeder($success);
} catch (\Throwable $e) {
$ex = true;
} catch (\Exception $e) {
$ex = true;
}
if (!$ex) {
2016-12-23 13:14:11 +01:00
$promise->when(function ($e, $v) use (&$invoked) {
2016-10-24 17:08:08 +02:00
$invoked = true;
2016-12-23 13:14:11 +01:00
$this->assertFalse($v instanceof Promise);
2016-10-24 17:08:08 +02:00
});
$this->assertTrue($invoked);
}
}
function testThrowingInCallback() {
2016-12-23 13:14:11 +01:00
$invoked = 0;
Promise\ErrorHandler::set(function () use (&$invoked) {
2016-12-23 13:14:11 +01:00
$invoked++;
});
2016-12-23 13:14:11 +01:00
list($promise, $succeeder) = $this->promise();
$succeeder(true);
$promise->when(function($e, $v) use (&$invoked, $promise) {
2016-12-23 13:14:11 +01:00
$this->assertSame(null, $e);
$this->assertSame(true, $v);
$invoked++;
2016-10-24 17:08:08 +02:00
2016-12-23 13:14:11 +01:00
throw new \Exception;
2016-10-24 17:08:08 +02:00
});
2016-12-23 13:14:11 +01:00
list($promise, $succeeder) = $this->promise();
$promise->when(function($e, $v) use (&$invoked, $promise) {
2016-12-23 13:14:11 +01:00
$this->assertSame(null, $e);
$this->assertSame(true, $v);
$invoked++;
throw new \Exception;
});
$succeeder(true);
$this->assertEquals(4, $invoked);
Promise\ErrorHandler::set($original);
2016-10-24 17:08:08 +02:00
}
2016-12-29 18:57:42 +01:00
function testThrowingInCallbackOnFailure() {
$invoked = 0;
Promise\ErrorHandler::set(function () use (&$invoked) {
$invoked++;
});
list($promise, , $failer) = $this->promise();
$exception = new \Exception;
$failer($exception);
$promise->when(function($e, $v) use (&$invoked, $exception) {
$this->assertSame($exception, $e);
$this->assertNull($v);
$invoked++;
throw $e;
});
list($promise, , $failer) = $this->promise();
$exception = new \Exception;
$promise->when(function($e, $v) use (&$invoked, $exception) {
$this->assertSame($exception, $e);
$this->assertNull($v);
$invoked++;
throw $e;
});
$failer($exception);
$this->assertEquals(4, $invoked);
}
/**
* @requires PHP 7
*/
2016-12-29 18:57:42 +01:00
function testWeakTypes() {
$invoked = 0;
list($promise, $succeeder) = $this->promise();
$expectedData = "15.24";
$promise->when(function($e, int $v) use (&$invoked, $expectedData) {
$invoked++;
$this->assertSame((int) $expectedData, $v);
});
$succeeder($expectedData);
$promise->when(function($e, int $v) use (&$invoked, $expectedData) {
$invoked++;
$this->assertSame((int) $expectedData, $v);
});
$this->assertEquals(2, $invoked);
}
2016-10-24 17:08:08 +02:00
}