This commit is contained in:
2022-10-23 01:39:27 +02:00
parent 8c17aab483
commit 1929b84685
4130 changed files with 479334 additions and 0 deletions

2
vendor/react/promise-timer/.gitignore vendored Executable file
View File

@@ -0,0 +1,2 @@
/vendor
/composer.lock

26
vendor/react/promise-timer/.travis.yml vendored Executable file
View File

@@ -0,0 +1,26 @@
language: php
php:
# - 5.3 # requires old distro, see below
- 5.4
- 5.5
- 5.6
- 7.0
- 7.1
- hhvm # ignore errors, see below
# lock distro so new future defaults will not break the build
dist: trusty
matrix:
include:
- php: 5.3
dist: precise
allow_failures:
- php: hhvm
install:
- composer install --no-interaction
script:
- vendor/bin/phpunit --coverage-text

63
vendor/react/promise-timer/CHANGELOG.md vendored Executable file
View File

@@ -0,0 +1,63 @@
# Changelog
## 1.5.1 (2019-03-27)
* Fix: Typo in readme
(#35 by @aak74)
* Improvement: Only include functions file when functions aren't defined
(#36 by @Niko9911)
## 1.5.0 (2018-06-13)
* Feature: Improve memory consumption by cleaning up garbage references to pending promise without canceller.
(#34 by @clue)
## 1.4.0 (2018-06-11)
* Feature: Improve memory consumption by cleaning up garbage references.
(#33 by @clue)
## 1.3.0 (2018-04-24)
* Feature: Improve memory consumption by cleaning up unneeded references.
(#32 by @clue)
## 1.2.1 (2017-12-22)
* README improvements
(#28 by @jsor)
* Improve test suite by adding forward compatiblity with PHPUnit 6 and
fix test suite forward compatibility with upcoming EventLoop releases
(#30 and #31 by @clue)
## 1.2.0 (2017-08-08)
* Feature: Only start timers if input Promise is still pending and
return a settled output promise if the input is already settled.
(#25 by @clue)
* Feature: Cap minimum timer interval at 1µs across all versions
(#23 by @clue)
* Feature: Forward compatibility with EventLoop v1.0 and v0.5
(#27 by @clue)
* Improve test suite by adding PHPUnit to require-dev and
lock Travis distro so new defaults will not break the build
(#24 and #26 by @clue)
## 1.1.1 (2016-12-27)
* Improve test suite to use PSR-4 autoloader and proper namespaces.
(#21 by @clue)
## 1.1.0 (2016-02-29)
* Feature: Support promise cancellation for all timer primitives
(#18 by @clue)
## 1.0.0 (2015-09-29)
* First tagged release

21
vendor/react/promise-timer/LICENSE vendored Executable file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Christian Lück
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

372
vendor/react/promise-timer/README.md vendored Executable file
View File

@@ -0,0 +1,372 @@
# PromiseTimer
[![Build Status](https://travis-ci.org/reactphp/promise-timer.svg?branch=master)](https://travis-ci.org/reactphp/promise-timer)
A trivial implementation of timeouts for `Promise`s, built on top of [ReactPHP](https://reactphp.org/).
**Table of contents**
* [Usage](#usage)
* [timeout()](#timeout)
* [Timeout cancellation](#timeout-cancellation)
* [Cancellation handler](#cancellation-handler)
* [Input cancellation](#input-cancellation)
* [Output cancellation](#output-cancellation)
* [Collections](#collections)
* [resolve()](#resolve)
* [Resolve cancellation](#resolve-cancellation)
* [reject()](#reject)
* [Reject cancellation](#reject-cancellation)
* [TimeoutException](#timeoutexception)
* [Install](#install)
* [Tests](#tests)
* [License](#license)
## Usage
This lightweight library consists only of a few simple functions.
All functions reside under the `React\Promise\Timer` namespace.
The below examples assume you use an import statement similar to this:
```php
use React\Promise\Timer;
Timer\timeout();
```
Alternatively, you can also refer to them with their fully-qualified name:
```php
\React\Promise\Timer\timeout();
```
### timeout()
The `timeout(PromiseInterface $promise, $time, LoopInterface $loop)` function
can be used to *cancel* operations that take *too long*.
You need to pass in an input `$promise` that represents a pending operation and timeout parameters.
It returns a new `Promise` with the following resolution behavior:
* If the input `$promise` resolves before `$time` seconds, resolve the resulting promise with its fulfillment value.
* If the input `$promise` rejects before `$time` seconds, reject the resulting promise with its rejection value.
* If the input `$promise` does not settle before `$time` seconds, *cancel* the operation and reject the resulting promise with a [`TimeoutException`](#timeoutexception).
Internally, the given `$time` value will be used to start a timer that will
*cancel* the pending operation once it triggers.
This implies that if you pass a really small (or negative) value, it will still
start a timer and will thus trigger at the earliest possible time in the future.
If the input `$promise` is already settled, then the resulting promise will
resolve or reject immediately without starting a timer at all.
A common use case for handling only resolved values looks like this:
```php
$promise = accessSomeRemoteResource();
Timer\timeout($promise, 10.0, $loop)->then(function ($value) {
// the operation finished within 10.0 seconds
});
```
A more complete example could look like this:
```php
$promise = accessSomeRemoteResource();
Timer\timeout($promise, 10.0, $loop)->then(
function ($value) {
// the operation finished within 10.0 seconds
},
function ($error) {
if ($error instanceof Timer\TimeoutException) {
// the operation has failed due to a timeout
} else {
// the input operation has failed due to some other error
}
}
);
```
Or if you're using [react/promise v2.2.0](https://github.com/reactphp/promise) or up:
```php
Timer\timeout($promise, 10.0, $loop)
->then(function ($value) {
// the operation finished within 10.0 seconds
})
->otherwise(function (Timer\TimeoutException $error) {
// the operation has failed due to a timeout
})
->otherwise(function ($error) {
// the input operation has failed due to some other error
})
;
```
#### Timeout cancellation
As discussed above, the [`timeout()`](#timeout) function will *cancel* the
underlying operation if it takes *too long*.
This means that you can be sure the resulting promise will then be rejected
with a [`TimeoutException`](#timeoutexception).
However, what happens to the underlying input `$promise` is a bit more tricky:
Once the timer fires, we will try to call
[`$promise->cancel()`](https://github.com/reactphp/promise#cancellablepromiseinterfacecancel)
on the input `$promise` which in turn invokes its [cancellation handler](#cancellation-handler).
This means that it's actually up the input `$promise` to handle
[cancellation support](https://github.com/reactphp/promise#cancellablepromiseinterface).
* A common use case involves cleaning up any resources like open network sockets or
file handles or terminating external processes or timers.
* If the given input `$promise` does not support cancellation, then this is a NO-OP.
This means that while the resulting promise will still be rejected, the underlying
input `$promise` may still be pending and can hence continue consuming resources.
See the following chapter for more details on the cancellation handler.
#### Cancellation handler
For example, an implementation for the above operation could look like this:
```php
function accessSomeRemoteResource()
{
return new Promise(
function ($resolve, $reject) use (&$socket) {
// this will be called once the promise is created
// a common use case involves opening any resources and eventually resolving
$socket = createSocket();
$socket->on('data', function ($data) use ($resolve) {
$resolve($data);
});
},
function ($resolve, $reject) use (&$socket) {
// this will be called once calling `cancel()` on this promise
// a common use case involves cleaning any resources and then rejecting
$socket->close();
$reject(new \RuntimeException('Operation cancelled'));
}
);
}
```
In this example, calling `$promise->cancel()` will invoke the registered cancellation
handler which then closes the network socket and rejects the `Promise` instance.
If no cancellation handler is passed to the `Promise` constructor, then invoking
its `cancel()` method it is effectively a NO-OP.
This means that it may still be pending and can hence continue consuming resources.
For more details on the promise cancellation, please refer to the
[Promise documentation](https://github.com/reactphp/promise#cancellablepromiseinterface).
#### Input cancellation
Irrespective of the timeout handling, you can also explicitly `cancel()` the
input `$promise` at any time.
This means that the `timeout()` handling does not affect cancellation of the
input `$promise`, as demonstrated in the following example:
```php
$promise = accessSomeRemoteResource();
$timeout = Timer\timeout($promise, 10.0, $loop);
$promise->cancel();
```
The registered [cancellation handler](#cancellation-handler) is responsible for
handling the `cancel()` call:
* A described above, a common use involves resource cleanup and will then *reject*
the `Promise`.
If the input `$promise` is being rejected, then the timeout will be aborted
and the resulting promise will also be rejected.
* If the input `$promise` is still pending, then the timout will continue
running until the timer expires.
The same happens if the input `$promise` does not register a
[cancellation handler](#cancellation-handler).
#### Output cancellation
Similarily, you can also explicitly `cancel()` the resulting promise like this:
```php
$promise = accessSomeRemoteResource();
$timeout = Timer\timeout($promise, 10.0, $loop);
$timeout->cancel();
```
Note how this looks very similar to the above [input cancellation](#input-cancellation)
example. Accordingly, it also behaves very similar.
Calling `cancel()` on the resulting promise will merely try
to `cancel()` the input `$promise`.
This means that we do not take over responsibility of the outcome and it's
entirely up to the input `$promise` to handle cancellation support.
The registered [cancellation handler](#cancellation-handler) is responsible for
handling the `cancel()` call:
* As described above, a common use involves resource cleanup and will then *reject*
the `Promise`.
If the input `$promise` is being rejected, then the timeout will be aborted
and the resulting promise will also be rejected.
* If the input `$promise` is still pending, then the timout will continue
running until the timer expires.
The same happens if the input `$promise` does not register a
[cancellation handler](#cancellation-handler).
To re-iterate, note that calling `cancel()` on the resulting promise will merely
try to cancel the input `$promise` only.
It is then up to the cancellation handler of the input promise to settle the promise.
If the input promise is still pending when the timeout occurs, then the normal
[timeout cancellation](#timeout-cancellation) handling will trigger, effectively rejecting
the output promise with a [`TimeoutException`](#timeoutexception).
This is done for consistency with the [timeout cancellation](#timeout-cancellation)
handling and also because it is assumed this is often used like this:
```php
$timeout = Timer\timeout(accessSomeRemoteResource(), 10.0, $loop);
$timeout->cancel();
```
As described above, this example works as expected and cleans up any resources
allocated for the input `$promise`.
Note that if the given input `$promise` does not support cancellation, then this
is a NO-OP.
This means that while the resulting promise will still be rejected after the
timeout, the underlying input `$promise` may still be pending and can hence
continue consuming resources.
#### Collections
If you want to wait for multiple promises to resolve, you can use the normal promise primitives like this:
```php
$promises = array(
accessSomeRemoteResource(),
accessSomeRemoteResource(),
accessSomeRemoteResource()
);
$promise = \React\Promise\all($promises);
Timer\timeout($promise, 10, $loop)->then(function ($values) {
// *all* promises resolved
});
```
The applies to all promise collection primitives alike, i.e. `all()`, `race()`, `any()`, `some()` etc.
For more details on the promise primitives, please refer to the
[Promise documentation](https://github.com/reactphp/promise#functions).
### resolve()
The `resolve($time, LoopInterface $loop)` function can be used to create a new Promise that
resolves in `$time` seconds with the `$time` as the fulfillment value.
```php
Timer\resolve(1.5, $loop)->then(function ($time) {
echo 'Thanks for waiting ' . $time . ' seconds' . PHP_EOL;
});
```
Internally, the given `$time` value will be used to start a timer that will
resolve the promise once it triggers.
This implies that if you pass a really small (or negative) value, it will still
start a timer and will thus trigger at the earliest possible time in the future.
#### Resolve cancellation
You can explicitly `cancel()` the resulting timer promise at any time:
```php
$timer = Timer\resolve(2.0, $loop);
$timer->cancel();
```
This will abort the timer and *reject* with a `RuntimeException`.
### reject()
The `reject($time, LoopInterface $loop)` function can be used to create a new Promise
which rejects in `$time` seconds with a `TimeoutException`.
```php
Timer\reject(2.0, $loop)->then(null, function (TimeoutException $e) {
echo 'Rejected after ' . $e->getTimeout() . ' seconds ' . PHP_EOL;
});
```
Internally, the given `$time` value will be used to start a timer that will
reject the promise once it triggers.
This implies that if you pass a really small (or negative) value, it will still
start a timer and will thus trigger at the earliest possible time in the future.
This function complements the [`resolve()`](#resolve) function
and can be used as a basic building block for higher-level promise consumers.
#### Reject cancellation
You can explicitly `cancel()` the resulting timer promise at any time:
```php
$timer = Timer\reject(2.0, $loop);
$timer->cancel();
```
This will abort the timer and *reject* with a `RuntimeException`.
### TimeoutException
The `TimeoutException` extends PHP's built-in `RuntimeException`.
The `getTimeout()` method can be used to get the timeout value in seconds.
## Install
The recommended way to install this library is [through Composer](https://getcomposer.org).
[New to Composer?](https://getcomposer.org/doc/00-intro.md)
This project follows [SemVer](https://semver.org/).
This will install the latest supported version:
```bash
$ composer require react/promise-timer:^1.5
```
See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
This project aims to run on any platform and thus does not require any PHP
extensions and supports running on legacy PHP 5.3 through current PHP 7+ and
HHVM.
It's *highly recommended to use PHP 7+* for this project.
## Tests
To run the test suite, you first need to clone this repo and then install all
dependencies [through Composer](https://getcomposer.org):
```bash
$ composer install
```
To run the test suite, go to the project root and run:
```bash
$ php vendor/bin/phpunit
```
## License
MIT, see [LICENSE file](LICENSE).

28
vendor/react/promise-timer/composer.json vendored Executable file
View File

@@ -0,0 +1,28 @@
{
"name": "react/promise-timer",
"description": "A trivial implementation of timeouts for Promises, built on top of ReactPHP.",
"keywords": ["Promise", "timeout", "timer", "event-loop", "ReactPHP", "async"],
"homepage": "https://github.com/reactphp/promise-timer",
"license": "MIT",
"authors": [
{
"name": "Christian Lück",
"email": "christian@lueck.tv"
}
],
"autoload": {
"psr-4": { "React\\Promise\\Timer\\": "src/" },
"files": [ "src/functions_include.php" ]
},
"autoload-dev": {
"psr-4": { "React\\Tests\\Promise\\Timer\\": "tests/" }
},
"require": {
"php": ">=5.3",
"react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3.5",
"react/promise": "^2.7.0 || ^1.2.1"
},
"require-dev": {
"phpunit/phpunit": "^6.4 || ^5.7 || ^4.8.35"
}
}

19
vendor/react/promise-timer/phpunit.xml.dist vendored Executable file
View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
>
<testsuites>
<testsuite name="Promise Timer Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src/</directory>
</whitelist>
</filter>
</phpunit>

View File

@@ -0,0 +1,22 @@
<?php
namespace React\Promise\Timer;
use RuntimeException;
class TimeoutException extends RuntimeException
{
private $timeout;
public function __construct($timeout, $message = null, $code = null, $previous = null)
{
parent::__construct($message, $code, $previous);
$this->timeout = $timeout;
}
public function getTimeout()
{
return $this->timeout;
}
}

81
vendor/react/promise-timer/src/functions.php vendored Executable file
View File

@@ -0,0 +1,81 @@
<?php
namespace React\Promise\Timer;
use React\Promise\CancellablePromiseInterface;
use React\EventLoop\LoopInterface;
use React\Promise\PromiseInterface;
use React\Promise\Promise;
function timeout(PromiseInterface $promise, $time, LoopInterface $loop)
{
// cancelling this promise will only try to cancel the input promise,
// thus leaving responsibility to the input promise.
$canceller = null;
if ($promise instanceof CancellablePromiseInterface) {
// pass promise by reference to clean reference after cancellation handler
// has been invoked once in order to avoid garbage references in call stack.
$canceller = function () use (&$promise) {
$promise->cancel();
$promise = null;
};
}
return new Promise(function ($resolve, $reject) use ($loop, $time, $promise) {
$timer = null;
$promise = $promise->then(function ($v) use (&$timer, $loop, $resolve) {
if ($timer) {
$loop->cancelTimer($timer);
}
$timer = false;
$resolve($v);
}, function ($v) use (&$timer, $loop, $reject) {
if ($timer) {
$loop->cancelTimer($timer);
}
$timer = false;
$reject($v);
});
// promise already resolved => no need to start timer
if ($timer === false) {
return;
}
// start timeout timer which will cancel the input promise
$timer = $loop->addTimer($time, function () use ($time, &$promise, $reject) {
$reject(new TimeoutException($time, 'Timed out after ' . $time . ' seconds'));
// try to invoke cancellation handler of input promise and then clean
// reference in order to avoid garbage references in call stack.
if ($promise instanceof CancellablePromiseInterface) {
$promise->cancel();
}
$promise = null;
});
}, $canceller);
}
function resolve($time, LoopInterface $loop)
{
return new Promise(function ($resolve) use ($loop, $time, &$timer) {
// resolve the promise when the timer fires in $time seconds
$timer = $loop->addTimer($time, function () use ($time, $resolve) {
$resolve($time);
});
}, function () use (&$timer, $loop) {
// cancelling this promise will cancel the timer, clean the reference
// in order to avoid garbage references in call stack and then reject.
$loop->cancelTimer($timer);
$timer = null;
throw new \RuntimeException('Timer cancelled');
});
}
function reject($time, LoopInterface $loop)
{
return resolve($time, $loop)->then(function ($time) {
throw new TimeoutException($time, 'Timer expired after ' . $time . ' seconds');
});
}

View File

@@ -0,0 +1,7 @@
<?php
namespace React\Promise\Timer;
if (!function_exists('React\\Promise\\Timer\\timeout')) {
require __DIR__ . '/functions.php';
}

View File

@@ -0,0 +1,10 @@
<?php
namespace React\Tests\Promise\Timer;
class CallableStub
{
public function __invoke()
{
}
}

View File

@@ -0,0 +1,79 @@
<?php
namespace React\Tests\Promise\Timer;
use React\Promise\Timer;
class FunctionRejectTest extends TestCase
{
public function testPromiseIsPendingWithoutRunningLoop()
{
$promise = Timer\reject(0.01, $this->loop);
$this->expectPromisePending($promise);
}
public function testPromiseExpiredIsPendingWithoutRunningLoop()
{
$promise = Timer\reject(-1, $this->loop);
$this->expectPromisePending($promise);
}
public function testPromiseWillBeRejectedOnTimeout()
{
$promise = Timer\reject(0.01, $this->loop);
$this->loop->run();
$this->expectPromiseRejected($promise);
}
public function testPromiseExpiredWillBeRejectedOnTimeout()
{
$promise = Timer\reject(-1, $this->loop);
$this->loop->run();
$this->expectPromiseRejected($promise);
}
public function testCancellingPromiseWillRejectTimer()
{
$promise = Timer\reject(0.01, $this->loop);
$promise->cancel();
$this->expectPromiseRejected($promise);
}
public function testWaitingForPromiseToRejectDoesNotLeaveGarbageCycles()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
gc_collect_cycles();
$promise = Timer\reject(0.01, $this->loop);
$this->loop->run();
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
public function testCancellingPromiseDoesNotLeaveGarbageCycles()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
gc_collect_cycles();
$promise = Timer\reject(0.01, $this->loop);
$promise->cancel();
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace React\Tests\Promise\Timer;
use React\Promise\Timer;
class FunctionResolveTest extends TestCase
{
public function testPromiseIsPendingWithoutRunningLoop()
{
$promise = Timer\resolve(0.01, $this->loop);
$this->expectPromisePending($promise);
}
public function testPromiseExpiredIsPendingWithoutRunningLoop()
{
$promise = Timer\resolve(-1, $this->loop);
$this->expectPromisePending($promise);
}
public function testPromiseWillBeResolvedOnTimeout()
{
$promise = Timer\resolve(0.01, $this->loop);
$this->loop->run();
$this->expectPromiseResolved($promise);
}
public function testPromiseExpiredWillBeResolvedOnTimeout()
{
$promise = Timer\resolve(-1, $this->loop);
$this->loop->run();
$this->expectPromiseResolved($promise);
}
public function testWillStartLoopTimer()
{
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
$loop->expects($this->once())->method('addTimer')->with($this->equalTo(0.01));
Timer\resolve(0.01, $loop);
}
public function testCancellingPromiseWillCancelLoopTimer()
{
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
$timer = $this->getMockBuilder(interface_exists('React\EventLoop\TimerInterface') ? 'React\EventLoop\TimerInterface' : 'React\EventLoop\Timer\TimerInterface')->getMock();
$loop->expects($this->once())->method('addTimer')->will($this->returnValue($timer));
$promise = Timer\resolve(0.01, $loop);
$loop->expects($this->once())->method('cancelTimer')->with($this->equalTo($timer));
$promise->cancel();
}
public function testCancellingPromiseWillRejectTimer()
{
$promise = Timer\resolve(0.01, $this->loop);
$promise->cancel();
$this->expectPromiseRejected($promise);
}
public function testWaitingForPromiseToResolveDoesNotLeaveGarbageCycles()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
gc_collect_cycles();
$promise = Timer\resolve(0.01, $this->loop);
$this->loop->run();
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
public function testCancellingPromiseDoesNotLeaveGarbageCycles()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
gc_collect_cycles();
$promise = Timer\resolve(0.01, $this->loop);
$promise->cancel();
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
}

View File

@@ -0,0 +1,286 @@
<?php
namespace React\Tests\Promise\Timer;
use React\Promise\Timer;
use React\Promise;
class FunctionTimeoutTest extends TestCase
{
public function testResolvedWillResolveRightAway()
{
$promise = Promise\resolve();
$promise = Timer\timeout($promise, 3, $this->loop);
$this->expectPromiseResolved($promise);
}
public function testResolvedExpiredWillResolveRightAway()
{
$promise = Promise\resolve();
$promise = Timer\timeout($promise, -1, $this->loop);
$this->expectPromiseResolved($promise);
}
public function testResolvedWillNotStartTimer()
{
$promise = Promise\resolve();
Timer\timeout($promise, 3, $this->loop);
$time = microtime(true);
$this->loop->run();
$time = microtime(true) - $time;
$this->assertLessThan(0.5, $time);
}
public function testRejectedWillRejectRightAway()
{
$promise = Promise\reject();
$promise = Timer\timeout($promise, 3, $this->loop);
$this->expectPromiseRejected($promise);
}
public function testRejectedWillNotStartTimer()
{
$promise = Promise\reject();
Timer\timeout($promise, 3, $this->loop);
$time = microtime(true);
$this->loop->run();
$time = microtime(true) - $time;
$this->assertLessThan(0.5, $time);
}
public function testPendingWillRejectOnTimeout()
{
$promise = $this->getMockBuilder('React\Promise\PromiseInterface')->getMock();
$promise = Timer\timeout($promise, 0.01, $this->loop);
$this->loop->run();
$this->expectPromiseRejected($promise);
}
public function testPendingCancellableWillBeCancelledThroughFollowerOnTimeout()
{
$cancellable = $this->getMockBuilder('React\Promise\CancellablePromiseInterface')->getMock();
$cancellable->expects($this->once())->method('cancel');
$promise = $this->getMockBuilder('React\Promise\CancellablePromiseInterface')->getMock();
$promise->expects($this->once())->method('then')->willReturn($cancellable);
Timer\timeout($promise, 0.01, $this->loop);
$this->loop->run();
}
public function testCancelTimeoutWithoutCancellationhandlerWillNotCancelTimerAndWillNotReject()
{
$promise = new \React\Promise\Promise(function () { });
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
$timer = $this->getMockBuilder('React\EventLoop\Timer\TimerInterface')->getMock();
$loop->expects($this->once())->method('addTimer')->will($this->returnValue($timer));
$loop->expects($this->never())->method('cancelTimer');
$timeout = Timer\timeout($promise, 0.01, $loop);
$timeout->cancel();
$this->expectPromisePending($timeout);
}
public function testResolvedPromiseWillNotStartTimer()
{
$promise = new \React\Promise\Promise(function ($resolve) { $resolve(true); });
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
$loop->expects($this->never())->method('addTimer');
$timeout = Timer\timeout($promise, 0.01, $loop);
$this->expectPromiseResolved($timeout);
}
public function testRejectedPromiseWillNotStartTimer()
{
$promise = Promise\reject(new \RuntimeException());
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
$loop->expects($this->never())->method('addTimer');
$timeout = Timer\timeout($promise, 0.01, $loop);
$this->expectPromiseRejected($timeout);
}
public function testCancelTimeoutWillCancelGivenPromise()
{
$promise = new \React\Promise\Promise(function () { }, $this->expectCallableOnce());
$timeout = Timer\timeout($promise, 0.01, $this->loop);
$timeout->cancel();
}
public function testCancelGivenPromiseWillReject()
{
$promise = new \React\Promise\Promise(function () { }, function ($resolve, $reject) { $reject(); });
$timeout = Timer\timeout($promise, 0.01, $this->loop);
$promise->cancel();
$this->expectPromiseRejected($promise);
$this->expectPromiseRejected($timeout);
}
public function testCancelTimeoutWillRejectIfGivenPromiseWillReject()
{
$promise = new \React\Promise\Promise(function () { }, function ($resolve, $reject) { $reject(); });
$timeout = Timer\timeout($promise, 0.01, $this->loop);
$timeout->cancel();
$this->expectPromiseRejected($promise);
$this->expectPromiseRejected($timeout);
}
public function testCancelTimeoutWillResolveIfGivenPromiseWillResolve()
{
$promise = new \React\Promise\Promise(function () { }, function ($resolve, $reject) { $resolve(); });
$timeout = Timer\timeout($promise, 0.01, $this->loop);
$timeout->cancel();
$this->expectPromiseResolved($promise);
$this->expectPromiseResolved($timeout);
}
public function testWaitingForPromiseToResolveBeforeTimeoutDoesNotLeaveGarbageCycles()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
gc_collect_cycles();
$promise = Timer\resolve(0.01, $this->loop);
$promise = Timer\timeout($promise, 1.0, $this->loop);
$this->loop->run();
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
public function testWaitingForPromiseToRejectBeforeTimeoutDoesNotLeaveGarbageCycles()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
gc_collect_cycles();
$promise = Timer\reject(0.01, $this->loop);
$promise = Timer\timeout($promise, 1.0, $this->loop);
$this->loop->run();
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
public function testWaitingForPromiseToTimeoutDoesNotLeaveGarbageCycles()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
gc_collect_cycles();
$promise = new \React\Promise\Promise(function () { }, function () {
throw new \RuntimeException();
});
$promise = Timer\timeout($promise, 0.01, $this->loop);
$this->loop->run();
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
public function testWaitingForPromiseToTimeoutWithoutCancellerDoesNotLeaveGarbageCycles()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
gc_collect_cycles();
$promise = new \React\Promise\Promise(function () { });
$promise = Timer\timeout($promise, 0.01, $this->loop);
$this->loop->run();
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
public function testWaitingForPromiseToTimeoutWithNoOpCancellerDoesNotLeaveGarbageCycles()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
gc_collect_cycles();
$promise = new \React\Promise\Promise(function () { }, function () {
// no-op
});
$promise = Timer\timeout($promise, 0.01, $this->loop);
$this->loop->run();
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
public function testCancellingPromiseDoesNotLeaveGarbageCycles()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
gc_collect_cycles();
$promise = new \React\Promise\Promise(function () { }, function () {
throw new \RuntimeException();
});
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
$promise = Timer\timeout($promise, 0.01, $loop);
$promise->cancel();
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
}

61
vendor/react/promise-timer/tests/TestCase.php vendored Executable file
View File

@@ -0,0 +1,61 @@
<?php
namespace React\Tests\Promise\Timer;
use PHPUnit\Framework\TestCase as BaseTestCase;
use React\EventLoop\Factory;
class TestCase extends BaseTestCase
{
protected $loop;
public function setUp()
{
$this->loop = Factory::create();
}
protected function expectCallableOnce()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke');
return $mock;
}
protected function expectCallableNever()
{
$mock = $this->createCallableMock();
$mock
->expects($this->never())
->method('__invoke');
return $mock;
}
/**
* @link https://github.com/reactphp/react/blob/master/tests/React/Tests/Socket/TestCase.php (taken from reactphp/react)
*/
protected function createCallableMock()
{
return $this->getMockBuilder('React\Tests\Promise\Timer\CallableStub')->getMock();
}
protected function expectPromiseRejected($promise)
{
return $promise->then($this->expectCallableNever(), $this->expectCallableOnce());
}
protected function expectPromiseResolved($promise)
{
return $promise->then($this->expectCallableOnce(), $this->expectCallableNever());
}
protected function expectPromisePending($promise)
{
return $promise->then($this->expectCallableNever(), $this->expectCallableNever());
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace React\Tests\Promise\Timer;
use React\Promise\Timer\TimeoutException;
class TimeoutExceptionTest extends TestCase
{
public function testAccessTimeout()
{
$e = new TimeoutException(10);
$this->assertEquals(10, $e->getTimeout());
}
}