mirror of
https://github.com/danog/loop.git
synced 2024-11-30 04:19:04 +01:00
Finalize tests
This commit is contained in:
parent
aa6250b05a
commit
ee04355a63
10
.travis.yml
10
.travis.yml
@ -22,9 +22,6 @@ before_install:
|
|||||||
|
|
||||||
install:
|
install:
|
||||||
- composer update -n --prefer-dist
|
- composer update -n --prefer-dist
|
||||||
- mkdir -p coverage/cov coverage/bin
|
|
||||||
- wget https://phar.phpunit.de/phpcov.phar -O coverage/bin/phpcov
|
|
||||||
- chmod +x coverage/bin/phpcov
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- vendor/bin/phpunit --coverage-text --coverage-clover build/logs/clover.xml
|
- vendor/bin/phpunit --coverage-text --coverage-clover build/logs/clover.xml
|
||||||
@ -32,10 +29,9 @@ script:
|
|||||||
- vendor/bin/psalm
|
- vendor/bin/psalm
|
||||||
|
|
||||||
after_script:
|
after_script:
|
||||||
- curl -OL https://github.com/php-coveralls/php-coveralls/releases/download/v1.0.0/coveralls.phar
|
- curl -OL https://github.com/php-coveralls/php-coveralls/releases/download/v2.2.0/php-coveralls.phar
|
||||||
- chmod +x coveralls.phar
|
- chmod +x php-coveralls.phar
|
||||||
- phpdbg -qrr coverage/bin/phpcov merge --clover build/logs/clover.xml coverage/cov
|
- ./php-coveralls.phar -v
|
||||||
- ./coveralls.phar
|
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# IPC
|
# IPC
|
||||||
|
|
||||||
[![Build Status](https://img.shields.io/travis/danog/loop/master.svg?style=flat-square)](https://travis-ci.com/danog/loop)
|
[![Build Status](https://travis-ci.com/danog/loop.svg?branch=master)](https://travis-ci.com/danog/loop)
|
||||||
![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)
|
![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)
|
||||||
|
|
||||||
`danog/loop` provides a very useful set of async loop APIs based on [AMPHP](https://amphp.org), for executing operations periodically or on demand, in background loops a-la threads.
|
`danog/loop` provides a very useful set of async loop APIs based on [AMPHP](https://amphp.org), for executing operations periodically or on demand, in background loops a-la threads.
|
||||||
|
@ -43,6 +43,6 @@
|
|||||||
],
|
],
|
||||||
"cs": "php-cs-fixer fix -v --diff --dry-run",
|
"cs": "php-cs-fixer fix -v --diff --dry-run",
|
||||||
"cs-fix": "php-cs-fixer fix -v --diff",
|
"cs-fix": "php-cs-fixer fix -v --diff",
|
||||||
"test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
|
"test": "phpdbg -qrr -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,12 @@ use danog\Loop\ResumableSignalLoop;
|
|||||||
* The loop can be stopped from the outside or
|
* The loop can be stopped from the outside or
|
||||||
* from the inside by signaling or returning `true`.
|
* from the inside by signaling or returning `true`.
|
||||||
*
|
*
|
||||||
|
* @template T as bool
|
||||||
|
* @template TGenerator as \Generator<mixed,Promise|array<array-key,Promise>,mixed,Promise<T>|T>
|
||||||
|
* @template TPromise as Promise<T>
|
||||||
|
*
|
||||||
|
* @template TCallable as T|TPromise|TGenerator
|
||||||
|
*
|
||||||
* @author Daniil Gentili <daniil@daniil.it>
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
*/
|
*/
|
||||||
class PeriodicLoop extends ResumableSignalLoop
|
class PeriodicLoop extends ResumableSignalLoop
|
||||||
@ -28,6 +34,8 @@ class PeriodicLoop extends ResumableSignalLoop
|
|||||||
* Callback.
|
* Callback.
|
||||||
*
|
*
|
||||||
* @var callable
|
* @var callable
|
||||||
|
*
|
||||||
|
* @psalm-var callable():TCallable
|
||||||
*/
|
*/
|
||||||
private $callback;
|
private $callback;
|
||||||
/**
|
/**
|
||||||
@ -48,6 +56,8 @@ class PeriodicLoop extends ResumableSignalLoop
|
|||||||
* @param callable $callback Callback to call
|
* @param callable $callback Callback to call
|
||||||
* @param string $name Loop name
|
* @param string $name Loop name
|
||||||
* @param ?int $interval Loop interval
|
* @param ?int $interval Loop interval
|
||||||
|
*
|
||||||
|
* @psalm-param callable():TCallable $callback Callable to run
|
||||||
*/
|
*/
|
||||||
public function __construct(callable $callback, string $name, ?int $interval)
|
public function __construct(callable $callback, string $name, ?int $interval)
|
||||||
{
|
{
|
||||||
@ -65,16 +75,21 @@ class PeriodicLoop extends ResumableSignalLoop
|
|||||||
$callback = $this->callback;
|
$callback = $this->callback;
|
||||||
while (true) {
|
while (true) {
|
||||||
/** @psalm-suppress MixedAssignment */
|
/** @psalm-suppress MixedAssignment */
|
||||||
$result = yield $this->waitSignal($this->pause($this->interval));
|
$result = $callback();
|
||||||
if ($result) {
|
if ($result instanceof \Generator) {
|
||||||
|
/** @psalm-var TGenerator */
|
||||||
|
$result = yield from $result;
|
||||||
|
} elseif ($result instanceof Promise) {
|
||||||
|
/** @psalm-var TPromise */
|
||||||
|
$result = yield $result;
|
||||||
|
}
|
||||||
|
if ($result === true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/** @psalm-suppress MixedAssignment */
|
/** @psalm-suppress MixedAssignment */
|
||||||
$result = $callback();
|
$result = yield $this->waitSignal($this->pause($this->interval));
|
||||||
if ($result instanceof \Generator) {
|
if ($result === true) {
|
||||||
yield from $result;
|
return;
|
||||||
} elseif ($result instanceof Promise) {
|
|
||||||
yield $result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ abstract class Fixtures extends AsyncTestCase
|
|||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public static function isResolved(Promise $promise): bool
|
protected static function isResolved(Promise $promise): bool
|
||||||
{
|
{
|
||||||
$resolved = false;
|
$resolved = false;
|
||||||
$promise->onResolve(static function ($e, $res) use (&$resolved) {
|
$promise->onResolve(static function ($e, $res) use (&$resolved) {
|
||||||
@ -44,7 +44,7 @@ abstract class Fixtures extends AsyncTestCase
|
|||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function assertPreStart(BasicInterface $loop)
|
protected function assertPreStart(BasicInterface $loop)
|
||||||
{
|
{
|
||||||
$this->assertEquals(self::LOOP_NAME, "$loop");
|
$this->assertEquals(self::LOOP_NAME, "$loop");
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ abstract class Fixtures extends AsyncTestCase
|
|||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function assertAfterStart(BasicInterface $loop, bool $running = true)
|
protected function assertAfterStart(BasicInterface $loop, bool $running = true)
|
||||||
{
|
{
|
||||||
$this->assertTrue($loop->inited());
|
$this->assertTrue($loop->inited());
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ abstract class Fixtures extends AsyncTestCase
|
|||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function assertFinal(BasicInterface $loop)
|
protected function assertFinal(BasicInterface $loop)
|
||||||
{
|
{
|
||||||
$this->assertTrue($loop->ran());
|
$this->assertTrue($loop->ran());
|
||||||
$this->assertFalse($loop->isRunning());
|
$this->assertFalse($loop->isRunning());
|
||||||
|
187
test/GenericTest.php
Normal file
187
test/GenericTest.php
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Loop test.
|
||||||
|
*
|
||||||
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @license https://opensource.org/licenses/MIT MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace danog\Loop\Test;
|
||||||
|
|
||||||
|
use Amp\PHPUnit\AsyncTestCase;
|
||||||
|
use Amp\Promise;
|
||||||
|
use Amp\Success;
|
||||||
|
use danog\Loop\Generic\GenericLoop;
|
||||||
|
use danog\Loop\Loop;
|
||||||
|
use danog\Loop\Test\Interfaces\LoggingPauseInterface;
|
||||||
|
use danog\Loop\Test\Traits\Basic;
|
||||||
|
use danog\Loop\Test\Traits\LoggingPause;
|
||||||
|
|
||||||
|
use function Amp\delay;
|
||||||
|
|
||||||
|
class GenericTest extends AsyncTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Test basic loop.
|
||||||
|
*
|
||||||
|
* @param bool $stopSig Whether to stop with signal
|
||||||
|
*
|
||||||
|
* @return \Generator
|
||||||
|
*
|
||||||
|
* @dataProvider provideTrueFalse
|
||||||
|
*/
|
||||||
|
public function testGeneric(bool $stopSig): \Generator
|
||||||
|
{
|
||||||
|
$runCount = 0;
|
||||||
|
$pauseTime = GenericLoop::PAUSE;
|
||||||
|
$callable = function () use (&$runCount, &$pauseTime) {
|
||||||
|
$runCount++;
|
||||||
|
return $pauseTime;
|
||||||
|
};
|
||||||
|
yield from $this->fixtureAssertions($callable, $runCount, $pauseTime, $stopSig);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Test generator loop.
|
||||||
|
*
|
||||||
|
* @param bool $stopSig Whether to stop with signal
|
||||||
|
*
|
||||||
|
* @return \Generator
|
||||||
|
*
|
||||||
|
* @dataProvider provideTrueFalse
|
||||||
|
*/
|
||||||
|
public function testGenerator(bool $stopSig): \Generator
|
||||||
|
{
|
||||||
|
$runCount = 0;
|
||||||
|
$pauseTime = GenericLoop::PAUSE;
|
||||||
|
$callable = function () use (&$runCount, &$pauseTime): \Generator {
|
||||||
|
yield delay(1);
|
||||||
|
$runCount++;
|
||||||
|
return $pauseTime;
|
||||||
|
};
|
||||||
|
yield from $this->fixtureAssertions($callable, $runCount, $pauseTime, $stopSig);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Test promise loop.
|
||||||
|
*
|
||||||
|
* @param bool $stopSig Whether to stop with signal
|
||||||
|
*
|
||||||
|
* @return \Generator
|
||||||
|
*
|
||||||
|
* @dataProvider provideTrueFalse
|
||||||
|
*/
|
||||||
|
public function testPromise(bool $stopSig): \Generator
|
||||||
|
{
|
||||||
|
$runCount = 0;
|
||||||
|
$pauseTime = GenericLoop::PAUSE;
|
||||||
|
$callable = function () use (&$runCount, &$pauseTime): Promise {
|
||||||
|
$runCount++;
|
||||||
|
return new Success($pauseTime);
|
||||||
|
};
|
||||||
|
yield from $this->fixtureAssertions($callable, $runCount, $pauseTime, $stopSig);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Fixture assertions for started loop.
|
||||||
|
*
|
||||||
|
* @param LoggingPauseInterface $loop Loop
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function fixtureStarted(LoggingPauseInterface $loop): void
|
||||||
|
{
|
||||||
|
$this->assertTrue($loop->isRunning());
|
||||||
|
$this->assertEquals(1, $loop->startCounter());
|
||||||
|
$this->assertEquals(0, $loop->endCounter());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Run fixture assertions.
|
||||||
|
*
|
||||||
|
* @param \Closure $closure Closure
|
||||||
|
* @param integer $runCount Run count
|
||||||
|
* @param ?integer $pauseTime Pause time
|
||||||
|
* @param bool $stopSig Whether to stop with signal
|
||||||
|
*
|
||||||
|
* @return \Generator
|
||||||
|
*/
|
||||||
|
private function fixtureAssertions(\Closure $closure, int &$runCount, ?int &$pauseTime, bool $stopSig = false): \Generator
|
||||||
|
{
|
||||||
|
$loop = new class($closure, Fixtures::LOOP_NAME) extends GenericLoop implements LoggingPauseInterface {
|
||||||
|
use LoggingPause;
|
||||||
|
};
|
||||||
|
$this->assertEquals(Fixtures::LOOP_NAME, "$loop");
|
||||||
|
|
||||||
|
$this->assertFalse($loop->isRunning());
|
||||||
|
$this->assertEquals(0, $loop->startCounter());
|
||||||
|
$this->assertEquals(0, $loop->endCounter());
|
||||||
|
|
||||||
|
$this->assertEquals(0, $runCount);
|
||||||
|
$this->assertEquals(0, $loop->getPauseCount());
|
||||||
|
|
||||||
|
$loop->start();
|
||||||
|
yield delay(2);
|
||||||
|
$this->fixtureStarted($loop);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $runCount);
|
||||||
|
$this->assertEquals(1, $loop->getPauseCount());
|
||||||
|
$this->assertEquals(0, $loop->getLastPause());
|
||||||
|
|
||||||
|
$pauseTime = 100;
|
||||||
|
$loop->resume();
|
||||||
|
yield delay(2);
|
||||||
|
$this->fixtureStarted($loop);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $runCount);
|
||||||
|
$this->assertEquals(2, $loop->getPauseCount());
|
||||||
|
$this->assertEquals(100, $loop->getLastPause());
|
||||||
|
|
||||||
|
yield delay(48);
|
||||||
|
$this->fixtureStarted($loop);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $runCount);
|
||||||
|
$this->assertEquals(2, $loop->getPauseCount());
|
||||||
|
$this->assertEquals(100, $loop->getLastPause());
|
||||||
|
|
||||||
|
yield delay(60);
|
||||||
|
$this->fixtureStarted($loop);
|
||||||
|
|
||||||
|
$this->assertEquals(3, $runCount);
|
||||||
|
$this->assertEquals(3, $loop->getPauseCount());
|
||||||
|
$this->assertEquals(100, $loop->getLastPause());
|
||||||
|
|
||||||
|
$loop->resume();
|
||||||
|
yield delay(1);
|
||||||
|
|
||||||
|
$this->assertEquals(4, $runCount);
|
||||||
|
$this->assertEquals(4, $loop->getPauseCount());
|
||||||
|
$this->assertEquals(100, $loop->getLastPause());
|
||||||
|
|
||||||
|
if ($stopSig) {
|
||||||
|
$loop->signal(true);
|
||||||
|
} else {
|
||||||
|
$pauseTime = GenericLoop::STOP;
|
||||||
|
$loop->resume();
|
||||||
|
}
|
||||||
|
yield delay(1);
|
||||||
|
$this->assertEquals($stopSig ? 4 : 5, $runCount);
|
||||||
|
$this->assertEquals(4, $loop->getPauseCount());
|
||||||
|
$this->assertEquals(100, $loop->getLastPause());
|
||||||
|
|
||||||
|
$this->assertFalse($loop->isRunning());
|
||||||
|
|
||||||
|
$this->assertEquals(1, $loop->startCounter());
|
||||||
|
$this->assertEquals(1, $loop->endCounter());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide true false.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function provideTrueFalse(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[true],
|
||||||
|
[false]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -17,7 +17,7 @@ use danog\Loop\Interfaces\LoopInterface;
|
|||||||
*
|
*
|
||||||
* @author Daniil Gentili <daniil@daniil.it>
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
*/
|
*/
|
||||||
interface BasicInterface extends LoopInterface
|
interface BasicInterface extends LoopInterface, LoggingInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Check whether the loop inited.
|
* Check whether the loop inited.
|
||||||
@ -31,16 +31,4 @@ interface BasicInterface extends LoopInterface
|
|||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function ran(): bool;
|
public function ran(): bool;
|
||||||
/**
|
|
||||||
* Get start counter.
|
|
||||||
*
|
|
||||||
* @return integer
|
|
||||||
*/
|
|
||||||
public function startCounter(): int;
|
|
||||||
/**
|
|
||||||
* Get end counter.
|
|
||||||
*
|
|
||||||
* @return integer
|
|
||||||
*/
|
|
||||||
public function endCounter(): int;
|
|
||||||
}
|
}
|
||||||
|
28
test/Interfaces/IntervalInterface.php
Normal file
28
test/Interfaces/IntervalInterface.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resumable loop test interface.
|
||||||
|
*
|
||||||
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @license https://opensource.org/licenses/MIT MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace danog\Loop\Test\Interfaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resumable loop test interface.
|
||||||
|
*
|
||||||
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
|
*/
|
||||||
|
interface IntervalInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Set sleep interval.
|
||||||
|
*
|
||||||
|
* @param ?int $interval Interval
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setInterval(?int $interval): void;
|
||||||
|
}
|
34
test/Interfaces/LoggingInterface.php
Normal file
34
test/Interfaces/LoggingInterface.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic loop test interface.
|
||||||
|
*
|
||||||
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @license https://opensource.org/licenses/MIT MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace danog\Loop\Test\Interfaces;
|
||||||
|
|
||||||
|
use danog\Loop\Interfaces\LoopInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic loop test interface.
|
||||||
|
*
|
||||||
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
|
*/
|
||||||
|
interface LoggingInterface extends LoopInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get start counter.
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function startCounter(): int;
|
||||||
|
/**
|
||||||
|
* Get end counter.
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function endCounter(): int;
|
||||||
|
}
|
34
test/Interfaces/LoggingPauseInterface.php
Normal file
34
test/Interfaces/LoggingPauseInterface.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic loop test interface.
|
||||||
|
*
|
||||||
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @license https://opensource.org/licenses/MIT MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace danog\Loop\Test\Interfaces;
|
||||||
|
|
||||||
|
use danog\Loop\Interfaces\LoopInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic loop test interface.
|
||||||
|
*
|
||||||
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
|
*/
|
||||||
|
interface LoggingPauseInterface extends LoopInterface, LoggingInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get number of times loop was paused.
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getPauseCount(): int;
|
||||||
|
/**
|
||||||
|
* Get last pause.
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getLastPause(): int;
|
||||||
|
}
|
@ -10,19 +10,13 @@
|
|||||||
|
|
||||||
namespace danog\Loop\Test\Interfaces;
|
namespace danog\Loop\Test\Interfaces;
|
||||||
|
|
||||||
|
use danog\Loop\Interfaces\ResumableLoopInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resumable loop test interface.
|
* Resumable loop test interface.
|
||||||
*
|
*
|
||||||
* @author Daniil Gentili <daniil@daniil.it>
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
*/
|
*/
|
||||||
interface ResumableInterface extends BasicInterface
|
interface ResumableInterface extends BasicInterface, IntervalInterface, ResumableLoopInterface
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Set sleep interval.
|
|
||||||
*
|
|
||||||
* @param ?int $interval Interval
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function setInterval(?int $interval): void;
|
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ use danog\Loop\Interfaces\SignalLoopInterface;
|
|||||||
*
|
*
|
||||||
* @author Daniil Gentili <daniil@daniil.it>
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
*/
|
*/
|
||||||
interface SignalInterface extends ResumableInterface, SignalLoopInterface
|
interface SignalInterface extends BasicInterface, IntervalInterface, SignalLoopInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get signaled payload.
|
* Get signaled payload.
|
||||||
|
167
test/PeriodicTest.php
Normal file
167
test/PeriodicTest.php
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Loop test.
|
||||||
|
*
|
||||||
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @license https://opensource.org/licenses/MIT MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace danog\Loop\Test;
|
||||||
|
|
||||||
|
use Amp\PHPUnit\AsyncTestCase;
|
||||||
|
use Amp\Promise;
|
||||||
|
use Amp\Success;
|
||||||
|
use danog\Loop\Generic\PeriodicLoop;
|
||||||
|
use danog\Loop\Loop;
|
||||||
|
use danog\Loop\Test\Interfaces\LoggingInterface;
|
||||||
|
use danog\Loop\Test\Traits\Basic;
|
||||||
|
use danog\Loop\Test\Traits\Logging;
|
||||||
|
|
||||||
|
use function Amp\delay;
|
||||||
|
|
||||||
|
class PeriodicTest extends AsyncTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Test basic loop.
|
||||||
|
*
|
||||||
|
* @param bool $stopSig Whether to stop with signal
|
||||||
|
*
|
||||||
|
* @return \Generator
|
||||||
|
*
|
||||||
|
* @dataProvider provideTrueFalse
|
||||||
|
*/
|
||||||
|
public function testGeneric(bool $stopSig): \Generator
|
||||||
|
{
|
||||||
|
$runCount = 0;
|
||||||
|
$retValue = false;
|
||||||
|
$callable = function () use (&$runCount, &$retValue) {
|
||||||
|
$runCount++;
|
||||||
|
return $retValue;
|
||||||
|
};
|
||||||
|
yield from $this->fixtureAssertions($callable, $runCount, $retValue, $stopSig);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Test generator loop.
|
||||||
|
*
|
||||||
|
* @param bool $stopSig Whether to stop with signal
|
||||||
|
*
|
||||||
|
* @return \Generator
|
||||||
|
*
|
||||||
|
* @dataProvider provideTrueFalse
|
||||||
|
*/
|
||||||
|
public function testGenerator(bool $stopSig): \Generator
|
||||||
|
{
|
||||||
|
$runCount = 0;
|
||||||
|
$retValue = false;
|
||||||
|
$callable = function () use (&$runCount, &$retValue): \Generator {
|
||||||
|
yield delay(1);
|
||||||
|
$runCount++;
|
||||||
|
return $retValue;
|
||||||
|
};
|
||||||
|
yield from $this->fixtureAssertions($callable, $runCount, $retValue, $stopSig);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Test promise loop.
|
||||||
|
*
|
||||||
|
* @param bool $stopSig Whether to stop with signal
|
||||||
|
*
|
||||||
|
* @return \Generator
|
||||||
|
*
|
||||||
|
* @dataProvider provideTrueFalse
|
||||||
|
*/
|
||||||
|
public function testPromise(bool $stopSig): \Generator
|
||||||
|
{
|
||||||
|
$runCount = 0;
|
||||||
|
$retValue = false;
|
||||||
|
$callable = function () use (&$runCount, &$retValue): Promise {
|
||||||
|
$runCount++;
|
||||||
|
return new Success($retValue);
|
||||||
|
};
|
||||||
|
yield from $this->fixtureAssertions($callable, $runCount, $retValue, $stopSig);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Fixture assertions for started loop.
|
||||||
|
*
|
||||||
|
* @param LoggingInterface $loop Loop
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function fixtureStarted(LoggingInterface $loop): void
|
||||||
|
{
|
||||||
|
$this->assertTrue($loop->isRunning());
|
||||||
|
$this->assertEquals(1, $loop->startCounter());
|
||||||
|
$this->assertEquals(0, $loop->endCounter());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Run fixture assertions.
|
||||||
|
*
|
||||||
|
* @param \Closure $closure Closure
|
||||||
|
* @param integer $runCount Run count
|
||||||
|
* @param bool $retValue Pause time
|
||||||
|
* @param bool $stopSig Whether to stop with signal
|
||||||
|
*
|
||||||
|
* @return \Generator
|
||||||
|
*/
|
||||||
|
private function fixtureAssertions(\Closure $closure, int &$runCount, bool &$retValue, bool $stopSig = false): \Generator
|
||||||
|
{
|
||||||
|
$loop = new class($closure, Fixtures::LOOP_NAME, 100) extends PeriodicLoop implements LoggingInterface {
|
||||||
|
use Logging;
|
||||||
|
};
|
||||||
|
$this->assertEquals(Fixtures::LOOP_NAME, "$loop");
|
||||||
|
|
||||||
|
$this->assertFalse($loop->isRunning());
|
||||||
|
$this->assertEquals(0, $loop->startCounter());
|
||||||
|
$this->assertEquals(0, $loop->endCounter());
|
||||||
|
|
||||||
|
$this->assertEquals(0, $runCount);
|
||||||
|
|
||||||
|
$loop->start();
|
||||||
|
yield delay(2);
|
||||||
|
$this->fixtureStarted($loop);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $runCount);
|
||||||
|
|
||||||
|
yield delay(48);
|
||||||
|
$this->fixtureStarted($loop);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $runCount);
|
||||||
|
|
||||||
|
yield delay(60);
|
||||||
|
$this->fixtureStarted($loop);
|
||||||
|
|
||||||
|
$this->assertEquals(2, $runCount);
|
||||||
|
|
||||||
|
$loop->resume();
|
||||||
|
yield delay(1);
|
||||||
|
|
||||||
|
$this->assertEquals(3, $runCount);
|
||||||
|
|
||||||
|
if ($stopSig) {
|
||||||
|
$loop->signal(true);
|
||||||
|
} else {
|
||||||
|
$retValue = true;
|
||||||
|
$loop->resume();
|
||||||
|
}
|
||||||
|
yield delay(1);
|
||||||
|
$this->assertEquals($stopSig ? 3 : 4, $runCount);
|
||||||
|
|
||||||
|
$this->assertFalse($loop->isRunning());
|
||||||
|
|
||||||
|
$this->assertEquals(1, $loop->startCounter());
|
||||||
|
$this->assertEquals(1, $loop->endCounter());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide true false.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function provideTrueFalse(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[true],
|
||||||
|
[false]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -16,18 +16,7 @@ use function Amp\delay;
|
|||||||
|
|
||||||
trait Basic
|
trait Basic
|
||||||
{
|
{
|
||||||
/**
|
use Logging;
|
||||||
* Check whether the loop started.
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $startCounter = 0;
|
|
||||||
/**
|
|
||||||
* Check whether the loop ended.
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $endCounter = 0;
|
|
||||||
/**
|
/**
|
||||||
* Check whether the loop inited.
|
* Check whether the loop inited.
|
||||||
*
|
*
|
||||||
@ -78,44 +67,4 @@ trait Basic
|
|||||||
{
|
{
|
||||||
return LoopTest::LOOP_NAME;
|
return LoopTest::LOOP_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Signal that loop started.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function startedLoop(): void
|
|
||||||
{
|
|
||||||
$this->startCounter++;
|
|
||||||
parent::startedLoop();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Signal that loop ended.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function exitedLoop(): void
|
|
||||||
{
|
|
||||||
$this->endCounter++;
|
|
||||||
parent::exitedLoop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get start counter.
|
|
||||||
*
|
|
||||||
* @return integer
|
|
||||||
*/
|
|
||||||
public function startCounter(): int
|
|
||||||
{
|
|
||||||
return $this->startCounter;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get end counter.
|
|
||||||
*
|
|
||||||
* @return integer
|
|
||||||
*/
|
|
||||||
public function endCounter(): int
|
|
||||||
{
|
|
||||||
return $this->endCounter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
66
test/Traits/Logging.php
Normal file
66
test/Traits/Logging.php
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Loop test trait.
|
||||||
|
*
|
||||||
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @license https://opensource.org/licenses/MIT MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace danog\Loop\Test\Traits;
|
||||||
|
|
||||||
|
trait Logging
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Check whether the loop started.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $startCounter = 0;
|
||||||
|
/**
|
||||||
|
* Check whether the loop ended.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $endCounter = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal that loop started.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function startedLoop(): void
|
||||||
|
{
|
||||||
|
$this->startCounter++;
|
||||||
|
parent::startedLoop();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Signal that loop ended.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function exitedLoop(): void
|
||||||
|
{
|
||||||
|
$this->endCounter++;
|
||||||
|
parent::exitedLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get start counter.
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function startCounter(): int
|
||||||
|
{
|
||||||
|
return $this->startCounter;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get end counter.
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function endCounter(): int
|
||||||
|
{
|
||||||
|
return $this->endCounter;
|
||||||
|
}
|
||||||
|
}
|
60
test/Traits/LoggingPause.php
Normal file
60
test/Traits/LoggingPause.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Loop test trait.
|
||||||
|
*
|
||||||
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @license https://opensource.org/licenses/MIT MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace danog\Loop\Test\Traits;
|
||||||
|
|
||||||
|
use function Amp\delay;
|
||||||
|
|
||||||
|
trait LoggingPause
|
||||||
|
{
|
||||||
|
use Logging;
|
||||||
|
/**
|
||||||
|
* Number of times loop was paused.
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
private $pauseCount = 0;
|
||||||
|
/**
|
||||||
|
* Last pause delay.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $lastPause = 0;
|
||||||
|
/**
|
||||||
|
* Get number of times loop was paused.
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getPauseCount(): int
|
||||||
|
{
|
||||||
|
return $this->pauseCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get last pause.
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getLastPause(): int
|
||||||
|
{
|
||||||
|
return $this->lastPause;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Report pause, can be overriden for logging.
|
||||||
|
*
|
||||||
|
* @param integer $timeout Pause duration, 0 = forever
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function reportPause(int $timeout): void
|
||||||
|
{
|
||||||
|
$this->pauseCount++;
|
||||||
|
$this->lastPause= $timeout;
|
||||||
|
}
|
||||||
|
}
|
@ -48,6 +48,17 @@ trait Signal
|
|||||||
{
|
{
|
||||||
return $this->exception;
|
return $this->exception;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Test waiting signal on interval.
|
||||||
|
*
|
||||||
|
* @param integer $interval Interval
|
||||||
|
*
|
||||||
|
* @return \Generator
|
||||||
|
*/
|
||||||
|
private function testGenerator(int $interval): \Generator
|
||||||
|
{
|
||||||
|
yield delay($interval);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Loop implementation.
|
* Loop implementation.
|
||||||
*
|
*
|
||||||
@ -58,7 +69,7 @@ trait Signal
|
|||||||
$this->inited = true;
|
$this->inited = true;
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
$this->payload = yield $this->waitSignal($this instanceof ResumableLoopInterface ? $this->pause($this->interval) : delay($this->interval));
|
$this->payload = yield $this->waitSignal($this instanceof ResumableLoopInterface ? $this->pause($this->interval) : $this->testGenerator($this->interval));
|
||||||
}
|
}
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
$this->exception = $e;
|
$this->exception = $e;
|
||||||
|
Loading…
Reference in New Issue
Block a user