diff --git a/README.md b/README.md index 853766b2..b5559f6c 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ single [`run()`](#run) call that is controlled by the user. * [Quickstart example](#quickstart-example) * [Usage](#usage) * [Loop](#loop) + * [Loop methods](#loop-methods) * [get()](#get) * [Factory](#factory) * [create()](#create) @@ -52,88 +53,215 @@ use React\EventLoop\Loop; $server = stream_socket_server('tcp://127.0.0.1:8080'); stream_set_blocking($server, false); -Loop::get()->addReadStream($server, function ($server) { +Loop::addReadStream($server, function ($server) { $conn = stream_socket_accept($server); $data = "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nHi\n"; - Loop::get()->addWriteStream($conn, function ($conn) use (&$data) { + Loop::addWriteStream($conn, function ($conn) use (&$data) { $written = fwrite($conn, $data); if ($written === strlen($data)) { fclose($conn); - Loop::get()->removeWriteStream($conn); + Loop::removeWriteStream($conn); } else { $data = substr($data, $written); } }); }); -Loop::get()->addPeriodicTimer(5, function () { +Loop::addPeriodicTimer(5, function () { $memory = memory_get_usage() / 1024; $formatted = number_format($memory, 3).'K'; echo "Current memory usage: {$formatted}\n"; }); -Loop::get()->run(); +Loop::run(); ``` See also the [examples](examples). ## Usage -Typical applications use a single event loop which is created at the beginning -and run at the end of the program. +As of `v1.2.0`, typical applications would use the [`Loop` object](#loop) +to use the currently active event loop instance like this: ```php -// [1] -$loop = React\EventLoop\Factory::create(); +use React\EventLoop\Loop; -// [2] -$loop->addPeriodicTimer(1, function () { - echo "Tick\n"; +$timer = Loop::addPeriodicTimer(0.1, function () { + echo "Tick" . PHP_EOL; +}); +Loop::addTimer(1.0, function () use ($timer) { + Loop::cancelTimer($timer); + echo 'Done' . PHP_EOL; }); -$stream = new React\Stream\ReadableResourceStream( - fopen('file.txt', 'r'), - $loop -); +Loop::run(); +``` + +As an alternative, you can also explicitly create an event loop instance at the +beginning, reuse it throughout your program and finally run it at the end of the +program like this: + +```php +$loop = React\EventLoop\Loop::get(); // or deprecated React\EventLoop\Factory::create(); + +$timer = $loop->addPeriodicTimer(0.1, function () { + echo "Tick" . PHP_EOL; +}); +$loop->addTimer(1.0, function () use ($loop, $timer) { + $loop->cancelTimer($timer); + echo 'Done' . PHP_EOL; +}); -// [3] $loop->run(); ``` -1. The loop instance is created at the beginning of the program. A convenience - factory [`React\EventLoop\Factory::create()`](#create) is provided by this library which - picks the best available [loop implementation](#loop-implementations). -2. The loop instance is used directly or passed to library and application code. - In this example, a periodic timer is registered with the event loop which - simply outputs `Tick` every second and a - [readable stream](https://github.com/reactphp/stream#readableresourcestream) - is created by using ReactPHP's - [stream component](https://github.com/reactphp/stream) for demonstration - purposes. -3. The loop is run with a single [`$loop->run()`](#run) call at the end of the program. +While the former is more concise, the latter is more explicit. +In both cases, the program would perform the exact same steps. + +1. The event loop instance is created at the beginning of the program. This is + implicitly done the first time you call the [`Loop` class](#loop) or + explicitly when using the deprecated [`Factory::create() method`](#create) + (or manually instantiating any of the [loop implementation](#loop-implementations)). +2. The event loop is used directly or passed as an instance to library and + application code. In this example, a periodic timer is registered with the + event loop which simply outputs `Tick` every fraction of a second until another + timer stops the periodic timer after a second. +3. The event loop is run at the end of the program with a single [`run()`](#run) + call at the end of the program. + +As of `v1.2.0`, we highly recommend using the [`Loop` class](#loop). +The explicit loop instructions are still valid and may still be useful in some +applications, especially for a transition period towards the more concise style. ### Loop The `Loop` class exists as a convenient global accessor for the event loop. -#### get() +#### Loop methods -The `get(): LoopInterface` method is the preferred way to get and use the event loop. With -it there is no need to always pass the loop around anymore. +The `Loop` class provides all methods that exist on the [`LoopInterface`](#loopinterface) +as static methods: + +* [run()](#run) +* [stop()](#stop) +* [addTimer()](#addtimer) +* [addPeriodicTimer()](#addperiodictimer) +* [cancelTimer()](#canceltimer) +* [futureTick()](#futuretick) +* [addSignal()](#addsignal) +* [removeSignal()](#removesignal) +* [addReadStream()](#addreadstream) +* [addWriteStream()](#addwritestream) +* [removeReadStream()](#removereadstream) +* [removeWriteStream()](#removewritestream) + +If you're working with the event loop in your application code, it's often +easiest to directly interface with the static methods defined on the `Loop` class +like this: ```php use React\EventLoop\Loop; -Loop::get()->addTimer(0.02, function () { - echo 'World!'; +$timer = Loop::addPeriodicTimer(0.1, function () { + echo 'tick!' . PHP_EOL; }); -Loop::get()->addTimer(0.01, function () { - echo 'Hello '; + +Loop::addTimer(1.0, function () use ($timer) { + Loop::cancelTimer($timer); + echo 'Done' . PHP_EOL; }); -Loop::get()->run(); +Loop::run(); ``` +On the other hand, if you're familiar with object-oriented programming (OOP) and +dependency injection (DI), you may want to inject an event loop instance and +invoke instance methods on the `LoopInterface` like this: + +```php +use React\EventLoop\Loop; +use React\EventLoop\LoopInterface; + +class Greeter +{ + private $loop; + + public function __construct(LoopInterface $loop) + { + $this->loop = $loop; + } + + public function greet(string $name) + { + $this->loop->addTimer(1.0, function () use ($name) { + echo 'Hello ' . $name . '!' . PHP_EOL; + }); + } +} + +$greeter = new Greeter(Loop::get()); +$greeter->greet('Alice'); +$greeter->greet('Bob'); + +Loop::run(); +``` + +Each static method call will be forwarded as-is to the underlying event loop +instance by using the [`Loop::get()`](#get) call internally. +See [`LoopInterface`](#loopinterface) for more details about available methods. + +#### get() + +The `get(): LoopInterface` method can be used to +get the currently active event loop instance. + +This method will always return the same event loop instance throughout the +lifetime of your application. + +```php +use React\EventLoop\Loop; +use React\EventLoop\LoopInterface; + +$loop = Loop::get(); + +assert($loop instanceof LoopInterface); +assert($loop === Loop::get()); +``` + +This is particularly useful if you're using object-oriented programming (OOP) +and dependency injection (DI). In this case, you may want to inject an event +loop instance and invoke instance methods on the `LoopInterface` like this: + +```php +use React\EventLoop\Loop; +use React\EventLoop\LoopInterface; + +class Greeter +{ + private $loop; + + public function __construct(LoopInterface $loop) + { + $this->loop = $loop; + } + + public function greet(string $name) + { + $this->loop->addTimer(1.0, function () use ($name) { + echo 'Hello ' . $name . '!' . PHP_EOL; + }); + } +} + +$greeter = new Greeter(Loop::get()); +$greeter->greet('Alice'); +$greeter->greet('Bob'); + +Loop::run(); +``` + +See [`LoopInterface`](#loopinterface) for more details about available methods. + ### Factory The `Factory` class exists as a convenient way to pick the best available diff --git a/examples/01-timers.php b/examples/01-timers.php index 5be2f3e2..a7bf3945 100644 --- a/examples/01-timers.php +++ b/examples/01-timers.php @@ -4,12 +4,12 @@ require __DIR__ . '/../vendor/autoload.php'; -Loop::get()->addTimer(0.8, function () { +Loop::addTimer(0.8, function () { echo 'world!' . PHP_EOL; }); -Loop::get()->addTimer(0.3, function () { +Loop::addTimer(0.3, function () { echo 'hello '; }); -Loop::get()->run(); +Loop::run(); diff --git a/examples/02-periodic.php b/examples/02-periodic.php index 6f549055..0604f846 100644 --- a/examples/02-periodic.php +++ b/examples/02-periodic.php @@ -4,13 +4,13 @@ require __DIR__ . '/../vendor/autoload.php'; -$timer = Loop::get()->addPeriodicTimer(0.1, function () { +$timer = Loop::addPeriodicTimer(0.1, function () { echo 'tick!' . PHP_EOL; }); -Loop::get()->addTimer(1.0, function () use ($timer) { - Loop::get()->cancelTimer($timer); +Loop::addTimer(1.0, function () use ($timer) { + Loop::cancelTimer($timer); echo 'Done' . PHP_EOL; }); -Loop::get()->run(); +Loop::run(); diff --git a/examples/03-ticks.php b/examples/03-ticks.php index 0eee59bd..4b2077da 100644 --- a/examples/03-ticks.php +++ b/examples/03-ticks.php @@ -4,12 +4,12 @@ require __DIR__ . '/../vendor/autoload.php'; -Loop::get()->futureTick(function () { +Loop::futureTick(function () { echo 'b'; }); -Loop::get()->futureTick(function () { +Loop::futureTick(function () { echo 'c'; }); echo 'a'; -Loop::get()->run(); +Loop::run(); diff --git a/examples/04-signals.php b/examples/04-signals.php index dc7e0293..ceca3521 100644 --- a/examples/04-signals.php +++ b/examples/04-signals.php @@ -9,11 +9,11 @@ exit(1); } -Loop::get()->addSignal(SIGINT, $func = function ($signal) use (&$func) { +Loop::addSignal(SIGINT, $func = function ($signal) use (&$func) { echo 'Signal: ', (string)$signal, PHP_EOL; - Loop::get()->removeSignal(SIGINT, $func); + Loop::removeSignal(SIGINT, $func); }); echo 'Listening for SIGINT. Use "kill -SIGINT ' . getmypid() . '" or CTRL+C' . PHP_EOL; -Loop::get()->run(); +Loop::run(); diff --git a/examples/11-consume-stdin.php b/examples/11-consume-stdin.php index 146a55eb..f567d84a 100644 --- a/examples/11-consume-stdin.php +++ b/examples/11-consume-stdin.php @@ -11,12 +11,12 @@ // read everything from STDIN and report number of bytes // for illustration purposes only, should use react/stream instead -Loop::get()->addReadStream(STDIN, function ($stream) { +Loop::addReadStream(STDIN, function ($stream) { $chunk = fread($stream, 64 * 1024); // reading nothing means we reached EOF if ($chunk === '') { - Loop::get()->removeReadStream($stream); + Loop::removeReadStream($stream); stream_set_blocking($stream, true); fclose($stream); return; @@ -25,4 +25,4 @@ echo strlen($chunk) . ' bytes' . PHP_EOL; }); -Loop::get()->run(); +Loop::run(); diff --git a/examples/12-generate-yes.php b/examples/12-generate-yes.php index b0da7c60..4424b8ec 100644 --- a/examples/12-generate-yes.php +++ b/examples/12-generate-yes.php @@ -17,13 +17,13 @@ // write data to STDOUT whenever its write buffer accepts data // for illustrations purpose only, should use react/stream instead -Loop::get()->addWriteStream(STDOUT, function ($stdout) use (&$data) { +Loop::addWriteStream(STDOUT, function ($stdout) use (&$data) { // try to write data $r = fwrite($stdout, $data); // nothing could be written despite being writable => closed if ($r === 0) { - Loop::get()->removeWriteStream($stdout); + Loop::removeWriteStream($stdout); fclose($stdout); stream_set_blocking($stdout, true); fwrite(STDERR, 'Stopped because STDOUT closed' . PHP_EOL); @@ -38,4 +38,4 @@ } }); -Loop::get()->run(); +Loop::run(); diff --git a/examples/13-http-client-blocking.php b/examples/13-http-client-blocking.php index eb34b24d..efd8cc86 100644 --- a/examples/13-http-client-blocking.php +++ b/examples/13-http-client-blocking.php @@ -16,13 +16,13 @@ fwrite($stream, "GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n"); // wait for HTTP response -Loop::get()->addReadStream($stream, function ($stream) { +Loop::addReadStream($stream, function ($stream) { $chunk = fread($stream, 64 * 1024); // reading nothing means we reached EOF if ($chunk === '') { echo '[END]' . PHP_EOL; - Loop::get()->removeReadStream($stream); + Loop::removeReadStream($stream); fclose($stream); return; } @@ -30,4 +30,4 @@ echo $chunk; }); -Loop::get()->run(); +Loop::run(); diff --git a/examples/14-http-client-async.php b/examples/14-http-client-async.php index 2e3e7e35..ceed3ec7 100644 --- a/examples/14-http-client-async.php +++ b/examples/14-http-client-async.php @@ -23,14 +23,14 @@ // print progress every 10ms echo 'Connecting'; -$timer = Loop::get()->addPeriodicTimer(0.01, function () { +$timer = Loop::addPeriodicTimer(0.01, function () { echo '.'; }); // wait for connection success/error -Loop::get()->addWriteStream($stream, function ($stream) use ($timer) { - Loop::get()->removeWriteStream($stream); - Loop::get()->cancelTimer($timer); +Loop::addWriteStream($stream, function ($stream) use ($timer) { + Loop::removeWriteStream($stream); + Loop::cancelTimer($timer); // check for socket error (connection rejected) if (stream_socket_get_name($stream, true) === false) { @@ -44,13 +44,13 @@ fwrite($stream, "GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n"); // wait for HTTP response - Loop::get()->addReadStream($stream, function ($stream) { + Loop::addReadStream($stream, function ($stream) { $chunk = fread($stream, 64 * 1024); // reading nothing means we reached EOF if ($chunk === '') { echo '[END]' . PHP_EOL; - Loop::get()->removeReadStream($stream); + Loop::removeReadStream($stream); fclose($stream); return; } @@ -59,4 +59,4 @@ }); }); -Loop::get()->run(); +Loop::run(); diff --git a/examples/21-http-server.php b/examples/21-http-server.php index 4e238158..e000eb51 100644 --- a/examples/21-http-server.php +++ b/examples/21-http-server.php @@ -13,24 +13,24 @@ stream_set_blocking($server, false); // wait for incoming connections on server socket -Loop::get()->addReadStream($server, function ($server) { +Loop::addReadStream($server, function ($server) { $conn = stream_socket_accept($server); $data = "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nHi\n"; - Loop::get()->addWriteStream($conn, function ($conn) use (&$data) { + Loop::addWriteStream($conn, function ($conn) use (&$data) { $written = fwrite($conn, $data); if ($written === strlen($data)) { fclose($conn); - Loop::get()->removeWriteStream($conn); + Loop::removeWriteStream($conn); } else { $data = substr($data, $written); } }); }); -Loop::get()->addPeriodicTimer(5, function () { +Loop::addPeriodicTimer(5, function () { $memory = memory_get_usage() / 1024; $formatted = number_format($memory, 3).'K'; echo "Current memory usage: {$formatted}\n"; }); -Loop::get()->run(); +Loop::run(); diff --git a/examples/91-benchmark-ticks.php b/examples/91-benchmark-ticks.php index 8a768568..452abbac 100644 --- a/examples/91-benchmark-ticks.php +++ b/examples/91-benchmark-ticks.php @@ -7,7 +7,7 @@ $n = isset($argv[1]) ? (int)$argv[1] : 1000 * 100; for ($i = 0; $i < $n; ++$i) { - Loop::get()->futureTick(function () { }); + Loop::futureTick(function () { }); } -Loop::get()->run(); +Loop::run(); diff --git a/examples/92-benchmark-timers.php b/examples/92-benchmark-timers.php index 51cb9596..da381f16 100644 --- a/examples/92-benchmark-timers.php +++ b/examples/92-benchmark-timers.php @@ -7,7 +7,7 @@ $n = isset($argv[1]) ? (int)$argv[1] : 1000 * 100; for ($i = 0; $i < $n; ++$i) { - Loop::get()->addTimer(0, function () { }); + Loop::addTimer(0, function () { }); } -Loop::get()->run(); +Loop::run(); diff --git a/examples/93-benchmark-ticks-delay.php b/examples/93-benchmark-ticks-delay.php index b37cfbc2..ac5094f3 100644 --- a/examples/93-benchmark-ticks-delay.php +++ b/examples/93-benchmark-ticks-delay.php @@ -9,7 +9,7 @@ if ($ticks > 0) { --$ticks; //$loop->addTimer(0, $tick); - Loop::get()->futureTick($tick); + Loop::futureTick($tick); } else { echo 'done'; } @@ -17,4 +17,4 @@ $tick(); -Loop::get()->run(); +Loop::run(); diff --git a/examples/94-benchmark-timers-delay.php b/examples/94-benchmark-timers-delay.php index e8e380a2..eb4fc5cb 100644 --- a/examples/94-benchmark-timers-delay.php +++ b/examples/94-benchmark-timers-delay.php @@ -9,7 +9,7 @@ if ($ticks > 0) { --$ticks; //$loop->futureTick($tick); - Loop::get()->addTimer(0, $tick); + Loop::addTimer(0, $tick); } else { echo 'done'; } @@ -17,4 +17,4 @@ $tick(); -Loop::get()->run(); +Loop::run(); diff --git a/examples/95-benchmark-memory.php b/examples/95-benchmark-memory.php index 14d77872..06735bd2 100644 --- a/examples/95-benchmark-memory.php +++ b/examples/95-benchmark-memory.php @@ -7,7 +7,6 @@ * php 95-benchmark-memory.php -t 30 -l StreamSelect -r 10 */ -use React\EventLoop\Factory; use React\EventLoop\Loop; use React\EventLoop\LoopInterface; use React\EventLoop\TimerInterface; @@ -27,21 +26,21 @@ $runs = 0; if (5 < $t) { - Loop::get()->addTimer($t, function () { - Loop::get()->stop(); + Loop::addTimer($t, function () { + Loop::stop(); }); } -Loop::get()->addPeriodicTimer(0.001, function () use (&$runs) { +Loop::addPeriodicTimer(0.001, function () use (&$runs) { $runs++; - Loop::get()->addPeriodicTimer(1, function (TimerInterface $timer) { - Loop::get()->cancelTimer($timer); + Loop::addPeriodicTimer(1, function (TimerInterface $timer) { + Loop::cancelTimer($timer); }); }); -Loop::get()->addPeriodicTimer($r, function () use (&$runs) { +Loop::addPeriodicTimer($r, function () use (&$runs) { $kmem = round(memory_get_usage() / 1024); $kmemReal = round(memory_get_usage(true) / 1024); echo "Runs:\t\t\t$runs\n"; @@ -57,7 +56,7 @@ echo str_repeat('-', 50), "\n"; $beginTime = time(); -Loop::get()->run(); +Loop::run(); $endTime = time(); $timeTaken = $endTime - $beginTime; diff --git a/src/Loop.php b/src/Loop.php index e91291e3..fed27cba 100644 --- a/src/Loop.php +++ b/src/Loop.php @@ -47,4 +47,154 @@ public static function set(LoopInterface $loop) { self::$instance = $loop; } + + /** + * [Advanced] Register a listener to be notified when a stream is ready to read. + * + * @param resource $stream + * @param callable $listener + * @return void + * @throws \Exception + * @see LoopInterface::addReadStream() + */ + public static function addReadStream($stream, $listener) + { + self::get()->addReadStream($stream, $listener); + } + + /** + * [Advanced] Register a listener to be notified when a stream is ready to write. + * + * @param resource $stream + * @param callable $listener + * @return void + * @throws \Exception + * @see LoopInterface::addWriteStream() + */ + public static function addWriteStream($stream, $listener) + { + self::get()->addWriteStream($stream, $listener); + } + + /** + * Remove the read event listener for the given stream. + * + * @param resource $stream + * @return void + * @see LoopInterface::removeReadStream() + */ + public static function removeReadStream($stream) + { + self::get()->removeReadStream($stream); + } + + /** + * Remove the write event listener for the given stream. + * + * @param resource $stream + * @return void + * @see LoopInterface::removeWriteStream() + */ + public static function removeWriteStream($stream) + { + self::get()->removeWriteStream($stream); + } + + /** + * Enqueue a callback to be invoked once after the given interval. + * + * @param float $interval + * @param callable $callback + * @return TimerInterface + * @see LoopInterface::addTimer() + */ + public static function addTimer($interval, $callback) + { + return self::get()->addTimer($interval, $callback); + } + + /** + * Enqueue a callback to be invoked repeatedly after the given interval. + * + * @param float $interval + * @param callable $callback + * @return TimerInterface + * @see LoopInterface::addPeriodicTimer() + */ + public static function addPeriodicTimer($interval, $callback) + { + return self::get()->addPeriodicTimer($interval, $callback); + } + + /** + * Cancel a pending timer. + * + * @param TimerInterface $timer + * @return void + * @see LoopInterface::cancelTimer() + */ + public static function cancelTimer(TimerInterface $timer) + { + return self::get()->cancelTimer($timer); + } + + /** + * Schedule a callback to be invoked on a future tick of the event loop. + * + * @param callable $listener + * @return void + * @see LoopInterface::futureTick() + */ + public static function futureTick($listener) + { + self::get()->futureTick($listener); + } + + /** + * Register a listener to be notified when a signal has been caught by this process. + * + * @param int $signal + * @param callable $listener + * @return void + * @see LoopInterface::addSignal() + */ + public static function addSignal($signal, $listener) + { + self::get()->addSignal($signal, $listener); + } + + /** + * Removes a previously added signal listener. + * + * @param int $signal + * @param callable $listener + * @return void + * @see LoopInterface::removeSignal() + */ + public static function removeSignal($signal, $listener) + { + self::get()->removeSignal($signal, $listener); + } + + /** + * Run the event loop until there are no more tasks to perform. + * + * @return void + * @see LoopInterface::run() + */ + public static function run() + { + self::get()->run(); + } + + /** + * Instruct a running event loop to stop. + * + * @return void + * @see LoopInterface::stop() + */ + public static function stop() + { + self::get()->stop(); + } } diff --git a/tests/LoopTest.php b/tests/LoopTest.php index a653035a..f3a13d34 100644 --- a/tests/LoopTest.php +++ b/tests/LoopTest.php @@ -49,6 +49,158 @@ public function numberOfTests() return array(array(), array(), array()); } + public function testStaticAddReadStreamCallsAddReadStreamOnLoopInstance() + { + $stream = tmpfile(); + $listener = function () { }; + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('addReadStream')->with($stream, $listener); + + Loop::set($loop); + + Loop::addReadStream($stream, $listener); + } + + public function testStaticAddWriteStreamCallsAddWriteStreamOnLoopInstance() + { + $stream = tmpfile(); + $listener = function () { }; + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('addWriteStream')->with($stream, $listener); + + Loop::set($loop); + + Loop::addWriteStream($stream, $listener); + } + + public function testStaticRemoveReadStreamCallsRemoveReadStreamOnLoopInstance() + { + $stream = tmpfile(); + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('removeReadStream')->with($stream); + + Loop::set($loop); + + Loop::removeReadStream($stream); + } + + public function testStaticRemoveWriteStreamCallsRemoveWriteStreamOnLoopInstance() + { + $stream = tmpfile(); + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('removeWriteStream')->with($stream); + + Loop::set($loop); + + Loop::removeWriteStream($stream); + } + + public function testStaticAddTimerCallsAddTimerOnLoopInstanceAndReturnsTimerInstance() + { + $interval = 1.0; + $callback = function () { }; + $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('addTimer')->with($interval, $callback)->willReturn($timer); + + Loop::set($loop); + + $ret = Loop::addTimer($interval, $callback); + + $this->assertSame($timer, $ret); + } + + public function testStaticAddPeriodicTimerCallsAddPeriodicTimerOnLoopInstanceAndReturnsTimerInstance() + { + $interval = 1.0; + $callback = function () { }; + $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('addPeriodicTimer')->with($interval, $callback)->willReturn($timer); + + Loop::set($loop); + + $ret = Loop::addPeriodicTimer($interval, $callback); + + $this->assertSame($timer, $ret); + } + + public function testStaticCancelTimerCallsCancelTimerOnLoopInstance() + { + $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('cancelTimer')->with($timer); + + Loop::set($loop); + + Loop::cancelTimer($timer); + } + + public function testStaticFutureTickCallsFutureTickOnLoopInstance() + { + $listener = function () { }; + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('futureTick')->with($listener); + + Loop::set($loop); + + Loop::futureTick($listener); + } + + public function testStaticAddSignalCallsAddSignalOnLoopInstance() + { + $signal = 1; + $listener = function () { }; + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('addSignal')->with($signal, $listener); + + Loop::set($loop); + + Loop::addSignal($signal, $listener); + } + + public function testStaticRemoveSignalCallsRemoveSignalOnLoopInstance() + { + $signal = 1; + $listener = function () { }; + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('removeSignal')->with($signal, $listener); + + Loop::set($loop); + + Loop::removeSignal($signal, $listener); + } + + public function testStaticRunCallsRunOnLoopInstance() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('run')->with(); + + Loop::set($loop); + + Loop::run(); + } + + public function testStaticStopCallsStopOnLoopInstance() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('stop')->with(); + + Loop::set($loop); + + Loop::stop(); + } + /** * @after * @before
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: