diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc36a4d..f654fb0 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 @@ -52,23 +47,3 @@ jobs: - run: composer install - run: vendor/bin/phpunit --coverage-text - run: time php examples/91-benchmark-throughput.php - - 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 - - name: Run time hhvm examples/91-benchmark-throughput.php - uses: docker://hhvm/hhvm:3.30-lts-latest - with: - args: bash -c "time hhvm examples/91-benchmark-throughput.php" diff --git a/README.md b/README.md index 3920a75..cce1408 100644 --- a/README.md +++ b/README.md @@ -353,7 +353,7 @@ By default, this will call `end()` on the destination stream once the source stream emits an `end` event. This can be disabled like this: ```php -$source->pipe($dest, array('end' => false)); +$source->pipe($dest, ['end' => false]); ``` Note that this only applies to the `end` event. @@ -1126,7 +1126,7 @@ $through = new ThroughStream(function ($data) { }); $through->on('data', $this->expectCallableOnceWith("[2, true]\n")); -$through->write(array(2, true)); +$through->write([2, true]); ``` The callback function is allowed to throw an `Exception`. In this case, @@ -1217,9 +1217,8 @@ composer require react/stream:^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. -It's *highly recommended to use PHP 7+* for this project due to its vast -performance improvements. +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. ## Tests diff --git a/composer.json b/composer.json index 09d8b71..b8d34d4 100644 --- a/composer.json +++ b/composer.json @@ -26,12 +26,12 @@ } ], "require": { - "php": ">=5.3.8", + "php": ">=7.1", "react/event-loop": "^1.2", "evenement/evenement": "^3.0 || ^2.0 || ^1.0" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "phpunit/phpunit": "^9.6 || ^7.5", "clue/stream-filter": "~1.2" }, "autoload": { diff --git a/examples/01-http.php b/examples/01-http.php index e70691d..786aefc 100644 --- a/examples/01-http.php +++ b/examples/01-http.php @@ -15,7 +15,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$host = isset($argv[1]) ? $argv[1] : 'www.google.com'; +$host = $argv[1] ?? 'www.google.com'; // connect to tcp://www.google.com:80 (blocking call!) // for illustration purposes only, should use react/http-client or react/socket instead! diff --git a/examples/02-https.php b/examples/02-https.php index 1d212da..e629791 100644 --- a/examples/02-https.php +++ b/examples/02-https.php @@ -15,7 +15,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$host = isset($argv[1]) ? $argv[1] : 'www.google.com'; +$host = $argv[1] ?? 'www.google.com'; // connect to tls://www.google.com:443 (blocking call!) // for illustration purposes only, should use react/http-client or react/socket instead! diff --git a/examples/91-benchmark-throughput.php b/examples/91-benchmark-throughput.php index 4203950..c396606 100644 --- a/examples/91-benchmark-throughput.php +++ b/examples/91-benchmark-throughput.php @@ -21,9 +21,9 @@ } $args = getopt('i:o:t:'); -$if = isset($args['i']) ? $args['i'] : '/dev/zero'; -$of = isset($args['o']) ? $args['o'] : '/dev/null'; -$t = isset($args['t']) ? $args['t'] : 1; +$if = $args['i'] ?? '/dev/zero'; +$of = $args['o'] ?? '/dev/null'; +$t = $args['t'] ?? 1; // passing file descriptors requires mapping paths (https://bugs.php.net/bug.php?id=53465) $if = str_replace('/dev/fd/', 'php://fd/', $if); diff --git a/phpunit.xml.legacy b/phpunit.xml.legacy index 8916116..0086860 100644 --- a/phpunit.xml.legacy +++ b/phpunit.xml.legacy @@ -2,7 +2,7 @@ diff --git a/src/CompositeStream.php b/src/CompositeStream.php index dde091d..d0b934b 100644 --- a/src/CompositeStream.php +++ b/src/CompositeStream.php @@ -20,11 +20,11 @@ public function __construct(ReadableStreamInterface $readable, WritableStreamInt return; } - Util::forwardEvents($this->readable, $this, array('data', 'end', 'error')); - Util::forwardEvents($this->writable, $this, array('drain', 'error', 'pipe')); + Util::forwardEvents($this->readable, $this, ['data', 'end', 'error']); + Util::forwardEvents($this->writable, $this, ['drain', 'error', 'pipe']); - $this->readable->on('close', array($this, 'close')); - $this->writable->on('close', array($this, 'close')); + $this->readable->on('close', [$this, 'close']); + $this->writable->on('close', [$this, 'close']); } public function isReadable() @@ -46,7 +46,7 @@ public function resume() $this->readable->resume(); } - public function pipe(WritableStreamInterface $dest, array $options = array()) + public function pipe(WritableStreamInterface $dest, array $options = []) { return Util::pipe($this, $dest, $options); } diff --git a/src/DuplexResourceStream.php b/src/DuplexResourceStream.php index 4da2139..0b52c9b 100644 --- a/src/DuplexResourceStream.php +++ b/src/DuplexResourceStream.php @@ -46,7 +46,7 @@ public function __construct($stream, LoopInterface $loop = null, $readChunkSize // ensure resource is opened for reading and wrting (fopen mode must contain "+") $meta = \stream_get_meta_data($stream); - if (isset($meta['mode']) && $meta['mode'] !== '' && \strpos($meta['mode'], '+') === false) { + if (\strpos($meta['mode'], '+') === false) { throw new InvalidArgumentException('Given stream resource is not opened in read and write mode'); } @@ -59,14 +59,9 @@ public function __construct($stream, LoopInterface $loop = null, $readChunkSize // Use unbuffered read operations on the underlying stream resource. // Reading chunks from the stream may otherwise leave unread bytes in // PHP's stream buffers which some event loop implementations do not - // trigger events on (edge triggered). - // This does not affect the default event loop implementation (level - // triggered), so we can ignore platforms not supporting this (HHVM). - // Pipe streams (such as STDIN) do not seem to require this and legacy - // PHP versions cause SEGFAULTs on unbuffered pipe streams, so skip this. - if (\function_exists('stream_set_read_buffer') && !$this->isLegacyPipe($stream)) { - \stream_set_read_buffer($stream, 0); - } + // trigger events on (edge triggered). This does not affect the default + // event loop implementation (level triggered). + \stream_set_read_buffer($stream, 0); if ($buffer === null) { $buffer = new WritableResourceStream($stream, $loop); @@ -77,16 +72,14 @@ public function __construct($stream, LoopInterface $loop = null, $readChunkSize $this->bufferSize = ($readChunkSize === null) ? 65536 : (int)$readChunkSize; $this->buffer = $buffer; - $that = $this; - - $this->buffer->on('error', function ($error) use ($that) { - $that->emit('error', array($error)); + $this->buffer->on('error', function ($error) { + $this->emit('error', [$error]); }); - $this->buffer->on('close', array($this, 'close')); + $this->buffer->on('close', [$this, 'close']); - $this->buffer->on('drain', function () use ($that) { - $that->emit('drain'); + $this->buffer->on('drain', function () { + $this->emit('drain'); }); $this->resume(); @@ -113,7 +106,7 @@ public function pause() public function resume() { if (!$this->listening && $this->readable) { - $this->loop->addReadStream($this->stream, array($this, 'handleData')); + $this->loop->addReadStream($this->stream, [$this, 'handleData']); $this->listening = true; } } @@ -163,7 +156,7 @@ public function end($data = null) $this->buffer->end($data); } - public function pipe(WritableStreamInterface $dest, array $options = array()) + public function pipe(WritableStreamInterface $dest, array $options = []) { return Util::pipe($this, $dest, $options); } @@ -187,41 +180,17 @@ public function handleData($stream) \restore_error_handler(); if ($error !== null) { - $this->emit('error', array(new \RuntimeException('Unable to read from stream: ' . $error->getMessage(), 0, $error))); + $this->emit('error', [new \RuntimeException('Unable to read from stream: ' . $error->getMessage(), 0, $error)]); $this->close(); return; } if ($data !== '') { - $this->emit('data', array($data)); + $this->emit('data', [$data]); } elseif (\feof($this->stream)) { // no data read => we reached the end and close the stream $this->emit('end'); $this->close(); } } - - /** - * Returns whether this is a pipe resource in a legacy environment - * - * This works around a legacy PHP bug (#61019) that was fixed in PHP 5.4.28+ - * and PHP 5.5.12+ and newer. - * - * @param resource $resource - * @return bool - * @link https://github.com/reactphp/child-process/issues/40 - * - * @codeCoverageIgnore - */ - private function isLegacyPipe($resource) - { - if (\PHP_VERSION_ID < 50428 || (\PHP_VERSION_ID >= 50500 && \PHP_VERSION_ID < 50512)) { - $meta = \stream_get_meta_data($resource); - - if (isset($meta['stream_type']) && $meta['stream_type'] === 'STDIO') { - return true; - } - } - return false; - } } diff --git a/src/ReadableResourceStream.php b/src/ReadableResourceStream.php index 1b0b08c..41314fe 100644 --- a/src/ReadableResourceStream.php +++ b/src/ReadableResourceStream.php @@ -48,7 +48,7 @@ public function __construct($stream, LoopInterface $loop = null, $readChunkSize // ensure resource is opened for reading (fopen mode must contain "r" or "+") $meta = \stream_get_meta_data($stream); - if (isset($meta['mode']) && $meta['mode'] !== '' && \strpos($meta['mode'], 'r') === \strpos($meta['mode'], '+')) { + if (\strpos($meta['mode'], 'r') === \strpos($meta['mode'], '+')) { throw new InvalidArgumentException('Given stream resource is not opened in read mode'); } @@ -61,14 +61,9 @@ public function __construct($stream, LoopInterface $loop = null, $readChunkSize // Use unbuffered read operations on the underlying stream resource. // Reading chunks from the stream may otherwise leave unread bytes in // PHP's stream buffers which some event loop implementations do not - // trigger events on (edge triggered). - // This does not affect the default event loop implementation (level - // triggered), so we can ignore platforms not supporting this (HHVM). - // Pipe streams (such as STDIN) do not seem to require this and legacy - // PHP versions cause SEGFAULTs on unbuffered pipe streams, so skip this. - if (\function_exists('stream_set_read_buffer') && !$this->isLegacyPipe($stream)) { - \stream_set_read_buffer($stream, 0); - } + // trigger events on (edge triggered). This does not affect the default + // event loop implementation (level triggered). + \stream_set_read_buffer($stream, 0); $this->stream = $stream; $this->loop = $loop ?: Loop::get(); @@ -93,12 +88,12 @@ public function pause() public function resume() { if (!$this->listening && !$this->closed) { - $this->loop->addReadStream($this->stream, array($this, 'handleData')); + $this->loop->addReadStream($this->stream, [$this, 'handleData']); $this->listening = true; } } - public function pipe(WritableStreamInterface $dest, array $options = array()) + public function pipe(WritableStreamInterface $dest, array $options = []) { return Util::pipe($this, $dest, $options); } @@ -139,41 +134,17 @@ public function handleData() \restore_error_handler(); if ($error !== null) { - $this->emit('error', array(new \RuntimeException('Unable to read from stream: ' . $error->getMessage(), 0, $error))); + $this->emit('error', [new \RuntimeException('Unable to read from stream: ' . $error->getMessage(), 0, $error)]); $this->close(); return; } if ($data !== '') { - $this->emit('data', array($data)); + $this->emit('data', [$data]); } elseif (\feof($this->stream)) { // no data read => we reached the end and close the stream $this->emit('end'); $this->close(); } } - - /** - * Returns whether this is a pipe resource in a legacy environment - * - * This works around a legacy PHP bug (#61019) that was fixed in PHP 5.4.28+ - * and PHP 5.5.12+ and newer. - * - * @param resource $resource - * @return bool - * @link https://github.com/reactphp/child-process/issues/40 - * - * @codeCoverageIgnore - */ - private function isLegacyPipe($resource) - { - if (\PHP_VERSION_ID < 50428 || (\PHP_VERSION_ID >= 50500 && \PHP_VERSION_ID < 50512)) { - $meta = \stream_get_meta_data($resource); - - if (isset($meta['stream_type']) && $meta['stream_type'] === 'STDIO') { - return true; - } - } - return false; - } } diff --git a/src/ReadableStreamInterface.php b/src/ReadableStreamInterface.php index fa3d59c..ecc5267 100644 --- a/src/ReadableStreamInterface.php +++ b/src/ReadableStreamInterface.php @@ -278,7 +278,7 @@ public function resume(); * source stream emits an `end` event. This can be disabled like this: * * ```php - * $source->pipe($dest, array('end' => false)); + * $source->pipe($dest, ['end' => false]); * ``` * * Note that this only applies to the `end` event. @@ -322,7 +322,7 @@ public function resume(); * @param array $options * @return WritableStreamInterface $dest stream as-is */ - public function pipe(WritableStreamInterface $dest, array $options = array()); + public function pipe(WritableStreamInterface $dest, array $options = []); /** * Closes the stream (forcefully). diff --git a/src/ThroughStream.php b/src/ThroughStream.php index 3b4fbb7..c49ebfc 100644 --- a/src/ThroughStream.php +++ b/src/ThroughStream.php @@ -48,7 +48,7 @@ * }); * $through->on('data', $this->expectCallableOnceWith("[2, true]\n")); * - * $through->write(array(2, true)); + * $through->write([2, true]); * ``` * * The callback function is allowed to throw an `Exception`. In this case, @@ -108,7 +108,7 @@ public function resume() } } - public function pipe(WritableStreamInterface $dest, array $options = array()) + public function pipe(WritableStreamInterface $dest, array $options = []) { return Util::pipe($this, $dest, $options); } @@ -133,14 +133,14 @@ public function write($data) try { $data = \call_user_func($this->callback, $data); } catch (\Exception $e) { - $this->emit('error', array($e)); + $this->emit('error', [$e]); $this->close(); return false; } } - $this->emit('data', array($data)); + $this->emit('data', [$data]); // emit drain event on next resume if currently paused (throttled) if ($this->paused) { diff --git a/src/Util.php b/src/Util.php index 056b037..114ccb8 100644 --- a/src/Util.php +++ b/src/Util.php @@ -13,7 +13,7 @@ final class Util * @return WritableStreamInterface $dest stream as-is * @see ReadableStreamInterface::pipe() for more details */ - public static function pipe(ReadableStreamInterface $source, WritableStreamInterface $dest, array $options = array()) + public static function pipe(ReadableStreamInterface $source, WritableStreamInterface $dest, array $options = []) { // source not readable => NO-OP if (!$source->isReadable()) { @@ -27,7 +27,7 @@ public static function pipe(ReadableStreamInterface $source, WritableStreamInter return $dest; } - $dest->emit('pipe', array($source)); + $dest->emit('pipe', [$source]); // forward all source data events as $dest->write() $source->on('data', $dataer = function ($data) use ($source, $dest) { diff --git a/src/WritableResourceStream.php b/src/WritableResourceStream.php index 1af16b1..9665721 100644 --- a/src/WritableResourceStream.php +++ b/src/WritableResourceStream.php @@ -36,7 +36,7 @@ public function __construct($stream, LoopInterface $loop = null, $writeBufferSof // ensure resource is opened for writing (fopen mode must contain either of "waxc+") $meta = \stream_get_meta_data($stream); - if (isset($meta['mode']) && $meta['mode'] !== '' && \strtr($meta['mode'], 'waxc+', '.....') === $meta['mode']) { + if (\strtr($meta['mode'], 'waxc+', '.....') === $meta['mode']) { throw new \InvalidArgumentException('Given stream resource is not opened in write mode'); } @@ -68,7 +68,7 @@ public function write($data) if (!$this->listening && $this->data !== '') { $this->listening = true; - $this->loop->addWriteStream($this->stream, array($this, 'handleWrite')); + $this->loop->addWriteStream($this->stream, [$this, 'handleWrite']); } return !isset($this->data[$this->softLimit - 1]); @@ -137,7 +137,7 @@ public function handleWrite() // Should this turn out to be a permanent error later, it will eventually // send *nothing* and we can detect this. if (($sent === 0 || $sent === false) && $error !== null) { - $this->emit('error', array(new \RuntimeException('Unable to write to stream: ' . $error))); + $this->emit('error', [new \RuntimeException('Unable to write to stream: ' . $error)]); $this->close(); return; diff --git a/tests/CompositeStreamTest.php b/tests/CompositeStreamTest.php index df89c3e..75a0426 100644 --- a/tests/CompositeStreamTest.php +++ b/tests/CompositeStreamTest.php @@ -3,7 +3,9 @@ namespace React\Tests\Stream; use React\Stream\CompositeStream; +use React\Stream\ReadableStreamInterface; use React\Stream\ThroughStream; +use React\Stream\WritableStreamInterface; /** * @covers React\Stream\CompositeStream @@ -13,7 +15,7 @@ class CompositeStreamTest extends TestCase /** @test */ public function itShouldCloseReadableIfNotWritable() { - $readable = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + $readable = $this->createMock(ReadableStreamInterface::class); $readable ->expects($this->once()) ->method('isReadable') @@ -22,7 +24,7 @@ public function itShouldCloseReadableIfNotWritable() ->expects($this->once()) ->method('close'); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable ->expects($this->once()) ->method('isWritable') @@ -37,13 +39,13 @@ public function itShouldCloseReadableIfNotWritable() /** @test */ public function itShouldCloseWritableIfNotReadable() { - $readable = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + $readable = $this->createMock(ReadableStreamInterface::class); $readable ->expects($this->once()) ->method('isReadable') ->willReturn(false); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable ->expects($this->once()) ->method('close'); @@ -57,13 +59,13 @@ public function itShouldCloseWritableIfNotReadable() /** @test */ public function itShouldForwardWritableCallsToWritableStream() { - $readable = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + $readable = $this->createMock(ReadableStreamInterface::class); $readable ->expects($this->once()) ->method('isReadable') ->willReturn(true); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable ->expects($this->once()) ->method('write') @@ -81,7 +83,7 @@ public function itShouldForwardWritableCallsToWritableStream() /** @test */ public function itShouldForwardReadableCallsToReadableStream() { - $readable = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + $readable = $this->createMock(ReadableStreamInterface::class); $readable ->expects($this->exactly(2)) ->method('isReadable') @@ -93,7 +95,7 @@ public function itShouldForwardReadableCallsToReadableStream() ->expects($this->once()) ->method('resume'); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable ->expects($this->any()) ->method('isWritable') @@ -108,7 +110,7 @@ public function itShouldForwardReadableCallsToReadableStream() /** @test */ public function itShouldNotForwardResumeIfStreamIsNotWritable() { - $readable = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + $readable = $this->createMock(ReadableStreamInterface::class); $readable ->expects($this->once()) ->method('isReadable') @@ -117,7 +119,7 @@ public function itShouldNotForwardResumeIfStreamIsNotWritable() ->expects($this->never()) ->method('resume'); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable ->expects($this->exactly(2)) ->method('isWritable') @@ -130,13 +132,13 @@ public function itShouldNotForwardResumeIfStreamIsNotWritable() /** @test */ public function endShouldDelegateToWritableWithData() { - $readable = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + $readable = $this->createMock(ReadableStreamInterface::class); $readable ->expects($this->once()) ->method('isReadable') ->willReturn(true); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable ->expects($this->once()) ->method('isWritable') @@ -153,7 +155,7 @@ public function endShouldDelegateToWritableWithData() /** @test */ public function closeShouldCloseBothStreams() { - $readable = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + $readable = $this->createMock(ReadableStreamInterface::class); $readable ->expects($this->once()) ->method('isReadable') @@ -162,7 +164,7 @@ public function closeShouldCloseBothStreams() ->expects($this->once()) ->method('close'); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable ->expects($this->once()) ->method('isWritable') @@ -217,20 +219,20 @@ public function itShouldReceiveForwardedEvents() $composite->on('data', $this->expectCallableOnce()); $composite->on('drain', $this->expectCallableOnce()); - $readable->emit('data', array('foo')); + $readable->emit('data', ['foo']); $writable->emit('drain'); } /** @test */ public function itShouldHandlePipingCorrectly() { - $readable = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + $readable = $this->createMock(ReadableStreamInterface::class); $readable ->expects($this->once()) ->method('isReadable') ->willReturn(true); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable->expects($this->any())->method('isWritable')->willReturn(True); $writable ->expects($this->once()) @@ -241,7 +243,7 @@ public function itShouldHandlePipingCorrectly() $input = new ThroughStream(); $input->pipe($composite); - $input->emit('data', array('foo')); + $input->emit('data', ['foo']); } /** @test */ @@ -249,12 +251,12 @@ public function itShouldForwardPipeCallsToReadableStream() { $readable = new ThroughStream(); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable->expects($this->any())->method('isWritable')->willReturn(True); $composite = new CompositeStream($readable, $writable); - $output = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $output = $this->createMock(WritableStreamInterface::class); $output->expects($this->any())->method('isWritable')->willReturn(True); $output ->expects($this->once()) @@ -262,6 +264,6 @@ public function itShouldForwardPipeCallsToReadableStream() ->with('foo'); $composite->pipe($output); - $readable->emit('data', array('foo')); + $readable->emit('data', ['foo']); } } diff --git a/tests/DuplexResourceStreamIntegrationTest.php b/tests/DuplexResourceStreamIntegrationTest.php index 7135e15..02da5d2 100644 --- a/tests/DuplexResourceStreamIntegrationTest.php +++ b/tests/DuplexResourceStreamIntegrationTest.php @@ -2,55 +2,33 @@ namespace React\Tests\Stream; -use Clue\StreamFilter as Filter; use React\Stream\DuplexResourceStream; use React\Stream\ReadableResourceStream; use React\EventLoop\ExtEventLoop; -use React\EventLoop\ExtLibeventLoop; -use React\EventLoop\ExtLibevLoop; use React\EventLoop\LoopInterface; -use React\EventLoop\LibEventLoop; -use React\EventLoop\LibEvLoop; use React\EventLoop\StreamSelectLoop; +use function Clue\StreamFilter\append as filter_append; class DuplexResourceStreamIntegrationTest extends TestCase { public function loopProvider() { - return array( - array( - function() { - return true; - }, - function () { - return new StreamSelectLoop(); - } - ), - array( - function () { - return function_exists('event_base_new'); - }, - function () { - return class_exists('React\EventLoop\ExtLibeventLoop') ? new ExtLibeventLoop() : new LibEventLoop(); - } - ), - array( - function () { - return class_exists('libev\EventLoop'); - }, - function () { - return class_exists('React\EventLoop\ExtLibevLoop') ? new ExtLibevLoop() : new LibEvLoop(); - } - ), - array( - function () { - return class_exists('EventBase') && class_exists('React\EventLoop\ExtEventLoop'); - }, - function () { - return new ExtEventLoop(); - } - ) - ); + yield [ + function() { + return true; + }, + function () { + return new StreamSelectLoop(); + } + ]; + yield [ + function () { + return class_exists('EventBase'); + }, + function () { + return new ExtEventLoop(); + } + ]; } /** @@ -360,7 +338,7 @@ public function testEmptyReadShouldntFcloseStream($condition, $loopFactory) // add a filter which returns an error when encountering an 'a' when reading - Filter\append($stream, function ($chunk) { + filter_append($stream, function ($chunk) { return ''; }, STREAM_FILTER_READ); diff --git a/tests/DuplexResourceStreamTest.php b/tests/DuplexResourceStreamTest.php index e61f14b..52477fe 100644 --- a/tests/DuplexResourceStreamTest.php +++ b/tests/DuplexResourceStreamTest.php @@ -2,9 +2,11 @@ namespace React\Tests\Stream; +use React\EventLoop\LoopInterface; use React\Stream\DuplexResourceStream; -use Clue\StreamFilter as Filter; use React\Stream\WritableResourceStream; +use React\Stream\WritableStreamInterface; +use function Clue\StreamFilter\append as filter_append; class DuplexResourceStreamTest extends TestCase { @@ -56,7 +58,7 @@ public function testConstructorThrowsExceptionOnInvalidStream() { $loop = $this->createLoopMock(); - $this->setExpectedException('InvalidArgumentException'); + $this->expectException(\InvalidArgumentException::class); new DuplexResourceStream('breakme', $loop); } @@ -65,13 +67,9 @@ public function testConstructorThrowsExceptionOnInvalidStream() */ public function testConstructorThrowsExceptionOnWriteOnlyStream() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('HHVM does not report fopen mode for STDOUT'); - } - $loop = $this->createLoopMock(); - $this->setExpectedException('InvalidArgumentException'); + $this->expectException(\InvalidArgumentException::class); new DuplexResourceStream(STDOUT, $loop); } @@ -86,7 +84,7 @@ public function testConstructorThrowsExceptionOnWriteOnlyStreamWithExcessiveMode unlink($name); $loop = $this->createLoopMock(); - $this->setExpectedException('InvalidArgumentException'); + $this->expectException(\InvalidArgumentException::class); new DuplexResourceStream($stream, $loop); } @@ -102,7 +100,7 @@ public function testConstructorThrowsExceptionIfStreamDoesNotSupportNonBlocking( $stream = fopen('blocking://test', 'r+'); $loop = $this->createLoopMock(); - $this->setExpectedException('RunTimeException'); + $this->expectException(\RuntimeException::class); new DuplexResourceStream($stream, $loop); } @@ -115,7 +113,7 @@ public function testConstructorAcceptsBuffer() $stream = fopen('php://temp', 'r+'); $loop = $this->createLoopMock(); - $buffer = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $buffer = $this->createMock(WritableStreamInterface::class); new DuplexResourceStream($stream, $loop, null, $buffer); } @@ -134,7 +132,7 @@ public function testConstructorThrowsExceptionIfStreamDoesNotSupportNonBlockingW $buffer = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); - $this->setExpectedException('RunTimeException'); + $this->expectException(\RuntimeException::class); new DuplexResourceStream($stream, $loop, null, $buffer); } @@ -157,7 +155,7 @@ public function testEndShouldEndBuffer() $stream = fopen('php://temp', 'r+'); $loop = $this->createLoopMock(); - $buffer = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $buffer = $this->createMock(WritableStreamInterface::class); $buffer->expects($this->once())->method('end')->with('foo'); $conn = new DuplexResourceStream($stream, $loop, null, $buffer); @@ -170,7 +168,7 @@ public function testEndAfterCloseIsNoOp() $stream = fopen('php://temp', 'r+'); $loop = $this->createLoopMock(); - $buffer = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $buffer = $this->createMock(WritableStreamInterface::class); $buffer->expects($this->never())->method('end'); $conn = new DuplexResourceStream($stream, $loop); @@ -410,7 +408,7 @@ public function testPipeShouldReturnDestination() $loop = $this->createLoopMock(); $conn = new DuplexResourceStream($stream, $loop); - $dest = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $dest = $this->createMock(WritableStreamInterface::class); $this->assertSame($dest, $conn->pipe($dest)); } @@ -427,7 +425,7 @@ public function testBufferEventsShouldBubbleUp() $conn->on('error', $this->expectCallableOnce()); $buffer->emit('drain'); - $buffer->emit('error', array(new \RuntimeException('Whoops'))); + $buffer->emit('error', [new \RuntimeException('Whoops')]); } /** @@ -458,7 +456,7 @@ public function testDataFiltered() $stream = fopen('php://temp', 'r+'); // add a filter which removes every 'a' when reading - Filter\append($stream, function ($chunk) { + filter_append($stream, function ($chunk) { return str_replace('a', '', $chunk); }, STREAM_FILTER_READ); @@ -486,7 +484,7 @@ public function testDataErrorShouldEmitErrorAndClose() $stream = fopen('php://temp', 'r+'); // add a filter which returns an error when encountering an 'a' when reading - Filter\append($stream, function ($chunk) { + filter_append($stream, function ($chunk) { if (strpos($chunk, 'a') !== false) { throw new \Exception('Invalid'); } @@ -521,6 +519,6 @@ private function createWriteableLoopMock() private function createLoopMock() { - return $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + return $this->createMock(LoopInterface::class); } } diff --git a/tests/FunctionalInternetTest.php b/tests/FunctionalInternetTest.php index 4f07537..5113e7b 100644 --- a/tests/FunctionalInternetTest.php +++ b/tests/FunctionalInternetTest.php @@ -87,8 +87,8 @@ public function testUploadBiggerBlockSecure() $stream = stream_socket_client('ssl://httpbin.org:443'); - // PHP < 7.1.4 (and PHP < 7.0.18) suffers from a bug when writing big - // chunks of data over TLS streams at once. + // PHP < 7.1.4 suffers from a bug when writing big chunks of data over + // TLS streams at once. // We work around this by limiting the write chunk size to 8192 bytes // here to also support older PHP versions. // See https://github.com/reactphp/socket/issues/105 @@ -120,10 +120,9 @@ private function awaitStreamClose(DuplexResourceStream $stream, LoopInterface $l $loop->stop(); }); - $that = $this; - $loop->addTimer($timeout, function () use ($loop, $that) { + $loop->addTimer($timeout, function () use ($loop) { $loop->stop(); - $that->fail('Timed out while waiting for stream to close'); + $this->fail('Timed out while waiting for stream to close'); }); $loop->run(); diff --git a/tests/ReadableResourceStreamTest.php b/tests/ReadableResourceStreamTest.php index f534488..4cebb5a 100644 --- a/tests/ReadableResourceStreamTest.php +++ b/tests/ReadableResourceStreamTest.php @@ -2,8 +2,10 @@ namespace React\Tests\Stream; +use React\EventLoop\LoopInterface; use React\Stream\ReadableResourceStream; -use Clue\StreamFilter as Filter; +use React\Stream\WritableStreamInterface; +use function Clue\StreamFilter\append as filter_append; class ReadableResourceStreamTest extends TestCase { @@ -55,7 +57,7 @@ public function testConstructorThrowsExceptionOnInvalidStream() { $loop = $this->createLoopMock(); - $this->setExpectedException('InvalidArgumentException'); + $this->expectException(\InvalidArgumentException::class); new ReadableResourceStream(false, $loop); } @@ -64,13 +66,9 @@ public function testConstructorThrowsExceptionOnInvalidStream() */ public function testConstructorThrowsExceptionOnWriteOnlyStream() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('HHVM does not report fopen mode for STDOUT'); - } - $loop = $this->createLoopMock(); - $this->setExpectedException('InvalidArgumentException'); + $this->expectException(\InvalidArgumentException::class); new ReadableResourceStream(STDOUT, $loop); } @@ -85,7 +83,7 @@ public function testConstructorThrowsExceptionOnWriteOnlyStreamWithExcessiveMode unlink($name); $loop = $this->createLoopMock(); - $this->setExpectedException('InvalidArgumentException'); + $this->expectException(\InvalidArgumentException::class); new ReadableResourceStream($stream, $loop); } @@ -101,7 +99,7 @@ public function testConstructorThrowsExceptionIfStreamDoesNotSupportNonBlocking( $stream = fopen('blocking://test', 'r+'); $loop = $this->createLoopMock(); - $this->setExpectedException('RuntimeException'); + $this->expectException(\RuntimeException::class); new ReadableResourceStream($stream, $loop); } @@ -225,7 +223,7 @@ public function testPipeShouldReturnDestination() $loop = $this->createLoopMock(); $conn = new ReadableResourceStream($stream, $loop); - $dest = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $dest = $this->createMock(WritableStreamInterface::class); $this->assertSame($dest, $conn->pipe($dest)); } @@ -330,7 +328,7 @@ public function testDataFiltered() $stream = fopen('php://temp', 'r+'); // add a filter which removes every 'a' when reading - Filter\append($stream, function ($chunk) { + filter_append($stream, function ($chunk) { return str_replace('a', '', $chunk); }, STREAM_FILTER_READ); @@ -358,7 +356,7 @@ public function testDataErrorShouldEmitErrorAndClose() $stream = fopen('php://temp', 'r+'); // add a filter which returns an error when encountering an 'a' when reading - Filter\append($stream, function ($chunk) { + filter_append($stream, function ($chunk) { if (strpos($chunk, 'a') !== false) { throw new \Exception('Invalid'); } @@ -399,6 +397,6 @@ public function testEmptyReadShouldntFcloseStream() private function createLoopMock() { - return $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + return $this->createMock(LoopInterface::class); } } diff --git a/tests/Stub/ReadableStreamStub.php b/tests/Stub/ReadableStreamStub.php index 6984f24..3fa56a8 100644 --- a/tests/Stub/ReadableStreamStub.php +++ b/tests/Stub/ReadableStreamStub.php @@ -20,19 +20,19 @@ public function isReadable() // trigger data event public function write($data) { - $this->emit('data', array($data)); + $this->emit('data', [$data]); } // trigger error event public function error($error) { - $this->emit('error', array($error)); + $this->emit('error', [$error]); } // trigger end event public function end() { - $this->emit('end', array()); + $this->emit('end', []); } public function pause() @@ -52,7 +52,7 @@ public function close() $this->emit('close'); } - public function pipe(WritableStreamInterface $dest, array $options = array()) + public function pipe(WritableStreamInterface $dest, array $options = []) { Util::pipe($this, $dest, $options); diff --git a/tests/TestCase.php b/tests/TestCase.php index af07e3e..b161c46 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -39,62 +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(); - } - } - - public function setExpectedException($exception, $exceptionMessage = '', $exceptionCode = null) - { - if (method_exists($this, 'expectException')) { - // PHPUnit 5.2+ - $this->expectException($exception); - if ($exceptionMessage !== '') { - $this->expectExceptionMessage($exceptionMessage); - } - if ($exceptionCode !== null) { - $this->expectExceptionCode($exceptionCode); - } - } else { - // legacy PHPUnit 4 - PHPUnit 5.1 - parent::setExpectedException($exception, $exceptionMessage, $exceptionCode); - } - } - - public function assertContainsString($needle, $haystack) - { - if (method_exists($this, 'assertStringContainsString')) { - // PHPUnit 7.5+ - $this->assertStringContainsString($needle, $haystack); - } else { - // legacy PHPUnit 4 - PHPUnit 7.5 - $this->assertContains($needle, $haystack); - } - } - - public function assertContainsStringIgnoringCase($needle, $haystack) - { - if (method_exists($this, 'assertStringContainsStringIgnoringCase')) { - // PHPUnit 7.5+ - $this->assertStringContainsStringIgnoringCase($needle, $haystack); - } else { - // legacy PHPUnit 4 - PHPUnit 7.5 - $this->assertContains($needle, $haystack, '', true); - } - } - - public function assertSameIgnoringCase($expected, $actual) - { - if (method_exists($this, 'assertEqualsIgnoringCase')) { - // PHPUnit 7.5+ - $this->assertEqualsIgnoringCase($expected, $actual); - } else { - // legacy PHPUnit 4 - PHPUnit 7.5 - $this->assertSame($expected, $actual); + // legacy PHPUnit + return $builder->setMethods(['__invoke'])->getMock(); } } } diff --git a/tests/ThroughStreamTest.php b/tests/ThroughStreamTest.php index 42c251a..04a49d0 100644 --- a/tests/ThroughStreamTest.php +++ b/tests/ThroughStreamTest.php @@ -3,6 +3,7 @@ namespace React\Tests\Stream; use React\Stream\ThroughStream; +use React\Stream\WritableStreamInterface; /** * @covers React\Stream\ThroughStream @@ -14,7 +15,7 @@ class ThroughStreamTest extends TestCase */ public function itShouldRejectInvalidCallback() { - $this->setExpectedException('InvalidArgumentException'); + $this->expectException(\InvalidArgumentException::class); new ThroughStream(123); } @@ -185,7 +186,7 @@ public function pipingStuffIntoItShouldWork() $through->on('data', $this->expectCallableOnceWith('foo')); $readable->pipe($through); - $readable->emit('data', array('foo')); + $readable->emit('data', ['foo']); } /** @test */ @@ -243,7 +244,7 @@ public function writeAfterEndShouldReturnFalse() public function writeDataWillCloseStreamShouldReturnFalse() { $through = new ThroughStream(); - $through->on('data', array($through, 'close')); + $through->on('data', [$through, 'close']); $this->assertFalse($through->write('foo')); } @@ -311,7 +312,7 @@ public function doubleCloseShouldCloseOnce() /** @test */ public function pipeShouldPipeCorrectly() { - $output = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $output = $this->createMock(WritableStreamInterface::class); $output->expects($this->any())->method('isWritable')->willReturn(True); $output ->expects($this->once()) diff --git a/tests/UtilTest.php b/tests/UtilTest.php index f12baad..50b2e75 100644 --- a/tests/UtilTest.php +++ b/tests/UtilTest.php @@ -2,10 +2,13 @@ namespace React\Tests\Stream; -use React\Stream\WritableResourceStream; -use React\Stream\Util; +use React\EventLoop\LoopInterface; use React\Stream\CompositeStream; +use React\Stream\ReadableStreamInterface; use React\Stream\ThroughStream; +use React\Stream\Util; +use React\Stream\WritableResourceStream; +use React\Stream\WritableStreamInterface; /** * @covers React\Stream\Util @@ -14,9 +17,9 @@ class UtilTest extends TestCase { public function testPipeReturnsDestinationStream() { - $readable = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + $readable = $this->createMock(ReadableStreamInterface::class); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $ret = Util::pipe($readable, $writable); @@ -25,13 +28,13 @@ public function testPipeReturnsDestinationStream() public function testPipeNonReadableSourceShouldDoNothing() { - $readable = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + $readable = $this->createMock(ReadableStreamInterface::class); $readable ->expects($this->any()) ->method('isReadable') ->willReturn(false); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable ->expects($this->never()) ->method('isWritable'); @@ -44,7 +47,7 @@ public function testPipeNonReadableSourceShouldDoNothing() public function testPipeIntoNonWritableDestinationShouldPauseSource() { - $readable = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + $readable = $this->createMock(ReadableStreamInterface::class); $readable ->expects($this->any()) ->method('isReadable') @@ -53,7 +56,7 @@ public function testPipeIntoNonWritableDestinationShouldPauseSource() ->expects($this->once()) ->method('pause'); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable ->expects($this->any()) ->method('isWritable') @@ -67,7 +70,7 @@ public function testPipeIntoNonWritableDestinationShouldPauseSource() public function testPipeClosingDestPausesSource() { - $readable = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + $readable = $this->createMock(ReadableStreamInterface::class); $readable ->expects($this->any()) ->method('isReadable') @@ -87,7 +90,7 @@ public function testPipeWithEnd() { $readable = new Stub\ReadableStreamStub(); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable ->expects($this->any()) ->method('isWritable') @@ -105,7 +108,7 @@ public function testPipeWithoutEnd() { $readable = new Stub\ReadableStreamStub(); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable ->expects($this->any()) ->method('isWritable') @@ -114,7 +117,7 @@ public function testPipeWithoutEnd() ->expects($this->never()) ->method('end'); - Util::pipe($readable, $writable, array('end' => false)); + Util::pipe($readable, $writable, ['end' => false]); $readable->end(); } @@ -123,7 +126,7 @@ public function testPipeWithTooSlowWritableShouldPauseReadable() { $readable = new Stub\ReadableStreamStub(); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable ->expects($this->any()) ->method('isWritable') @@ -147,7 +150,7 @@ public function testPipeWithTooSlowWritableShouldResumeOnDrain() $onDrain = null; - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable ->expects($this->any()) ->method('isWritable') @@ -175,7 +178,7 @@ public function testPipeWithWritableResourceStream() $readable = new Stub\ReadableStreamStub(); $stream = fopen('php://temp', 'r+'); - $loop = $this->createLoopMock(); + $loop = $this->createMock(LoopInterface::class); $buffer = new WritableResourceStream($stream, $loop); $readable->pipe($buffer); @@ -234,9 +237,9 @@ public function testPipeClosingDestRemovesListeners() public function testPipeDuplexIntoSelfEndsOnEnd() { - $readable = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + $readable = $this->createMock(ReadableStreamInterface::class); $readable->expects($this->any())->method('isReadable')->willReturn(true); - $writable = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock(); + $writable = $this->createMock(WritableStreamInterface::class); $writable->expects($this->any())->method('isWritable')->willReturn(true); $duplex = new CompositeStream($readable, $writable); @@ -253,16 +256,11 @@ public function forwardEventsShouldSetupForwards() $source = new ThroughStream(); $target = new ThroughStream(); - Util::forwardEvents($source, $target, array('data')); + Util::forwardEvents($source, $target, ['data']); $target->on('data', $this->expectCallableOnce()); $target->on('foo', $this->expectCallableNever()); - $source->emit('data', array('hello')); - $source->emit('foo', array('bar')); - } - - private function createLoopMock() - { - return $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $source->emit('data', ['hello']); + $source->emit('foo', ['bar']); } } diff --git a/tests/WritableResourceStreamTest.php b/tests/WritableResourceStreamTest.php index 678db98..02f2367 100644 --- a/tests/WritableResourceStreamTest.php +++ b/tests/WritableResourceStreamTest.php @@ -2,8 +2,9 @@ namespace React\Tests\Stream; -use Clue\StreamFilter as Filter; +use React\EventLoop\LoopInterface; use React\Stream\WritableResourceStream; +use function Clue\StreamFilter\append as filter_append; class WritableResourceStreamTest extends TestCase { @@ -56,7 +57,7 @@ public function testConstructorThrowsIfNotAValidStreamResource() $stream = null; $loop = $this->createLoopMock(); - $this->setExpectedException('InvalidArgumentException'); + $this->expectException(\InvalidArgumentException::class); new WritableResourceStream($stream, $loop); } @@ -68,7 +69,7 @@ public function testConstructorThrowsExceptionOnReadOnlyStream() $stream = fopen('php://temp', 'r'); $loop = $this->createLoopMock(); - $this->setExpectedException('InvalidArgumentException'); + $this->expectException(\InvalidArgumentException::class); new WritableResourceStream($stream, $loop); } @@ -83,7 +84,7 @@ public function testConstructorThrowsExceptionOnReadOnlyStreamWithExcessiveMode( unlink($name); $loop = $this->createLoopMock(); - $this->setExpectedException('InvalidArgumentException'); + $this->expectException(\InvalidArgumentException::class); new WritableResourceStream($stream, $loop); } @@ -99,7 +100,7 @@ public function testConstructorThrowsExceptionIfStreamDoesNotSupportNonBlocking( $stream = fopen('blocking://test', 'r+'); $loop = $this->createLoopMock(); - $this->setExpectedException('RuntimeException'); + $this->expectException(\RuntimeException::class); new WritableResourceStream($stream, $loop); } @@ -347,10 +348,6 @@ public function testEndWithoutDataDoesNotCloseIfWritableResourceStreamIsFull() */ public function testEndWithDataClosesImmediatelyIfWritableResourceStreamFlushes() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('Not supported on HHVM'); - } - $stream = fopen('php://temp', 'r+'); $filterBuffer = ''; $loop = $this->createLoopMock(); @@ -359,7 +356,7 @@ public function testEndWithDataClosesImmediatelyIfWritableResourceStreamFlushes( $buffer->on('error', $this->expectCallableNever()); $buffer->on('close', $this->expectCallableOnce()); - Filter\append($stream, function ($chunk) use (&$filterBuffer) { + filter_append($stream, function ($chunk) use (&$filterBuffer) { $filterBuffer .= $chunk; return $chunk; }); @@ -411,7 +408,7 @@ public function testClose() $buffer->close(); $this->assertFalse($buffer->isWritable()); - $this->assertEquals(array(), $buffer->listeners('close')); + $this->assertEquals([], $buffer->listeners('close')); } /** @@ -470,7 +467,7 @@ public function testWritingToClosedWritableResourceStreamShouldNotWriteToStream( $buffer = new WritableResourceStream($stream, $loop); - Filter\append($stream, function ($chunk) use (&$filterBuffer) { + filter_append($stream, function ($chunk) use (&$filterBuffer) { $filterBuffer .= $chunk; return $chunk; }); @@ -506,8 +503,8 @@ public function testWritingToClosedStream() $buffer->write('bar'); $buffer->handleWrite(); - $this->assertInstanceOf('Exception', $error); - $this->assertSameIgnoringCase('Unable to write to stream: fwrite(): send of 3 bytes failed with errno=32 Broken pipe', $error->getMessage()); + $this->assertInstanceOf(\Exception::class, $error); + $this->assertEqualsIgnoringCase('Unable to write to stream: fwrite(): send of 3 bytes failed with errno=32 Broken pipe', $error->getMessage()); } private function createWriteableLoopMock() @@ -525,6 +522,6 @@ private function createWriteableLoopMock() private function createLoopMock() { - return $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + return $this->createMock(LoopInterface::class); } }