From d3c10522025ddd811575af2d258a2bc6ee00c80f Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Sat, 24 Feb 2024 14:58:18 +0100 Subject: [PATCH 1/3] Update to require PHP 7.1+ --- .github/workflows/ci.yml | 26 ++------------------------ README.md | 11 +++++------ composer.json | 4 ++-- phpunit.xml.legacy | 2 +- src/ExtEvLoop.php | 2 +- src/ExtEventLoop.php | 10 +++------- src/ExtUvLoop.php | 2 +- src/StreamSelectLoop.php | 9 +++------ tests/AbstractLoopTest.php | 4 ---- tests/BinTest.php | 4 ---- tests/ExtEventLoopTest.php | 25 ------------------------- tests/StreamSelectLoopTest.php | 8 -------- 12 files changed, 18 insertions(+), 89 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b4bf2b84..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 @@ -56,7 +51,6 @@ jobs: - 7.3 - 7.2 - 7.1 - - 7.0 steps: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 @@ -65,7 +59,7 @@ 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' }} @@ -104,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 ed9f0f45..8394784f 100644 --- a/README.md +++ b/README.md @@ -330,7 +330,7 @@ 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) will use this event loop by default if @@ -373,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 @@ -384,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 @@ -394,7 +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+. +This loop is known to work with PHP 7.1 through PHP 8+. ### LoopInterface @@ -830,8 +830,7 @@ 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..522bd8ca 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 || ^5.7" }, "suggest": { "ext-pcntl": "For signal handling support when using the StreamSelectLoop" diff --git a/phpunit.xml.legacy b/phpunit.xml.legacy index 03c2fed5..37671595 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..1cfc4b41 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 diff --git a/src/ExtEventLoop.php b/src/ExtEventLoop.php index b162a402..8f5ce58b 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 */ @@ -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) diff --git a/src/ExtUvLoop.php b/src/ExtUvLoop.php index 4434720d..fc4cb3ab 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 */ diff --git a/src/StreamSelectLoop.php b/src/StreamSelectLoop.php index 943a81aa..4ff5cca8 100644 --- a/src/StreamSelectLoop.php +++ b/src/StreamSelectLoop.php @@ -12,7 +12,7 @@ * 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) will use this event loop by default if @@ -302,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/tests/AbstractLoopTest.php b/tests/AbstractLoopTest.php index a3511d66..eb9591ba 100644 --- a/tests/AbstractLoopTest.php +++ b/tests/AbstractLoopTest.php @@ -118,10 +118,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 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/StreamSelectLoopTest.php b/tests/StreamSelectLoopTest.php index 7e2435a8..578bbe4b 100644 --- a/tests/StreamSelectLoopTest.php +++ b/tests/StreamSelectLoopTest.php @@ -42,10 +42,6 @@ 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'); @@ -80,10 +76,6 @@ 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'); From e95a017499aad09ebabb71d75269728ef90ffc74 Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Sat, 24 Feb 2024 15:31:33 +0100 Subject: [PATCH 2/3] Update PHP language syntax and remove legacy workarounds --- examples/12-generate-yes.php | 2 +- examples/91-benchmark-ticks.php | 2 +- examples/92-benchmark-timers.php | 2 +- examples/93-benchmark-ticks-delay.php | 2 +- examples/94-benchmark-timers-delay.php | 2 +- examples/95-benchmark-memory.php | 4 +- src/ExtEvLoop.php | 14 +-- src/ExtEventLoop.php | 37 +++--- src/ExtUvLoop.php | 21 ++-- src/Loop.php | 52 ++------ src/SignalsHandler.php | 4 +- src/StreamSelectLoop.php | 12 +- src/Timer/Timers.php | 4 +- tests/AbstractLoopTest.php | 167 +++++++++++-------------- tests/ExtUvLoopTest.php | 48 +++---- tests/LoopTest.php | 2 +- tests/StreamSelectLoopTest.php | 34 +++-- tests/TestCase.php | 6 +- 18 files changed, 173 insertions(+), 242 deletions(-) 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/src/ExtEvLoop.php b/src/ExtEvLoop.php index 1cfc4b41..363ad0c4 100644 --- a/src/ExtEvLoop.php +++ b/src/ExtEvLoop.php @@ -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 8f5ce58b..d6f24b2a 100644 --- a/src/ExtEventLoop.php +++ b/src/ExtEventLoop.php @@ -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) @@ -169,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(); } } @@ -235,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); } }; @@ -254,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/ExtUvLoop.php b/src/ExtUvLoop.php index fc4cb3ab..e9e79524 100644 --- a/src/ExtUvLoop.php +++ b/src/ExtUvLoop.php @@ -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/Loop.php b/src/Loop.php index 10976eea..732c5d5e 100644 --- a/src/Loop.php +++ b/src/Loop.php @@ -43,15 +43,14 @@ public static function get() $hasRun = true; }); - $stopped =& self::$stopped; - register_shutdown_function(function () use ($loop, &$hasRun, &$stopped) { + register_shutdown_function(function () use ($loop, &$hasRun) { // Don't run if we're coming from a fatal error (uncaught exception). $error = error_get_last(); - if ((isset($error['type']) ? $error['type'] : 0) & (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR)) { + if (($error['type'] ?? 0) & (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR)) { return; } - if (!$hasRun && !$stopped) { + if (!$hasRun && !self::$stopped) { $loop->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(); } /** 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 4ff5cca8..41dd2cb3 100644 --- a/src/StreamSelectLoop.php +++ b/src/StreamSelectLoop.php @@ -56,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; @@ -157,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']); } } @@ -278,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; 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 eb9591ba..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(); @@ -128,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(); @@ -201,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 . ']'; } }); } @@ -347,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); }); @@ -370,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); }); @@ -401,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); }); @@ -433,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"); @@ -448,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"); @@ -460,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(); } ); @@ -485,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; } @@ -579,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; } @@ -608,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; } @@ -628,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; } @@ -671,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 () { @@ -710,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(); @@ -729,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); @@ -749,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); @@ -763,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/ExtUvLoopTest.php b/tests/ExtUvLoopTest.php index 267eddf1..da07d767 100644 --- a/tests/ExtUvLoopTest.php +++ b/tests/ExtUvLoopTest.php @@ -45,51 +45,51 @@ public function intervalProvider() $tenMillionsIntMax = PHP_INT_MAX + 10000000; $tenThousandsTimesIntMax = PHP_INT_MAX * 1000; - return array( - array( + return [ + [ $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.", - ), - ); + ], + ]; } } diff --git a/tests/LoopTest.php b/tests/LoopTest.php index 80f5cccc..1a56404b 100644 --- a/tests/LoopTest.php +++ b/tests/LoopTest.php @@ -21,7 +21,7 @@ public function testCallingLoopGetShouldAlwaysReturnTheSameEventLoop() */ public function numberOfTests() { - return array(array(), array(), array()); + return [[], [], []]; } public function testStaticAddReadStreamCallsAddReadStreamOnLoopInstance() diff --git a/tests/StreamSelectLoopTest.php b/tests/StreamSelectLoopTest.php index 578bbe4b..e402266e 100644 --- a/tests/StreamSelectLoopTest.php +++ b/tests/StreamSelectLoopTest.php @@ -47,10 +47,9 @@ public function testStreamSelectReportsWarningForStreamWithFilter() $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); }); }); @@ -81,10 +80,9 @@ public function testStreamSelectThrowsWhenCustomErrorHandlerThrowsForStreamWithF $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); }); }); @@ -113,11 +111,11 @@ public function testStreamSelectThrowsWhenCustomErrorHandlerThrowsForStreamWithF public function signalProvider() { - return array( - array('SIGUSR1'), - array('SIGHUP'), - array('SIGTERM'), - ); + return [ + ['SIGUSR1'], + ['SIGHUP'], + ['SIGTERM'], + ]; } /** @@ -133,9 +131,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; @@ -165,13 +162,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..8b998e0b 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -41,10 +41,10 @@ protected function createCallableMock() { if (method_exists('PHPUnit\Framework\MockObject\MockBuilder', 'addMethods')) { // PHPUnit 9+ - return $this->getMockBuilder('stdClass')->addMethods(array('__invoke'))->getMock(); + return $this->getMockBuilder('stdClass')->addMethods(['__invoke'])->getMock(); } else { - // legacy PHPUnit 4 - PHPUnit 9 - return $this->getMockBuilder('stdClass')->setMethods(array('__invoke'))->getMock(); + // legacy PHPUnit + return $this->getMockBuilder('stdClass')->setMethods(['__invoke'])->getMock(); } } From cde40177b179a6741bf4fcb8371776652e77d78e Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Sat, 24 Feb 2024 16:10:58 +0100 Subject: [PATCH 3/3] Update test suite and remove legacy PHPUnit workarounds --- composer.json | 2 +- phpunit.xml.legacy | 2 +- tests/ExtUvLoopTest.php | 88 +++++++++++++++---------------- tests/LoopTest.php | 78 ++++++++++++++------------- tests/StreamSelectLoopTest.php | 10 ++-- tests/TestCase.php | 7 +-- tests/Timer/AbstractTimerTest.php | 5 +- 7 files changed, 96 insertions(+), 96 deletions(-) diff --git a/composer.json b/composer.json index 522bd8ca..6d31e81d 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7" + "phpunit/phpunit": "^9.6 || ^7.5" }, "suggest": { "ext-pcntl": "For signal handling support when using the StreamSelectLoop" diff --git a/phpunit.xml.legacy b/phpunit.xml.legacy index 37671595..7c148001 100644 --- a/phpunit.xml.legacy +++ b/phpunit.xml.legacy @@ -2,7 +2,7 @@ diff --git a/tests/ExtUvLoopTest.php b/tests/ExtUvLoopTest.php index da07d767..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 [ - [ - $oversizeInterval, - "Interval overflow, value must be lower than '{$maxValue}', but '{$oversizeInterval}' passed." - ], - [ - $oneMaxValue, - "Interval overflow, value must be lower than '{$maxValue}', but '{$oneMaxValue}' passed.", - ], - [ - $tenMaxValue, - "Interval overflow, value must be lower than '{$maxValue}', but '{$tenMaxValue}' passed.", - ], - [ - $tenMillionsMaxValue, - "Interval overflow, value must be lower than '{$maxValue}', but '{$tenMillionsMaxValue}' passed.", - ], - [ - $intMax, - "Interval overflow, value must be lower than '{$maxValue}', but '{$intMax}' passed.", - ], - [ - $oneIntMax, - "Interval overflow, value must be lower than '{$maxValue}', but '{$oneIntMax}' passed.", - ], - [ - $tenIntMax, - "Interval overflow, value must be lower than '{$maxValue}', but '{$tenIntMax}' passed.", - ], - [ - $oneHundredIntMax, - "Interval overflow, value must be lower than '{$maxValue}', but '{$oneHundredIntMax}' passed.", - ], - [ - $oneThousandIntMax, - "Interval overflow, value must be lower than '{$maxValue}', but '{$oneThousandIntMax}' passed.", - ], - [ - $tenMillionsIntMax, - "Interval overflow, value must be lower than '{$maxValue}', but '{$tenMillionsIntMax}' passed.", - ], - [ - $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 1a56404b..08e2107e 100644 --- a/tests/LoopTest.php +++ b/tests/LoopTest.php @@ -3,6 +3,8 @@ namespace React\Tests\EventLoop; use React\EventLoop\Loop; +use React\EventLoop\LoopInterface; +use React\EventLoop\TimerInterface; final class LoopTest extends TestCase { @@ -29,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); @@ -39,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); @@ -47,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() @@ -55,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); @@ -65,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); @@ -73,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); @@ -90,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); @@ -104,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); @@ -114,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); @@ -128,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); @@ -142,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); @@ -150,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); @@ -172,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); @@ -180,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); @@ -199,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()); @@ -213,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); @@ -223,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() @@ -238,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); @@ -252,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); @@ -264,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() @@ -272,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); @@ -282,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); @@ -295,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); @@ -305,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); @@ -326,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); @@ -341,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 e402266e..b2672d4e 100644 --- a/tests/StreamSelectLoopTest.php +++ b/tests/StreamSelectLoopTest.php @@ -102,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(); @@ -111,11 +111,9 @@ public function testStreamSelectThrowsWhenCustomErrorHandlerThrowsForStreamWithF public function signalProvider() { - return [ - ['SIGUSR1'], - ['SIGHUP'], - ['SIGTERM'], - ]; + yield ['SIGUSR1']; + yield ['SIGHUP']; + yield ['SIGTERM']; } /** diff --git a/tests/TestCase.php b/tests/TestCase.php index 8b998e0b..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(['__invoke'])->getMock(); + return $builder->addMethods(['__invoke'])->getMock(); } else { // legacy PHPUnit - return $this->getMockBuilder('stdClass')->setMethods(['__invoke'])->getMock(); + 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()); }