diff --git a/.php_cs.dist b/.php_cs.dist new file mode 100644 index 0000000..50b81f4 --- /dev/null +++ b/.php_cs.dist @@ -0,0 +1,98 @@ +fixer = $fixer; + $this->pathRegex = $pathRegex; + } + + public function isCandidate(Tokens $tokens) : bool + { + return $this->fixer->isCandidate($tokens); + } + + public function isRisky() : bool + { + return $this->fixer->isRisky(); + } + + public function fix(\SplFileInfo $file, Tokens $tokens) : void + { + $this->fixer->fix($file, $tokens); + } + + public function getName() : string + { + return (new \ReflectionClass($this))->getShortName().'/'.$this->fixer->getName(); + } + + public function getPriority() : int + { + return $this->fixer->getPriority(); + } + + public function supports(\SplFileInfo $file) : bool + { + if (1 !== preg_match($this->pathRegex, $file->getRealPath())) { + return false; + } + + return $this->fixer->supports($file); + } +}; + +$header = << + +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. +EOF; + +return Config::create() + ->setUsingCache(false) + ->setRiskyAllowed(true) + ->registerCustomFixers([ + new FilterableFixer(new NativeConstantInvocationFixer(), '/\bsrc\b/'), + new FilterableFixer(new NativeFunctionInvocationFixer(), '/\bsrc\b/'), + ]) + ->setRules([ + '@Symfony' => true, + '@Symfony:risky' => true, + 'array_syntax' => ['syntax' => 'short'], + 'binary_operator_spaces' => ['operators' => ['=' => null, '=>' => null]], + 'declare_strict_types' => true, + 'native_constant_invocation' => false, + 'native_function_invocation' => false, + 'FilterableFixer/native_constant_invocation' => true, + 'FilterableFixer/native_function_invocation' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'ordered_imports' => true, + 'phpdoc_order' => true, + 'phpdoc_align' => false, + 'return_type_declaration' => ['space_before' => 'one'], + 'strict_comparison' => true, + 'header_comment' => [ + 'header' => $header, + 'location' => 'after_declare_strict', + 'separate' => 'both', + ], + ]) +; diff --git a/.travis.yml b/.travis.yml index 542c677..ec091d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,13 +6,10 @@ services: - docker env: - - IMAGE='php:5.6-cli' TNT_CLIENT=pecl - - IMAGE='php:7.0-cli' TNT_CLIENT=pecl - IMAGE='php:7.1-cli' TNT_CLIENT=pecl - - IMAGE='php:5.6-cli' TNT_CLIENT=pure - - IMAGE='php:7.0-cli' TNT_CLIENT=pure - - IMAGE='php:7.1-cli' TNT_CLIENT=pure - - IMAGE='php:7.2-cli' TNT_CLIENT=pure PHPUNIT_OPTS='--coverage-clover=coverage.clover' + - IMAGE='php:7.1-cli' CHECK_CS=1 + - IMAGE='php:7.2-cli' PHPUNIT_OPTS='--coverage-clover=coverage.clover' + - IMAGE='php:7.3-rc-cli' install: - ./dockerfile.sh | tee /dev/tty | docker build -t queue - @@ -25,5 +22,5 @@ script: after_script: - if [[ -f coverage.clover ]]; then curl -sSOL https://scrutinizer-ci.com/ocular.phar && - docker run --rm -v $(pwd):/coverage -w /coverage queue php ocular.phar code-coverage:upload --format=php-clover coverage.clover; + docker run --rm -v $(pwd):/queue -w /queue queue php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi diff --git a/README.md b/README.md index c8b8f8d..003c546 100644 --- a/README.md +++ b/README.md @@ -3,18 +3,34 @@ [![Build Status](https://travis-ci.org/tarantool-php/queue.svg?branch=master)](https://travis-ci.org/tarantool-php/queue) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/tarantool-php/queue/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/tarantool-php/queue/?branch=master) [![Code Coverage](https://scrutinizer-ci.com/g/tarantool-php/queue/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/tarantool-php/queue/?branch=master) +[![Mentioned in Awesome PHP](https://awesome.re/mentioned-badge.svg)](https://github.com/ziadoz/awesome-php) [Tarantool](http://tarantool.org/) is a NoSQL database running in a Lua application server. It integrates Lua modules, called [LuaRocks](https://luarocks.org/). This package provides PHP bindings for [Tarantool Queue LuaRock](https://github.com/tarantool/queue/). +## Table of contents + + * [Installation](#installation) + * [Before start](#before-start) + * [Working with queue](#working-with-queue) + * [Data types](#data-types) + * [Tasks](#tasks) + * [Producer API](#producer-api) + * [Consumer API](#consumer-api) + * [Statistics](#statistics) + * [Custom methods](#custom-methods) + * [Tests](#tests) + * [License](#license) + + ## Installation The recommended way to install the library is through [Composer](http://getcomposer.org): -```sh -$ composer require tarantool/queue +```bash +composer require tarantool/queue ``` @@ -38,8 +54,8 @@ queue.create_tube('foobar', 'fifottl', {if_not_exists=true}) To start the instance you need to copy (or symlink) `queues.lua` file into the `/etc/tarantool/instances.enabled` directory and run the following command: -```sh -$ sudo tarantoolctl start queues +```bash +sudo tarantoolctl start queues ``` @@ -104,15 +120,15 @@ Task::isDelayed() As you've already seen, to insert a task into a queue you need to call `put()` method, which accepts two arguments: the data you want to process and optional array of task options, which this particular -queue supports. For example, `fifottl` queue (which we defined earlier in our Lua config file), -supports `delay`, `ttl`, `ttr` and `pri` options: +queue supports. For example, `fifottl` queue (which we defined [earlier](#before-start) in our Lua config +file), supports `delay`, `ttl`, `ttr` and `pri` options: ```php use Tarantool\Queue\Options; -$queue->put('foo', [Options::DELAY => 30]); -$queue->put('bar', [Options::TTL => 5]); -$queue->put('baz', [Options::TTR => 10, Options::PRI => 42]); +$queue->put('foo', [Options::DELAY => 30.0]); +$queue->put('bar', [Options::TTL => 5.0]); +$queue->put('baz', [Options::TTR => 10.0, Options::PRI => 42]); ``` > *See the full list of available options [here](https://github.com/tarantool/queue#queue-types).* @@ -128,7 +144,7 @@ The method returns either a [Task](#tasks) object or `null`: $taskOrNull = $queue->take(); // wait 2 seconds -$taskOrNull = $queue->take(2); +$taskOrNull = $queue->take(2.0); // wait 100 milliseconds $taskOrNull = $queue->take(.1); @@ -150,7 +166,7 @@ Or put back into the queue in case it cannot be executed: $task = $queue->release($task->getId()); // for *ttl queues you can specify a delay -$task = $queue->release($task->getId(), [Options::DELAY => 30]); +$task = $queue->release($task->getId(), [Options::DELAY => 30.0]); ``` To look at a task without changing its state, use: @@ -174,7 +190,7 @@ $count = $queue->kick(3); // kick 3 buried tasks To increase TTR and/or TTL of a running task (only for *ttl queues): ```php -$taskOrNull = $queue->touch($takenTask->getId(), 5); // increase ttr/ttl to 5 seconds +$taskOrNull = $queue->touch($takenTask->getId(), 5.0); // increase ttr/ttl to 5 seconds ``` A task (in any state) can be deleted permanently with `delete()`: @@ -259,10 +275,10 @@ end To call this method on a `$queue` object, use `Queue::call()`: ```php -$result = $queue->call('put_many', [[ - 'foo' => ['foo', [Options::DELAY => 30]], +$result = $queue->call('put_many', [ + 'foo' => ['foo', [Options::DELAY => 30.0]], 'bar' => ['bar'], -]]); +]); ``` @@ -270,30 +286,30 @@ $result = $queue->call('put_many', [[ The easiest way to run tests is with Docker. First, build an image using the [dockerfile.sh](dockerfile.sh) generator: -```sh -$ ./dockerfile.sh | docker build -t queue - +```bash +./dockerfile.sh | docker build -t queue - ``` Then run Tarantool instance (needed for integration tests): -```sh -$ docker network create tarantool-php -$ docker run -d --net=tarantool-php --name=tarantool -v `pwd`:/queue \ +```bash +docker network create tarantool-php +docker run -d --net=tarantool-php --name=tarantool -v `pwd`:/queue \ tarantool/tarantool:1 tarantool /queue/tests/Integration/queues.lua ``` And then run both unit and integration tests: -```sh -$ docker run --rm --net=tarantool-php --name=queue -v `pwd`:/queue -w /queue queue +```bash +docker run --rm --net=tarantool-php --name=queue -v `pwd`:/queue -w /queue queue ``` To run only integration or unit tests, set the `PHPUNIT_OPTS` environment variable -to either `--testsuite Integration` or `--testsuite Unit` respectively, e.g.: +to either `--testsuite integration` or `--testsuite unit` respectively, e.g.: -```sh -$ docker run --rm --net=tarantool-php --name=queue -v `pwd`:/queue -w /queue \ - -e PHPUNIT_OPTS='--testsuite Unit' queue +```bash +docker run --rm --net=tarantool-php --name=queue -v `pwd`:/queue -w /queue \ + -e PHPUNIT_OPTS='--testsuite unit' queue ``` diff --git a/composer.json b/composer.json index cc27595..5f62113 100644 --- a/composer.json +++ b/composer.json @@ -11,9 +11,11 @@ } ], "require": { - "php": "^5.4|^7.0" + "php": "^7.1" }, "require-dev": { + "friendsofphp/php-cs-fixer": "^2.13", + "phpunit/phpunit": "^7.4", "rybakit/msgpack": "@dev", "tarantool/client": "@dev" }, @@ -30,5 +32,11 @@ "psr-4": { "Tarantool\\Queue\\Tests\\": "tests/" } + }, + "config": { + "preferred-install": { + "*": "dist" + }, + "sort-packages": true } } diff --git a/dockerfile.sh b/dockerfile.sh index 6222ed9..3a5f99d 100755 --- a/dockerfile.sh +++ b/dockerfile.sh @@ -8,34 +8,34 @@ if [[ -z "$TNT_CLIENT" ]] ; then TNT_CLIENT='pure' fi -RUN_CMDS='' -RUN_POST_CMDS='' - -if [[ $IMAGE == php* ]]; then - RUN_CMDS="$RUN_CMDS && \\\\\n docker-php-ext-install zip" - if [[ $TNT_CLIENT == pure ]]; then - RUN_POST_CMDS="$RUN_POST_CMDS && \\\\\n composer require tarantool/client:@dev" - else - RUN_CMDS="$RUN_CMDS && \\\\\n git clone https://github.com/tarantool/tarantool-php.git /usr/src/php/ext/tarantool" - if [[ $IMAGE == php:7* ]]; then RUN_CMDS="$RUN_CMDS && \\\\\n git --git-dir=/usr/src/php/ext/tarantool/.git --work-tree=/usr/src/php/ext/tarantool checkout php7-v2"; fi - RUN_CMDS="$RUN_CMDS && \\\\\n echo tarantool >> /usr/src/php-available-exts && docker-php-ext-install tarantool" - fi +if [[ $TNT_CLIENT == pecl ]]; then + RUN_CMDS="$RUN_CMDS && \\\\\n git clone https://github.com/tarantool/tarantool-php.git /usr/src/php/ext/tarantool" + RUN_CMDS="$RUN_CMDS && \\\\\n git --git-dir=/usr/src/php/ext/tarantool/.git --work-tree=/usr/src/php/ext/tarantool checkout php7-v2" + RUN_CMDS="$RUN_CMDS && \\\\\n echo tarantool >> /usr/src/php-available-exts && docker-php-ext-install tarantool" + COMPOSER_REMOVE='tarantool/client' fi if [[ $PHPUNIT_OPTS =~ (^|[[:space:]])--coverage-[[:alpha:]] ]]; then RUN_CMDS="$RUN_CMDS && \\\\\n pecl install xdebug && docker-php-ext-enable xdebug" fi +if [[ "1" != "$CHECK_CS" ]]; then + COMPOSER_REMOVE="$COMPOSER_REMOVE friendsofphp/php-cs-fixer" +fi + echo -e " FROM $IMAGE RUN apt-get update && \\ - apt-get install -y git curl zlib1g-dev${RUN_CMDS} && \\ - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \\ - composer global require 'phpunit/phpunit'${RUN_POST_CMDS} + apt-get install -y git curl libzip-dev && \\ + docker-php-ext-configure zip --with-libzip && \\ + docker-php-ext-install zip${RUN_CMDS} + +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer ENV PATH=~/.composer/vendor/bin:\$PATH ENV TARANTOOL_HOST=tarantool TARANTOOL_PORT=3301 -CMD if [ ! -f composer.lock ]; then composer install; fi && ~/.composer/vendor/bin/phpunit\${PHPUNIT_OPTS:+ }\$PHPUNIT_OPTS +CMD if [ ! -f composer.lock ]; then ${COMPOSER_REMOVE:+composer remove --dev --no-update }$COMPOSER_REMOVE${COMPOSER_REMOVE:+ && }composer install; fi && \\ + vendor/bin/phpunit\${PHPUNIT_OPTS:+ }\$PHPUNIT_OPTS " diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 14ea045..23116a3 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,16 +1,9 @@ - @@ -23,11 +16,11 @@ - + tests/Unit - + tests/Integration diff --git a/src/ClientAdapter.php b/src/ClientAdapter.php index 4920fe9..2d8da3e 100644 --- a/src/ClientAdapter.php +++ b/src/ClientAdapter.php @@ -1,5 +1,7 @@ client = $client; } - public function call($funcName, array $args = []) + public function call(string $funcName, array $args = []) : array { $data = $this->client->call($funcName, $args)->getData(); diff --git a/src/Options.php b/src/Options.php index f5c6c05..360a0aa 100644 --- a/src/Options.php +++ b/src/Options.php @@ -1,5 +1,7 @@ name = $name; } - /** - * @return string - */ - public function getName() + public function getName() : string { return $this->name; } - /** - * @param mixed $data - * @param array $options - * - * @return Task - */ - public function put($data, array $options = []) + public function put($data, array $options = []) : Task { $args = $options ? [$data, $options] : [$data]; $result = $this->client->call("queue.tube.$this->name:put", $args); @@ -61,12 +54,7 @@ public function put($data, array $options = []) return Task::createFromTuple($result[0]); } - /** - * @param int|float|null $timeout - * - * @return Task|null - */ - public function take($timeout = null) + public function take(float $timeout = null) : ?Task { $args = null === $timeout ? [] : [$timeout]; $result = $this->client->call("queue.tube.$this->name:take", $args); @@ -74,38 +62,21 @@ public function take($timeout = null) return empty($result[0]) ? null : Task::createFromTuple($result[0]); } - /** - * @param int $taskId - * @param int|float $increment - * - * @return Task|null - */ - public function touch($taskId, $increment) + public function touch(int $taskId, float $increment) : ?Task { $result = $this->client->call("queue.tube.$this->name:touch", [$taskId, $increment]); return empty($result[0]) ? null : Task::createFromTuple($result[0]); } - /** - * @param int $taskId - * - * @return Task - */ - public function ack($taskId) + public function ack(int $taskId) : Task { $result = $this->client->call("queue.tube.$this->name:ack", [$taskId]); return Task::createFromTuple($result[0]); } - /** - * @param int $taskId - * @param array $options - * - * @return Task - */ - public function release($taskId, array $options = []) + public function release(int $taskId, array $options = []) : Task { $args = $options ? [$taskId, $options] : [$taskId]; $result = $this->client->call("queue.tube.$this->name:release", $args); @@ -113,55 +84,35 @@ public function release($taskId, array $options = []) return Task::createFromTuple($result[0]); } - /** - * @param int $taskId - * - * @return Task - */ - public function peek($taskId) + public function peek(int $taskId) : Task { $result = $this->client->call("queue.tube.$this->name:peek", [$taskId]); return Task::createFromTuple($result[0]); } - /** - * @param int $taskId - * - * @return Task - */ - public function bury($taskId) + public function bury(int $taskId) : Task { $result = $this->client->call("queue.tube.$this->name:bury", [$taskId]); return Task::createFromTuple($result[0]); } - /** - * @param int $count - * - * @return int - */ - public function kick($count) + public function kick(int $count) : int { $result = $this->client->call("queue.tube.$this->name:kick", [$count]); return $result[0][0]; } - /** - * @param int $taskId - * - * @return Task - */ - public function delete($taskId) + public function delete(int $taskId) : Task { $result = $this->client->call("queue.tube.$this->name:delete", [$taskId]); return Task::createFromTuple($result[0]); } - public function truncate() + public function truncate() : void { $this->client->call("queue.tube.$this->name:truncate"); } @@ -169,11 +120,11 @@ public function truncate() /** * @param string|null $path * - * @return array|int - * * @throws \InvalidArgumentException + * + * @return array|int */ - public function stats($path = null) + public function stats(string $path = null) { $result = $this->client->call('queue.stats', [$this->name]); @@ -182,9 +133,9 @@ public function stats($path = null) } $result = $result[0][0]; - foreach (explode('.', $path) as $key) { + foreach (\explode('.', $path) as $key) { if (!isset($result[$key])) { - throw new \InvalidArgumentException(sprintf('Invalid path "%s".', $path)); + throw new \InvalidArgumentException(\sprintf('Invalid path "%s".', $path)); } $result = $result[$key]; } @@ -192,14 +143,8 @@ public function stats($path = null) return $result; } - /** - * @param string $method - * @param array $args - * - * @return array - */ - public function call($method, array $args = []) + public function call(string $methodName, ...$args) : array { - return $this->client->call("queue.tube.$this->name:$method", $args); + return $this->client->call("queue.tube.$this->name:$methodName", $args); } } diff --git a/src/States.php b/src/States.php index 518ecd5..9be7af6 100644 --- a/src/States.php +++ b/src/States.php @@ -1,5 +1,7 @@ id = $id; $this->state = $state; $this->data = $data; } - public static function createFromTuple(array $tuple) + public static function createFromTuple(array $tuple) : self { - list($id, $state, $data) = $tuple + [2 => null]; + [$id, $state, $data] = $tuple + [2 => null]; return new self($id, $state, $data); } - public function getId() + public function getId() : int { return $this->id; } - public function getState() + public function getState() : string { return $this->state; } @@ -46,27 +48,27 @@ public function getData() return $this->data; } - public function isReady() + public function isReady() : bool { return States::READY === $this->state; } - public function isTaken() + public function isTaken() : bool { return States::TAKEN === $this->state; } - public function isDone() + public function isDone() : bool { return States::DONE === $this->state; } - public function isBuried() + public function isBuried() : bool { return States::BURIED === $this->state; } - public function isDelayed() + public function isDelayed() : bool { return States::DELAYED === $this->state; } diff --git a/tests/Integration/FifoQueueTest.php b/tests/Integration/FifoQueueTest.php index 5c4a3f0..529f097 100644 --- a/tests/Integration/FifoQueueTest.php +++ b/tests/Integration/FifoQueueTest.php @@ -1,5 +1,7 @@ getName()); + $testName = preg_replace('/^test(\S+).*$/', '\1', $this->getName()); $testName = strtolower($testName); $tubeType = $this->getTubeType(); @@ -71,7 +75,7 @@ protected function setUp() $this->queue = new Queue(self::$client, $queueName); } - protected function tearDown() + protected function tearDown() : void { $this->queue = null; } @@ -79,14 +83,14 @@ protected function tearDown() /** * @dataProvider provideTaskData */ - public function testPut($data) + public function testPut($data) : void { $task = $this->queue->put($data); - $this->assertTask($task, 0, States::READY, $data); + self::assertTask($task, 0, States::READY, $data); } - public function provideTaskData() + public function provideTaskData() : iterable { return [ [null], @@ -103,73 +107,73 @@ public function provideTaskData() /** * @eval queue.tube['%tube_name%']:put('peek_0') */ - public function testPeek() + public function testPeek() : void { $task = $this->queue->peek(0); - $this->assertTask($task, 0, States::READY, 'peek_0'); + self::assertTask($task, 0, States::READY, 'peek_0'); } /** * @eval queue.tube['%tube_name%']:put('take') */ - public function testTake() + public function testTake() : void { $task = $this->queue->take(); - $this->assertTask($task, 0, States::TAKEN, 'take'); + self::assertTask($task, 0, States::TAKEN, 'take'); } - public function testTakeNone() + public function testTakeNone() : void { $time = time(); $task = $this->queue->take(2); - $this->assertGreaterThanOrEqual(2, time() - $time); - $this->assertNull($task); + self::assertGreaterThanOrEqual(2, time() - $time); + self::assertNull($task); } /** * @eval queue.tube['%tube_name%']:put('release_0') * @eval queue.tube['%tube_name%']:take() */ - public function testRelease() + public function testRelease() : void { $task = $this->queue->release(0); - $this->assertTask($task, 0, States::READY, 'release_0'); + self::assertTask($task, 0, States::READY, 'release_0'); } /** * @eval queue.tube['%tube_name%']:put('ack_0') * @eval queue.tube['%tube_name%']:take() */ - public function testAck() + public function testAck() : void { $task = $this->queue->ack(0); - $this->assertTask($task, 0, States::DONE, 'ack_0'); + self::assertTask($task, 0, States::DONE, 'ack_0'); } /** * @eval queue.tube['%tube_name%']:put('bury_0') */ - public function testBury() + public function testBury() : void { $task = $this->queue->bury(0); - $this->assertTask($task, 0, States::BURIED, 'bury_0'); + self::assertTask($task, 0, States::BURIED, 'bury_0'); } /** * @eval queue.tube['%tube_name%']:put('kick_1') * @eval queue.tube['%tube_name%']:bury(0) */ - public function testKickOne() + public function testKickOne() : void { $count = $this->queue->kick(1); - $this->assertSame(1, $count); + self::assertSame(1, $count); } /** @@ -180,43 +184,43 @@ public function testKickOne() * @eval queue.tube['%tube_name%']:bury(1) * @eval queue.tube['%tube_name%']:bury(2) */ - public function testKickMany() + public function testKickMany() : void { $count = $this->queue->kick(3); - $this->assertSame(3, $count); + self::assertSame(3, $count); } /** * @eval queue.tube['%tube_name%']:put('delete_0') */ - public function testDelete() + public function testDelete() : void { $task = $this->queue->delete(0); - $this->assertTask($task, 0, States::DONE, 'delete_0'); + self::assertTask($task, 0, States::DONE, 'delete_0'); } /** * @eval queue.tube['%tube_name%']:put('truncate_0') * @eval queue.tube['%tube_name%']:put('truncate_1') */ - public function testTruncate() + public function testTruncate() : void { - $this->assertSame(2, $this->queue->stats('tasks.total')); + self::assertSame(2, $this->queue->stats('tasks.total')); $this->queue->truncate(); - $this->assertSame(0, $this->queue->stats('tasks.total')); + self::assertSame(0, $this->queue->stats('tasks.total')); } - public function testTruncateEmpty() + public function testTruncateEmpty() : void { - $this->assertSame(0, $this->queue->stats('tasks.total')); + self::assertSame(0, $this->queue->stats('tasks.total')); $this->queue->truncate(); - $this->assertSame(0, $this->queue->stats('tasks.total')); + self::assertSame(0, $this->queue->stats('tasks.total')); } /** @@ -235,11 +239,11 @@ public function testTruncateEmpty() * @eval queue.tube['%tube_name%']:kick(1) * @eval queue.tube['%tube_name%']:take(.001) */ - public function testStats() + public function testStats() : void { $stats = $this->queue->stats(); - $this->assertEquals([ + self::assertEquals([ 'tasks' => [ 'taken' => 1, 'buried' => 1, @@ -264,11 +268,11 @@ public function testStats() ], $stats, '', 0.0, 3, true); } - public function testEmptyStats() + public function testEmptyStats() : void { $stats = $this->queue->stats(); - $this->assertEquals([ + self::assertEquals([ 'tasks' => [ 'taken' => 0, 'buried' => 0, @@ -317,9 +321,9 @@ public function testEmptyStats() * @eval queue.tube['%tube_name%']:delete(8) * @eval queue.tube['%tube_name%']:take(.001) */ - public function testStatsPath() + public function testStatsPath() : void { - $this->assertSameArray([ + self::assertSameArray([ 'taken' => 1, 'buried' => 2, 'ready' => 3, @@ -328,14 +332,14 @@ public function testStatsPath() 'total' => 6, ], $this->queue->stats('tasks')); - $this->assertSame(1, $this->queue->stats('tasks.taken')); - $this->assertSame(2, $this->queue->stats('tasks.buried')); - $this->assertSame(3, $this->queue->stats('tasks.ready')); - $this->assertSame(4, $this->queue->stats('tasks.done')); - $this->assertSame(0, $this->queue->stats('tasks.delayed')); - $this->assertSame(6, $this->queue->stats('tasks.total')); + self::assertSame(1, $this->queue->stats('tasks.taken')); + self::assertSame(2, $this->queue->stats('tasks.buried')); + self::assertSame(3, $this->queue->stats('tasks.ready')); + self::assertSame(4, $this->queue->stats('tasks.done')); + self::assertSame(0, $this->queue->stats('tasks.delayed')); + self::assertSame(6, $this->queue->stats('tasks.total')); - $this->assertSameArray([ + self::assertSameArray([ 'ack' => 1, 'delete' => 3, 'take' => 3, @@ -349,27 +353,28 @@ public function testStatsPath() 'ttl' => 0, ], $this->queue->stats('calls')); - $this->assertSame(1, $this->queue->stats('calls.ack')); - $this->assertSame(3, $this->queue->stats('calls.delete')); - $this->assertSame(3, $this->queue->stats('calls.take')); - $this->assertSame(1, $this->queue->stats('calls.kick')); - $this->assertSame(1, $this->queue->stats('calls.release')); - $this->assertSame(0, $this->queue->stats('calls.touch')); - $this->assertSame(10, $this->queue->stats('calls.put')); - $this->assertSame(3, $this->queue->stats('calls.bury')); + self::assertSame(1, $this->queue->stats('calls.ack')); + self::assertSame(3, $this->queue->stats('calls.delete')); + self::assertSame(3, $this->queue->stats('calls.take')); + self::assertSame(1, $this->queue->stats('calls.kick')); + self::assertSame(1, $this->queue->stats('calls.release')); + self::assertSame(0, $this->queue->stats('calls.touch')); + self::assertSame(10, $this->queue->stats('calls.put')); + self::assertSame(3, $this->queue->stats('calls.bury')); } /** * @dataProvider provideStatsInvalidPathData - * @expectedException \InvalidArgumentException - * @expectedExceptionMessageRegExp /^Invalid path ".*?"\.$/ */ - public function testStatsInvalidPath($path) + public function testStatsInvalidPath($path) : void { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessageRegExp('/^Invalid path ".*?"\.$/'); + $this->queue->stats($path); } - public function provideStatsInvalidPathData() + public function provideStatsInvalidPathData() : iterable { return [ [''], @@ -387,23 +392,24 @@ public function provideStatsInvalidPathData() /** * @eval queue.tube['%tube_name%'].pow = function(self, base, exp) return math.pow(base, exp) end */ - public function testCall() + public function testCall() : void { - $result = $this->queue->call('pow', [2, 8]); + $result = $this->queue->call('pow', 2, 8); - $this->assertSame(256, $result[0][0]); + self::assertSame(256, $result[0][0]); } /** * @dataProvider provideFailureCallbackData - * @expectedException \Exception */ - public function testThrowException($methodName, array $args) + public function testThrowException(string $methodName, array $args) : void { - call_user_func_array([$this->queue, $methodName], $args); + $this->expectException(\Throwable::class); + + $this->queue->$methodName(...$args); } - public function provideFailureCallbackData() + public function provideFailureCallbackData() : iterable { return [ ['ack', [42]], @@ -415,29 +421,32 @@ public function provideFailureCallbackData() ]; } - protected function assertTaskInstance($task) + protected static function assertTaskInstance($task) : void { - $this->assertInstanceOf('Tarantool\Queue\Task', $task); + self::assertInstanceOf(Task::class, $task); } - protected function assertTask($task, $expectedId, $expectedState, $expectedData) + protected static function assertTask(Task $task, int $expectedId, string $expectedState, $expectedData) : void { - $this->assertTaskInstance($task); - - $this->assertSame($expectedId, $task->getId()); - $this->assertSame($expectedState, $task->getState()); - $this->assertSame($expectedData, $task->getData()); + self::assertSame($expectedId, $task->getId()); + self::assertSame($expectedState, $task->getState()); + self::assertSame($expectedData, $task->getData()); } - protected function assertSameArray(array $expected, array $actual) + protected static function assertSameArray(array $expected, array $actual) : void { ksort($expected); ksort($actual); - $this->assertSame($expected, $actual); + self::assertSame($expected, $actual); + } + + protected function getQueue() : Queue + { + return $this->queue; } - protected function getTubeType() + protected function getTubeType() : string { $class = new \ReflectionClass($this); $type = str_replace('QueueTest', '', $class->getShortName()); diff --git a/tests/Integration/Ttl.php b/tests/Integration/Ttl.php index ed7dd14..121bc41 100644 --- a/tests/Integration/Ttl.php +++ b/tests/Integration/Ttl.php @@ -1,5 +1,7 @@ queue->take(.1); + $queue = $this->getQueue(); + + $task1 = $queue->take(.1); sleep(1); - $task2 = $this->queue->take(.1); + $task2 = $queue->take(.1); - $this->assertTaskInstance($task1); - $this->assertSame('ttr_1', $task1->getData()); - $this->assertEquals($task1, $task2); + self::assertTaskInstance($task1); + self::assertSame('ttr_1', $task1->getData()); + self::assertEquals($task1, $task2); } /** * @eval queue.tube['%tube_name%']:put('ttl_1', {ttl = 1}) */ - public function testTimeToLive() + public function testTimeToLive() : void { sleep(1); - $task = $this->queue->take(.1); + $task = $this->getQueue()->take(.1); - $this->assertNull($task); + self::assertNull($task); } /** * @eval queue.tube['%tube_name%']:put('touch_ttr_1', {ttr = 1}) */ - public function testTouchTimeToRun() + public function testTouchTimeToRun() : void { - $task1 = $this->queue->take(.1); - $task2 = $this->queue->touch($task1->getId(), 1); + $queue = $this->getQueue(); + + $task1 = $queue->take(.1); + $task2 = $queue->touch($task1->getId(), 1); sleep(1); - $task3 = $this->queue->take(.1); + $task3 = $queue->take(.1); - $this->assertTaskInstance($task2); - $this->assertSame('touch_ttr_1', $task2->getData()); - $this->assertEquals($task1, $task2); - $this->assertNull($task3); + self::assertTaskInstance($task2); + self::assertSame('touch_ttr_1', $task2->getData()); + self::assertEquals($task1, $task2); + self::assertNull($task3); } /** * @eval queue.tube['%tube_name%']:put('touch_ttl_1', {ttl = 1}) */ - public function testTouchTimeToLive() + public function testTouchTimeToLive() : void { - $task1 = $this->queue->take(.1); - $task2 = $this->queue->touch($task1->getId(), 1); - $this->queue->release($task1->getId()); + $queue = $this->getQueue(); + + $task1 = $queue->take(.1); + $task2 = $queue->touch($task1->getId(), 1); + $queue->release($task1->getId()); sleep(1); - $task3 = $this->queue->take(.1); + $task3 = $queue->take(.1); - $this->assertTaskInstance($task2); - $this->assertSame('touch_ttl_1', $task2->getData()); - $this->assertEquals($task1, $task2); - $this->assertEquals($task2, $task3); + self::assertTaskInstance($task2); + self::assertSame('touch_ttl_1', $task2->getData()); + self::assertEquals($task1, $task2); + self::assertEquals($task2, $task3); } /** * @eval queue.tube['%tube_name%']:put('touch_invalid_interval') */ - public function testTouchInvalidInterval() + public function testTouchInvalidInterval() : void { - $task = $this->queue->take(.1); + $queue = $this->getQueue(); + $task = $queue->take(.1); foreach ([0, -1] as $interval) { - $this->assertNull($this->queue->touch($task->getId(), $interval)); + self::assertNull($queue->touch($task->getId(), $interval)); } } @@ -89,57 +99,65 @@ public function testTouchInvalidInterval() * @eval queue.tube['%tube_name%']:put('pri_low', {pri = 2}) * @eval queue.tube['%tube_name%']:put('pri_high', {pri = 1}) */ - public function testPriority() + public function testPriority() : void { - $task1 = $this->queue->take(.1); - $this->queue->delete($task1->getId()); + $queue = $this->getQueue(); - $task2 = $this->queue->take(.1); - $this->queue->delete($task2->getId()); + $task1 = $queue->take(.1); + $queue->delete($task1->getId()); - $this->assertSame('pri_high', $task1->getData()); - $this->assertSame('pri_low', $task2->getData()); + $task2 = $queue->take(.1); + $queue->delete($task2->getId()); + + self::assertSame('pri_high', $task1->getData()); + self::assertSame('pri_low', $task2->getData()); } /** * @eval queue.tube['%tube_name%']:put('delay_1', {delay = 1}) */ - public function testDelay() + public function testDelay() : void { - $task = $this->queue->peek(0); - $this->assertTask($task, 0, States::DELAYED, 'delay_1'); + $queue = $this->getQueue(); + + $task = $queue->peek(0); + self::assertTask($task, 0, States::DELAYED, 'delay_1'); sleep(1); - $task = $this->queue->take(.1); - $this->assertTask($task, 0, States::TAKEN, 'delay_1'); + $task = $queue->take(.1); + self::assertTask($task, 0, States::TAKEN, 'delay_1'); } /** * @eval queue.tube['%tube_name%']:put('release_0') * @eval queue.tube['%tube_name%']:take() */ - public function testDelayedRelease() + public function testDelayedRelease() : void { - $this->queue->release(0, ['delay' => 1]); + $queue = $this->getQueue(); - $task = $this->queue->peek(0); - $this->assertTask($task, 0, States::DELAYED, 'release_0'); + $queue->release(0, ['delay' => 1]); + + $task = $queue->peek(0); + self::assertTask($task, 0, States::DELAYED, 'release_0'); sleep(1); - $task = $this->queue->take(.1); - $this->assertTask($task, 0, States::TAKEN, 'release_0'); + $task = $queue->take(.1); + self::assertTask($task, 0, States::TAKEN, 'release_0'); } /** * @eval queue.tube['%tube_name%']:put('stat_delayed_0', {delay = 9999}) * @eval queue.tube['%tube_name%']:put('stat_delayed_1', {delay = 9999}) */ - public function testStatsDelayed() + public function testStatsDelayed() : void { - $count = $this->queue->stats('tasks.delayed'); + $count = $this->getQueue()->stats('tasks.delayed'); - $this->assertSame(2, $count); + self::assertSame(2, $count); } + + abstract protected function getQueue() : Queue; } diff --git a/tests/Integration/UtubeQueueTest.php b/tests/Integration/UtubeQueueTest.php index 63a31fd..6801c89 100644 --- a/tests/Integration/UtubeQueueTest.php +++ b/tests/Integration/UtubeQueueTest.php @@ -1,5 +1,7 @@ assertInstanceOf('InvalidArgumentException', $e); - $this->assertSame( - "Tarantool\\Queue\\Queue::__construct() expects parameter 1 to be Tarantool or Tarantool\\Client\\Client, $type given.", - $e->getMessage() - ); + self::assertContains('__construct() expects parameter 1 to be ', $e->getMessage()); + self::assertStringEndsWith(", $type given.", $e->getMessage()); return; } @@ -35,7 +37,7 @@ public function testConstructorThrowsInvalidArgumentException($invalidClient, $t $this->fail(); } - public function provideConstructorInvalidArgumentData() + public function provideConstructorInvalidArgumentData() : iterable { return [ [new \stdClass(), 'stdClass'], @@ -43,15 +45,22 @@ public function provideConstructorInvalidArgumentData() ]; } - public function testGetName() + public function testGetName() : void { - $client = $this->getMockBuilder('Tarantool\Client\Client') - ->disableOriginalConstructor() - ->getMock(); + // temporary skip the test for the pecl connector until this PR is merged: + // https://github.com/tarantool/tarantool-php/pull/134 + if (!class_exists(Client::class)) { + $this->markTestSkipped('The package "tarantool\client" is not installed.'); + } + + /** @var \Tarantool|Client|MockObject $client */ + $client = class_exists(\Tarantool::class, false) + ? $this->createMock(\Tarantool::class) + : $this->createMock(Client::class); $queueName = uniqid('queue_', true); $queue = new Queue($client, $queueName); - $this->assertSame($queueName, $queue->getName()); + self::assertSame($queueName, $queue->getName()); } } diff --git a/tests/Unit/TaskTest.php b/tests/Unit/TaskTest.php index e94b532..af74132 100644 --- a/tests/Unit/TaskTest.php +++ b/tests/Unit/TaskTest.php @@ -1,5 +1,7 @@ assertSame($tuple[0], $task->getId()); - $this->assertSame($tuple[1], $task->getState()); + self::assertSame($tuple[0], $task->getId()); + self::assertSame($tuple[1], $task->getState()); - if (3 === count($tuple)) { - $this->assertSame($tuple[2], $task->getData()); + if (3 === \count($tuple)) { + self::assertSame($tuple[2], $task->getData()); } - - return $task; } - public function provideTuples() + public function provideTuples() : iterable { return [ [[0, States::READY, [42]]], @@ -45,7 +46,7 @@ public function provideTuples() /** * @dataProvider provideStates */ - public function testIsser($state) + public function testIsser(string $state) : void { static $map = [ States::READY => 'isReady', @@ -57,17 +58,17 @@ public function testIsser($state) $task = Task::createFromTuple([0, $state, null]); - $this->assertTrue($task->{$map[$state]}()); + self::assertTrue($task->{$map[$state]}()); $issers = $map; unset($issers[$state]); foreach ($issers as $isser) { - $this->assertFalse($task->$isser()); + self::assertFalse($task->$isser()); } } - public function provideStates() + public function provideStates() : iterable { return [ [States::READY], diff --git a/tests/bootstrap.php b/tests/bootstrap.php deleted file mode 100644 index f23b418..0000000 --- a/tests/bootstrap.php +++ /dev/null @@ -1,11 +0,0 @@ -