From 97e0478326d60bcf15fdd90dce564a9afa1db323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Tue, 17 May 2022 20:41:56 +0200 Subject: [PATCH 1/3] Update to require PHP 7.1+ --- .github/workflows/ci.yml | 19 ------------------- README.md | 5 ++--- composer.json | 4 ++-- phpunit.xml.legacy | 2 +- 4 files changed, 5 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79e1ca3..ff52770 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,11 +17,6 @@ jobs: - 7.3 - 7.2 - 7.1 - - 7.0 - - 5.6 - - 5.5 - - 5.4 - - 5.3 steps: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 @@ -34,17 +29,3 @@ jobs: if: ${{ matrix.php >= 7.3 }} - run: REDIS_URI=localhost:6379 vendor/bin/phpunit --coverage-text -c phpunit.xml.legacy if: ${{ matrix.php < 7.3 }} - - PHPUnit-hhvm: - name: PHPUnit (HHVM) - runs-on: ubuntu-18.04 - continue-on-error: true - steps: - - uses: actions/checkout@v2 - - uses: azjezz/setup-hhvm@v1 - with: - version: lts-3.30 - - run: composer self-update --2.2 # downgrade Composer for HHVM - - run: hhvm $(which composer) install - - run: docker run --net=host -d redis - - run: REDIS_URI=localhost:6379 hhvm vendor/bin/phpunit diff --git a/README.md b/README.md index aef11c1..2d66d05 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Async [Redis](https://redis.io/) client implementation, built on top of [ReactPH > **Development version:** This branch contains the code for the upcoming 3.0 release. > For the code of the current stable 2.x release, check out the -> [`2.x` branch](https://github.com/reactphp/promise/tree/2.x). +> [`2.x` branch](https://github.com/clue/reactphp-redis/tree/2.x). > > The upcoming 3.0 release will be the way forward for this package. > However, we will still actively support 2.x for those not yet @@ -625,8 +625,7 @@ $ composer require clue/redis-react:^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. We're committed to providing long-term support (LTS) options and to provide a diff --git a/composer.json b/composer.json index c1752cc..55e91e6 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ } ], "require": { - "php": ">=5.3", + "php": ">=7.1", "clue/redis-protocol": "0.3.*", "evenement/evenement": "^3.0 || ^2.0 || ^1.0", "react/event-loop": "^1.2", @@ -21,7 +21,7 @@ }, "require-dev": { "clue/block-react": "^1.1", - "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" + "phpunit/phpunit": "^9.3 || ^5.7" }, "autoload": { "psr-4": { "Clue\\React\\Redis\\": "src/" } diff --git a/phpunit.xml.legacy b/phpunit.xml.legacy index 8d93c4f..a853976 100644 --- a/phpunit.xml.legacy +++ b/phpunit.xml.legacy @@ -2,7 +2,7 @@ From 15ac1e98ae95e855adf6e6b9746daa102837486c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Fri, 20 May 2022 13:56:23 +0200 Subject: [PATCH 2/3] Update PHP lanuage syntax --- README.md | 14 +++--- examples/cli.php | 2 +- examples/publish.php | 4 +- examples/subscribe.php | 2 +- src/Factory.php | 30 ++++++------ src/LazyClient.php | 100 ++++++++++++++++++---------------------- src/StreamingClient.php | 35 ++++++-------- 7 files changed, 86 insertions(+), 101 deletions(-) diff --git a/README.md b/README.md index 2d66d05..8d75af6 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ send a message to all clients currently subscribed to a given channel: ```php $channel = 'user'; -$message = json_encode(array('id' => 10)); +$message = json_encode(['id' => 10]); $redis->publish($channel, $message); ``` @@ -288,16 +288,16 @@ proxy servers etc.), you can explicitly pass a custom instance of the [`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface): ```php -$connector = new React\Socket\Connector(array( +$connector = new React\Socket\Connector([ 'dns' => '127.0.0.1', - 'tcp' => array( + 'tcp' => [ 'bindto' => '192.168.10.1:0' - ), - 'tls' => array( + ], + 'tls' => [ 'verify_peer' => false, 'verify_peer_name' => false - ) -)); + ] +]); $factory = new Clue\React\Redis\Factory(null, $connector); ``` diff --git a/examples/cli.php b/examples/cli.php index c1c629f..d0b41f8 100644 --- a/examples/cli.php +++ b/examples/cli.php @@ -29,7 +29,7 @@ $params = explode(' ', $line); $method = array_shift($params); - $promise = call_user_func_array(array($redis, $method), $params); + $promise = call_user_func_array([$redis, $method], $params); // special method such as end() / close() called if (!$promise instanceof React\Promise\PromiseInterface) { diff --git a/examples/publish.php b/examples/publish.php index 6eb2f9d..70a8bb0 100644 --- a/examples/publish.php +++ b/examples/publish.php @@ -8,8 +8,8 @@ $factory = new Clue\React\Redis\Factory(); $redis = $factory->createLazyClient(getenv('REDIS_URI') ?: 'localhost:6379'); -$channel = isset($argv[1]) ? $argv[1] : 'channel'; -$message = isset($argv[2]) ? $argv[2] : 'message'; +$channel = $argv[1] ?? 'channel'; +$message = $argv[2] ?? 'message'; $redis->publish($channel, $message)->then(function ($received) { echo 'Successfully published. Received by ' . $received . PHP_EOL; diff --git a/examples/subscribe.php b/examples/subscribe.php index 9f93f2e..b7871f5 100644 --- a/examples/subscribe.php +++ b/examples/subscribe.php @@ -10,7 +10,7 @@ $factory = new Clue\React\Redis\Factory(); $redis = $factory->createLazyClient(getenv('REDIS_URI') ?: 'localhost:6379'); -$channel = isset($argv[1]) ? $argv[1] : 'channel'; +$channel = $argv[1] ?? 'channel'; $redis->subscribe($channel)->then(function () { echo 'Now subscribed to channel ' . PHP_EOL; diff --git a/src/Factory.php b/src/Factory.php index 4e94905..e79abac 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -10,6 +10,8 @@ use React\Socket\ConnectionInterface; use React\Socket\Connector; use React\Socket\ConnectorInterface; +use function React\Promise\reject; +use function React\Promise\Timer\timeout; class Factory { @@ -30,7 +32,7 @@ class Factory public function __construct(LoopInterface $loop = null, ConnectorInterface $connector = null, ProtocolFactory $protocol = null) { $this->loop = $loop ?: Loop::get(); - $this->connector = $connector ?: new Connector(array(), $this->loop); + $this->connector = $connector ?: new Connector([], $this->loop); $this->protocol = $protocol ?: new ProtocolFactory(); } @@ -54,18 +56,18 @@ public function createClient($uri) $parts = parse_url($uri); } - $uri = preg_replace(array('/(:)[^:\/]*(@)/', '/([?&]password=).*?($|&)/'), '$1***$2', $uri); - if ($parts === false || !isset($parts['scheme'], $parts['host']) || !in_array($parts['scheme'], array('redis', 'rediss', 'redis+unix'))) { - return \React\Promise\reject(new \InvalidArgumentException( + $uri = preg_replace(['/(:)[^:\/]*(@)/', '/([?&]password=).*?($|&)/'], '$1***$2', $uri); + if ($parts === false || !isset($parts['scheme'], $parts['host']) || !in_array($parts['scheme'], ['redis', 'rediss', 'redis+unix'])) { + return reject(new \InvalidArgumentException( 'Invalid Redis URI given (EINVAL)', defined('SOCKET_EINVAL') ? SOCKET_EINVAL : 22 )); } - $args = array(); - parse_str(isset($parts['query']) ? $parts['query'] : '', $args); + $args = []; + parse_str($parts['query'] ?? '', $args); - $authority = $parts['host'] . ':' . (isset($parts['port']) ? $parts['port'] : 6379); + $authority = $parts['host'] . ':' . ($parts['port'] ?? 6379); if ($parts['scheme'] === 'rediss') { $authority = 'tls://' . $authority; } elseif ($parts['scheme'] === 'redis+unix') { @@ -88,9 +90,8 @@ public function createClient($uri) $connecting->cancel(); }); - $protocol = $this->protocol; - $promise = $connecting->then(function (ConnectionInterface $stream) use ($protocol) { - return new StreamingClient($stream, $protocol->createResponseParser(), $protocol->createSerializer()); + $promise = $connecting->then(function (ConnectionInterface $stream) { + return new StreamingClient($stream, $this->protocol->createResponseParser(), $this->protocol->createSerializer()); }, function (\Exception $e) use ($uri) { throw new \RuntimeException( 'Connection to ' . $uri . ' failed: ' . $e->getMessage(), @@ -100,9 +101,8 @@ public function createClient($uri) }); // use `?password=secret` query or `user:secret@host` password form URL - $pass = isset($args['password']) ? $args['password'] : (isset($parts['pass']) ? rawurldecode($parts['pass']) : null); if (isset($args['password']) || isset($parts['pass'])) { - $pass = isset($args['password']) ? $args['password'] : rawurldecode($parts['pass']); + $pass = $args['password'] ?? rawurldecode($parts['pass']); $promise = $promise->then(function (StreamingClient $redis) use ($pass, $uri) { return $redis->auth($pass)->then( function () use ($redis) { @@ -130,7 +130,7 @@ function (\Exception $e) use ($redis, $uri) { // use `?db=1` query or `/1` path (skip first slash) if (isset($args['db']) || (isset($parts['path']) && $parts['path'] !== '/')) { - $db = isset($args['db']) ? $args['db'] : substr($parts['path'], 1); + $db = $args['db'] ?? substr($parts['path'], 1); $promise = $promise->then(function (StreamingClient $redis) use ($db, $uri) { return $redis->select($db)->then( function () use ($redis) { @@ -159,7 +159,7 @@ function (\Exception $e) use ($redis, $uri) { }); } - $promise->then(array($deferred, 'resolve'), array($deferred, 'reject')); + $promise->then([$deferred, 'resolve'], [$deferred, 'reject']); // use timeout from explicit ?timeout=x parameter or default to PHP's default_socket_timeout (60) $timeout = isset($args['timeout']) ? (float) $args['timeout'] : (int) ini_get("default_socket_timeout"); @@ -167,7 +167,7 @@ function (\Exception $e) use ($redis, $uri) { return $deferred->promise(); } - return \React\Promise\Timer\timeout($deferred->promise(), $timeout, $this->loop)->then(null, function ($e) use ($uri) { + return timeout($deferred->promise(), $timeout, $this->loop)->then(null, function ($e) use ($uri) { if ($e instanceof TimeoutException) { throw new \RuntimeException( 'Connection to ' . $uri . ' timed out after ' . $e->getTimeout() . ' seconds (ETIMEDOUT)', diff --git a/src/LazyClient.php b/src/LazyClient.php index d82b257..291bb27 100644 --- a/src/LazyClient.php +++ b/src/LazyClient.php @@ -5,6 +5,7 @@ use Evenement\EventEmitter; use React\Stream\Util; use React\EventLoop\LoopInterface; +use function React\Promise\reject; /** * @internal @@ -22,15 +23,15 @@ class LazyClient extends EventEmitter implements Client private $idleTimer; private $pending = 0; - private $subscribed = array(); - private $psubscribed = array(); + private $subscribed = []; + private $psubscribed = []; /** * @param $target */ public function __construct($target, Factory $factory, LoopInterface $loop) { - $args = array(); + $args = []; \parse_str((string) \parse_url($target, \PHP_URL_QUERY), $args); if (isset($args['idle'])) { $this->idlePeriod = (float)$args['idle']; @@ -47,66 +48,59 @@ private function client() return $this->promise; } - $self = $this; - $pending =& $this->promise; - $idleTimer=& $this->idleTimer; - $subscribed =& $this->subscribed; - $psubscribed =& $this->psubscribed; - $loop = $this->loop; - return $pending = $this->factory->createClient($this->target)->then(function (Client $redis) use ($self, &$pending, &$idleTimer, &$subscribed, &$psubscribed, $loop) { + return $this->promise = $this->factory->createClient($this->target)->then(function (Client $redis) { // connection completed => remember only until closed - $redis->on('close', function () use (&$pending, $self, &$subscribed, &$psubscribed, &$idleTimer, $loop) { - $pending = null; + $redis->on('close', function () { + $this->promise = null; // foward unsubscribe/punsubscribe events when underlying connection closes - $n = count($subscribed); - foreach ($subscribed as $channel => $_) { - $self->emit('unsubscribe', array($channel, --$n)); + $n = count($this->subscribed); + foreach ($this->subscribed as $channel => $_) { + $this->emit('unsubscribe', [$channel, --$n]); } - $n = count($psubscribed); - foreach ($psubscribed as $pattern => $_) { - $self->emit('punsubscribe', array($pattern, --$n)); + $n = count($this->psubscribed); + foreach ($this->psubscribed as $pattern => $_) { + $this->emit('punsubscribe', [$pattern, --$n]); } - $subscribed = array(); - $psubscribed = array(); + $this->subscribed = $this->psubscribed = []; - if ($idleTimer !== null) { - $loop->cancelTimer($idleTimer); - $idleTimer = null; + if ($this->idleTimer !== null) { + $this->loop->cancelTimer($this->idleTimer); + $this->idleTimer = null; } }); // keep track of all channels and patterns this connection is subscribed to - $redis->on('subscribe', function ($channel) use (&$subscribed) { - $subscribed[$channel] = true; + $redis->on('subscribe', function ($channel) { + $this->subscribed[$channel] = true; }); - $redis->on('psubscribe', function ($pattern) use (&$psubscribed) { - $psubscribed[$pattern] = true; + $redis->on('psubscribe', function ($pattern) { + $this->psubscribed[$pattern] = true; }); - $redis->on('unsubscribe', function ($channel) use (&$subscribed) { - unset($subscribed[$channel]); + $redis->on('unsubscribe', function ($channel) { + unset($this->subscribed[$channel]); }); - $redis->on('punsubscribe', function ($pattern) use (&$psubscribed) { - unset($psubscribed[$pattern]); + $redis->on('punsubscribe', function ($pattern) { + unset($this->psubscribed[$pattern]); }); Util::forwardEvents( $redis, - $self, - array( + $this, + [ 'message', 'subscribe', 'unsubscribe', 'pmessage', 'psubscribe', 'punsubscribe', - ) + ] ); return $redis; - }, function (\Exception $e) use (&$pending) { + }, function (\Exception $e) { // connection failed => discard connection attempt - $pending = null; + $this->promise = null; throw $e; }); @@ -115,22 +109,21 @@ private function client() public function __call($name, $args) { if ($this->closed) { - return \React\Promise\reject(new \RuntimeException( + return reject(new \RuntimeException( 'Connection closed (ENOTCONN)', defined('SOCKET_ENOTCONN') ? SOCKET_ENOTCONN : 107 )); } - $that = $this; - return $this->client()->then(function (Client $redis) use ($name, $args, $that) { - $that->awake(); - return \call_user_func_array(array($redis, $name), $args)->then( - function ($result) use ($that) { - $that->idle(); + return $this->client()->then(function (Client $redis) use ($name, $args) { + $this->awake(); + return \call_user_func_array([$redis, $name], $args)->then( + function ($result) { + $this->idle(); return $result; }, - function ($error) use ($that) { - $that->idle(); + function ($error) { + $this->idle(); throw $error; } ); @@ -147,10 +140,9 @@ public function end() return; } - $that = $this; - return $this->client()->then(function (Client $redis) use ($that) { - $redis->on('close', function () use ($that) { - $that->close(); + return $this->client()->then(function (Client $redis) { + $redis->on('close', function () { + $this->close(); }); $redis->end(); }); @@ -205,14 +197,12 @@ public function idle() --$this->pending; if ($this->pending < 1 && $this->idlePeriod >= 0 && !$this->subscribed && !$this->psubscribed && $this->promise !== null) { - $idleTimer =& $this->idleTimer; - $promise =& $this->promise; - $idleTimer = $this->loop->addTimer($this->idlePeriod, function () use (&$idleTimer, &$promise) { - $promise->then(function (Client $redis) { + $this->idleTimer = $this->loop->addTimer($this->idlePeriod, function () { + $this->promise->then(function (Client $redis) { $redis->close(); }); - $promise = null; - $idleTimer = null; + $this->promise = null; + $this->idleTimer = null; }); } } diff --git a/src/StreamingClient.php b/src/StreamingClient.php index 8afd84d..5ad14a9 100644 --- a/src/StreamingClient.php +++ b/src/StreamingClient.php @@ -21,7 +21,7 @@ class StreamingClient extends EventEmitter implements Client private $stream; private $parser; private $serializer; - private $requests = array(); + private $requests = []; private $ending = false; private $closed = false; @@ -40,32 +40,31 @@ public function __construct(DuplexStreamInterface $stream, ParserInterface $pars } } - $that = $this; - $stream->on('data', function($chunk) use ($parser, $that) { + $stream->on('data', function($chunk) use ($parser) { try { $models = $parser->pushIncoming($chunk); } catch (ParserException $error) { - $that->emit('error', array(new \UnexpectedValueException( + $this->emit('error', [new \UnexpectedValueException( 'Invalid data received: ' . $error->getMessage() . ' (EBADMSG)', defined('SOCKET_EBADMSG') ? SOCKET_EBADMSG : 77, $error - ))); - $that->close(); + )]); + $this->close(); return; } foreach ($models as $data) { try { - $that->handleMessage($data); + $this->handleMessage($data); } catch (\UnderflowException $error) { - $that->emit('error', array($error)); - $that->close(); + $this->emit('error', [$error]); + $this->close(); return; } } }); - $stream->on('close', array($this, 'close')); + $stream->on('close', [$this, 'close']); $this->stream = $stream; $this->parser = $parser; @@ -80,7 +79,7 @@ public function __call($name, $args) $name = strtolower($name); // special (p)(un)subscribe commands only accept a single parameter and have custom response logic applied - static $pubsubs = array('subscribe', 'unsubscribe', 'psubscribe', 'punsubscribe'); + static $pubsubs = ['subscribe', 'unsubscribe', 'psubscribe', 'punsubscribe']; if ($this->ending) { $request->reject(new \RuntimeException( @@ -103,21 +102,17 @@ public function __call($name, $args) } if (in_array($name, $pubsubs)) { - $that = $this; - $subscribed =& $this->subscribed; - $psubscribed =& $this->psubscribed; - - $promise->then(function ($array) use ($that, &$subscribed, &$psubscribed) { + $promise->then(function ($array) { $first = array_shift($array); // (p)(un)subscribe messages are to be forwarded - $that->emit($first, $array); + $this->emit($first, $array); // remember number of (p)subscribe topics if ($first === 'subscribe' || $first === 'unsubscribe') { - $subscribed = $array[1]; + $this->subscribed = $array[1]; } else { - $psubscribed = $array[1]; + $this->psubscribed = $array[1]; } }); } @@ -132,7 +127,7 @@ public function handleMessage(ModelInterface $message) $first = array_shift($array); // pub/sub messages are to be forwarded and should not be processed as request responses - if (in_array($first, array('message', 'pmessage'))) { + if (in_array($first, ['message', 'pmessage'])) { $this->emit($first, $array); return; } From 73b9460b33bc11b6b2f63068dac4de27eecc0beb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Fri, 20 May 2022 14:30:39 +0200 Subject: [PATCH 3/3] Update PHPUnit and PHP syntax for tests --- composer.json | 2 +- phpunit.xml.legacy | 4 +- tests/FactoryLazyClientTest.php | 69 ++++---- tests/FactoryStreamingClientTest.php | 231 ++++++++++++++------------- tests/FunctionalTest.php | 41 +++-- tests/LazyClientTest.php | 108 ++++++------- tests/StreamingClientTest.php | 53 +++--- tests/TestCase.php | 28 ++-- 8 files changed, 263 insertions(+), 273 deletions(-) diff --git a/composer.json b/composer.json index 55e91e6..9dff4b7 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ }, "require-dev": { "clue/block-react": "^1.1", - "phpunit/phpunit": "^9.3 || ^5.7" + "phpunit/phpunit": "^9.3 || ^7.5" }, "autoload": { "psr-4": { "Clue\\React\\Redis\\": "src/" } diff --git a/phpunit.xml.legacy b/phpunit.xml.legacy index a853976..b325858 100644 --- a/phpunit.xml.legacy +++ b/phpunit.xml.legacy @@ -1,8 +1,8 @@ - + diff --git a/tests/FactoryLazyClientTest.php b/tests/FactoryLazyClientTest.php index 8b5005b..e6b6730 100644 --- a/tests/FactoryLazyClientTest.php +++ b/tests/FactoryLazyClientTest.php @@ -2,8 +2,13 @@ namespace Clue\Tests\React\Redis; +use Clue\React\Redis\Client; use Clue\React\Redis\Factory; -use React\Promise; +use React\EventLoop\LoopInterface; +use React\Socket\ConnectionInterface; +use React\Socket\ConnectorInterface; +use function React\Promise\reject; +use function React\Promise\resolve; class FactoryLazyClientTest extends TestCase { @@ -16,8 +21,8 @@ class FactoryLazyClientTest extends TestCase */ public function setUpFactory() { - $this->loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); - $this->connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); + $this->loop = $this->createMock(LoopInterface::class); + $this->connector = $this->createMock(ConnectorInterface::class); $this->factory = new Factory($this->loop, $this->connector); } @@ -29,134 +34,134 @@ public function testConstructWithoutLoopAssignsLoopAutomatically() $ref->setAccessible(true); $loop = $ref->getValue($factory); - $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); + $this->assertInstanceOf(LoopInterface::class, $loop); } public function testWillConnectWithDefaultPort() { - $this->connector->expects($this->never())->method('connect')->with('redis.example.com:6379')->willReturn(Promise\reject(new \RuntimeException())); + $this->connector->expects($this->never())->method('connect')->with('redis.example.com:6379')->willReturn(reject(new \RuntimeException())); $this->factory->createLazyClient('redis.example.com'); } public function testWillConnectToLocalhost() { - $this->connector->expects($this->never())->method('connect')->with('localhost:1337')->willReturn(Promise\reject(new \RuntimeException())); + $this->connector->expects($this->never())->method('connect')->with('localhost:1337')->willReturn(reject(new \RuntimeException())); $this->factory->createLazyClient('localhost:1337'); } public function testWillResolveIfConnectorResolves() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->never())->method('write'); - $this->connector->expects($this->never())->method('connect')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->never())->method('connect')->willReturn(resolve($stream)); $redis = $this->factory->createLazyClient('localhost'); - $this->assertInstanceOf('Clue\React\Redis\Client', $redis); + $this->assertInstanceOf(Client::class, $redis); } public function testWillWriteSelectCommandIfTargetContainsPath() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->never())->method('write')->with("*2\r\n$6\r\nselect\r\n$4\r\ndemo\r\n"); - $this->connector->expects($this->never())->method('connect')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->never())->method('connect')->willReturn(resolve($stream)); $this->factory->createLazyClient('redis://127.0.0.1/demo'); } public function testWillWriteSelectCommandIfTargetContainsDbQueryParameter() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->never())->method('write')->with("*2\r\n$6\r\nselect\r\n$1\r\n4\r\n"); - $this->connector->expects($this->never())->method('connect')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->never())->method('connect')->willReturn(resolve($stream)); $this->factory->createLazyClient('redis://127.0.0.1?db=4'); } public function testWillWriteAuthCommandIfRedisUriContainsUserInfo() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->never())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); - $this->connector->expects($this->never())->method('connect')->with('example.com:6379')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->never())->method('connect')->with('example.com:6379')->willReturn(resolve($stream)); $this->factory->createLazyClient('redis://hello:world@example.com'); } public function testWillWriteAuthCommandIfRedisUriContainsEncodedUserInfo() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->never())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nh@llo\r\n"); - $this->connector->expects($this->never())->method('connect')->with('example.com:6379')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->never())->method('connect')->with('example.com:6379')->willReturn(resolve($stream)); $this->factory->createLazyClient('redis://:h%40llo@example.com'); } public function testWillWriteAuthCommandIfTargetContainsPasswordQueryParameter() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->never())->method('write')->with("*2\r\n$4\r\nauth\r\n$6\r\nsecret\r\n"); - $this->connector->expects($this->never())->method('connect')->with('example.com:6379')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->never())->method('connect')->with('example.com:6379')->willReturn(resolve($stream)); $this->factory->createLazyClient('redis://example.com?password=secret'); } public function testWillWriteAuthCommandIfTargetContainsEncodedPasswordQueryParameter() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->never())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nh@llo\r\n"); - $this->connector->expects($this->never())->method('connect')->with('example.com:6379')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->never())->method('connect')->with('example.com:6379')->willReturn(resolve($stream)); $this->factory->createLazyClient('redis://example.com?password=h%40llo'); } public function testWillWriteAuthCommandIfRedissUriContainsUserInfo() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->never())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); - $this->connector->expects($this->never())->method('connect')->with('tls://example.com:6379')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->never())->method('connect')->with('tls://example.com:6379')->willReturn(resolve($stream)); $this->factory->createLazyClient('rediss://hello:world@example.com'); } public function testWillWriteAuthCommandIfRedisUnixUriContainsPasswordQueryParameter() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->never())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); - $this->connector->expects($this->never())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->never())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(resolve($stream)); $this->factory->createLazyClient('redis+unix:///tmp/redis.sock?password=world'); } public function testWillWriteAuthCommandIfRedisUnixUriContainsUserInfo() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->never())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); - $this->connector->expects($this->never())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->never())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(resolve($stream)); $this->factory->createLazyClient('redis+unix://hello:world@/tmp/redis.sock'); } public function testWillWriteSelectCommandIfRedisUnixUriContainsDbQueryParameter() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->never())->method('write')->with("*2\r\n$6\r\nselect\r\n$4\r\ndemo\r\n"); - $this->connector->expects($this->never())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->never())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(resolve($stream)); $this->factory->createLazyClient('redis+unix:///tmp/redis.sock?db=demo'); } public function testWillRejectIfConnectorRejects() { - $this->connector->expects($this->never())->method('connect')->with('127.0.0.1:2')->willReturn(Promise\reject(new \RuntimeException())); + $this->connector->expects($this->never())->method('connect')->with('127.0.0.1:2')->willReturn(reject(new \RuntimeException())); $redis = $this->factory->createLazyClient('redis://127.0.0.1:2'); - $this->assertInstanceOf('Clue\React\Redis\Client', $redis); + $this->assertInstanceOf(Client::class, $redis); } public function testWillRejectIfTargetIsInvalid() { $redis = $this->factory->createLazyClient('http://invalid target'); - $this->assertInstanceOf('Clue\React\Redis\Client', $redis); + $this->assertInstanceOf(Client::class, $redis); } } diff --git a/tests/FactoryStreamingClientTest.php b/tests/FactoryStreamingClientTest.php index 882af76..938f4e7 100644 --- a/tests/FactoryStreamingClientTest.php +++ b/tests/FactoryStreamingClientTest.php @@ -2,9 +2,14 @@ namespace Clue\Tests\React\Redis; +use Clue\React\Redis\Client; use Clue\React\Redis\Factory; -use React\Promise; +use React\EventLoop\LoopInterface; use React\Promise\Deferred; +use React\Socket\ConnectionInterface; +use React\Socket\ConnectorInterface; +use function React\Promise\reject; +use function React\Promise\resolve; class FactoryStreamingClientTest extends TestCase { @@ -17,8 +22,8 @@ class FactoryStreamingClientTest extends TestCase */ public function setUpFactory() { - $this->loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); - $this->connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); + $this->loop = $this->createMock(LoopInterface::class); + $this->connector = $this->createMock(ConnectorInterface::class); $this->factory = new Factory($this->loop, $this->connector); } @@ -30,7 +35,7 @@ public function testConstructWithoutLoopAssignsLoopAutomatically() $ref->setAccessible(true); $loop = $ref->getValue($factory); - $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); + $this->assertInstanceOf(LoopInterface::class, $loop); } /** @@ -43,22 +48,22 @@ public function testCtor() public function testWillConnectWithDefaultPort() { - $this->connector->expects($this->once())->method('connect')->with('redis.example.com:6379')->willReturn(Promise\reject(new \RuntimeException())); + $this->connector->expects($this->once())->method('connect')->with('redis.example.com:6379')->willReturn(reject(new \RuntimeException())); $this->factory->createClient('redis.example.com'); } public function testWillConnectToLocalhost() { - $this->connector->expects($this->once())->method('connect')->with('localhost:1337')->willReturn(Promise\reject(new \RuntimeException())); + $this->connector->expects($this->once())->method('connect')->with('localhost:1337')->willReturn(reject(new \RuntimeException())); $this->factory->createClient('localhost:1337'); } public function testWillResolveIfConnectorResolves() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->never())->method('write'); - $this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->willReturn(resolve($stream)); $promise = $this->factory->createClient('localhost'); $this->expectPromiseResolve($promise); @@ -66,131 +71,131 @@ public function testWillResolveIfConnectorResolves() public function testWillWriteSelectCommandIfTargetContainsPath() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$6\r\nselect\r\n$4\r\ndemo\r\n"); - $this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->willReturn(resolve($stream)); $this->factory->createClient('redis://127.0.0.1/demo'); } public function testWillWriteSelectCommandIfTargetContainsDbQueryParameter() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$6\r\nselect\r\n$1\r\n4\r\n"); - $this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->willReturn(resolve($stream)); $this->factory->createClient('redis://127.0.0.1?db=4'); } public function testWillWriteAuthCommandIfRedisUriContainsUserInfo() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); - $this->connector->expects($this->once())->method('connect')->with('example.com:6379')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->with('example.com:6379')->willReturn(resolve($stream)); $this->factory->createClient('redis://hello:world@example.com'); } public function testWillWriteAuthCommandIfRedisUriContainsEncodedUserInfo() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nh@llo\r\n"); - $this->connector->expects($this->once())->method('connect')->with('example.com:6379')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->with('example.com:6379')->willReturn(resolve($stream)); $this->factory->createClient('redis://:h%40llo@example.com'); } public function testWillWriteAuthCommandIfTargetContainsPasswordQueryParameter() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$6\r\nsecret\r\n"); - $this->connector->expects($this->once())->method('connect')->with('example.com:6379')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->with('example.com:6379')->willReturn(resolve($stream)); $this->factory->createClient('redis://example.com?password=secret'); } public function testWillWriteAuthCommandIfTargetContainsEncodedPasswordQueryParameter() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nh@llo\r\n"); - $this->connector->expects($this->once())->method('connect')->with('example.com:6379')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->with('example.com:6379')->willReturn(resolve($stream)); $this->factory->createClient('redis://example.com?password=h%40llo'); } public function testWillWriteAuthCommandIfRedissUriContainsUserInfo() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); - $this->connector->expects($this->once())->method('connect')->with('tls://example.com:6379')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->with('tls://example.com:6379')->willReturn(resolve($stream)); $this->factory->createClient('rediss://hello:world@example.com'); } public function testWillWriteAuthCommandIfRedisUnixUriContainsPasswordQueryParameter() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); - $this->connector->expects($this->once())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(resolve($stream)); $this->factory->createClient('redis+unix:///tmp/redis.sock?password=world'); } public function testWillNotWriteAnyCommandIfRedisUnixUriContainsNoPasswordOrDb() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->never())->method('write'); - $this->connector->expects($this->once())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(resolve($stream)); $this->factory->createClient('redis+unix:///tmp/redis.sock'); } public function testWillWriteAuthCommandIfRedisUnixUriContainsUserInfo() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); - $this->connector->expects($this->once())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(resolve($stream)); $this->factory->createClient('redis+unix://hello:world@/tmp/redis.sock'); } public function testWillResolveWhenAuthCommandReceivesOkResponseIfRedisUriContainsUserInfo() { $dataHandler = null; - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); $stream->expects($this->exactly(2))->method('on')->withConsecutive( - array('data', $this->callback(function ($arg) use (&$dataHandler) { + ['data', $this->callback(function ($arg) use (&$dataHandler) { $dataHandler = $arg; return true; - })), - array('close', $this->anything()) + })], + ['close', $this->anything()] ); - $this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->willReturn(resolve($stream)); $promise = $this->factory->createClient('redis://:world@localhost'); $this->assertTrue(is_callable($dataHandler)); $dataHandler("+OK\r\n"); - $promise->then($this->expectCallableOnceWith($this->isInstanceOf('Clue\React\Redis\Client'))); + $promise->then($this->expectCallableOnceWith($this->isInstanceOf(Client::class))); } public function testWillRejectAndCloseAutomaticallyWhenAuthCommandReceivesErrorResponseIfRedisUriContainsUserInfo() { $dataHandler = null; - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); $stream->expects($this->once())->method('close'); $stream->expects($this->exactly(2))->method('on')->withConsecutive( - array('data', $this->callback(function ($arg) use (&$dataHandler) { + ['data', $this->callback(function ($arg) use (&$dataHandler) { $dataHandler = $arg; return true; - })), - array('close', $this->anything()) + })], + ['close', $this->anything()] ); - $this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->willReturn(resolve($stream)); $promise = $this->factory->createClient('redis://:world@localhost'); $this->assertTrue(is_callable($dataHandler)); @@ -198,7 +203,7 @@ public function testWillRejectAndCloseAutomaticallyWhenAuthCommandReceivesErrorR $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('RuntimeException'), + $this->isInstanceOf(\RuntimeException::class), $this->callback(function (\RuntimeException $e) { return $e->getMessage() === 'Connection to redis://:***@localhost failed during AUTH command: ERR invalid password (EACCES)'; }), @@ -215,18 +220,18 @@ public function testWillRejectAndCloseAutomaticallyWhenAuthCommandReceivesErrorR public function testWillRejectAndCloseAutomaticallyWhenConnectionIsClosedWhileWaitingForAuthCommand() { $closeHandler = null; - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n"); $stream->expects($this->once())->method('close'); $stream->expects($this->exactly(2))->method('on')->withConsecutive( - array('data', $this->anything()), - array('close', $this->callback(function ($arg) use (&$closeHandler) { + ['data', $this->anything()], + ['close', $this->callback(function ($arg) use (&$closeHandler) { $closeHandler = $arg; return true; - })) + })] ); - $this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->willReturn(resolve($stream)); $promise = $this->factory->createClient('redis://:world@localhost'); $this->assertTrue(is_callable($closeHandler)); @@ -236,7 +241,7 @@ public function testWillRejectAndCloseAutomaticallyWhenConnectionIsClosedWhileWa $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('RuntimeException'), + $this->isInstanceOf(\RuntimeException::class), $this->callback(function (\Exception $e) { return $e->getMessage() === 'Connection to redis://:***@localhost failed during AUTH command: Connection closed by peer (ECONNRESET)'; }), @@ -252,50 +257,50 @@ public function testWillRejectAndCloseAutomaticallyWhenConnectionIsClosedWhileWa public function testWillWriteSelectCommandIfRedisUnixUriContainsDbQueryParameter() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$6\r\nselect\r\n$4\r\ndemo\r\n"); - $this->connector->expects($this->once())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->with('unix:///tmp/redis.sock')->willReturn(resolve($stream)); $this->factory->createClient('redis+unix:///tmp/redis.sock?db=demo'); } public function testWillResolveWhenSelectCommandReceivesOkResponseIfRedisUriContainsPath() { $dataHandler = null; - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$6\r\nselect\r\n$3\r\n123\r\n"); $stream->expects($this->exactly(2))->method('on')->withConsecutive( - array('data', $this->callback(function ($arg) use (&$dataHandler) { + ['data', $this->callback(function ($arg) use (&$dataHandler) { $dataHandler = $arg; return true; - })), - array('close', $this->anything()) + })], + ['close', $this->anything()] ); - $this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->willReturn(resolve($stream)); $promise = $this->factory->createClient('redis://localhost/123'); $this->assertTrue(is_callable($dataHandler)); $dataHandler("+OK\r\n"); - $promise->then($this->expectCallableOnceWith($this->isInstanceOf('Clue\React\Redis\Client'))); + $promise->then($this->expectCallableOnceWith($this->isInstanceOf(Client::class))); } public function testWillRejectAndCloseAutomaticallyWhenSelectCommandReceivesErrorResponseIfRedisUriContainsPath() { $dataHandler = null; - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$6\r\nselect\r\n$3\r\n123\r\n"); $stream->expects($this->once())->method('close'); $stream->expects($this->exactly(2))->method('on')->withConsecutive( - array('data', $this->callback(function ($arg) use (&$dataHandler) { + ['data', $this->callback(function ($arg) use (&$dataHandler) { $dataHandler = $arg; return true; - })), - array('close', $this->anything()) + })], + ['close', $this->anything()] ); - $this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->willReturn(resolve($stream)); $promise = $this->factory->createClient('redis://localhost/123'); $this->assertTrue(is_callable($dataHandler)); @@ -303,7 +308,7 @@ public function testWillRejectAndCloseAutomaticallyWhenSelectCommandReceivesErro $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('RuntimeException'), + $this->isInstanceOf(\RuntimeException::class), $this->callback(function (\RuntimeException $e) { return $e->getMessage() === 'Connection to redis://localhost/123 failed during SELECT command: ERR DB index is out of range (ENOENT)'; }), @@ -320,18 +325,18 @@ public function testWillRejectAndCloseAutomaticallyWhenSelectCommandReceivesErro public function testWillRejectAndCloseAutomaticallyWhenSelectCommandReceivesAuthErrorResponseIfRedisUriContainsPath() { $dataHandler = null; - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$6\r\nselect\r\n$3\r\n123\r\n"); $stream->expects($this->once())->method('close'); $stream->expects($this->exactly(2))->method('on')->withConsecutive( - array('data', $this->callback(function ($arg) use (&$dataHandler) { + ['data', $this->callback(function ($arg) use (&$dataHandler) { $dataHandler = $arg; return true; - })), - array('close', $this->anything()) + })], + ['close', $this->anything()] ); - $this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->willReturn(resolve($stream)); $promise = $this->factory->createClient('redis://localhost/123'); $this->assertTrue(is_callable($dataHandler)); @@ -339,7 +344,7 @@ public function testWillRejectAndCloseAutomaticallyWhenSelectCommandReceivesAuth $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('RuntimeException'), + $this->isInstanceOf(\RuntimeException::class), $this->callback(function (\Exception $e) { return $e->getMessage() === 'Connection to redis://localhost/123 failed during SELECT command: NOAUTH Authentication required. (EACCES)'; }), @@ -356,18 +361,18 @@ public function testWillRejectAndCloseAutomaticallyWhenSelectCommandReceivesAuth public function testWillRejectAndCloseAutomaticallyWhenConnectionIsClosedWhileWaitingForSelectCommand() { $closeHandler = null; - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write')->with("*2\r\n$6\r\nselect\r\n$3\r\n123\r\n"); $stream->expects($this->once())->method('close'); $stream->expects($this->exactly(2))->method('on')->withConsecutive( - array('data', $this->anything()), - array('close', $this->callback(function ($arg) use (&$closeHandler) { + ['data', $this->anything()], + ['close', $this->callback(function ($arg) use (&$closeHandler) { $closeHandler = $arg; return true; - })) + })] ); - $this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->willReturn(resolve($stream)); $promise = $this->factory->createClient('redis://localhost/123'); $this->assertTrue(is_callable($closeHandler)); @@ -377,7 +382,7 @@ public function testWillRejectAndCloseAutomaticallyWhenConnectionIsClosedWhileWa $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('RuntimeException'), + $this->isInstanceOf(\RuntimeException::class), $this->callback(function (\Exception $e) { return $e->getMessage() === 'Connection to redis://localhost/123 failed during SELECT command: Connection closed by peer (ECONNRESET)'; }), @@ -393,12 +398,12 @@ public function testWillRejectAndCloseAutomaticallyWhenConnectionIsClosedWhileWa public function testWillRejectIfConnectorRejects() { - $this->connector->expects($this->once())->method('connect')->with('127.0.0.1:2')->willReturn(Promise\reject(new \RuntimeException('Foo', 42))); + $this->connector->expects($this->once())->method('connect')->with('127.0.0.1:2')->willReturn(reject(new \RuntimeException('Foo', 42))); $promise = $this->factory->createClient('redis://127.0.0.1:2'); $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('RuntimeException'), + $this->isInstanceOf(\RuntimeException::class), $this->callback(function (\RuntimeException $e) { return $e->getMessage() === 'Connection to redis://127.0.0.1:2 failed: Foo'; }), @@ -418,7 +423,7 @@ public function testWillRejectIfTargetIsInvalid() $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('InvalidArgumentException'), + $this->isInstanceOf(\InvalidArgumentException::class), $this->callback(function (\InvalidArgumentException $e) { return $e->getMessage() === 'Invalid Redis URI given (EINVAL)'; }), @@ -437,73 +442,73 @@ public function testCancelWillRejectPromise() $promise = $this->factory->createClient('redis://127.0.0.1:2'); $promise->cancel(); - $promise->then(null, $this->expectCallableOnceWith($this->isInstanceOf('RuntimeException'))); + $promise->then(null, $this->expectCallableOnceWith($this->isInstanceOf(\RuntimeException::class))); } public function provideUris() { - return array( - array( + return [ + [ 'localhost', 'redis://localhost' - ), - array( + ], + [ 'redis://localhost', 'redis://localhost' - ), - array( + ], + [ 'redis://localhost:6379', 'redis://localhost:6379' - ), - array( + ], + [ 'redis://localhost/0', 'redis://localhost/0' - ), - array( + ], + [ 'redis://user@localhost', 'redis://user@localhost' - ), - array( + ], + [ 'redis://:secret@localhost', 'redis://:***@localhost' - ), - array( + ], + [ 'redis://user:secret@localhost', 'redis://user:***@localhost' - ), - array( + ], + [ 'redis://:@localhost', 'redis://:***@localhost' - ), - array( + ], + [ 'redis://localhost?password=secret', 'redis://localhost?password=***' - ), - array( + ], + [ 'redis://localhost/0?password=secret', 'redis://localhost/0?password=***' - ), - array( + ], + [ 'redis://localhost?password=', 'redis://localhost?password=***' - ), - array( + ], + [ 'redis://localhost?foo=1&password=secret&bar=2', 'redis://localhost?foo=1&password=***&bar=2' - ), - array( + ], + [ 'rediss://localhost', 'rediss://localhost' - ), - array( + ], + [ 'redis+unix://:secret@/tmp/redis.sock', 'redis+unix://:***@/tmp/redis.sock' - ), - array( + ], + [ 'redis+unix:///tmp/redis.sock?password=secret', 'redis+unix:///tmp/redis.sock?password=***' - ) - ); + ] + ]; } /** @@ -521,7 +526,7 @@ public function testCancelWillRejectWithUriInMessageAndCancelConnectorWhenConnec $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('RuntimeException'), + $this->isInstanceOf(\RuntimeException::class), $this->callback(function (\RuntimeException $e) use ($safe) { return $e->getMessage() === 'Connection to ' . $safe . ' cancelled (ECONNABORTED)'; }), @@ -534,18 +539,18 @@ public function testCancelWillRejectWithUriInMessageAndCancelConnectorWhenConnec public function testCancelWillCloseConnectionWhenConnectionWaitsForSelect() { - $stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $stream = $this->createMock(ConnectionInterface::class); $stream->expects($this->once())->method('write'); $stream->expects($this->once())->method('close'); - $this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream)); + $this->connector->expects($this->once())->method('connect')->willReturn(resolve($stream)); $promise = $this->factory->createClient('redis://127.0.0.1:2/123'); $promise->cancel(); $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('RuntimeException'), + $this->isInstanceOf(\RuntimeException::class), $this->callback(function (\RuntimeException $e) { return $e->getMessage() === 'Connection to redis://127.0.0.1:2/123 cancelled (ECONNABORTED)'; }), @@ -574,7 +579,7 @@ public function testCreateClientWithTimeoutParameterWillStartTimerAndRejectOnExp $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('RuntimeException'), + $this->isInstanceOf(\RuntimeException::class), $this->callback(function (\Exception $e) { return $e->getMessage() === 'Connection to redis://127.0.0.1:2?timeout=0 timed out after 0 seconds (ETIMEDOUT)'; }), diff --git a/tests/FunctionalTest.php b/tests/FunctionalTest.php index 45a9fcd..74aa600 100644 --- a/tests/FunctionalTest.php +++ b/tests/FunctionalTest.php @@ -2,13 +2,14 @@ namespace Clue\Tests\React\Redis; -use Clue\React\Block; use Clue\React\Redis\Client; use Clue\React\Redis\Factory; use Clue\React\Redis\StreamingClient; use React\EventLoop\StreamSelectLoop; use React\Promise\Deferred; +use React\Promise\PromiseInterface; use React\Stream\DuplexResourceStream; +use function Clue\React\Block\await; class FunctionalTest extends TestCase { @@ -35,9 +36,9 @@ public function testPing() $redis = $this->createClient($this->uri); $promise = $redis->ping(); - $this->assertInstanceOf('React\Promise\PromiseInterface', $promise); + $this->assertInstanceOf(PromiseInterface::class, $promise); - $ret = Block\await($promise, $this->loop); + $ret = await($promise, $this->loop); $this->assertEquals('PONG', $ret); } @@ -47,9 +48,9 @@ public function testPingLazy() $redis = $this->factory->createLazyClient($this->uri); $promise = $redis->ping(); - $this->assertInstanceOf('React\Promise\PromiseInterface', $promise); + $this->assertInstanceOf(PromiseInterface::class, $promise); - $ret = Block\await($promise, $this->loop); + $ret = await($promise, $this->loop); $this->assertEquals('PONG', $ret); } @@ -87,7 +88,7 @@ public function testMgetIsNotInterpretedAsSubMessage() $promise = $redis->mget('message', 'channel', 'payload')->then($this->expectCallableOnce()); $redis->on('message', $this->expectCallableNever()); - Block\await($promise, $this->loop); + await($promise, $this->loop); } public function testPipeline() @@ -99,7 +100,7 @@ public function testPipeline() $redis->incr('a')->then($this->expectCallableOnceWith(3)); $promise = $redis->get('a')->then($this->expectCallableOnceWith('3')); - Block\await($promise, $this->loop); + await($promise, $this->loop); } public function testInvalidCommand() @@ -112,16 +113,16 @@ public function testInvalidCommand() } else { $this->setExpectedException('Exception'); } - Block\await($promise, $this->loop); + await($promise, $this->loop); } public function testMultiExecEmpty() { $redis = $this->createClient($this->uri); $redis->multi()->then($this->expectCallableOnceWith('OK')); - $promise = $redis->exec()->then($this->expectCallableOnceWith(array())); + $promise = $redis->exec()->then($this->expectCallableOnceWith([])); - Block\await($promise, $this->loop); + await($promise, $this->loop); } public function testMultiExecQueuedExecHasValues() @@ -133,9 +134,9 @@ public function testMultiExecQueuedExecHasValues() $redis->expire('b', 20)->then($this->expectCallableOnceWith('QUEUED')); $redis->incrBy('b', 2)->then($this->expectCallableOnceWith('QUEUED')); $redis->ttl('b')->then($this->expectCallableOnceWith('QUEUED')); - $promise = $redis->exec()->then($this->expectCallableOnceWith(array('OK', 1, 12, 20))); + $promise = $redis->exec()->then($this->expectCallableOnceWith(['OK', 1, 12, 20])); - Block\await($promise, $this->loop); + await($promise, $this->loop); } public function testPubSub() @@ -148,7 +149,7 @@ public function testPubSub() // consumer receives a single message $deferred = new Deferred(); $consumer->on('message', $this->expectCallableOnce()); - $consumer->on('message', array($deferred, 'resolve')); + $consumer->on('message', [$deferred, 'resolve']); $once = $this->expectCallableOnceWith(1); $consumer->subscribe($channel)->then(function() use ($producer, $channel, $once){ // producer sends a single message @@ -156,7 +157,7 @@ public function testPubSub() })->then($this->expectCallableOnce()); // expect "message" event to take no longer than 0.1s - Block\await($deferred->promise(), $this->loop, 0.1); + await($deferred->promise(), $this->loop, 0.1); } public function testClose() @@ -190,12 +191,8 @@ public function testInvalidProtocol() $promise = $redis->get('willBeRejectedDueToClosing'); - if (method_exists($this, 'expectException')) { - $this->expectException('Exception'); - } else { - $this->setExpectedException('Exception'); - } - Block\await($promise, $this->loop); + $this->expectException(\Exception::class); + await($promise, $this->loop); } public function testInvalidServerRepliesWithDuplicateMessages() @@ -207,7 +204,7 @@ public function testInvalidServerRepliesWithDuplicateMessages() $promise = $redis->set('a', 0)->then($this->expectCallableOnceWith('OK')); - Block\await($promise, $this->loop); + await($promise, $this->loop); } /** @@ -216,7 +213,7 @@ public function testInvalidServerRepliesWithDuplicateMessages() */ protected function createClient($uri) { - return Block\await($this->factory->createClient($uri), $this->loop); + return await($this->factory->createClient($uri), $this->loop); } protected function createClientResponse($response) diff --git a/tests/LazyClientTest.php b/tests/LazyClientTest.php index 2ad644e..f1cd894 100644 --- a/tests/LazyClientTest.php +++ b/tests/LazyClientTest.php @@ -2,16 +2,11 @@ namespace Clue\Tests\React\Redis; -use Clue\React\Redis\LazyClient; -use Clue\React\Redis\StreamingClient; -use Clue\Redis\Protocol\Parser\ParserException; -use Clue\Redis\Protocol\Model\IntegerReply; -use Clue\Redis\Protocol\Model\BulkReply; -use Clue\Redis\Protocol\Model\ErrorReply; -use Clue\Redis\Protocol\Model\MultiBulkReply; use Clue\React\Redis\Client; -use React\EventLoop\Factory; -use React\Stream\ThroughStream; +use Clue\React\Redis\Factory; +use Clue\React\Redis\LazyClient; +use React\EventLoop\LoopInterface; +use React\EventLoop\TimerInterface; use React\Promise\Promise; use React\Promise\Deferred; @@ -26,8 +21,8 @@ class LazyClientTest extends TestCase */ public function setUpClient() { - $this->factory = $this->getMockBuilder('Clue\React\Redis\Factory')->disableOriginalConstructor()->getMock(); - $this->loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $this->factory = $this->createMock(Factory::class); + $this->loop = $this->createMock(LoopInterface::class); $this->redis = new LazyClient('localhost', $this->factory, $this->loop); } @@ -55,7 +50,7 @@ public function testPingTwiceWillCreateOnceUnderlyingClient() public function testPingWillResolveWhenUnderlyingClientResolvesPingAndStartIdleTimer() { - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->with('ping')->willReturn(\React\Promise\resolve('PONG')); $deferred = new Deferred(); @@ -73,7 +68,7 @@ public function testPingWillResolveWhenUnderlyingClientResolvesPingAndStartIdleT { $this->redis = new LazyClient('localhost?idle=10', $this->factory, $this->loop); - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->with('ping')->willReturn(\React\Promise\resolve('PONG')); $deferred = new Deferred(); @@ -91,7 +86,7 @@ public function testPingWillResolveWhenUnderlyingClientResolvesPingAndNotStartId { $this->redis = new LazyClient('localhost?idle=-1', $this->factory, $this->loop); - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->with('ping')->willReturn(\React\Promise\resolve('PONG')); $deferred = new Deferred(); @@ -108,7 +103,7 @@ public function testPingWillResolveWhenUnderlyingClientResolvesPingAndNotStartId public function testPingWillRejectWhenUnderlyingClientRejectsPingAndStartIdleTimer() { $error = new \RuntimeException(); - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->with('ping')->willReturn(\React\Promise\reject($error)); $deferred = new Deferred(); @@ -157,13 +152,13 @@ public function testPingAfterPreviousFactoryRejectsUnderlyingClientWillCreateNew public function testPingAfterPreviousUnderlyingClientAlreadyClosedWillCreateNewUnderlyingConnection() { $closeHandler = null; - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->with('ping')->willReturn(\React\Promise\resolve('PONG')); $client->expects($this->any())->method('on')->withConsecutive( - array('close', $this->callback(function ($arg) use (&$closeHandler) { + ['close', $this->callback(function ($arg) use (&$closeHandler) { $closeHandler = $arg; return true; - })) + })] ); $this->factory->expects($this->exactly(2))->method('createClient')->willReturnOnConsecutiveCalls( @@ -187,7 +182,7 @@ public function testPingAfterCloseWillRejectWithoutCreatingUnderlyingConnection( $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('RuntimeException'), + $this->isInstanceOf(\RuntimeException::class), $this->callback(function (\RuntimeException $e) { return $e->getMessage() === 'Connection closed (ENOTCONN)'; }), @@ -201,7 +196,7 @@ public function testPingAfterCloseWillRejectWithoutCreatingUnderlyingConnection( public function testPingAfterPingWillNotStartIdleTimerWhenFirstPingResolves() { $deferred = new Deferred(); - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->exactly(2))->method('__call')->willReturnOnConsecutiveCalls( $deferred->promise(), new Promise(function () { }) @@ -219,7 +214,7 @@ public function testPingAfterPingWillNotStartIdleTimerWhenFirstPingResolves() public function testPingAfterPingWillStartAndCancelIdleTimerWhenSecondPingStartsAfterFirstResolves() { $deferred = new Deferred(); - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->exactly(2))->method('__call')->willReturnOnConsecutiveCalls( $deferred->promise(), new Promise(function () { }) @@ -227,7 +222,7 @@ public function testPingAfterPingWillStartAndCancelIdleTimerWhenSecondPingStarts $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); + $timer = $this->createMock(TimerInterface::class); $this->loop->expects($this->once())->method('addTimer')->willReturn($timer); $this->loop->expects($this->once())->method('cancelTimer')->with($timer); @@ -238,14 +233,14 @@ public function testPingAfterPingWillStartAndCancelIdleTimerWhenSecondPingStarts public function testPingFollowedByIdleTimerWillCloseUnderlyingConnectionWithoutCloseEvent() { - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->willReturn(\React\Promise\resolve()); $client->expects($this->once())->method('close')->willReturn(\React\Promise\resolve()); $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); $timeout = null; - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); + $timer = $this->createMock(TimerInterface::class); $this->loop->expects($this->once())->method('addTimer')->with($this->anything(), $this->callback(function ($cb) use (&$timeout) { $timeout = $cb; return true; @@ -301,7 +296,7 @@ public function testCloseAfterPingWillEmitCloseWithoutErrorWhenUnderlyingClientC public function testCloseAfterPingWillCloseUnderlyingClientConnectionWhenAlreadyResolved() { - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->willReturn(\React\Promise\resolve()); $client->expects($this->once())->method('close'); @@ -316,13 +311,13 @@ public function testCloseAfterPingWillCloseUnderlyingClientConnectionWhenAlready public function testCloseAfterPingWillCancelIdleTimerWhenPingIsAlreadyResolved() { $deferred = new Deferred(); - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->willReturn($deferred->promise()); $client->expects($this->once())->method('close'); $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); + $timer = $this->createMock(TimerInterface::class); $this->loop->expects($this->once())->method('addTimer')->willReturn($timer); $this->loop->expects($this->once())->method('cancelTimer')->with($timer); @@ -334,7 +329,7 @@ public function testCloseAfterPingWillCancelIdleTimerWhenPingIsAlreadyResolved() public function testCloseAfterPingRejectsWillEmitClose() { $deferred = new Deferred(); - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->willReturn($deferred->promise()); $client->expects($this->once())->method('close')->willReturnCallback(function () use ($client) { $client->emit('close'); @@ -342,7 +337,7 @@ public function testCloseAfterPingRejectsWillEmitClose() $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); + $timer = $this->createMock(TimerInterface::class); $this->loop->expects($this->once())->method('addTimer')->willReturn($timer); $this->loop->expects($this->once())->method('cancelTimer')->with($timer); @@ -362,7 +357,7 @@ public function testEndWillCloseClientIfUnderlyingConnectionIsNotPending() public function testEndAfterPingWillEndUnderlyingClient() { - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->with('ping')->willReturn(\React\Promise\resolve('PONG')); $client->expects($this->once())->method('end'); @@ -377,7 +372,7 @@ public function testEndAfterPingWillEndUnderlyingClient() public function testEndAfterPingWillCloseClientWhenUnderlyingClientEmitsClose() { $closeHandler = null; - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->with('ping')->willReturn(\React\Promise\resolve('PONG')); $client->expects($this->once())->method('end'); $client->expects($this->any())->method('on')->willReturnCallback(function ($event, $callback) use (&$closeHandler) { @@ -403,7 +398,7 @@ public function testEmitsNoErrorEventWhenUnderlyingClientEmitsError() { $error = new \RuntimeException(); - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->willReturn(\React\Promise\resolve()); $deferred = new Deferred(); @@ -413,12 +408,12 @@ public function testEmitsNoErrorEventWhenUnderlyingClientEmitsError() $deferred->resolve($client); $this->redis->on('error', $this->expectCallableNever()); - $client->emit('error', array($error)); + $client->emit('error', [$error]); } public function testEmitsNoCloseEventWhenUnderlyingClientEmitsClose() { - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->willReturn(\React\Promise\resolve()); $deferred = new Deferred(); @@ -434,19 +429,19 @@ public function testEmitsNoCloseEventWhenUnderlyingClientEmitsClose() public function testEmitsNoCloseEventButWillCancelIdleTimerWhenUnderlyingConnectionEmitsCloseAfterPingIsAlreadyResolved() { $closeHandler = null; - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $deferred = new Deferred(); $client->expects($this->once())->method('__call')->willReturn($deferred->promise()); $client->expects($this->any())->method('on')->withConsecutive( - array('close', $this->callback(function ($arg) use (&$closeHandler) { + ['close', $this->callback(function ($arg) use (&$closeHandler) { $closeHandler = $arg; return true; - })) + })] ); $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); + $timer = $this->createMock(TimerInterface::class); $this->loop->expects($this->once())->method('addTimer')->willReturn($timer); $this->loop->expects($this->once())->method('cancelTimer')->with($timer); @@ -462,7 +457,7 @@ public function testEmitsNoCloseEventButWillCancelIdleTimerWhenUnderlyingConnect public function testEmitsMessageEventWhenUnderlyingClientEmitsMessageForPubSubChannel() { $messageHandler = null; - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->willReturn(\React\Promise\resolve()); $client->expects($this->any())->method('on')->willReturnCallback(function ($event, $callback) use (&$messageHandler) { if ($event === 'message') { @@ -484,7 +479,7 @@ public function testEmitsMessageEventWhenUnderlyingClientEmitsMessageForPubSubCh public function testEmitsUnsubscribeAndPunsubscribeEventsWhenUnderlyingClientClosesWhileUsingPubSubChannel() { $allHandler = null; - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->exactly(6))->method('__call')->willReturn(\React\Promise\resolve()); $client->expects($this->any())->method('on')->willReturnCallback(function ($event, $callback) use (&$allHandler) { if (!isset($allHandler[$event])) { @@ -529,7 +524,7 @@ public function testSubscribeWillResolveWhenUnderlyingClientResolvesSubscribeAnd { $subscribeHandler = null; $deferred = new Deferred(); - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->with('subscribe')->willReturn($deferred->promise()); $client->expects($this->any())->method('on')->willReturnCallback(function ($event, $callback) use (&$subscribeHandler) { if ($event === 'subscribe' && $subscribeHandler === null) { @@ -544,9 +539,9 @@ public function testSubscribeWillResolveWhenUnderlyingClientResolvesSubscribeAnd $promise = $this->redis->subscribe('foo'); $this->assertTrue(is_callable($subscribeHandler)); $subscribeHandler('foo', 1); - $deferred->resolve(array('subscribe', 'foo', 1)); + $deferred->resolve(['subscribe', 'foo', 1]); - $promise->then($this->expectCallableOnceWith(array('subscribe', 'foo', 1))); + $promise->then($this->expectCallableOnceWith(['subscribe', 'foo', 1])); } public function testUnsubscribeAfterSubscribeWillResolveWhenUnderlyingClientResolvesUnsubscribeAndStartIdleTimerWhenSubscriptionStopped() @@ -555,7 +550,7 @@ public function testUnsubscribeAfterSubscribeWillResolveWhenUnderlyingClientReso $unsubscribeHandler = null; $deferredSubscribe = new Deferred(); $deferredUnsubscribe = new Deferred(); - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->exactly(2))->method('__call')->willReturnOnConsecutiveCalls($deferredSubscribe->promise(), $deferredUnsubscribe->promise()); $client->expects($this->any())->method('on')->willReturnCallback(function ($event, $callback) use (&$subscribeHandler, &$unsubscribeHandler) { if ($event === 'subscribe' && $subscribeHandler === null) { @@ -573,27 +568,27 @@ public function testUnsubscribeAfterSubscribeWillResolveWhenUnderlyingClientReso $promise = $this->redis->subscribe('foo'); $this->assertTrue(is_callable($subscribeHandler)); $subscribeHandler('foo', 1); - $deferredSubscribe->resolve(array('subscribe', 'foo', 1)); - $promise->then($this->expectCallableOnceWith(array('subscribe', 'foo', 1))); + $deferredSubscribe->resolve(['subscribe', 'foo', 1]); + $promise->then($this->expectCallableOnceWith(['subscribe', 'foo', 1])); $promise = $this->redis->unsubscribe('foo'); $this->assertTrue(is_callable($unsubscribeHandler)); $unsubscribeHandler('foo', 0); - $deferredUnsubscribe->resolve(array('unsubscribe', 'foo', 0)); - $promise->then($this->expectCallableOnceWith(array('unsubscribe', 'foo', 0))); + $deferredUnsubscribe->resolve(['unsubscribe', 'foo', 0]); + $promise->then($this->expectCallableOnceWith(['unsubscribe', 'foo', 0])); } public function testBlpopWillRejectWhenUnderlyingClientClosesWhileWaitingForResponse() { $closeHandler = null; $deferred = new Deferred(); - $client = $this->getMockBuilder('Clue\React\Redis\Client')->getMock(); + $client = $this->createMock(Client::class); $client->expects($this->once())->method('__call')->with('blpop')->willReturn($deferred->promise()); $client->expects($this->any())->method('on')->withConsecutive( - array('close', $this->callback(function ($arg) use (&$closeHandler) { + ['close', $this->callback(function ($arg) use (&$closeHandler) { $closeHandler = $arg; return true; - })) + })] ); $this->factory->expects($this->once())->method('createClient')->willReturn(\React\Promise\resolve($client)); @@ -609,15 +604,4 @@ public function testBlpopWillRejectWhenUnderlyingClientClosesWhileWaitingForResp $promise->then(null, $this->expectCallableOnceWith($e)); } - - public function createCallableMockWithOriginalConstructorDisabled($array) - { - if (method_exists('PHPUnit\Framework\MockObject\MockBuilder', 'addMethods')) { - // PHPUnit 9+ - return $this->getMockBuilder('Clue\React\Redis\StreamingClient')->disableOriginalConstructor()->onlyMethods($array)->getMock(); - } else { - // legacy PHPUnit 4 - PHPUnit 8 - return $this->getMockBuilder('Clue\React\Redis\StreamingClient')->disableOriginalConstructor()->setMethods($array)->getMock(); - } - } } diff --git a/tests/StreamingClientTest.php b/tests/StreamingClientTest.php index bff6ca1..00f50d4 100644 --- a/tests/StreamingClientTest.php +++ b/tests/StreamingClientTest.php @@ -7,9 +7,12 @@ use Clue\Redis\Protocol\Model\IntegerReply; use Clue\Redis\Protocol\Model\MultiBulkReply; use Clue\Redis\Protocol\Parser\ParserException; +use Clue\Redis\Protocol\Parser\ParserInterface; +use Clue\Redis\Protocol\Serializer\SerializerInterface; use Clue\React\Redis\Client; use Clue\React\Redis\StreamingClient; use React\Stream\ThroughStream; +use React\Stream\DuplexStreamInterface; class StreamingClientTest extends TestCase { @@ -23,9 +26,9 @@ class StreamingClientTest extends TestCase */ public function setUpClient() { - $this->stream = $this->getMockBuilder('React\Stream\DuplexStreamInterface')->getMock(); - $this->parser = $this->getMockBuilder('Clue\Redis\Protocol\Parser\ParserInterface')->getMock(); - $this->serializer = $this->getMockBuilder('Clue\Redis\Protocol\Serializer\SerializerInterface')->getMock(); + $this->stream = $this->createMock(DuplexStreamInterface::class); + $this->parser = $this->createMock(ParserInterface::class); + $this->serializer = $this->createMock(SerializerInterface::class); $this->redis = new StreamingClient($this->stream, $this->parser, $this->serializer); } @@ -38,7 +41,7 @@ public function testConstructWithoutParserAssignsParserAutomatically() $ref->setAccessible(true); $parser = $ref->getValue($this->redis); - $this->assertInstanceOf('Clue\Redis\Protocol\Parser\ParserInterface', $parser); + $this->assertInstanceOf(ParserInterface::class, $parser); } public function testConstructWithoutParserAndSerializerAssignsParserAndSerializerAutomatically() @@ -49,7 +52,7 @@ public function testConstructWithoutParserAndSerializerAssignsParserAndSerialize $ref->setAccessible(true); $serializer = $ref->getValue($this->redis); - $this->assertInstanceOf('Clue\Redis\Protocol\Serializer\SerializerInterface', $serializer); + $this->assertInstanceOf(SerializerInterface::class, $serializer); } public function testSending() @@ -84,7 +87,7 @@ public function testReceiveParseErrorEmitsErrorEvent() $this->redis->on('error', $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('UnexpectedValueException'), + $this->isInstanceOf(\UnexpectedValueException::class), $this->callback(function (\UnexpectedValueException $e) { return $e->getMessage() === 'Invalid data received: Foo (EBADMSG)'; }), @@ -96,7 +99,7 @@ public function testReceiveParseErrorEmitsErrorEvent() $this->redis->on('close', $this->expectCallableOnce()); $this->parser->expects($this->once())->method('pushIncoming')->with('message')->willThrowException(new ParserException('Foo')); - $this->stream->emit('data', array('message')); + $this->stream->emit('data', ['message']); } public function testReceiveUnexpectedReplyEmitsErrorEvent() @@ -107,7 +110,7 @@ public function testReceiveUnexpectedReplyEmitsErrorEvent() $this->redis->on('error', $this->expectCallableOnce()); $this->redis->on('error', $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('UnderflowException'), + $this->isInstanceOf(\UnderflowException::class), $this->callback(function (\UnderflowException $e) { return $e->getMessage() === 'Unexpected reply received, no matching request found (ENOMSG)'; }), @@ -118,8 +121,8 @@ public function testReceiveUnexpectedReplyEmitsErrorEvent() )); - $this->parser->expects($this->once())->method('pushIncoming')->with('message')->willReturn(array(new IntegerReply(2))); - $this->stream->emit('data', array('message')); + $this->parser->expects($this->once())->method('pushIncoming')->with('message')->willReturn([new IntegerReply(2)]); + $this->stream->emit('data', ['message']); } /** @@ -127,7 +130,7 @@ public function testReceiveUnexpectedReplyEmitsErrorEvent() */ public function testDefaultCtor() { - $client = new StreamingClient($this->stream); + new StreamingClient($this->stream); } public function testPingPong() @@ -148,7 +151,7 @@ public function testMonitorCommandIsNotSupported() $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('BadMethodCallException'), + $this->isInstanceOf(\BadMethodCallException::class), $this->callback(function (\BadMethodCallException $e) { return $e->getMessage() === 'MONITOR command explicitly not supported (ENOTSUP)'; }), @@ -176,7 +179,7 @@ public function testClosingClientRejectsAllRemainingRequests() $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('RuntimeException'), + $this->isInstanceOf(\RuntimeException::class), $this->callback(function (\RuntimeException $e) { return $e->getMessage() === 'Connection closing (ECONNABORTED)'; }), @@ -190,7 +193,7 @@ public function testClosingClientRejectsAllRemainingRequests() public function testClosingStreamRejectsAllRemainingRequests() { $this->stream = new ThroughStream(); - $this->parser->expects($this->once())->method('pushIncoming')->willReturn(array()); + $this->parser->expects($this->once())->method('pushIncoming')->willReturn([]); $this->redis = new StreamingClient($this->stream, $this->parser, $this->serializer); $promise = $this->redis->ping(); @@ -198,7 +201,7 @@ public function testClosingStreamRejectsAllRemainingRequests() $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('RuntimeException'), + $this->isInstanceOf(\RuntimeException::class), $this->callback(function (\RuntimeException $e) { return $e->getMessage() === 'Connection closed by peer (ECONNRESET)'; }), @@ -217,7 +220,7 @@ public function testEndingClientRejectsAllNewRequests() $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('RuntimeException'), + $this->isInstanceOf(\RuntimeException::class), $this->callback(function (\RuntimeException $e) { return $e->getMessage() === 'Connection closing (ENOTCONN)'; }), @@ -235,7 +238,7 @@ public function testClosedClientRejectsAllNewRequests() $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('RuntimeException'), + $this->isInstanceOf(\RuntimeException::class), $this->callback(function (\RuntimeException $e) { return $e->getMessage() === 'Connection closed (ENOTCONN)'; }), @@ -281,11 +284,7 @@ public function testClosingMultipleTimesEmitsOnce() public function testReceivingUnexpectedMessageThrowsException() { - if (method_exists($this, 'expectException')) { - $this->expectException('UnderflowException'); - } else { - $this->setExpectedException('UnderflowException'); - } + $this->expectException(\UnderflowException::class); $this->redis->handleMessage(new BulkReply('PONG')); } @@ -295,7 +294,7 @@ public function testPubsubSubscribe() $this->expectPromiseResolve($promise); $this->redis->on('subscribe', $this->expectCallableOnce()); - $this->redis->handleMessage(new MultiBulkReply(array(new BulkReply('subscribe'), new BulkReply('test'), new IntegerReply(1)))); + $this->redis->handleMessage(new MultiBulkReply([new BulkReply('subscribe'), new BulkReply('test'), new IntegerReply(1)])); return $this->redis; } @@ -310,7 +309,7 @@ public function testPubsubPatternSubscribe(Client $client) $this->expectPromiseResolve($promise); $client->on('psubscribe', $this->expectCallableOnce()); - $client->handleMessage(new MultiBulkReply(array(new BulkReply('psubscribe'), new BulkReply('demo_*'), new IntegerReply(1)))); + $client->handleMessage(new MultiBulkReply([new BulkReply('psubscribe'), new BulkReply('demo_*'), new IntegerReply(1)])); return $client; } @@ -322,7 +321,7 @@ public function testPubsubPatternSubscribe(Client $client) public function testPubsubMessage(Client $client) { $client->on('message', $this->expectCallableOnce()); - $client->handleMessage(new MultiBulkReply(array(new BulkReply('message'), new BulkReply('test'), new BulkReply('payload')))); + $client->handleMessage(new MultiBulkReply([new BulkReply('message'), new BulkReply('test'), new BulkReply('payload')])); } public function testSubscribeWithMultipleArgumentsRejects() @@ -331,7 +330,7 @@ public function testSubscribeWithMultipleArgumentsRejects() $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('InvalidArgumentException'), + $this->isInstanceOf(\InvalidArgumentException::class), $this->callback(function (\InvalidArgumentException $e) { return $e->getMessage() === 'PubSub commands limited to single argument (EINVAL)'; }), @@ -348,7 +347,7 @@ public function testUnsubscribeWithoutArgumentsRejects() $promise->then(null, $this->expectCallableOnceWith( $this->logicalAnd( - $this->isInstanceOf('InvalidArgumentException'), + $this->isInstanceOf(\InvalidArgumentException::class), $this->callback(function (\InvalidArgumentException $e) { return $e->getMessage() === 'PubSub commands limited to single argument (EINVAL)'; }), diff --git a/tests/TestCase.php b/tests/TestCase.php index 013aa7a..99189ef 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,7 +2,9 @@ namespace Clue\Tests\React\Redis; +use PHPUnit\Framework\MockObject\MockBuilder; use PHPUnit\Framework\TestCase as BaseTestCase; +use React\Promise\PromiseInterface; class TestCase extends BaseTestCase { @@ -32,23 +34,22 @@ protected function expectCallableNever() protected function createCallableMock() { - if (method_exists('PHPUnit\Framework\MockObject\MockBuilder', 'addMethods')) { + if (method_exists(MockBuilder::class, 'addMethods')) { // PHPUnit 9+ - return $this->getMockBuilder('stdClass')->addMethods(array('__invoke'))->getMock(); + return $this->getMockBuilder(\stdClass::class)->addMethods(['__invoke'])->getMock(); } else { - // legacy PHPUnit 4 - PHPUnit 8 - return $this->getMockBuilder('stdClass')->setMethods(array('__invoke'))->getMock(); + // legacy PHPUnit < 9 + return $this->getMockBuilder(\stdClass::class)->setMethods(['__invoke'])->getMock(); } } protected function expectPromiseResolve($promise) { - $this->assertInstanceOf('React\Promise\PromiseInterface', $promise); + $this->assertInstanceOf(PromiseInterface::class, $promise); - $that = $this; - $promise->then(null, function($error) use ($that) { - $that->assertNull($error); - $that->fail('promise rejected'); + $promise->then(null, function($error) { + $this->assertNull($error); + $this->fail('promise rejected'); }); $promise->then($this->expectCallableOnce(), $this->expectCallableNever()); @@ -57,12 +58,11 @@ protected function expectPromiseResolve($promise) protected function expectPromiseReject($promise) { - $this->assertInstanceOf('React\Promise\PromiseInterface', $promise); + $this->assertInstanceOf(PromiseInterface::class, $promise); - $that = $this; - $promise->then(function($value) use ($that) { - $that->assertNull($value); - $that->fail('promise resolved'); + $promise->then(function($value) { + $this->assertNull($value); + $this->fail('promise resolved'); }); $promise->then($this->expectCallableNever(), $this->expectCallableOnce());