diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0755cde8..4e69fa12 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,11 +19,6 @@ jobs: - 7.3 - 7.2 - 7.1 - - 7.0 - - 5.6 - - 5.5 - - 5.4 - - 5.3 steps: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 @@ -32,7 +27,7 @@ jobs: coverage: xdebug ini-file: development ini-values: disable_functions='' # do not disable PCNTL functions on PHP < 8.1 - extensions: sockets, pcntl ${{ matrix.php >= 5.6 && ', event' || '' }} ${{ matrix.php >= 5.4 && ', ev' || '' }} + extensions: sockets, pcntl, event, ev env: fail-fast: true # fail step if any extension can not be installed - run: composer install @@ -43,7 +38,7 @@ jobs: PHPUnit-Unstable: name: PHPUnit (Unstable PHP ${{ matrix.php }}) - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 continue-on-error: true strategy: matrix: @@ -56,11 +51,6 @@ jobs: - 7.3 - 7.2 - 7.1 - - 7.0 - - 5.6 - - 5.5 - - 5.4 - - 5.3 steps: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 @@ -69,35 +59,11 @@ jobs: coverage: xdebug ini-file: development extensions: sockets, pcntl - - name: Install ext-uv on PHP 7+ + - name: Install ext-uv run: | sudo apt-get update -q && sudo apt-get install libuv1-dev echo "yes" | sudo pecl install ${{ matrix.php >= 8.0 && 'uv-0.3.0' || 'uv-0.2.4' }} php -m | grep -q uv || echo "extension=uv.so" >> "$(php -r 'echo php_ini_loaded_file();')" - if: ${{ matrix.php >= 7.0 }} - - name: Install legacy ext-libevent on PHP < 7.0 - run: | - sudo apt-get update && sudo apt-get install libevent-dev - curl http://pecl.php.net/get/libevent-0.1.0.tgz | tar -xz - pushd libevent-0.1.0 - phpize - ./configure - make - sudo make install - popd - echo "extension=libevent.so" | sudo tee -a "$(php -r 'echo php_ini_loaded_file();')" - if: ${{ matrix.php < 7.0 }} - - name: Install legacy ext-libev on PHP < 7.0 - run: | - git clone --recursive https://github.com/m4rw3r/php-libev - pushd php-libev - phpize - ./configure --with-libev - make - sudo make install - popd - echo "extension=libev.so" | sudo tee -a "$(php -r 'echo php_ini_loaded_file();')" - if: ${{ matrix.php < 7.0 }} - run: composer install - run: vendor/bin/phpunit --coverage-text if: ${{ matrix.php >= 7.3 }} @@ -132,19 +98,3 @@ jobs: if: ${{ matrix.php >= 7.3 }} - run: vendor/bin/phpunit --coverage-text -c phpunit.xml.legacy if: ${{ matrix.php < 7.3 }} - - PHPUnit-hhvm: - name: PHPUnit (HHVM) - runs-on: ubuntu-22.04 - continue-on-error: true - steps: - - uses: actions/checkout@v4 - - run: cp "$(which composer)" composer.phar && ./composer.phar self-update --2.2 # downgrade Composer for HHVM - - name: Run hhvm composer.phar install - uses: docker://hhvm/hhvm:3.30-lts-latest - with: - args: hhvm composer.phar install - - name: Run hhvm vendor/bin/phpunit - uses: docker://hhvm/hhvm:3.30-lts-latest - with: - args: hhvm vendor/bin/phpunit diff --git a/README.md b/README.md index 88a3e18b..8394784f 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,14 @@ [ReactPHP](https://reactphp.org/)'s core reactor event loop that libraries can use for evented I/O. +> **Development version:** This branch contains the code for the upcoming v3 +> release. For the code of the current stable v1 release, check out the +> [`1.x` branch](https://github.com/reactphp/event-loop/tree/1.x). +> +> The upcoming v3 release will be the way forward for this package. However, +> we will still actively support v1 for those not yet on the latest version. +> See also [installation instructions](#install) for more details. + In order for async based libraries to be interoperable, they need to use the same event loop. This component provides a common `LoopInterface` that any library can target. This allows them to be used in the same loop, with one @@ -18,15 +26,11 @@ single [`run()`](#run) call that is controlled by the user. * [Loop methods](#loop-methods) * [Loop autorun](#loop-autorun) * [get()](#get) - * [~~Factory~~](#factory) - * [~~create()~~](#create) * [Loop implementations](#loop-implementations) * [StreamSelectLoop](#streamselectloop) * [ExtEventLoop](#exteventloop) * [ExtEvLoop](#extevloop) * [ExtUvLoop](#extuvloop) - * [~~ExtLibeventLoop~~](#extlibeventloop) - * [~~ExtLibevLoop~~](#extlibevloop) * [LoopInterface](#loopinterface) * [run()](#run) * [stop()](#stop) @@ -105,7 +109,7 @@ 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(); +$loop = React\EventLoop\Loop::get(); $timer = $loop->addPeriodicTimer(0.1, function () { echo 'Tick' . PHP_EOL; @@ -123,9 +127,8 @@ 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 implementations](#loop-implementations)). + implicitly done the first time you call the [`Loop` class](#loop) + (or by manually instantiating any of the [loop implementations](#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 @@ -299,33 +302,6 @@ $greeter->greet('Bob'); See [`LoopInterface`](#loopinterface) for more details about available methods. -### ~~Factory~~ - -> Deprecated since v1.2.0, see [`Loop` class](#loop) instead. - -The deprecated `Factory` class exists as a convenient way to pick the best available -[event loop implementation](#loop-implementations). - -#### ~~create()~~ - -> Deprecated since v1.2.0, see [`Loop::get()`](#get) instead. - -The deprecated `create(): LoopInterface` method can be used to -create a new event loop instance: - -```php -// deprecated -$loop = React\EventLoop\Factory::create(); - -// new -$loop = React\EventLoop\Loop::get(); -``` - -This method always returns an instance implementing [`LoopInterface`](#loopinterface), -the actual [event loop implementation](#loop-implementations) is an implementation detail. - -This method should usually only be called once at the beginning of the program. - ### Loop implementations In addition to the [`LoopInterface`](#loopinterface), there are a number of @@ -354,12 +330,11 @@ A `stream_select()` based event loop. This uses the [`stream_select()`](https://www.php.net/manual/en/function.stream-select.php) function and is the only implementation that works out of the box with PHP. -This event loop works out of the box on PHP 5.3 through PHP 8+ and HHVM. +This event loop works out of the box on any PHP version. This means that no installation is required and this library works on all platforms and supported PHP versions. -Accordingly, the [`Loop` class](#loop) and the deprecated [`Factory`](#factory) -will use this event loop by default if you do not install any of the event loop -extensions listed below. +Accordingly, the [`Loop` class](#loop) will use this event loop by default if +you do not install any of the event loop extensions listed below. Under the hood, it does a simple `select` system call. This system call is limited to the maximum file descriptor number of @@ -398,7 +373,7 @@ This uses the [`event` PECL extension](https://pecl.php.net/package/event), that provides an interface to `libevent` library. `libevent` itself supports a number of system-specific backends (epoll, kqueue). -This loop is known to work with PHP 5.4 through PHP 8+. +This loop is known to work with PHP 7.1 through PHP 8+. #### ExtEvLoop @@ -409,7 +384,7 @@ that provides an interface to `libev` library. `libev` itself supports a number of system-specific backends (epoll, kqueue). -This loop is known to work with PHP 5.4 through PHP 8+. +This loop is known to work with PHP 7.1 through PHP 8+. #### ExtUvLoop @@ -419,47 +394,7 @@ This loop uses the [`uv` PECL extension](https://pecl.php.net/package/uv), that provides an interface to `libuv` library. `libuv` itself supports a number of system-specific backends (epoll, kqueue). -This loop is known to work with PHP 7+. - -#### ~~ExtLibeventLoop~~ - -> Deprecated since v1.2.0, use [`ExtEventLoop`](#exteventloop) instead. - -An `ext-libevent` based event loop. - -This uses the [`libevent` PECL extension](https://pecl.php.net/package/libevent), -that provides an interface to `libevent` library. -`libevent` itself supports a number of system-specific backends (epoll, kqueue). - -This event loop does only work with PHP 5. -An [unofficial update](https://github.com/php/pecl-event-libevent/pull/2) for -PHP 7 does exist, but it is known to cause regular crashes due to `SEGFAULT`s. -To reiterate: Using this event loop on PHP 7 is not recommended. -Accordingly, neither the [`Loop` class](#loop) nor the deprecated -[`Factory` class](#factory) will try to use this event loop on PHP 7. - -This event loop is known to trigger a readable listener only if -the stream *becomes* readable (edge-triggered) and may not trigger if the -stream has already been readable from the beginning. -This also implies that a stream may not be recognized as readable when data -is still left in PHP's internal stream buffers. -As such, it's recommended to use `stream_set_read_buffer($stream, 0);` -to disable PHP's internal read buffer in this case. -See also [`addReadStream()`](#addreadstream) for more details. - -#### ~~ExtLibevLoop~~ - -> Deprecated since v1.2.0, use [`ExtEvLoop`](#extevloop) instead. - -An `ext-libev` based event loop. - -This uses an [unofficial `libev` extension](https://github.com/m4rw3r/php-libev), -that provides an interface to `libev` library. -`libev` itself supports a number of system-specific backends (epoll, kqueue). - -This loop does only work with PHP 5. -An update for PHP 7 is [unlikely](https://github.com/m4rw3r/php-libev/issues/8) -to happen any time soon. +This loop is known to work with PHP 7.1 through PHP 8+. ### LoopInterface @@ -885,18 +820,17 @@ to remove a stream that was never added or is invalid has no effect. 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: +Once released, this project will follow [SemVer](https://semver.org/). +At the moment, this will install the latest development version: ```bash -composer require react/event-loop:^1.5 +composer require react/event-loop:^3@dev ``` 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 8+ and -HHVM. +extensions and supports running on PHP 7.1 through current PHP 8+. It's *highly recommended to use the latest supported PHP version* for this project. Installing any of the event loop extensions is suggested, but entirely optional. diff --git a/composer.json b/composer.json index 25a41fe1..6d31e81d 100644 --- a/composer.json +++ b/composer.json @@ -26,10 +26,10 @@ } ], "require": { - "php": ">=5.3.0" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + "phpunit/phpunit": "^9.6 || ^7.5" }, "suggest": { "ext-pcntl": "For signal handling support when using the StreamSelectLoop" diff --git a/examples/12-generate-yes.php b/examples/12-generate-yes.php index a57e8d6e..91442016 100644 --- a/examples/12-generate-yes.php +++ b/examples/12-generate-yes.php @@ -5,7 +5,7 @@ require __DIR__ . '/../vendor/autoload.php'; // data can be given as first argument or defaults to "y" -$data = (isset($argv[1]) ? $argv[1] : 'y') . "\n"; +$data = ($argv[1] ?? 'y') . "\n"; // repeat data X times in order to fill around 200 KB $data = str_repeat($data, round(200000 / strlen($data))); diff --git a/examples/91-benchmark-ticks.php b/examples/91-benchmark-ticks.php index e3dc2b1c..7a38f424 100644 --- a/examples/91-benchmark-ticks.php +++ b/examples/91-benchmark-ticks.php @@ -4,7 +4,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$n = isset($argv[1]) ? (int)$argv[1] : 1000 * 100; +$n = (int) ($argv[1] ?? 1000 * 100); for ($i = 0; $i < $n; ++$i) { Loop::futureTick(function () { }); diff --git a/examples/92-benchmark-timers.php b/examples/92-benchmark-timers.php index dd42ec77..ef838e60 100644 --- a/examples/92-benchmark-timers.php +++ b/examples/92-benchmark-timers.php @@ -4,7 +4,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$n = isset($argv[1]) ? (int)$argv[1] : 1000 * 100; +$n = (int) ($argv[1] ?? 1000 * 100); for ($i = 0; $i < $n; ++$i) { Loop::addTimer(0, function () { }); diff --git a/examples/93-benchmark-ticks-delay.php b/examples/93-benchmark-ticks-delay.php index 1976124f..28a99070 100644 --- a/examples/93-benchmark-ticks-delay.php +++ b/examples/93-benchmark-ticks-delay.php @@ -4,7 +4,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$ticks = isset($argv[1]) ? (int)$argv[1] : 1000 * 100; +$ticks = (int) ($argv[1] ?? 1000 * 100); $tick = function () use (&$tick, &$ticks) { if ($ticks > 0) { --$ticks; diff --git a/examples/94-benchmark-timers-delay.php b/examples/94-benchmark-timers-delay.php index dfe6c8c0..df237264 100644 --- a/examples/94-benchmark-timers-delay.php +++ b/examples/94-benchmark-timers-delay.php @@ -4,7 +4,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$ticks = isset($argv[1]) ? (int)$argv[1] : 1000 * 100; +$ticks = (int) ($argv[1] ?? 1000 * 100); $tick = function () use (&$tick, &$ticks) { if ($ticks > 0) { --$ticks; diff --git a/examples/95-benchmark-memory.php b/examples/95-benchmark-memory.php index 06735bd2..efd8c82d 100644 --- a/examples/95-benchmark-memory.php +++ b/examples/95-benchmark-memory.php @@ -14,14 +14,14 @@ require __DIR__ . '/../vendor/autoload.php'; $args = getopt('t:l:r:'); -$t = isset($args['t']) ? (int)$args['t'] : 0; +$t = (int) ($args['t'] ?? 0); $loop = isset($args['l']) && class_exists('React\EventLoop\\' . $args['l'] . 'Loop') ? 'React\EventLoop\\' . $args['l'] . 'Loop' : Loop::get(); if (!($loop instanceof LoopInterface)) { Loop::set(new $loop()); } -$r = isset($args['r']) ? (int)$args['r'] : 2; +$r = (int) ($args['r'] ?? 2); $runs = 0; diff --git a/phpunit.xml.legacy b/phpunit.xml.legacy index 03c2fed5..7c148001 100644 --- a/phpunit.xml.legacy +++ b/phpunit.xml.legacy @@ -2,7 +2,7 @@ diff --git a/src/ExtEvLoop.php b/src/ExtEvLoop.php index a3fcec68..363ad0c4 100644 --- a/src/ExtEvLoop.php +++ b/src/ExtEvLoop.php @@ -16,7 +16,7 @@ * that provides an interface to `libev` library. * `libev` itself supports a number of system-specific backends (epoll, kqueue). * - * This loop is known to work with PHP 5.4 through PHP 8+. + * This loop is known to work with PHP 7.1 through PHP 8+. * * @see http://php.net/manual/en/book.ev.php * @see https://bitbucket.org/osmanov/pecl-ev/overview @@ -41,12 +41,12 @@ class ExtEvLoop implements LoopInterface /** * @var EvIo[] */ - private $readStreams = array(); + private $readStreams = []; /** * @var EvIo[] */ - private $writeStreams = array(); + private $writeStreams = []; /** * @var bool @@ -61,7 +61,7 @@ class ExtEvLoop implements LoopInterface /** * @var \EvSignal[] */ - private $signalEvents = array(); + private $signalEvents = []; public function __construct() { @@ -138,13 +138,11 @@ public function addTimer($interval, $callback) { $timer = new Timer($interval, $callback, false); - $that = $this; - $timers = $this->timers; - $callback = function () use ($timer, $timers, $that) { + $callback = function () use ($timer) { \call_user_func($timer->getCallback(), $timer); - if ($timers->contains($timer)) { - $that->cancelTimer($timer); + if ($this->timers->contains($timer)) { + $this->cancelTimer($timer); } }; diff --git a/src/ExtEventLoop.php b/src/ExtEventLoop.php index b162a402..d6f24b2a 100644 --- a/src/ExtEventLoop.php +++ b/src/ExtEventLoop.php @@ -16,7 +16,7 @@ * that provides an interface to `libevent` library. * `libevent` itself supports a number of system-specific backends (epoll, kqueue). * - * This loop is known to work with PHP 5.4 through PHP 8+. + * This loop is known to work with PHP 7.1 through PHP 8+. * * @link https://pecl.php.net/package/event */ @@ -27,15 +27,15 @@ final class ExtEventLoop implements LoopInterface private $timerCallback; private $timerEvents; private $streamCallback; - private $readEvents = array(); - private $writeEvents = array(); - private $readListeners = array(); - private $writeListeners = array(); - private $readRefs = array(); - private $writeRefs = array(); + private $readEvents = []; + private $writeEvents = []; + private $readListeners = []; + private $writeListeners = []; + private $readRefs = []; + private $writeRefs = []; private $running; private $signals; - private $signalEvents = array(); + private $signalEvents = []; public function __construct() { @@ -67,8 +67,8 @@ public function __destruct() $this->timerEvents->detach($timer); } - $this->readEvents = array(); - $this->writeEvents = array(); + $this->readEvents = []; + $this->writeEvents = []; } public function addReadStream($stream, $listener) @@ -85,9 +85,7 @@ public function addReadStream($stream, $listener) // ext-event does not increase refcount on stream resources for PHP 7+ // manually keep track of stream resource to prevent premature garbage collection - if (\PHP_VERSION_ID >= 70000) { - $this->readRefs[$key] = $stream; - } + $this->readRefs[$key] = $stream; } public function addWriteStream($stream, $listener) @@ -104,9 +102,7 @@ public function addWriteStream($stream, $listener) // ext-event does not increase refcount on stream resources for PHP 7+ // manually keep track of stream resource to prevent premature garbage collection - if (\PHP_VERSION_ID >= 70000) { - $this->writeRefs[$key] = $stream; - } + $this->writeRefs[$key] = $stream; } public function removeReadStream($stream) @@ -173,7 +169,7 @@ public function addSignal($signal, $listener) $this->signals->add($signal, $listener); if (!isset($this->signalEvents[$signal])) { - $this->signalEvents[$signal] = Event::signal($this->eventBase, $signal, array($this->signals, 'call')); + $this->signalEvents[$signal] = Event::signal($this->eventBase, $signal, [$this->signals, 'call']); $this->signalEvents[$signal]->add(); } } @@ -239,11 +235,10 @@ private function scheduleTimer(TimerInterface $timer) */ private function createTimerCallback() { - $timers = $this->timerEvents; - $this->timerCallback = function ($_, $__, $timer) use ($timers) { + $this->timerCallback = function ($_, $__, $timer) { \call_user_func($timer->getCallback(), $timer); - if (!$timer->isPeriodic() && $timers->contains($timer)) { + if (!$timer->isPeriodic() && $this->timerEvents->contains($timer)) { $this->cancelTimer($timer); } }; @@ -258,17 +253,15 @@ private function createTimerCallback() */ private function createStreamCallback() { - $read =& $this->readListeners; - $write =& $this->writeListeners; - $this->streamCallback = function ($stream, $flags) use (&$read, &$write) { + $this->streamCallback = function ($stream, $flags) { $key = (int) $stream; - if (Event::READ === (Event::READ & $flags) && isset($read[$key])) { - \call_user_func($read[$key], $stream); + if (Event::READ === (Event::READ & $flags) && isset($this->readListeners[$key])) { + \call_user_func($this->readListeners[$key], $stream); } - if (Event::WRITE === (Event::WRITE & $flags) && isset($write[$key])) { - \call_user_func($write[$key], $stream); + if (Event::WRITE === (Event::WRITE & $flags) && isset($this->writeListeners[$key])) { + \call_user_func($this->writeListeners[$key], $stream); } }; } diff --git a/src/ExtLibevLoop.php b/src/ExtLibevLoop.php deleted file mode 100644 index c303fdd5..00000000 --- a/src/ExtLibevLoop.php +++ /dev/null @@ -1,201 +0,0 @@ -loop = new EventLoop(); - $this->futureTickQueue = new FutureTickQueue(); - $this->timerEvents = new SplObjectStorage(); - $this->signals = new SignalsHandler(); - } - - public function addReadStream($stream, $listener) - { - if (isset($this->readEvents[(int) $stream])) { - return; - } - - $callback = function () use ($stream, $listener) { - \call_user_func($listener, $stream); - }; - - $event = new IOEvent($callback, $stream, IOEvent::READ); - $this->loop->add($event); - - $this->readEvents[(int) $stream] = $event; - } - - public function addWriteStream($stream, $listener) - { - if (isset($this->writeEvents[(int) $stream])) { - return; - } - - $callback = function () use ($stream, $listener) { - \call_user_func($listener, $stream); - }; - - $event = new IOEvent($callback, $stream, IOEvent::WRITE); - $this->loop->add($event); - - $this->writeEvents[(int) $stream] = $event; - } - - public function removeReadStream($stream) - { - $key = (int) $stream; - - if (isset($this->readEvents[$key])) { - $this->readEvents[$key]->stop(); - $this->loop->remove($this->readEvents[$key]); - unset($this->readEvents[$key]); - } - } - - public function removeWriteStream($stream) - { - $key = (int) $stream; - - if (isset($this->writeEvents[$key])) { - $this->writeEvents[$key]->stop(); - $this->loop->remove($this->writeEvents[$key]); - unset($this->writeEvents[$key]); - } - } - - public function addTimer($interval, $callback) - { - $timer = new Timer( $interval, $callback, false); - - $that = $this; - $timers = $this->timerEvents; - $callback = function () use ($timer, $timers, $that) { - \call_user_func($timer->getCallback(), $timer); - - if ($timers->contains($timer)) { - $that->cancelTimer($timer); - } - }; - - $event = new TimerEvent($callback, $timer->getInterval()); - $this->timerEvents->attach($timer, $event); - $this->loop->add($event); - - return $timer; - } - - public function addPeriodicTimer($interval, $callback) - { - $timer = new Timer($interval, $callback, true); - - $callback = function () use ($timer) { - \call_user_func($timer->getCallback(), $timer); - }; - - $event = new TimerEvent($callback, $timer->getInterval(), $timer->getInterval()); - $this->timerEvents->attach($timer, $event); - $this->loop->add($event); - - return $timer; - } - - public function cancelTimer(TimerInterface $timer) - { - if (isset($this->timerEvents[$timer])) { - $this->loop->remove($this->timerEvents[$timer]); - $this->timerEvents->detach($timer); - } - } - - public function futureTick($listener) - { - $this->futureTickQueue->add($listener); - } - - public function addSignal($signal, $listener) - { - $this->signals->add($signal, $listener); - - if (!isset($this->signalEvents[$signal])) { - $signals = $this->signals; - $this->signalEvents[$signal] = new SignalEvent(function () use ($signals, $signal) { - $signals->call($signal); - }, $signal); - $this->loop->add($this->signalEvents[$signal]); - } - } - - public function removeSignal($signal, $listener) - { - $this->signals->remove($signal, $listener); - - if (isset($this->signalEvents[$signal]) && $this->signals->count($signal) === 0) { - $this->signalEvents[$signal]->stop(); - $this->loop->remove($this->signalEvents[$signal]); - unset($this->signalEvents[$signal]); - } - } - - public function run() - { - $this->running = true; - - while ($this->running) { - $this->futureTickQueue->tick(); - - $flags = EventLoop::RUN_ONCE; - if (!$this->running || !$this->futureTickQueue->isEmpty()) { - $flags |= EventLoop::RUN_NOWAIT; - } elseif (!$this->readEvents && !$this->writeEvents && !$this->timerEvents->count() && $this->signals->isEmpty()) { - break; - } - - $this->loop->run($flags); - } - } - - public function stop() - { - $this->running = false; - } -} diff --git a/src/ExtLibeventLoop.php b/src/ExtLibeventLoop.php deleted file mode 100644 index 099293a4..00000000 --- a/src/ExtLibeventLoop.php +++ /dev/null @@ -1,285 +0,0 @@ -eventBase = \event_base_new(); - $this->futureTickQueue = new FutureTickQueue(); - $this->timerEvents = new SplObjectStorage(); - $this->signals = new SignalsHandler(); - - $this->createTimerCallback(); - $this->createStreamCallback(); - } - - public function addReadStream($stream, $listener) - { - $key = (int) $stream; - if (isset($this->readListeners[$key])) { - return; - } - - $event = \event_new(); - \event_set($event, $stream, \EV_PERSIST | \EV_READ, $this->streamCallback); - \event_base_set($event, $this->eventBase); - \event_add($event); - - $this->readEvents[$key] = $event; - $this->readListeners[$key] = $listener; - } - - public function addWriteStream($stream, $listener) - { - $key = (int) $stream; - if (isset($this->writeListeners[$key])) { - return; - } - - $event = \event_new(); - \event_set($event, $stream, \EV_PERSIST | \EV_WRITE, $this->streamCallback); - \event_base_set($event, $this->eventBase); - \event_add($event); - - $this->writeEvents[$key] = $event; - $this->writeListeners[$key] = $listener; - } - - public function removeReadStream($stream) - { - $key = (int) $stream; - - if (isset($this->readListeners[$key])) { - $event = $this->readEvents[$key]; - \event_del($event); - \event_free($event); - - unset( - $this->readEvents[$key], - $this->readListeners[$key] - ); - } - } - - public function removeWriteStream($stream) - { - $key = (int) $stream; - - if (isset($this->writeListeners[$key])) { - $event = $this->writeEvents[$key]; - \event_del($event); - \event_free($event); - - unset( - $this->writeEvents[$key], - $this->writeListeners[$key] - ); - } - } - - public function addTimer($interval, $callback) - { - $timer = new Timer($interval, $callback, false); - - $this->scheduleTimer($timer); - - return $timer; - } - - public function addPeriodicTimer($interval, $callback) - { - $timer = new Timer($interval, $callback, true); - - $this->scheduleTimer($timer); - - return $timer; - } - - public function cancelTimer(TimerInterface $timer) - { - if ($this->timerEvents->contains($timer)) { - $event = $this->timerEvents[$timer]; - \event_del($event); - \event_free($event); - - $this->timerEvents->detach($timer); - } - } - - public function futureTick($listener) - { - $this->futureTickQueue->add($listener); - } - - public function addSignal($signal, $listener) - { - $this->signals->add($signal, $listener); - - if (!isset($this->signalEvents[$signal])) { - $this->signalEvents[$signal] = \event_new(); - \event_set($this->signalEvents[$signal], $signal, \EV_PERSIST | \EV_SIGNAL, array($this->signals, 'call')); - \event_base_set($this->signalEvents[$signal], $this->eventBase); - \event_add($this->signalEvents[$signal]); - } - } - - public function removeSignal($signal, $listener) - { - $this->signals->remove($signal, $listener); - - if (isset($this->signalEvents[$signal]) && $this->signals->count($signal) === 0) { - \event_del($this->signalEvents[$signal]); - \event_free($this->signalEvents[$signal]); - unset($this->signalEvents[$signal]); - } - } - - public function run() - { - $this->running = true; - - while ($this->running) { - $this->futureTickQueue->tick(); - - $flags = \EVLOOP_ONCE; - if (!$this->running || !$this->futureTickQueue->isEmpty()) { - $flags |= \EVLOOP_NONBLOCK; - } elseif (!$this->readEvents && !$this->writeEvents && !$this->timerEvents->count() && $this->signals->isEmpty()) { - break; - } - - \event_base_loop($this->eventBase, $flags); - } - } - - public function stop() - { - $this->running = false; - } - - /** - * Schedule a timer for execution. - * - * @param TimerInterface $timer - */ - private function scheduleTimer(TimerInterface $timer) - { - $this->timerEvents[$timer] = $event = \event_timer_new(); - - \event_timer_set($event, $this->timerCallback, $timer); - \event_base_set($event, $this->eventBase); - \event_add($event, $timer->getInterval() * self::MICROSECONDS_PER_SECOND); - } - - /** - * Create a callback used as the target of timer events. - * - * A reference is kept to the callback for the lifetime of the loop - * to prevent "Cannot destroy active lambda function" fatal error from - * the event extension. - */ - private function createTimerCallback() - { - $that = $this; - $timers = $this->timerEvents; - $this->timerCallback = function ($_, $__, $timer) use ($timers, $that) { - \call_user_func($timer->getCallback(), $timer); - - // Timer already cancelled ... - if (!$timers->contains($timer)) { - return; - } - - // Reschedule periodic timers ... - if ($timer->isPeriodic()) { - \event_add( - $timers[$timer], - $timer->getInterval() * ExtLibeventLoop::MICROSECONDS_PER_SECOND - ); - - // Clean-up one shot timers ... - } else { - $that->cancelTimer($timer); - } - }; - } - - /** - * Create a callback used as the target of stream events. - * - * A reference is kept to the callback for the lifetime of the loop - * to prevent "Cannot destroy active lambda function" fatal error from - * the event extension. - */ - private function createStreamCallback() - { - $read =& $this->readListeners; - $write =& $this->writeListeners; - $this->streamCallback = function ($stream, $flags) use (&$read, &$write) { - $key = (int) $stream; - - if (\EV_READ === (\EV_READ & $flags) && isset($read[$key])) { - \call_user_func($read[$key], $stream); - } - - if (\EV_WRITE === (\EV_WRITE & $flags) && isset($write[$key])) { - \call_user_func($write[$key], $stream); - } - }; - } -} diff --git a/src/ExtUvLoop.php b/src/ExtUvLoop.php index 4434720d..e9e79524 100644 --- a/src/ExtUvLoop.php +++ b/src/ExtUvLoop.php @@ -13,7 +13,7 @@ * that provides an interface to `libuv` library. * `libuv` itself supports a number of system-specific backends (epoll, kqueue). * - * This loop is known to work with PHP 7+. + * This loop is known to work with PHP 7.1 through PHP 8+. * * @see https://github.com/bwoebi/php-uv */ @@ -22,12 +22,12 @@ final class ExtUvLoop implements LoopInterface private $uv; private $futureTickQueue; private $timers; - private $streamEvents = array(); - private $readStreams = array(); - private $writeStreams = array(); + private $streamEvents = []; + private $readStreams = []; + private $writeStreams = []; private $running; private $signals; - private $signalEvents = array(); + private $signalEvents = []; private $streamListener; public function __construct() @@ -114,13 +114,11 @@ public function addTimer($interval, $callback) { $timer = new Timer($interval, $callback, false); - $that = $this; - $timers = $this->timers; - $callback = function () use ($timer, $timers, $that) { + $callback = function () use ($timer) { \call_user_func($timer->getCallback(), $timer); - if ($timers->contains($timer)) { - $that->cancelTimer($timer); + if ($this->timers->contains($timer)) { + $this->cancelTimer($timer); } }; @@ -184,10 +182,9 @@ public function addSignal($signal, $listener) $this->signals->add($signal, $listener); if (!isset($this->signalEvents[$signal])) { - $signals = $this->signals; $this->signalEvents[$signal] = \uv_signal_init($this->uv); - \uv_signal_start($this->signalEvents[$signal], function () use ($signals, $signal) { - $signals->call($signal); + \uv_signal_start($this->signalEvents[$signal], function () use ($signal) { + $this->signals->call($signal); }, $signal); } } diff --git a/src/Factory.php b/src/Factory.php deleted file mode 100644 index 30bbfd7c..00000000 --- a/src/Factory.php +++ /dev/null @@ -1,75 +0,0 @@ -run(); } }); @@ -83,11 +82,7 @@ public static function set(LoopInterface $loop) */ public static function addReadStream($stream, $listener) { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - self::$instance->addReadStream($stream, $listener); + (self::$instance ?? self::get())->addReadStream($stream, $listener); } /** @@ -101,11 +96,7 @@ public static function addReadStream($stream, $listener) */ public static function addWriteStream($stream, $listener) { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - self::$instance->addWriteStream($stream, $listener); + (self::$instance ?? self::get())->addWriteStream($stream, $listener); } /** @@ -146,11 +137,7 @@ public static function removeWriteStream($stream) */ public static function addTimer($interval, $callback) { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - return self::$instance->addTimer($interval, $callback); + return (self::$instance ?? self::get())->addTimer($interval, $callback); } /** @@ -163,11 +150,7 @@ public static function addTimer($interval, $callback) */ public static function addPeriodicTimer($interval, $callback) { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - return self::$instance->addPeriodicTimer($interval, $callback); + return (self::$instance ?? self::get())->addPeriodicTimer($interval, $callback); } /** @@ -193,12 +176,7 @@ public static function cancelTimer(TimerInterface $timer) */ public static function futureTick($listener) { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - - self::$instance->futureTick($listener); + (self::$instance ?? self::get())->futureTick($listener); } /** @@ -211,12 +189,7 @@ public static function futureTick($listener) */ public static function addSignal($signal, $listener) { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - - self::$instance->addSignal($signal, $listener); + (self::$instance ?? self::get())->addSignal($signal, $listener); } /** @@ -242,12 +215,7 @@ public static function removeSignal($signal, $listener) */ public static function run() { - // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls) - if (self::$instance === null) { - self::get(); - } - - self::$instance->run(); + (self::$instance ?? self::get())->run(); } /** @@ -263,4 +231,26 @@ public static function stop() self::$instance->stop(); } } + + /** + * @return LoopInterface + */ + private static function create() + { + // @codeCoverageIgnoreStart + if (\function_exists('uv_loop_new')) { + return new ExtUvLoop(); + } + + if (\class_exists('EvLoop', false)) { + return new ExtEvLoop(); + } + + if (\class_exists('EventBase', false)) { + return new ExtEventLoop(); + } + + return new StreamSelectLoop(); + // @codeCoverageIgnoreEnd + } } diff --git a/src/SignalsHandler.php b/src/SignalsHandler.php index 10d125df..e9b245ea 100644 --- a/src/SignalsHandler.php +++ b/src/SignalsHandler.php @@ -7,12 +7,12 @@ */ final class SignalsHandler { - private $signals = array(); + private $signals = []; public function add($signal, $listener) { if (!isset($this->signals[$signal])) { - $this->signals[$signal] = array(); + $this->signals[$signal] = []; } if (\in_array($listener, $this->signals[$signal])) { diff --git a/src/StreamSelectLoop.php b/src/StreamSelectLoop.php index 1686fd74..41dd2cb3 100644 --- a/src/StreamSelectLoop.php +++ b/src/StreamSelectLoop.php @@ -12,12 +12,11 @@ * This uses the [`stream_select()`](https://www.php.net/manual/en/function.stream-select.php) * function and is the only implementation that works out of the box with PHP. * - * This event loop works out of the box on PHP 5.4 through PHP 8+ and HHVM. + * This event loop works out of the box on any PHP version. * This means that no installation is required and this library works on all * platforms and supported PHP versions. - * Accordingly, the [`Loop` class](#loop) and the deprecated [`Factory`](#factory) - * will use this event loop by default if you do not install any of the event loop - * extensions listed below. + * Accordingly, the [`Loop` class](#loop) will use this event loop by default if + * you do not install any of the event loop extensions listed below. * * Under the hood, it does a simple `select` system call. * This system call is limited to the maximum file descriptor number of @@ -57,10 +56,10 @@ final class StreamSelectLoop implements LoopInterface private $futureTickQueue; private $timers; - private $readStreams = array(); - private $readListeners = array(); - private $writeStreams = array(); - private $writeListeners = array(); + private $readStreams = []; + private $readListeners = []; + private $writeStreams = []; + private $writeListeners = []; private $running; private $pcntl = false; private $pcntlPoll = false; @@ -158,7 +157,7 @@ public function addSignal($signal, $listener) $this->signals->add($signal, $listener); if ($first) { - \pcntl_signal($signal, array($this->signals, 'call')); + \pcntl_signal($signal, [$this->signals, 'call']); } } @@ -279,7 +278,7 @@ private function streamSelect(array &$read, array &$write, $timeout) // @link https://docs.microsoft.com/de-de/windows/win32/api/winsock2/nf-winsock2-select $except = null; if (\DIRECTORY_SEPARATOR === '\\') { - $except = array(); + $except = []; foreach ($write as $key => $socket) { if (!isset($read[$key]) && @\ftell($socket) === 0) { $except[$key] = $socket; @@ -303,13 +302,10 @@ private function streamSelect(array &$read, array &$write, $timeout) try { $ret = \stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout); \restore_error_handler(); - } catch (\Throwable $e) { // @codeCoverageIgnoreStart + } catch (\Throwable $e) { \restore_error_handler(); throw $e; - } catch (\Exception $e) { - \restore_error_handler(); - throw $e; - } // @codeCoverageIgnoreEnd + } if ($except) { $write = \array_merge($write, $except); diff --git a/src/Timer/Timers.php b/src/Timer/Timers.php index 53c46d03..c9ae5ed8 100644 --- a/src/Timer/Timers.php +++ b/src/Timer/Timers.php @@ -15,8 +15,8 @@ final class Timers { private $time; - private $timers = array(); - private $schedule = array(); + private $timers = []; + private $schedule = []; private $sorted = true; private $useHighResolution; diff --git a/tests/AbstractLoopTest.php b/tests/AbstractLoopTest.php index a3511d66..e89a8371 100644 --- a/tests/AbstractLoopTest.php +++ b/tests/AbstractLoopTest.php @@ -50,16 +50,15 @@ public function testAddReadStreamTriggersWhenSocketReceivesData() { list ($input, $output) = $this->createSocketPair(); - $loop = $this->loop; - $timeout = $loop->addTimer(0.1, function () use ($input, $loop) { - $loop->removeReadStream($input); + $timeout = $this->loop->addTimer(0.1, function () use ($input) { + $this->loop->removeReadStream($input); }); $called = 0; - $this->loop->addReadStream($input, function () use (&$called, $loop, $input, $timeout) { + $this->loop->addReadStream($input, function () use (&$called, $input, $timeout) { ++$called; - $loop->removeReadStream($input); - $loop->cancelTimer($timeout); + $this->loop->removeReadStream($input); + $this->loop->cancelTimer($timeout); }); fwrite($output, "foo\n"); @@ -73,16 +72,15 @@ public function testAddReadStreamTriggersWhenSocketCloses() { list ($input, $output) = $this->createSocketPair(); - $loop = $this->loop; - $timeout = $loop->addTimer(0.1, function () use ($input, $loop) { - $loop->removeReadStream($input); + $timeout = $this->loop->addTimer(0.1, function () use ($input) { + $this->loop->removeReadStream($input); }); $called = 0; - $this->loop->addReadStream($input, function () use (&$called, $loop, $input, $timeout) { + $this->loop->addReadStream($input, function () use (&$called, $input, $timeout) { ++$called; - $loop->removeReadStream($input); - $loop->cancelTimer($timeout); + $this->loop->removeReadStream($input); + $this->loop->cancelTimer($timeout); }); fclose($output); @@ -99,16 +97,15 @@ public function testAddWriteStreamTriggersWhenSocketConnectionSucceeds() $errno = $errstr = null; $connecting = stream_socket_client(stream_socket_get_name($server, false), $errno, $errstr, 0, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT); - $loop = $this->loop; - $timeout = $loop->addTimer(0.1, function () use ($connecting, $loop) { - $loop->removeWriteStream($connecting); + $timeout = $this->loop->addTimer(0.1, function () use ($connecting) { + $this->loop->removeWriteStream($connecting); }); $called = 0; - $this->loop->addWriteStream($connecting, function () use (&$called, $loop, $connecting, $timeout) { + $this->loop->addWriteStream($connecting, function () use (&$called, $connecting, $timeout) { ++$called; - $loop->removeWriteStream($connecting); - $loop->cancelTimer($timeout); + $this->loop->removeWriteStream($connecting); + $this->loop->cancelTimer($timeout); }); $this->loop->run(); @@ -118,10 +115,6 @@ public function testAddWriteStreamTriggersWhenSocketConnectionSucceeds() public function testAddWriteStreamTriggersWhenSocketConnectionRefused() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('Not supported on HHVM'); - } - // first verify the operating system actually refuses the connection and no firewall is in place // use higher timeout because Windows retires multiple times and has a noticeable delay // @link https://stackoverflow.com/questions/19440364/why-do-failed-attempts-of-socket-connect-take-1-sec-on-windows @@ -132,16 +125,15 @@ public function testAddWriteStreamTriggersWhenSocketConnectionRefused() $connecting = stream_socket_client('127.0.0.1:1', $errno, $errstr, 0, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT); - $loop = $this->loop; - $timeout = $loop->addTimer(10.0, function () use ($connecting, $loop) { - $loop->removeWriteStream($connecting); + $timeout = $this->loop->addTimer(10.0, function () use ($connecting) { + $this->loop->removeWriteStream($connecting); }); $called = 0; - $this->loop->addWriteStream($connecting, function () use (&$called, $loop, $connecting, $timeout) { + $this->loop->addWriteStream($connecting, function () use (&$called, $connecting, $timeout) { ++$called; - $loop->removeWriteStream($connecting); - $loop->cancelTimer($timeout); + $this->loop->removeWriteStream($connecting); + $this->loop->cancelTimer($timeout); }); $this->loop->run(); @@ -205,16 +197,14 @@ private function subAddReadStreamReceivesDataFromStreamReference() fwrite($input, 'hello'); fclose($input); - $loop = $this->loop; - $received =& $this->received; - $loop->addReadStream($output, function ($output) use ($loop, &$received) { + $this->loop->addReadStream($output, function ($output) { $chunk = fread($output, 1024); if ($chunk === '') { - $received .= 'X'; - $loop->removeReadStream($output); + $this->received .= 'X'; + $this->loop->removeReadStream($output); fclose($output); } else { - $received .= '[' . $chunk . ']'; + $this->received .= '[' . $chunk . ']'; } }); } @@ -351,10 +341,9 @@ public function testRemoveReadAndWriteStreamFromLoopOnceResourceClosesEndsLoop() $this->loop->addWriteStream($stream, function () { }); // remove stream when the stream is readable (closes) - $loop = $this->loop; - $loop->addReadStream($stream, function ($stream) use ($loop) { - $loop->removeReadStream($stream); - $loop->removeWriteStream($stream); + $this->loop->addReadStream($stream, function ($stream) { + $this->loop->removeReadStream($stream); + $this->loop->removeWriteStream($stream); fclose($stream); }); @@ -374,15 +363,14 @@ public function testRemoveReadAndWriteStreamFromLoopOnceResourceClosesOnEndOfFil $this->loop->addWriteStream($stream, function () { }); // remove stream when the stream is readable (closes) - $loop = $this->loop; - $loop->addReadStream($stream, function ($stream) use ($loop) { + $this->loop->addReadStream($stream, function ($stream) { $data = fread($stream, 1024); if ($data !== '') { return; } - $loop->removeReadStream($stream); - $loop->removeWriteStream($stream); + $this->loop->removeReadStream($stream); + $this->loop->removeWriteStream($stream); fclose($stream); }); @@ -405,10 +393,9 @@ public function testRemoveReadAndWriteStreamFromLoopWithClosingResourceEndsLoop( $this->loop->addWriteStream($stream, function () { }); // remove stream when the stream is readable (closes) - $loop = $this->loop; - $loop->addReadStream($stream, function ($stream) use ($loop) { - $loop->removeReadStream($stream); - $loop->removeWriteStream($stream); + $this->loop->addReadStream($stream, function ($stream) { + $this->loop->removeReadStream($stream); + $this->loop->removeWriteStream($stream); fclose($stream); }); @@ -437,9 +424,8 @@ public function runShouldReturnWhenNoMoreFds() { list ($input, $output) = $this->createSocketPair(); - $loop = $this->loop; - $this->loop->addReadStream($input, function ($stream) use ($loop) { - $loop->removeReadStream($stream); + $this->loop->addReadStream($input, function ($stream) { + $this->loop->removeReadStream($stream); }); fwrite($output, "foo\n"); @@ -452,9 +438,8 @@ public function stopShouldStopRunningLoop() { list ($input, $output) = $this->createSocketPair(); - $loop = $this->loop; - $this->loop->addReadStream($input, function ($stream) use ($loop) { - $loop->stop(); + $this->loop->addReadStream($input, function ($stream) { + $this->loop->stop(); }); fwrite($output, "foo\n"); @@ -464,18 +449,16 @@ public function stopShouldStopRunningLoop() public function testStopShouldPreventRunFromBlocking() { - $that = $this; $this->loop->addTimer( 1, - function () use ($that) { - $that->fail('Timer was executed.'); + function () { + $this->fail('Timer was executed.'); } ); - $loop = $this->loop; $this->loop->futureTick( - function () use ($loop) { - $loop->stop(); + function () { + $this->loop->stop(); } ); @@ -489,38 +472,34 @@ public function testIgnoreRemovedCallback() list ($input2, $output2) = $this->createSocketPair(); $called = false; - - $loop = $this->loop; - $loop->addReadStream($input1, function ($stream) use (& $called, $loop, $input2) { + $this->loop->addReadStream($input1, function ($stream) use (&$called, $input2) { // stream1 is readable, remove stream2 as well => this will invalidate its callback - $loop->removeReadStream($stream); - $loop->removeReadStream($input2); + $this->loop->removeReadStream($stream); + $this->loop->removeReadStream($input2); $called = true; }); // this callback would have to be called as well, but the first stream already removed us - $that = $this; - $loop->addReadStream($input2, function () use (& $called, $that) { + $this->loop->addReadStream($input2, function () use (&$called) { if ($called) { - $that->fail('Callback 2 must not be called after callback 1 was called'); + $this->fail('Callback 2 must not be called after callback 1 was called'); } }); fwrite($output1, "foo\n"); fwrite($output2, "foo\n"); - $loop->run(); + $this->loop->run(); $this->assertTrue($called); } public function testFutureTickEventGeneratedByFutureTick() { - $loop = $this->loop; $this->loop->futureTick( - function () use ($loop) { - $loop->futureTick( + function () { + $this->loop->futureTick( function () { echo 'future-tick' . PHP_EOL; } @@ -583,19 +562,18 @@ public function testRecursiveFutureTick() { list ($stream) = $this->createSocketPair(); - $loop = $this->loop; $this->loop->addWriteStream( $stream, - function () use ($stream, $loop) { + function () use ($stream) { echo 'stream' . PHP_EOL; - $loop->removeWriteStream($stream); + $this->loop->removeWriteStream($stream); } ); $this->loop->futureTick( - function () use ($loop) { + function () { echo 'future-tick-1' . PHP_EOL; - $loop->futureTick( + $this->loop->futureTick( function () { echo 'future-tick-2' . PHP_EOL; } @@ -612,12 +590,11 @@ public function testRunWaitsForFutureTickEvents() { list ($stream) = $this->createSocketPair(); - $loop = $this->loop; $this->loop->addWriteStream( $stream, - function () use ($stream, $loop) { - $loop->removeWriteStream($stream); - $loop->futureTick( + function () use ($stream) { + $this->loop->removeWriteStream($stream); + $this->loop->futureTick( function () { echo 'future-tick' . PHP_EOL; } @@ -632,11 +609,10 @@ function () { public function testFutureTickEventGeneratedByTimer() { - $loop = $this->loop; $this->loop->addTimer( 0.001, - function () use ($loop) { - $loop->futureTick( + function () { + $this->loop->futureTick( function () { echo 'future-tick' . PHP_EOL; } @@ -675,12 +651,11 @@ public function testSignal() $calledShouldNot = false; }); - $loop = $this->loop; - $this->loop->addSignal(SIGUSR1, $func1 = function () use (&$func1, &$func2, &$called, $timer, $loop) { + $this->loop->addSignal(SIGUSR1, $func1 = function () use (&$func1, &$func2, &$called, $timer) { $called = true; - $loop->removeSignal(SIGUSR1, $func1); - $loop->removeSignal(SIGUSR2, $func2); - $loop->cancelTimer($timer); + $this->loop->removeSignal(SIGUSR1, $func1); + $this->loop->removeSignal(SIGUSR2, $func2); + $this->loop->cancelTimer($timer); }); $this->loop->futureTick(function () { @@ -714,9 +689,8 @@ public function testSignalMultipleUsagesForTheSameListener() $this->loop->addTimer(0.4, function () { posix_kill(posix_getpid(), SIGUSR1); }); - $loop = $this->loop; - $this->loop->addTimer(0.9, function () use (&$func, $loop) { - $loop->removeSignal(SIGUSR1, $func); + $this->loop->addTimer(0.9, function () use (&$func) { + $this->loop->removeSignal(SIGUSR1, $func); }); $this->loop->run(); @@ -733,12 +707,11 @@ public function testSignalsKeepTheLoopRunning() $this->markTestSkipped('Signal handling with StreamSelectLoop requires pcntl_signal() and pcntl_signal_dispatch(), see also disable_functions'); } - $loop = $this->loop; $function = function () {}; $this->loop->addSignal(SIGUSR1, $function); - $this->loop->addTimer(1.5, function () use ($function, $loop) { - $loop->removeSignal(SIGUSR1, $function); - $loop->stop(); + $this->loop->addTimer(1.5, function () use ($function) { + $this->loop->removeSignal(SIGUSR1, $function); + $this->loop->stop(); }); $this->assertRunSlowerThan(1.4); @@ -753,11 +726,10 @@ public function testSignalsKeepTheLoopRunningAndRemovingItStopsTheLoop() $this->markTestSkipped('Signal handling with StreamSelectLoop requires pcntl_signal() and pcntl_signal_dispatch(), see also disable_functions'); } - $loop = $this->loop; $function = function () {}; $this->loop->addSignal(SIGUSR1, $function); - $this->loop->addTimer(1.5, function () use ($function, $loop) { - $loop->removeSignal(SIGUSR1, $function); + $this->loop->addTimer(1.5, function () use ($function) { + $this->loop->removeSignal(SIGUSR1, $function); }); $this->assertRunFasterThan(1.6); @@ -767,12 +739,11 @@ public function testTimerIntervalCanBeFarInFuture() { // Maximum interval for ExtUvLoop implementation $interval = ((int) (PHP_INT_MAX / 1000)) - 1; - $loop = $this->loop; // start a timer very far in the future $timer = $this->loop->addTimer($interval, function () { }); - $this->loop->futureTick(function () use ($timer, $loop) { - $loop->cancelTimer($timer); + $this->loop->futureTick(function () use ($timer) { + $this->loop->cancelTimer($timer); }); $this->assertRunFasterThan($this->tickTimeout); diff --git a/tests/BinTest.php b/tests/BinTest.php index 6f8231b8..ebbad5e5 100644 --- a/tests/BinTest.php +++ b/tests/BinTest.php @@ -9,10 +9,6 @@ class BinTest extends TestCase */ public function setUpBin() { - if (!defined('PHP_BINARY') || defined('HHVM_VERSION')) { - $this->markTestSkipped('Tests not supported on legacy PHP 5.3 or HHVM'); - } - chdir(__DIR__ . '/bin/'); } diff --git a/tests/ExtEventLoopTest.php b/tests/ExtEventLoopTest.php index af4caa13..ce40ba58 100644 --- a/tests/ExtEventLoopTest.php +++ b/tests/ExtEventLoopTest.php @@ -70,29 +70,4 @@ public function writeToStream($stream, $content) fwrite($stream, $content); } - - /** - * @group epoll-readable-error - */ - public function testCanUseReadableStreamWithFeatureFds() - { - if (PHP_VERSION_ID > 70000) { - $this->markTestSkipped('Memory stream not supported'); - } - - $this->loop = $this->createLoop(true); - - $input = fopen('php://temp/maxmemory:0', 'r+'); - - fwrite($input, 'x'); - ftruncate($input, 0); - - $this->loop->addReadStream($input, $this->expectCallableExactly(2)); - - fwrite($input, "foo\n"); - $this->tickLoop($this->loop); - - fwrite($input, "bar\n"); - $this->tickLoop($this->loop); - } } diff --git a/tests/ExtLibevLoopTest.php b/tests/ExtLibevLoopTest.php deleted file mode 100644 index 19a5e876..00000000 --- a/tests/ExtLibevLoopTest.php +++ /dev/null @@ -1,22 +0,0 @@ -markTestSkipped('libev tests skipped because ext-libev is not installed.'); - } - - return new ExtLibevLoop(); - } - - public function testLibEvConstructor() - { - $loop = new ExtLibevLoop(); - } -} diff --git a/tests/ExtLibeventLoopTest.php b/tests/ExtLibeventLoopTest.php deleted file mode 100644 index 524e0548..00000000 --- a/tests/ExtLibeventLoopTest.php +++ /dev/null @@ -1,63 +0,0 @@ -markTestSkipped('libevent tests skipped on linux due to linux epoll issues.'); - } - - if (!function_exists('event_base_new')) { - $this->markTestSkipped('libevent tests skipped because ext-libevent is not installed.'); - } - - return new ExtLibeventLoop(); - } - - /** - * @after - */ - public function tearDownFile() - { - if ($this->fifoPath !== null && file_exists($this->fifoPath)) { - unlink($this->fifoPath); - } - } - - public function createStream() - { - if ('Linux' !== PHP_OS) { - return parent::createStream(); - } - - $this->fifoPath = tempnam(sys_get_temp_dir(), 'react-'); - assert(is_string($this->fifoPath)); - - unlink($this->fifoPath); - - // Use a FIFO on linux to get around lack of support for disk-based file - // descriptors when using the EPOLL back-end. - posix_mkfifo($this->fifoPath, 0600); - - $stream = fopen($this->fifoPath, 'r+'); - - return $stream; - } - - public function writeToStream($stream, $content) - { - if ('Linux' !== PHP_OS) { - return parent::writeToStream($stream, $content); - } - - fwrite($stream, $content); - } -} diff --git a/tests/ExtUvLoopTest.php b/tests/ExtUvLoopTest.php index 267eddf1..45b251ef 100644 --- a/tests/ExtUvLoopTest.php +++ b/tests/ExtUvLoopTest.php @@ -45,51 +45,49 @@ public function intervalProvider() $tenMillionsIntMax = PHP_INT_MAX + 10000000; $tenThousandsTimesIntMax = PHP_INT_MAX * 1000; - return array( - array( - $oversizeInterval, - "Interval overflow, value must be lower than '{$maxValue}', but '{$oversizeInterval}' passed." - ), - array( - $oneMaxValue, - "Interval overflow, value must be lower than '{$maxValue}', but '{$oneMaxValue}' passed.", - ), - array( - $tenMaxValue, - "Interval overflow, value must be lower than '{$maxValue}', but '{$tenMaxValue}' passed.", - ), - array( - $tenMillionsMaxValue, - "Interval overflow, value must be lower than '{$maxValue}', but '{$tenMillionsMaxValue}' passed.", - ), - array( - $intMax, - "Interval overflow, value must be lower than '{$maxValue}', but '{$intMax}' passed.", - ), - array( - $oneIntMax, - "Interval overflow, value must be lower than '{$maxValue}', but '{$oneIntMax}' passed.", - ), - array( - $tenIntMax, - "Interval overflow, value must be lower than '{$maxValue}', but '{$tenIntMax}' passed.", - ), - array( - $oneHundredIntMax, - "Interval overflow, value must be lower than '{$maxValue}', but '{$oneHundredIntMax}' passed.", - ), - array( - $oneThousandIntMax, - "Interval overflow, value must be lower than '{$maxValue}', but '{$oneThousandIntMax}' passed.", - ), - array( - $tenMillionsIntMax, - "Interval overflow, value must be lower than '{$maxValue}', but '{$tenMillionsIntMax}' passed.", - ), - array( - $tenThousandsTimesIntMax, - "Interval overflow, value must be lower than '{$maxValue}', but '{$tenThousandsTimesIntMax}' passed.", - ), - ); + yield [ + $oversizeInterval, + "Interval overflow, value must be lower than '{$maxValue}', but '{$oversizeInterval}' passed." + ]; + yield [ + $oneMaxValue, + "Interval overflow, value must be lower than '{$maxValue}', but '{$oneMaxValue}' passed.", + ]; + yield [ + $tenMaxValue, + "Interval overflow, value must be lower than '{$maxValue}', but '{$tenMaxValue}' passed.", + ]; + yield [ + $tenMillionsMaxValue, + "Interval overflow, value must be lower than '{$maxValue}', but '{$tenMillionsMaxValue}' passed.", + ]; + yield [ + $intMax, + "Interval overflow, value must be lower than '{$maxValue}', but '{$intMax}' passed.", + ]; + yield [ + $oneIntMax, + "Interval overflow, value must be lower than '{$maxValue}', but '{$oneIntMax}' passed.", + ]; + yield [ + $tenIntMax, + "Interval overflow, value must be lower than '{$maxValue}', but '{$tenIntMax}' passed.", + ]; + yield [ + $oneHundredIntMax, + "Interval overflow, value must be lower than '{$maxValue}', but '{$oneHundredIntMax}' passed.", + ]; + yield [ + $oneThousandIntMax, + "Interval overflow, value must be lower than '{$maxValue}', but '{$oneThousandIntMax}' passed.", + ]; + yield [ + $tenMillionsIntMax, + "Interval overflow, value must be lower than '{$maxValue}', but '{$tenMillionsIntMax}' passed.", + ]; + yield [ + $tenThousandsTimesIntMax, + "Interval overflow, value must be lower than '{$maxValue}', but '{$tenThousandsTimesIntMax}' passed.", + ]; } } diff --git a/tests/LoopTest.php b/tests/LoopTest.php index 42f85244..08e2107e 100644 --- a/tests/LoopTest.php +++ b/tests/LoopTest.php @@ -2,34 +2,12 @@ namespace React\Tests\EventLoop; -use React\EventLoop\Factory; use React\EventLoop\Loop; +use React\EventLoop\LoopInterface; +use React\EventLoop\TimerInterface; final class LoopTest extends TestCase { - /** - * @dataProvider numberOfTests - */ - public function testFactoryCreateSetsEventLoopOnLoopAccessor() - { - $factoryLoop = Factory::create(); - $accessorLoop = Loop::get(); - - self::assertSame($factoryLoop, $accessorLoop); - } - - /** - * @dataProvider numberOfTests - */ - public function testCallingFactoryAfterCallingLoopGetYieldsADifferentInstanceOfTheEventLoop() - { - // Note that this behavior isn't wise and highly advised against. Always used Loop::get. - $accessorLoop = Loop::get(); - $factoryLoop = Factory::create(); - - self::assertNotSame($factoryLoop, $accessorLoop); - } - /** * @dataProvider numberOfTests */ @@ -45,7 +23,7 @@ public function testCallingLoopGetShouldAlwaysReturnTheSameEventLoop() */ public function numberOfTests() { - return array(array(), array(), array()); + return [[], [], []]; } public function testStaticAddReadStreamCallsAddReadStreamOnLoopInstance() @@ -53,7 +31,7 @@ public function testStaticAddReadStreamCallsAddReadStreamOnLoopInstance() $stream = tmpfile(); $listener = function () { }; - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop = $this->createMock(LoopInterface::class); $loop->expects($this->once())->method('addReadStream')->with($stream, $listener); Loop::set($loop); @@ -63,7 +41,7 @@ public function testStaticAddReadStreamCallsAddReadStreamOnLoopInstance() public function testStaticAddReadStreamWithNoDefaultLoopCallsAddReadStreamOnNewLoopInstance() { - $ref = new \ReflectionProperty('React\EventLoop\Loop', 'instance'); + $ref = new \ReflectionProperty(Loop::class, 'instance'); $ref->setAccessible(true); $ref->setValue(null, null); @@ -71,7 +49,7 @@ public function testStaticAddReadStreamWithNoDefaultLoopCallsAddReadStreamOnNewL $listener = function () { }; Loop::addReadStream($stream, $listener); - $this->assertInstanceOf('React\EventLoop\LoopInterface', $ref->getValue()); + $this->assertInstanceOf(LoopInterface::class, $ref->getValue()); } public function testStaticAddWriteStreamCallsAddWriteStreamOnLoopInstance() @@ -79,7 +57,7 @@ public function testStaticAddWriteStreamCallsAddWriteStreamOnLoopInstance() $stream = tmpfile(); $listener = function () { }; - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop = $this->createMock(LoopInterface::class); $loop->expects($this->once())->method('addWriteStream')->with($stream, $listener); Loop::set($loop); @@ -89,7 +67,7 @@ public function testStaticAddWriteStreamCallsAddWriteStreamOnLoopInstance() public function testStaticAddWriteStreamWithNoDefaultLoopCallsAddWriteStreamOnNewLoopInstance() { - $ref = new \ReflectionProperty('React\EventLoop\Loop', 'instance'); + $ref = new \ReflectionProperty(Loop::class, 'instance'); $ref->setAccessible(true); $ref->setValue(null, null); @@ -97,14 +75,14 @@ public function testStaticAddWriteStreamWithNoDefaultLoopCallsAddWriteStreamOnNe $listener = function () { }; Loop::addWriteStream($stream, $listener); - $this->assertInstanceOf('React\EventLoop\LoopInterface', $ref->getValue()); + $this->assertInstanceOf(LoopInterface::class, $ref->getValue()); } public function testStaticRemoveReadStreamCallsRemoveReadStreamOnLoopInstance() { $stream = tmpfile(); - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop = $this->createMock(LoopInterface::class); $loop->expects($this->once())->method('removeReadStream')->with($stream); Loop::set($loop); @@ -114,7 +92,7 @@ public function testStaticRemoveReadStreamCallsRemoveReadStreamOnLoopInstance() public function testStaticRemoveReadStreamWithNoDefaultLoopIsNoOp() { - $ref = new \ReflectionProperty('React\EventLoop\Loop', 'instance'); + $ref = new \ReflectionProperty(Loop::class, 'instance'); $ref->setAccessible(true); $ref->setValue(null, null); @@ -128,7 +106,7 @@ public function testStaticRemoveWriteStreamCallsRemoveWriteStreamOnLoopInstance( { $stream = tmpfile(); - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop = $this->createMock(LoopInterface::class); $loop->expects($this->once())->method('removeWriteStream')->with($stream); Loop::set($loop); @@ -138,7 +116,7 @@ public function testStaticRemoveWriteStreamCallsRemoveWriteStreamOnLoopInstance( public function testStaticRemoveWriteStreamWithNoDefaultLoopIsNoOp() { - $ref = new \ReflectionProperty('React\EventLoop\Loop', 'instance'); + $ref = new \ReflectionProperty(Loop::class, 'instance'); $ref->setAccessible(true); $ref->setValue(null, null); @@ -152,9 +130,9 @@ public function testStaticAddTimerCallsAddTimerOnLoopInstanceAndReturnsTimerInst { $interval = 1.0; $callback = function () { }; - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); + $timer = $this->createMock(TimerInterface::class); - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop = $this->createMock(LoopInterface::class); $loop->expects($this->once())->method('addTimer')->with($interval, $callback)->willReturn($timer); Loop::set($loop); @@ -166,7 +144,7 @@ public function testStaticAddTimerCallsAddTimerOnLoopInstanceAndReturnsTimerInst public function testStaticAddTimerWithNoDefaultLoopCallsAddTimerOnNewLoopInstance() { - $ref = new \ReflectionProperty('React\EventLoop\Loop', 'instance'); + $ref = new \ReflectionProperty(Loop::class, 'instance'); $ref->setAccessible(true); $ref->setValue(null, null); @@ -174,17 +152,17 @@ public function testStaticAddTimerWithNoDefaultLoopCallsAddTimerOnNewLoopInstanc $callback = function () { }; $ret = Loop::addTimer($interval, $callback); - $this->assertInstanceOf('React\EventLoop\TimerInterface', $ret); - $this->assertInstanceOf('React\EventLoop\LoopInterface', $ref->getValue()); + $this->assertInstanceOf(TimerInterface::class, $ret); + $this->assertInstanceOf(LoopInterface::class, $ref->getValue()); } public function testStaticAddPeriodicTimerCallsAddPeriodicTimerOnLoopInstanceAndReturnsTimerInstance() { $interval = 1.0; $callback = function () { }; - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); + $timer = $this->createMock(TimerInterface::class); - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop = $this->createMock(LoopInterface::class); $loop->expects($this->once())->method('addPeriodicTimer')->with($interval, $callback)->willReturn($timer); Loop::set($loop); @@ -196,7 +174,7 @@ public function testStaticAddPeriodicTimerCallsAddPeriodicTimerOnLoopInstanceAnd public function testStaticAddPeriodicTimerWithNoDefaultLoopCallsAddPeriodicTimerOnNewLoopInstance() { - $ref = new \ReflectionProperty('React\EventLoop\Loop', 'instance'); + $ref = new \ReflectionProperty(Loop::class, 'instance'); $ref->setAccessible(true); $ref->setValue(null, null); @@ -204,16 +182,16 @@ public function testStaticAddPeriodicTimerWithNoDefaultLoopCallsAddPeriodicTimer $callback = function () { }; $ret = Loop::addPeriodicTimer($interval, $callback); - $this->assertInstanceOf('React\EventLoop\TimerInterface', $ret); - $this->assertInstanceOf('React\EventLoop\LoopInterface', $ref->getValue()); + $this->assertInstanceOf(TimerInterface::class, $ret); + $this->assertInstanceOf(LoopInterface::class, $ref->getValue()); } public function testStaticCancelTimerCallsCancelTimerOnLoopInstance() { - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); + $timer = $this->createMock(TimerInterface::class); - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop = $this->createMock(LoopInterface::class); $loop->expects($this->once())->method('cancelTimer')->with($timer); Loop::set($loop); @@ -223,11 +201,11 @@ public function testStaticCancelTimerCallsCancelTimerOnLoopInstance() public function testStaticCancelTimerWithNoDefaultLoopIsNoOp() { - $ref = new \ReflectionProperty('React\EventLoop\Loop', 'instance'); + $ref = new \ReflectionProperty(Loop::class, 'instance'); $ref->setAccessible(true); $ref->setValue(null, null); - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); + $timer = $this->createMock(TimerInterface::class); Loop::cancelTimer($timer); $this->assertNull($ref->getValue()); @@ -237,7 +215,7 @@ public function testStaticFutureTickCallsFutureTickOnLoopInstance() { $listener = function () { }; - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop = $this->createMock(LoopInterface::class); $loop->expects($this->once())->method('futureTick')->with($listener); Loop::set($loop); @@ -247,14 +225,14 @@ public function testStaticFutureTickCallsFutureTickOnLoopInstance() public function testStaticFutureTickWithNoDefaultLoopCallsFutureTickOnNewLoopInstance() { - $ref = new \ReflectionProperty('React\EventLoop\Loop', 'instance'); + $ref = new \ReflectionProperty(Loop::class, 'instance'); $ref->setAccessible(true); $ref->setValue(null, null); $listener = function () { }; Loop::futureTick($listener); - $this->assertInstanceOf('React\EventLoop\LoopInterface', $ref->getValue()); + $this->assertInstanceOf(LoopInterface::class, $ref->getValue()); } public function testStaticAddSignalCallsAddSignalOnLoopInstance() @@ -262,7 +240,7 @@ public function testStaticAddSignalCallsAddSignalOnLoopInstance() $signal = 1; $listener = function () { }; - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop = $this->createMock(LoopInterface::class); $loop->expects($this->once())->method('addSignal')->with($signal, $listener); Loop::set($loop); @@ -276,7 +254,7 @@ public function testStaticAddSignalWithNoDefaultLoopCallsAddSignalOnNewLoopInsta $this->markTestSkipped('Not supported on Windows'); } - $ref = new \ReflectionProperty('React\EventLoop\Loop', 'instance'); + $ref = new \ReflectionProperty(Loop::class, 'instance'); $ref->setAccessible(true); $ref->setValue(null, null); @@ -288,7 +266,7 @@ public function testStaticAddSignalWithNoDefaultLoopCallsAddSignalOnNewLoopInsta $this->markTestSkipped('Skipped: ' . $e->getMessage()); } - $this->assertInstanceOf('React\EventLoop\LoopInterface', $ref->getValue()); + $this->assertInstanceOf(LoopInterface::class, $ref->getValue()); } public function testStaticRemoveSignalCallsRemoveSignalOnLoopInstance() @@ -296,7 +274,7 @@ public function testStaticRemoveSignalCallsRemoveSignalOnLoopInstance() $signal = 1; $listener = function () { }; - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop = $this->createMock(LoopInterface::class); $loop->expects($this->once())->method('removeSignal')->with($signal, $listener); Loop::set($loop); @@ -306,7 +284,7 @@ public function testStaticRemoveSignalCallsRemoveSignalOnLoopInstance() public function testStaticRemoveSignalWithNoDefaultLoopIsNoOp() { - $ref = new \ReflectionProperty('React\EventLoop\Loop', 'instance'); + $ref = new \ReflectionProperty(Loop::class, 'instance'); $ref->setAccessible(true); $ref->setValue(null, null); @@ -319,7 +297,7 @@ public function testStaticRemoveSignalWithNoDefaultLoopIsNoOp() public function testStaticRunCallsRunOnLoopInstance() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop = $this->createMock(LoopInterface::class); $loop->expects($this->once())->method('run')->with(); Loop::set($loop); @@ -329,18 +307,18 @@ public function testStaticRunCallsRunOnLoopInstance() public function testStaticRunWithNoDefaultLoopCallsRunsOnNewLoopInstance() { - $ref = new \ReflectionProperty('React\EventLoop\Loop', 'instance'); + $ref = new \ReflectionProperty(Loop::class, 'instance'); $ref->setAccessible(true); $ref->setValue(null, null); Loop::run(); - $this->assertInstanceOf('React\EventLoop\LoopInterface', $ref->getValue()); + $this->assertInstanceOf(LoopInterface::class, $ref->getValue()); } public function testStaticStopCallsStopOnLoopInstance() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop = $this->createMock(LoopInterface::class); $loop->expects($this->once())->method('stop')->with(); Loop::set($loop); @@ -350,7 +328,7 @@ public function testStaticStopCallsStopOnLoopInstance() public function testStaticStopCallWithNoDefaultLoopIsNoOp() { - $ref = new \ReflectionProperty('React\EventLoop\Loop', 'instance'); + $ref = new \ReflectionProperty(Loop::class, 'instance'); $ref->setAccessible(true); $ref->setValue(null, null); @@ -365,7 +343,7 @@ public function testStaticStopCallWithNoDefaultLoopIsNoOp() */ public function unsetLoopFromLoopAccessor() { - $ref = new \ReflectionProperty('React\EventLoop\Loop', 'instance'); + $ref = new \ReflectionProperty(Loop::class, 'instance'); $ref->setAccessible(true); $ref->setValue(null, null); } diff --git a/tests/StreamSelectLoopTest.php b/tests/StreamSelectLoopTest.php index 7e2435a8..b2672d4e 100644 --- a/tests/StreamSelectLoopTest.php +++ b/tests/StreamSelectLoopTest.php @@ -42,19 +42,14 @@ public function testStreamSelectTimeoutEmulation() public function testStreamSelectReportsWarningForStreamWithFilter() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('Not supported on legacy HHVM'); - } - $stream = tmpfile(); stream_filter_append($stream, 'string.rot13'); $this->loop->addReadStream($stream, $this->expectCallableNever()); - $loop = $this->loop; - $this->loop->futureTick(function () use ($loop, $stream) { - $loop->futureTick(function () use ($loop, $stream) { - $loop->removeReadStream($stream); + $this->loop->futureTick(function () use ($stream) { + $this->loop->futureTick(function () use ($stream) { + $this->loop->removeReadStream($stream); }); }); @@ -80,19 +75,14 @@ public function testStreamSelectReportsWarningForStreamWithFilter() public function testStreamSelectThrowsWhenCustomErrorHandlerThrowsForStreamWithFilter() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('Not supported on legacy HHVM'); - } - $stream = tmpfile(); stream_filter_append($stream, 'string.rot13'); $this->loop->addReadStream($stream, $this->expectCallableNever()); - $loop = $this->loop; - $this->loop->futureTick(function () use ($loop, $stream) { - $loop->futureTick(function () use ($loop, $stream) { - $loop->removeReadStream($stream); + $this->loop->futureTick(function () use ($stream) { + $this->loop->futureTick(function () use ($stream) { + $this->loop->removeReadStream($stream); }); }); @@ -112,7 +102,7 @@ public function testStreamSelectThrowsWhenCustomErrorHandlerThrowsForStreamWithF $e = $e->getPrevious(); } - $this->assertInstanceOf('RuntimeException', $e); + $this->assertInstanceOf(\RuntimeException::class, $e); $now = set_error_handler(function () { }); restore_error_handler(); @@ -121,11 +111,9 @@ public function testStreamSelectThrowsWhenCustomErrorHandlerThrowsForStreamWithF public function signalProvider() { - return array( - array('SIGUSR1'), - array('SIGHUP'), - array('SIGTERM'), - ); + yield ['SIGUSR1']; + yield ['SIGHUP']; + yield ['SIGTERM']; } /** @@ -141,9 +129,8 @@ public function testSignalInterruptNoStream($signal) $check = $this->loop->addPeriodicTimer(0.01, function() { pcntl_signal_dispatch(); }); - $loop = $this->loop; - $loop->addTimer(0.1, function () use ($check, $loop) { - $loop->cancelTimer($check); + $this->loop->addTimer(0.1, function () use ($check) { + $this->loop->cancelTimer($check); }); $handled = false; @@ -173,13 +160,12 @@ public function testSignalInterruptWithStream($signal) }); // add stream to the loop - $loop = $this->loop; list($writeStream, $readStream) = $this->createSocketPair(); - $loop->addReadStream($readStream, function ($stream) use ($loop) { + $this->loop->addReadStream($readStream, function ($stream) { /** @var $loop LoopInterface */ $read = fgets($stream); if ($read === "end loop\n") { - $loop->stop(); + $this->loop->stop(); } }); $this->loop->addTimer(0.1, function() use ($writeStream) { diff --git a/tests/TestCase.php b/tests/TestCase.php index 69b3b227..55f04cf3 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -39,12 +39,13 @@ protected function expectCallableNever() protected function createCallableMock() { - if (method_exists('PHPUnit\Framework\MockObject\MockBuilder', 'addMethods')) { + $builder = $this->getMockBuilder(\stdClass::class); + if (method_exists($builder, 'addMethods')) { // PHPUnit 9+ - return $this->getMockBuilder('stdClass')->addMethods(array('__invoke'))->getMock(); + return $builder->addMethods(['__invoke'])->getMock(); } else { - // legacy PHPUnit 4 - PHPUnit 9 - return $this->getMockBuilder('stdClass')->setMethods(array('__invoke'))->getMock(); + // legacy PHPUnit + return $builder->setMethods(['__invoke'])->getMock(); } } diff --git a/tests/Timer/AbstractTimerTest.php b/tests/Timer/AbstractTimerTest.php index bbea46f8..81099ff9 100644 --- a/tests/Timer/AbstractTimerTest.php +++ b/tests/Timer/AbstractTimerTest.php @@ -3,6 +3,7 @@ namespace React\Tests\EventLoop\Timer; use React\EventLoop\LoopInterface; +use React\EventLoop\TimerInterface; use React\Tests\EventLoop\TestCase; abstract class AbstractTimerTest extends TestCase @@ -18,7 +19,7 @@ public function testAddTimerReturnsNonPeriodicTimerInstance() $timer = $loop->addTimer(0.001, $this->expectCallableNever()); - $this->assertInstanceOf('React\EventLoop\TimerInterface', $timer); + $this->assertInstanceOf(TimerInterface::class, $timer); $this->assertFalse($timer->isPeriodic()); } @@ -45,7 +46,7 @@ public function testAddPeriodicTimerReturnsPeriodicTimerInstance() $periodic = $loop->addPeriodicTimer(0.1, $this->expectCallableNever()); - $this->assertInstanceOf('React\EventLoop\TimerInterface', $periodic); + $this->assertInstanceOf(TimerInterface::class, $periodic); $this->assertTrue($periodic->isPeriodic()); } diff --git a/tests/Timer/ExtLibevTimerTest.php b/tests/Timer/ExtLibevTimerTest.php deleted file mode 100644 index 65e82bee..00000000 --- a/tests/Timer/ExtLibevTimerTest.php +++ /dev/null @@ -1,17 +0,0 @@ -markTestSkipped('libev tests skipped because ext-libev is not installed.'); - } - - return new ExtLibevLoop(); - } -} diff --git a/tests/Timer/ExtLibeventTimerTest.php b/tests/Timer/ExtLibeventTimerTest.php deleted file mode 100644 index 9089b9a5..00000000 --- a/tests/Timer/ExtLibeventTimerTest.php +++ /dev/null @@ -1,17 +0,0 @@ -markTestSkipped('libevent tests skipped because ext-libevent is not installed.'); - } - - return new ExtLibeventLoop(); - } -} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

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:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy