diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml
index c2fe040..e09454f 100644
--- a/.github/workflows/qa.yml
+++ b/.github/workflows/qa.yml
@@ -9,25 +9,25 @@ jobs:
tests:
strategy:
matrix:
- operating-system: [ubuntu-latest]
- php-versions: ['7.2', '7.3', '7.4', '8.0', '8.1']
+ operating-system: [ubuntu-24.04]
+ php-versions: ['8.2', '8.3', '8.4', '8.5']
runs-on: ${{ matrix.operating-system }}
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v7
- name: Setup PHP
- uses: shivammathur/setup-php@v2
+ uses: shivammathur/setup-php@2.37.1
with:
php-version: ${{ matrix.php-versions }}
coverage: none
- name: Get composer cache directory
id: composer-cache
- run: echo "::set-output name=dir::$(composer config cache-files-dir)"
+ run: echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"
- name: Cache composer dependencies
- uses: actions/cache@v1
+ uses: actions/cache@v6
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
@@ -43,23 +43,23 @@ jobs:
static-analysis:
name: Static Analysis
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v7
- name: Setup PHP
- uses: shivammathur/setup-php@v2
+ uses: shivammathur/setup-php@2.37.1
with:
- php-version: '8.0'
+ php-version: '8.2'
coverage: none
- name: Get composer cache directory
id: composer-cache
- run: echo "::set-output name=dir::$(composer config cache-files-dir)"
+ run: echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"
- name: Cache composer dependencies
- uses: actions/cache@v1
+ uses: actions/cache@v6
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
@@ -73,23 +73,23 @@ jobs:
coding-standard:
name: Coding Standard
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v7
- name: Setup PHP
- uses: shivammathur/setup-php@v2
+ uses: shivammathur/setup-php@2.37.1
with:
- php-version: 8.0
+ php-version: '8.2'
coverage: none
- name: Get composer cache directory
id: composer-cache
- run: echo "::set-output name=dir::$(composer config cache-files-dir)"
+ run: echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"
- name: Cache composer dependencies
- uses: actions/cache@v2
+ uses: actions/cache@v6
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
diff --git a/.php_cs.dist b/.php-cs-fixer.dist.php
similarity index 98%
rename from .php_cs.dist
rename to .php-cs-fixer.dist.php
index da6bde7..992b9a0 100644
--- a/.php_cs.dist
+++ b/.php-cs-fixer.dist.php
@@ -15,7 +15,7 @@
file that was distributed with this source code.
EOF;
-return Config::create()
+return (new Config())
->setUsingCache(false)
->setRiskyAllowed(true)
->setRules([
diff --git a/README.md b/README.md
index 064dc69..1169268 100644
--- a/README.md
+++ b/README.md
@@ -10,13 +10,13 @@ It is based on [rybakit/phpunit-extras](https://github.com/rybakit/phpunit-extra
## Table of contents
* [Installation](#installation)
- * [Annotations](#annotations)
+ * [Attributes](#attributes)
* [Processors](#processors)
* [Lua](#lua)
* [Sql](#sql)
* [Requirements](#requirements)
- * [LuaCondition](#luacondition)
- * [TarantoolVersion](#tarantoolversion)
+ * [RequiresIfLua](#requiresiflua)
+ * [RequiresTarantool](#requirestarantool)
* [Expectations](#expectations)
* [Requests](#requests)
* [Prepared statements](#prepared-statements)
@@ -32,10 +32,10 @@ composer require --dev tarantool/phpunit-extras
```
-## Annotations
+## Attributes
-Besides the annotations provided by the package `rybakit/phpunit-extras`, the library is shipped
-with annotations specific to Tarantool. The easiest way to enable them is by inheriting your test classes
+Besides the attributes provided by the package `rybakit/phpunit-extras`, the library is shipped
+with attributes specific to Tarantool. The easiest way to enable them is by inheriting your test classes
from `Tarantool\PhpUnit\TestCase`:
```php
@@ -53,46 +53,41 @@ final class MyTest extends TestCase
}
```
-Another option is to register an extension called `AnnotationExtension`:
+Another option is to register an extension called `AttributeExtension`:
```xml
-
+
```
By default, the extension assumes that the Tarantool server you are going to connect to is available on `127.0.0.1:3301`.
You can customize the default settings by specifying either a [DSN string](https://github.com/tarantool-php/client#dsn-string) or an [array of options](https://github.com/tarantool-php/client#array-of-options)
-as extension configuration values:
+as extension configuration values. PHPUnit 10 passes extension parameters as strings, so use the DSN form for options that require numeric or Boolean values (such as `socket_timeout`):
```xml
-
-
- tcp://127.0.0.1:3301/?socket_timeout=10
-
-
+
+
+
+
+
```
or
```xml
-
-
-
-
- tcp://127.0.0.1:3301
-
-
- 10
-
-
-
-
+
+
+
+
+
+
+
```
On top of that, the configuration values can resolve environment variables,
@@ -100,14 +95,14 @@ which might be useful if you need to share the same settings with a Tarantool
instance file or any other script:
```xml
-
-
- tcp://%env(TARANTOOL_HOST)%:%env(TARANTOOL_PORT)%
-
-
+
+
+
+
+
```
-Once the annotations are configured, you can start using them:
+Once the attributes are configured, you can start using them:
### Processors
@@ -118,10 +113,10 @@ Allows executing Lua code before running a test.
*Example:*
```php
-/**
- * @lua tube:put('kick_me')
- * @lua tube:bury(0)
- */
+use Tarantool\PhpUnit\Attribute\Lua;
+
+#[Lua("tube:put('kick_me')")]
+#[Lua('tube:bury(0)')]
public function testKickReleasesBuriedTask() : void
{
// ...
@@ -135,11 +130,11 @@ Allows executing SQL statements before running a test (requires Tarantool 2.0+).
*Example:*
```php
-/**
- * @sql DROP TABLE IF EXISTS foobar
- * @sql CREATE TABLE foobar (id INTEGER PRIMARY KEY, name VARCHAR(50))
- * @sql INSERT INTO foobar VALUES (1, 'A'), (2, 'B')
- */
+use Tarantool\PhpUnit\Attribute\Sql;
+
+#[Sql('DROP TABLE IF EXISTS foobar')]
+#[Sql('CREATE TABLE foobar (id INTEGER PRIMARY KEY, name VARCHAR(50))')]
+#[Sql("INSERT INTO foobar VALUES (1, 'A'), (2, 'B')")]
public function testExecuteQueryFetchesAllRows() : void
{
// ...
@@ -151,50 +146,38 @@ public function testExecuteQueryFetchesAllRows() : void
Requirements allow skipping tests based on preconditions.
-#### LuaCondition
-
-*Format:*
-
-```
-@requires luaCondition
-```
+#### RequiresIfLua
where `` is an arbitrary lua expression that should be evaluated to a Boolean value.
*Example:*
```php
-/**
- * @requires luaCondition box.session.user() ~= 'guest'
- */
+use Tarantool\PhpUnit\Attribute\RequiresIfLua;
+
+#[RequiresIfLua("box.session.user() ~= 'guest'")]
public function testChangeUserPassword() : void
{
// ...
}
```
-#### TarantoolVersion
-
-*Format:*
-
-```
-@requires Tarantool
-```
+#### RequiresTarantool
where `` is a composer-like version constraint. For details on supported formats,
please see the Composer [documentation](https://getcomposer.org/doc/articles/versions.md#writing-version-constraints).
*Example:*
```php
-/**
- * @requires Tarantool ^2.3.2
- */
+use Tarantool\PhpUnit\Attribute\RequiresTarantool;
+
+#[RequiresTarantool('^2.3.2')]
public function testPrepareCreatesPreparedStatement() : void
{
// ...
}
```
-> *If you're interested in how to create and register your own annotations and requirements,
+> *If you're interested in how to create and register your own attributes and requirements,
> please refer to the `rybakit/phpunit-extras` [README](https://github.com/rybakit/phpunit-extras).*
diff --git a/composer.json b/composer.json
index f4c4d7d..d8f2bc3 100644
--- a/composer.json
+++ b/composer.json
@@ -1,7 +1,7 @@
{
"name": "tarantool/phpunit-extras",
"description": "A collection of helpers for PHPUnit to ease testing Tarantool libraries.",
- "keywords": ["tarantool", "phpunit", "annotations", "assertions", "expectations", "extensions", "mocking"],
+ "keywords": ["tarantool", "phpunit", "attributes", "assertions", "expectations", "extensions", "mocking"],
"type": "library",
"license": "MIT",
"authors": [
@@ -11,17 +11,16 @@
}
],
"require": {
- "php": "^7.2.5|^8",
- "composer/package-versions-deprecated": "1.11.99.5",
+ "php": "^8.2",
"composer/semver": "^3.3",
- "rybakit/phpunit-extras": "^0.2.4",
- "symfony/expression-language": "^3.3|^4|^5|^6",
+ "rybakit/phpunit-extras": "^0.3.0",
+ "symfony/expression-language": "^7.0",
"tarantool/client": "^0.10"
},
"require-dev": {
- "php": "^7.2.5|^8",
- "friendsofphp/php-cs-fixer": "^2.19",
- "vimeo/psalm": "^3.9|^4"
+ "friendsofphp/php-cs-fixer": "^3",
+ "phpunit/phpunit": "^10.5",
+ "vimeo/psalm": "^5.23|^6"
},
"autoload": {
"psr-4": {
@@ -38,5 +37,6 @@
"*": "dist"
},
"sort-packages": true
- }
+ },
+ "prefer-stable": true
}
diff --git a/phpunit-extension.xml b/phpunit-extension.xml
index fef869a..95bf519 100644
--- a/phpunit-extension.xml
+++ b/phpunit-extension.xml
@@ -1,45 +1,26 @@
-
-
-
-
-
-
-
-
-
-
-
- tests/Annotation/AnnotationExtensionTest.php
-
-
-
-
-
- src
-
-
-
-
-
-
-
-
- true
-
-
- 42
-
-
- foobar
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ tests/Attribute/AttributeExtensionTest.php
+
+
+
+
+ src
+
+
+
+
+
+
+
+
+
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index c48d998..2f26844 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,28 +1,20 @@
-
-
-
-
-
-
-
-
-
-
-
- tests
- tests/Annotation/AnnotationExtensionTest.php
-
-
-
-
-
- src
-
-
+
+
+
+
+
+
+
+
+
+ tests
+ tests/Attribute/AttributeExtensionTest.php
+
+
+
+
+ src
+
+
diff --git a/psalm.xml b/psalm.xml
index 18db1fb..fbc3fcb 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -14,15 +14,16 @@
-
+
+
+
+
+
+
+
-
-
-
-
-
-
+
-
+
diff --git a/src/Annotation/Annotations.php b/src/Annotation/Annotations.php
deleted file mode 100644
index 93db4a6..0000000
--- a/src/Annotation/Annotations.php
+++ /dev/null
@@ -1,43 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-declare(strict_types=1);
-
-namespace Tarantool\PhpUnit\Annotation;
-
-use PHPUnitExtras\Annotation\AnnotationProcessorBuilder;
-use PHPUnitExtras\Annotation\Annotations as BaseAnnotations;
-use Tarantool\Client\Client;
-use Tarantool\PhpUnit\Annotation\Processor\LuaProcessor;
-use Tarantool\PhpUnit\Annotation\Processor\SqlProcessor;
-use Tarantool\PhpUnit\Annotation\Requirement\LuaConditionRequirement;
-use Tarantool\PhpUnit\Annotation\Requirement\TarantoolVersionRequirement;
-
-trait Annotations
-{
- use BaseAnnotations {
- BaseAnnotations::createAnnotationProcessorBuilder as createBaseAnnotationProcessorBuilder;
- }
-
- protected function createAnnotationProcessorBuilder() : AnnotationProcessorBuilder
- {
- $client = $this->getClient();
-
- return $this->createBaseAnnotationProcessorBuilder()
- ->addProcessor(new LuaProcessor($client))
- ->addProcessor(new SqlProcessor($client))
- ->addRequirement(new LuaConditionRequirement($client))
- ->addRequirement(new TarantoolVersionRequirement($client))
- ;
- }
-
- abstract protected function getClient() : Client;
-}
diff --git a/src/Annotation/Processor/LuaProcessor.php b/src/Annotation/Processor/LuaProcessor.php
deleted file mode 100644
index 375bd67..0000000
--- a/src/Annotation/Processor/LuaProcessor.php
+++ /dev/null
@@ -1,37 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-declare(strict_types=1);
-
-namespace Tarantool\PhpUnit\Annotation\Processor;
-
-use PHPUnitExtras\Annotation\Processor\Processor;
-use Tarantool\Client\Client;
-
-final class LuaProcessor implements Processor
-{
- private $client;
-
- public function __construct(Client $client)
- {
- $this->client = $client;
- }
-
- public function getName() : string
- {
- return 'lua';
- }
-
- public function process(string $value) : void
- {
- $this->client->evaluate($value);
- }
-}
diff --git a/src/Annotation/Processor/SqlProcessor.php b/src/Annotation/Processor/SqlProcessor.php
deleted file mode 100644
index 144c6b5..0000000
--- a/src/Annotation/Processor/SqlProcessor.php
+++ /dev/null
@@ -1,37 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-declare(strict_types=1);
-
-namespace Tarantool\PhpUnit\Annotation\Processor;
-
-use PHPUnitExtras\Annotation\Processor\Processor;
-use Tarantool\Client\Client;
-
-final class SqlProcessor implements Processor
-{
- private $client;
-
- public function __construct(Client $client)
- {
- $this->client = $client;
- }
-
- public function getName() : string
- {
- return 'sql';
- }
-
- public function process(string $value) : void
- {
- $this->client->executeUpdate($value);
- }
-}
diff --git a/src/Annotation/Requirement/LuaConditionRequirement.php b/src/Annotation/Requirement/LuaConditionRequirement.php
deleted file mode 100644
index 9b1b950..0000000
--- a/src/Annotation/Requirement/LuaConditionRequirement.php
+++ /dev/null
@@ -1,43 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-declare(strict_types=1);
-
-namespace Tarantool\PhpUnit\Annotation\Requirement;
-
-use PHPUnitExtras\Annotation\Requirement\Requirement;
-use Tarantool\Client\Client;
-
-final class LuaConditionRequirement implements Requirement
-{
- private $client;
-
- public function __construct(Client $client)
- {
- $this->client = $client;
- }
-
- public function getName() : string
- {
- return 'luaCondition';
- }
-
- public function check(string $value) : ?string
- {
- [$result] = $this->client->evaluate("return ($value)");
-
- if ($result) {
- return null;
- }
-
- return sprintf('"%s" is not evaluated to true', $value);
- }
-}
diff --git a/src/Annotation/Requirement/TarantoolVersionRequirement.php b/src/Annotation/Requirement/TarantoolVersionRequirement.php
deleted file mode 100644
index 7d8ecb4..0000000
--- a/src/Annotation/Requirement/TarantoolVersionRequirement.php
+++ /dev/null
@@ -1,66 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-declare(strict_types=1);
-
-namespace Tarantool\PhpUnit\Annotation\Requirement;
-
-use Composer\Semver\Semver;
-use PHPUnitExtras\Annotation\Requirement\Requirement;
-use Tarantool\Client\Client;
-
-final class TarantoolVersionRequirement implements Requirement
-{
- private $client;
-
- /** @var string|null */
- private $version;
-
- public function __construct(Client $client)
- {
- $this->client = $client;
- }
-
- public function getName() : string
- {
- return 'Tarantool';
- }
-
- public function check(string $value) : ?string
- {
- // Replace dash with dot.
- $constraints = preg_replace('/(\d+\.\d+\.\d+)-(\d+)/', '$1.$2', $value);
-
- if (Semver::satisfies($this->getVersion(), $constraints)) {
- return null;
- }
-
- return sprintf('%s version %s is required', $this->getName(), $value);
- }
-
- private function getVersion() : string
- {
- if ($this->version) {
- return $this->version;
- }
-
- $version = $this->client->call('box.info')[0]['version'];
-
- // Normalize 2.2.1-3-g878e2a42c to 2.2.1.3.
- $version = preg_replace('/-(\d+)-[^-]+$/', '.$1', $version);
-
- // Treat "entrypoint" versions as "dev",
- // so 2.11.0-entrypoint.8 becomes 2.11.0-dev+entrypoint.8.
- $version = preg_replace('/(\d)-entrypoint/', '$1-dev+entrypoint', $version);
-
- return $this->version = $version;
- }
-}
diff --git a/src/Annotation/AnnotationExtension.php b/src/Attribute/AttributeExtension.php
similarity index 51%
rename from src/Annotation/AnnotationExtension.php
rename to src/Attribute/AttributeExtension.php
index 2c8ae49..0cc73ab 100644
--- a/src/Annotation/AnnotationExtension.php
+++ b/src/Attribute/AttributeExtension.php
@@ -11,30 +11,54 @@
declare(strict_types=1);
-namespace Tarantool\PhpUnit\Annotation;
+namespace Tarantool\PhpUnit\Attribute;
use PHPUnit\Exception;
-use PHPUnitExtras\Annotation\AnnotationExtension as BaseAnnotationExtension;
+use PHPUnit\Runner\Extension\Facade;
+use PHPUnit\Runner\Extension\ParameterCollection;
+use PHPUnit\TextUI\Configuration\Configuration;
+use PHPUnitExtras\Attribute\AttributeExtension as BaseAttributeExtension;
use Tarantool\Client\Client;
-class AnnotationExtension extends BaseAnnotationExtension
+/** @psalm-suppress ClassMustBeFinal This extension is intended to be extended. */
+class AttributeExtension extends BaseAttributeExtension
{
- use Annotations;
+ use Attributes;
/** @var array|string */
- private $clientConfig;
+ private $clientConfig = 'tcp://127.0.0.1:3301';
/** @var Client|null */
private $client;
- /**
- * @param array|string $clientConfig
- */
- public function __construct($clientConfig = 'tcp://127.0.0.1:3301')
+ #[\Override]
+ public function bootstrap(Configuration $configuration, Facade $facade, ParameterCollection $parameters) : void
{
- $this->clientConfig = $clientConfig;
+ $this->parseParameters($parameters);
+ parent::bootstrap($configuration, $facade, $parameters);
+ }
+
+ protected function parseParameters(ParameterCollection $parameters) : void
+ {
+ if ($parameters->has('dsn')) {
+ $this->clientConfig = $parameters->get('dsn');
+ } else {
+ $closure = \Closure::bind(function () {
+ /**
+ * @psalm-suppress InaccessibleProperty
+ * @var ParameterCollection $this
+ */
+ return $this->parameters;
+ }, $parameters, ParameterCollection::class);
+ $options = $closure ? $closure() : [];
+
+ if ([] !== $options) {
+ $this->clientConfig = $options;
+ }
+ }
}
+ #[\Override]
protected function getClient() : Client
{
if ($this->client) {
@@ -71,12 +95,12 @@ final protected function getClientConfig(bool $resolveEnvVars = true)
private static function resolveEnvValues(string $configValue) : string
{
- return preg_replace_callback('/%env\((?P.+?)\)%/', static function (array $matches) : string {
+ return (string) preg_replace_callback('/%env\((?P.+?)\)%/', static function (array $matches) : string {
if (false !== $value = getenv($matches['name'])) {
return $value;
}
- $errorMessage = sprintf('Environment variable "%s" does not exist', $matches['name']);
+ $errorMessage = \sprintf('Environment variable "%s" does not exist', $matches['name']);
throw new class($errorMessage) extends \RuntimeException implements Exception { };
}, $configValue);
}
diff --git a/src/Attribute/Attributes.php b/src/Attribute/Attributes.php
new file mode 100644
index 0000000..b553385
--- /dev/null
+++ b/src/Attribute/Attributes.php
@@ -0,0 +1,43 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Tarantool\PhpUnit\Attribute;
+
+use PHPUnitExtras\Attribute\AttributeProcessorBuilder;
+use PHPUnitExtras\Attribute\Attributes as BaseAttributes;
+use Tarantool\Client\Client;
+use Tarantool\PhpUnit\Attribute\Processor\LuaProcessor;
+use Tarantool\PhpUnit\Attribute\Processor\SqlProcessor;
+use Tarantool\PhpUnit\Attribute\Requirement\IfLuaRequirement;
+use Tarantool\PhpUnit\Attribute\Requirement\TarantoolRequirement;
+
+trait Attributes
+{
+ use BaseAttributes {
+ BaseAttributes::createAttributeProcessorBuilder as createBaseAttributeProcessorBuilder;
+ }
+
+ protected function createAttributeProcessorBuilder() : AttributeProcessorBuilder
+ {
+ $client = $this->getClient();
+
+ return $this->createBaseAttributeProcessorBuilder()
+ ->addProcessor(new LuaProcessor($client))
+ ->addProcessor(new SqlProcessor($client))
+ ->addRequirement(new IfLuaRequirement($client))
+ ->addRequirement(new TarantoolRequirement($client))
+ ;
+ }
+
+ abstract protected function getClient() : Client;
+}
diff --git a/src/Attribute/Lua.php b/src/Attribute/Lua.php
new file mode 100644
index 0000000..39a97b6
--- /dev/null
+++ b/src/Attribute/Lua.php
@@ -0,0 +1,24 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Tarantool\PhpUnit\Attribute;
+
+use PHPUnitExtras\Attribute\ProcessableAttribute;
+
+#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
+final class Lua implements ProcessableAttribute
+{
+ public function __construct(public readonly string $code)
+ {
+ }
+}
diff --git a/src/Attribute/Processor/LuaProcessor.php b/src/Attribute/Processor/LuaProcessor.php
new file mode 100644
index 0000000..2b97495
--- /dev/null
+++ b/src/Attribute/Processor/LuaProcessor.php
@@ -0,0 +1,47 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Tarantool\PhpUnit\Attribute\Processor;
+
+use PHPUnitExtras\Attribute\PlaceholderResolver\PlaceholderResolver;
+use PHPUnitExtras\Attribute\ProcessableAttribute;
+use PHPUnitExtras\Attribute\Processor\Processor;
+use PHPUnitExtras\Attribute\Target;
+use Tarantool\Client\Client;
+use Tarantool\PhpUnit\Attribute\Lua;
+
+final class LuaProcessor implements Processor
+{
+ private Client $client;
+
+ public function __construct(Client $client)
+ {
+ $this->client = $client;
+ }
+
+ #[\Override]
+ public function getAttributeClasses() : array
+ {
+ return [Lua::class];
+ }
+
+ #[\Override]
+ public function process(ProcessableAttribute $attribute, Target $target, PlaceholderResolver $placeholderResolver) : void
+ {
+ if (!$attribute instanceof Lua) {
+ throw new \InvalidArgumentException('LuaProcessor only handles Lua attributes');
+ }
+
+ $this->client->evaluate($placeholderResolver->resolve($attribute->code, $target));
+ }
+}
diff --git a/src/Attribute/Processor/SqlProcessor.php b/src/Attribute/Processor/SqlProcessor.php
new file mode 100644
index 0000000..5ef46a5
--- /dev/null
+++ b/src/Attribute/Processor/SqlProcessor.php
@@ -0,0 +1,47 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Tarantool\PhpUnit\Attribute\Processor;
+
+use PHPUnitExtras\Attribute\PlaceholderResolver\PlaceholderResolver;
+use PHPUnitExtras\Attribute\ProcessableAttribute;
+use PHPUnitExtras\Attribute\Processor\Processor;
+use PHPUnitExtras\Attribute\Target;
+use Tarantool\Client\Client;
+use Tarantool\PhpUnit\Attribute\Sql;
+
+final class SqlProcessor implements Processor
+{
+ private Client $client;
+
+ public function __construct(Client $client)
+ {
+ $this->client = $client;
+ }
+
+ #[\Override]
+ public function getAttributeClasses() : array
+ {
+ return [Sql::class];
+ }
+
+ #[\Override]
+ public function process(ProcessableAttribute $attribute, Target $target, PlaceholderResolver $placeholderResolver) : void
+ {
+ if (!$attribute instanceof Sql) {
+ throw new \InvalidArgumentException('SqlProcessor only handles Sql attributes');
+ }
+
+ $this->client->executeUpdate($placeholderResolver->resolve($attribute->code, $target));
+ }
+}
diff --git a/src/Attribute/Requirement/IfLuaRequirement.php b/src/Attribute/Requirement/IfLuaRequirement.php
new file mode 100644
index 0000000..bae15e0
--- /dev/null
+++ b/src/Attribute/Requirement/IfLuaRequirement.php
@@ -0,0 +1,54 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Tarantool\PhpUnit\Attribute\Requirement;
+
+use PHPUnitExtras\Attribute\PlaceholderResolver\PlaceholderResolver;
+use PHPUnitExtras\Attribute\ProcessableAttribute;
+use PHPUnitExtras\Attribute\Requirement\Requirement;
+use PHPUnitExtras\Attribute\Target;
+use Tarantool\Client\Client;
+use Tarantool\PhpUnit\Attribute\RequiresIfLua;
+
+final class IfLuaRequirement implements Requirement
+{
+ private Client $client;
+
+ public function __construct(Client $client)
+ {
+ $this->client = $client;
+ }
+
+ #[\Override]
+ public function getAttributeClass() : string
+ {
+ return RequiresIfLua::class;
+ }
+
+ #[\Override]
+ public function check(ProcessableAttribute $attribute, Target $target, PlaceholderResolver $placeholderResolver) : ?string
+ {
+ if (!$attribute instanceof RequiresIfLua) {
+ throw new \InvalidArgumentException('IfLuaRequirement only handles RequiresIfLua attributes');
+ }
+
+ $condition = $placeholderResolver->resolve($attribute->condition, $target);
+ [$result] = $this->client->evaluate("return ($condition)");
+
+ if ($result) {
+ return null;
+ }
+
+ return \sprintf('"%s" is not evaluated to true', $condition);
+ }
+}
diff --git a/src/Attribute/Requirement/TarantoolRequirement.php b/src/Attribute/Requirement/TarantoolRequirement.php
new file mode 100644
index 0000000..eb31de1
--- /dev/null
+++ b/src/Attribute/Requirement/TarantoolRequirement.php
@@ -0,0 +1,80 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Tarantool\PhpUnit\Attribute\Requirement;
+
+use Composer\Semver\Semver;
+use PHPUnitExtras\Attribute\PlaceholderResolver\PlaceholderResolver;
+use PHPUnitExtras\Attribute\ProcessableAttribute;
+use PHPUnitExtras\Attribute\Requirement\Requirement;
+use PHPUnitExtras\Attribute\Target;
+use Tarantool\Client\Client;
+use Tarantool\PhpUnit\Attribute\RequiresTarantool;
+
+final class TarantoolRequirement implements Requirement
+{
+ private Client $client;
+
+ /** @var string|null */
+ private $version;
+
+ public function __construct(Client $client)
+ {
+ $this->client = $client;
+ }
+
+ #[\Override]
+ public function getAttributeClass() : string
+ {
+ return RequiresTarantool::class;
+ }
+
+ #[\Override]
+ public function check(ProcessableAttribute $attribute, Target $target, PlaceholderResolver $placeholderResolver) : ?string
+ {
+ if (!$attribute instanceof RequiresTarantool) {
+ throw new \InvalidArgumentException('TarantoolRequirement only handles RequiresTarantool attributes');
+ }
+
+ $value = $placeholderResolver->resolve($attribute->constraint, $target);
+ // Replace dash with dot.
+ $constraints = (string) preg_replace('/(\d+\.\d+\.\d+)-(\d+)/', '$1.$2', $value);
+
+ if (Semver::satisfies($this->getVersion(), $constraints)) {
+ return null;
+ }
+
+ return \sprintf('Tarantool version %s is required', $value);
+ }
+
+ private function getVersion() : string
+ {
+ if (null !== $this->version) {
+ return $this->version;
+ }
+
+ $version = $this->client->call('box.info')[0]['version'];
+ if (!\is_string($version)) {
+ throw new \UnexpectedValueException('Tarantool version must be a string');
+ }
+
+ // Normalize 2.2.1-3-g878e2a42c to 2.2.1.3.
+ $version = (string) preg_replace('/-(\d+)-[^-]+$/', '.$1', $version);
+
+ // Treat "entrypoint" versions as "dev",
+ // so 2.11.0-entrypoint.8 becomes 2.11.0-dev+entrypoint.8.
+ $version = (string) preg_replace('/(\d)-entrypoint/', '$1-dev+entrypoint', $version);
+
+ return $this->version = $version;
+ }
+}
diff --git a/src/Attribute/RequiresIfLua.php b/src/Attribute/RequiresIfLua.php
new file mode 100644
index 0000000..b3fca83
--- /dev/null
+++ b/src/Attribute/RequiresIfLua.php
@@ -0,0 +1,24 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Tarantool\PhpUnit\Attribute;
+
+use PHPUnitExtras\Attribute\ProcessableAttribute;
+
+#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
+final class RequiresIfLua implements ProcessableAttribute
+{
+ public function __construct(public readonly string $condition)
+ {
+ }
+}
diff --git a/src/Attribute/RequiresTarantool.php b/src/Attribute/RequiresTarantool.php
new file mode 100644
index 0000000..975bbe5
--- /dev/null
+++ b/src/Attribute/RequiresTarantool.php
@@ -0,0 +1,24 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Tarantool\PhpUnit\Attribute;
+
+use PHPUnitExtras\Attribute\ProcessableAttribute;
+
+#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
+final class RequiresTarantool implements ProcessableAttribute
+{
+ public function __construct(public readonly string $constraint)
+ {
+ }
+}
diff --git a/src/Attribute/Sql.php b/src/Attribute/Sql.php
new file mode 100644
index 0000000..d51be8c
--- /dev/null
+++ b/src/Attribute/Sql.php
@@ -0,0 +1,24 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Tarantool\PhpUnit\Attribute;
+
+use PHPUnitExtras\Attribute\ProcessableAttribute;
+
+#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
+final class Sql implements ProcessableAttribute
+{
+ public function __construct(public readonly string $code)
+ {
+ }
+}
diff --git a/src/Client/IsRequestType.php b/src/Client/IsRequestType.php
index b8b4c57..951ac6e 100644
--- a/src/Client/IsRequestType.php
+++ b/src/Client/IsRequestType.php
@@ -24,20 +24,17 @@ final class IsRequestType extends Constraint
public function __construct(int $requestType)
{
- // needed for backward compatibility with PHPUnit 7
- if (\is_callable('parent::__construct')) {
- parent::__construct();
- }
-
$this->requestType = $requestType;
}
+ #[\Override]
public function toString() : string
{
- return sprintf('is a "%s" request', strtoupper(RequestTypes::getName($this->requestType)));
+ return \sprintf('is a "%s" request', strtoupper(RequestTypes::getName($this->requestType)));
}
- protected function matches($other) : bool
+ #[\Override]
+ protected function matches(mixed $other) : bool
{
return $other instanceof Request && $other->getType() === $this->requestType;
}
diff --git a/src/Client/TestDoubleClientBuilder.php b/src/Client/TestDoubleClientBuilder.php
index 8ce18b3..b74ecc1 100755
--- a/src/Client/TestDoubleClientBuilder.php
+++ b/src/Client/TestDoubleClientBuilder.php
@@ -41,7 +41,7 @@ final class TestDoubleClientBuilder
private $packer;
/** @var int|null */
- private $shouldBeCalledTimes = null;
+ private $shouldBeCalledTimes;
public function __construct(TestCase $testCase)
{
@@ -51,12 +51,8 @@ public function __construct(TestCase $testCase)
public static function buildDummy() : Client
{
- /**
- * @psalm-suppress InternalMethod
- * @psalm-suppress PropertyNotSetInConstructor
- */
- $self = new self(new class() extends TestCase {
- });
+ /** @psalm-suppress InternalMethod */
+ $self = new self(new class('dummy') extends TestCase {});
return $self->build();
}
@@ -79,9 +75,8 @@ public function shouldSend($request, ...$requests) : self
/**
* @param Request|Constraint|int $request
- * @param Response ...$responses
*/
- public function shouldHandle($request, ...$responses) : self
+ public function shouldHandle($request, Response ...$responses) : self
{
$this->shouldSend($request);
$this->willReceive(...$responses);
@@ -136,8 +131,25 @@ private function createHandler() : MockObject
? $handler->expects(TestCase::exactly($this->shouldBeCalledTimes))->method('handle')
: $handler->method('handle');
- if ($this->requests) {
- $handleMocker->withConsecutive(...array_chunk($this->requests, 1));
+ if (null !== $this->requests) {
+ $invocationCount = 0;
+ $requests = $this->requests;
+ $handleMocker->with(TestCase::callback(static function ($request) use (&$invocationCount, $requests) {
+ if (!isset($requests[$invocationCount])) {
+ ++$invocationCount;
+
+ return true;
+ }
+ $expected = $requests[$invocationCount++];
+
+ if ($expected instanceof Constraint) {
+ return (bool) $expected->evaluate($request, '', true);
+ }
+
+ $constraint = new \PHPUnit\Framework\Constraint\IsEqual($expected);
+
+ return (bool) $constraint->evaluate($request, '', true);
+ }));
}
if (1 === \count($this->responses)) {
@@ -181,8 +193,6 @@ private function createMock(string $originalClassName) : MockObject
return $this->testCase->getMockBuilder($originalClassName)
->disableOriginalConstructor()
->disableOriginalClone()
- ->disableArgumentCloning()
- ->disallowMockingUnknownTypes()
->getMock();
}
}
diff --git a/src/Client/TestDoubleFactory.php b/src/Client/TestDoubleFactory.php
old mode 100755
new mode 100644
diff --git a/src/Expectation/ExpressionContext/PreparedStatementCountContext.php b/src/Expectation/ExpressionContext/PreparedStatementCountContext.php
index 0d8d71d..ab69daa 100644
--- a/src/Expectation/ExpressionContext/PreparedStatementCountContext.php
+++ b/src/Expectation/ExpressionContext/PreparedStatementCountContext.php
@@ -52,11 +52,13 @@ public static function atMost(Client $client, int $count) : self
return new self($client, "new_count <= old_count + $count");
}
+ #[\Override]
public function getExpression() : string
{
return $this->expression;
}
+ #[\Override]
public function getValues() : array
{
if (null === $this->finalValue) {
diff --git a/src/Expectation/ExpressionContext/RequestCountContext.php b/src/Expectation/ExpressionContext/RequestCountContext.php
index b5f821a..20d4226 100644
--- a/src/Expectation/ExpressionContext/RequestCountContext.php
+++ b/src/Expectation/ExpressionContext/RequestCountContext.php
@@ -75,11 +75,13 @@ public static function atMost(Client $client, RequestCounter $requestCounter, st
return new self($client, $requestCounter, $requestName, "new_count <= old_count + $count");
}
+ #[\Override]
public function getExpression() : string
{
return $this->expression;
}
+ #[\Override]
public function getValues() : array
{
if (null === $this->finalValue) {
diff --git a/src/Expectation/ExpressionContext/RequestCounter.php b/src/Expectation/ExpressionContext/RequestCounter.php
index c020cea..a1cfee8 100644
--- a/src/Expectation/ExpressionContext/RequestCounter.php
+++ b/src/Expectation/ExpressionContext/RequestCounter.php
@@ -25,6 +25,7 @@ final class RequestCounter implements Middleware
*/
private $requestCount = [];
+ #[\Override]
public function process(Request $request, Handler $handler) : Response
{
$response = $handler->handle($request);
diff --git a/src/TestCase.php b/src/TestCase.php
index 941b81d..41bc960 100644
--- a/src/TestCase.php
+++ b/src/TestCase.php
@@ -14,13 +14,13 @@
namespace Tarantool\PhpUnit;
use PHPUnitExtras\TestCase as BaseTestCase;
-use Tarantool\PhpUnit\Annotation\Annotations;
+use Tarantool\PhpUnit\Attribute\Attributes;
use Tarantool\PhpUnit\Client\TestDoubleClient;
use Tarantool\PhpUnit\Expectation\Expectations;
abstract class TestCase extends BaseTestCase
{
- use Annotations;
+ use Attributes;
use Expectations;
use TestDoubleClient;
}
diff --git a/tests/Annotation/AnnotationExtension.php b/tests/Attribute/AttributeExtension.php
similarity index 59%
rename from tests/Annotation/AnnotationExtension.php
rename to tests/Attribute/AttributeExtension.php
index d2a9e83..58ed330 100755
--- a/tests/Annotation/AnnotationExtension.php
+++ b/tests/Attribute/AttributeExtension.php
@@ -11,13 +11,14 @@
declare(strict_types=1);
-namespace Tarantool\PhpUnit\Tests\Annotation;
+namespace Tarantool\PhpUnit\Tests\Attribute;
+use PHPUnit\Runner\Extension\ParameterCollection;
use Tarantool\Client\Client;
-use Tarantool\PhpUnit\Annotation\AnnotationExtension as BaseAnnotationExtension;
+use Tarantool\PhpUnit\Attribute\AttributeExtension as BaseAttributeExtension;
use Tarantool\PhpUnit\Client\TestDoubleClientBuilder;
-final class AnnotationExtension extends BaseAnnotationExtension
+final class AttributeExtension extends BaseAttributeExtension
{
public $resolvedDnsOrOptions;
@@ -27,4 +28,9 @@ protected function getClient() : Client
return TestDoubleClientBuilder::buildDummy();
}
+
+ public function doParseParameters(array $parameters) : void
+ {
+ $this->parseParameters(ParameterCollection::fromArray($parameters));
+ }
}
diff --git a/tests/Annotation/AnnotationExtensionTest.php b/tests/Attribute/AttributeExtensionTest.php
similarity index 58%
rename from tests/Annotation/AnnotationExtensionTest.php
rename to tests/Attribute/AttributeExtensionTest.php
index cf9c334..ef31179 100755
--- a/tests/Annotation/AnnotationExtensionTest.php
+++ b/tests/Attribute/AttributeExtensionTest.php
@@ -11,38 +11,40 @@
declare(strict_types=1);
-namespace Tarantool\PhpUnit\Tests\Annotation;
+namespace Tarantool\PhpUnit\Tests\Attribute;
use PHPUnit\Framework\TestCase;
+use Tarantool\PhpUnit\Attribute\Lua;
-final class AnnotationExtensionTest extends TestCase
+final class AttributeExtensionTest extends TestCase
{
- /**
- * @lua dummy_code_to_trigger_annotation_processing = true
- */
+ private function bootstrapExtension(string $method, array $parameters = []) : AttributeExtension
+ {
+ $ext = new AttributeExtension();
+ $ext->doParseParameters($parameters);
+ $ext->processTestAttributes(self::class, $method);
+
+ return $ext;
+ }
+
+ #[Lua('dummy_code_to_trigger_attribute_processing = true')]
public function testConstructorUsesDefaultDsn() : void
{
- $ext = new AnnotationExtension();
+ $ext = $this->bootstrapExtension(__FUNCTION__);
- $ext->executeBeforeTest(__METHOD__);
self::assertSame('tcp://127.0.0.1:3301', $ext->resolvedDnsOrOptions);
}
- /**
- * @lua dummy_code_to_trigger_annotation_processing = true
- */
+ #[Lua('dummy_code_to_trigger_attribute_processing = true')]
public function testConstructorUsesCustomDsn() : void
{
$dsn = 'tcp://tnt_foobar:3302';
- $ext = new AnnotationExtension($dsn);
+ $ext = $this->bootstrapExtension(__FUNCTION__, ['dsn' => $dsn]);
- $ext->executeBeforeTest(__METHOD__);
self::assertSame($dsn, $ext->resolvedDnsOrOptions);
}
- /**
- * @lua dummy_code_to_trigger_annotation_processing = true
- */
+ #[Lua('dummy_code_to_trigger_attribute_processing = true')]
public function testGetClientConfigNormalizesDsnString() : void
{
$hostname = 'tnt_foobar';
@@ -51,15 +53,12 @@ public function testGetClientConfigNormalizesDsnString() : void
$envPortName = 'tnt_phpunit_env_port_'.random_int(1, 1000);
putenv("$envHostName=$hostname");
putenv("$envPortName=$port");
- $ext = new AnnotationExtension("tcp://%env($envHostName)%:%env($envPortName)%");
+ $ext = $this->bootstrapExtension(__FUNCTION__, ['dsn' => "tcp://%env($envHostName)%:%env($envPortName)%"]);
- $ext->executeBeforeTest(__METHOD__);
self::assertSame("tcp://$hostname:$port", $ext->resolvedDnsOrOptions);
}
- /**
- * @lua dummy_code_to_trigger_annotation_processing = true
- */
+ #[Lua('dummy_code_to_trigger_attribute_processing = true')]
public function testGetClientConfigNormalizesOptionArray() : void
{
$hostname = 'tnt_foobar';
@@ -68,17 +67,16 @@ public function testGetClientConfigNormalizesOptionArray() : void
$envPortName = 'tnt_phpunit_env_port_'.random_int(1, 1000);
putenv("$envHostName=$hostname");
putenv("$envPortName=$port");
- $ext = new AnnotationExtension([
+ $ext = $this->bootstrapExtension(__FUNCTION__, [
'uri' => "tcp://%env($envHostName)%:%env($envPortName)%",
- 'socket_timeout' => 10,
- 'persistent' => true,
+ 'socket_timeout' => '10',
+ 'persistent' => '1',
]);
- $ext->executeBeforeTest(__METHOD__);
- self::assertSame([
+ self::assertEquals([
'uri' => "tcp://$hostname:$port",
- 'socket_timeout' => 10,
- 'persistent' => true,
+ 'socket_timeout' => '10',
+ 'persistent' => '1',
], $ext->resolvedDnsOrOptions);
}
}
diff --git a/tests/Annotation/Processor/LuaProcessorTest.php b/tests/Attribute/Processor/LuaProcessorTest.php
similarity index 59%
rename from tests/Annotation/Processor/LuaProcessorTest.php
rename to tests/Attribute/Processor/LuaProcessorTest.php
index 8fe890f..af61d98 100755
--- a/tests/Annotation/Processor/LuaProcessorTest.php
+++ b/tests/Attribute/Processor/LuaProcessorTest.php
@@ -11,11 +11,14 @@
declare(strict_types=1);
-namespace Tarantool\PhpUnit\Tests\Annotation\Processor;
+namespace Tarantool\PhpUnit\Tests\Attribute\Processor;
use PHPUnit\Framework\TestCase;
+use PHPUnitExtras\Attribute\PlaceholderResolver\PlaceholderResolver;
+use PHPUnitExtras\Attribute\Target;
use Tarantool\Client\Request\EvaluateRequest;
-use Tarantool\PhpUnit\Annotation\Processor\LuaProcessor;
+use Tarantool\PhpUnit\Attribute\Lua;
+use Tarantool\PhpUnit\Attribute\Processor\LuaProcessor;
use Tarantool\PhpUnit\Client\TestDoubleClient;
use Tarantool\PhpUnit\Client\TestDoubleFactory;
@@ -35,6 +38,16 @@ public function testProcessProcessesLuaExpression() : void
->build();
$processor = new LuaProcessor($mockClient);
- $processor->process($luaExpression);
+ $processor->process(new Lua($luaExpression), new Target(self::class), new class implements PlaceholderResolver {
+ public function getName() : string
+ {
+ return 'identity';
+ }
+
+ public function resolve(string $value, Target $target) : string
+ {
+ return $value;
+ }
+ });
}
}
diff --git a/tests/Annotation/Processor/SqlProcessorTest.php b/tests/Attribute/Processor/SqlProcessorTest.php
similarity index 61%
rename from tests/Annotation/Processor/SqlProcessorTest.php
rename to tests/Attribute/Processor/SqlProcessorTest.php
index 6c5a285..834035a 100755
--- a/tests/Annotation/Processor/SqlProcessorTest.php
+++ b/tests/Attribute/Processor/SqlProcessorTest.php
@@ -11,12 +11,15 @@
declare(strict_types=1);
-namespace Tarantool\PhpUnit\Tests\Annotation\Processor;
+namespace Tarantool\PhpUnit\Tests\Attribute\Processor;
use PHPUnit\Framework\TestCase;
+use PHPUnitExtras\Attribute\PlaceholderResolver\PlaceholderResolver;
+use PHPUnitExtras\Attribute\Target;
use Tarantool\Client\Keys;
use Tarantool\Client\Request\ExecuteRequest;
-use Tarantool\PhpUnit\Annotation\Processor\SqlProcessor;
+use Tarantool\PhpUnit\Attribute\Processor\SqlProcessor;
+use Tarantool\PhpUnit\Attribute\Sql;
use Tarantool\PhpUnit\Client\TestDoubleClient;
use Tarantool\PhpUnit\Client\TestDoubleFactory;
@@ -36,6 +39,16 @@ public function testProcessProcessesSqlStatement() : void
->build();
$processor = new SqlProcessor($mockClient);
- $processor->process($sqlStatement);
+ $processor->process(new Sql($sqlStatement), new Target(self::class), new class implements PlaceholderResolver {
+ public function getName() : string
+ {
+ return 'identity';
+ }
+
+ public function resolve(string $value, Target $target) : string
+ {
+ return $value;
+ }
+ });
}
}
diff --git a/tests/Annotation/Requirement/LuaConditionRequirementTest.php b/tests/Attribute/Requirement/IfLuaRequirementTest.php
similarity index 51%
rename from tests/Annotation/Requirement/LuaConditionRequirementTest.php
rename to tests/Attribute/Requirement/IfLuaRequirementTest.php
index 24096a2..cc0e6f4 100755
--- a/tests/Annotation/Requirement/LuaConditionRequirementTest.php
+++ b/tests/Attribute/Requirement/IfLuaRequirementTest.php
@@ -11,15 +11,18 @@
declare(strict_types=1);
-namespace Tarantool\PhpUnit\Tests\Annotation\Requirement;
+namespace Tarantool\PhpUnit\Tests\Attribute\Requirement;
use PHPUnit\Framework\TestCase;
+use PHPUnitExtras\Attribute\PlaceholderResolver\PlaceholderResolver;
+use PHPUnitExtras\Attribute\Target;
use Tarantool\Client\Request\EvaluateRequest;
-use Tarantool\PhpUnit\Annotation\Requirement\LuaConditionRequirement;
+use Tarantool\PhpUnit\Attribute\Requirement\IfLuaRequirement;
+use Tarantool\PhpUnit\Attribute\RequiresIfLua;
use Tarantool\PhpUnit\Client\TestDoubleClient;
use Tarantool\PhpUnit\Client\TestDoubleFactory;
-final class LuaConditionRequirementTest extends TestCase
+final class IfLuaRequirementTest extends TestCase
{
use TestDoubleClient;
@@ -34,9 +37,9 @@ public function testCheckPassesForTruthyExpression() : void
)
->build();
- $requirement = new LuaConditionRequirement($mockClient);
+ $requirement = new IfLuaRequirement($mockClient);
- self::assertNull($requirement->check($luaExpression));
+ self::assertNull($requirement->check(new RequiresIfLua($luaExpression), new Target(self::class), self::resolver()));
}
public function testCheckFailsForFalsyExpression() : void
@@ -50,9 +53,24 @@ public function testCheckFailsForFalsyExpression() : void
)
->build();
- $errorMessage = sprintf('"%s" is not evaluated to true', $luaExpression);
- $requirement = new LuaConditionRequirement($mockClient);
+ $errorMessage = \sprintf('"%s" is not evaluated to true', $luaExpression);
+ $requirement = new IfLuaRequirement($mockClient);
- self::assertSame($errorMessage, $requirement->check($luaExpression));
+ self::assertSame($errorMessage, $requirement->check(new RequiresIfLua($luaExpression), new Target(self::class), self::resolver()));
+ }
+
+ private static function resolver() : PlaceholderResolver
+ {
+ return new class implements PlaceholderResolver {
+ public function getName() : string
+ {
+ return 'identity';
+ }
+
+ public function resolve(string $value, Target $target) : string
+ {
+ return $value;
+ }
+ };
}
}
diff --git a/tests/Annotation/Requirement/TarantoolVersionRequirementTest.php b/tests/Attribute/Requirement/TarantoolRequirementTest.php
similarity index 71%
rename from tests/Annotation/Requirement/TarantoolVersionRequirementTest.php
rename to tests/Attribute/Requirement/TarantoolRequirementTest.php
index 57983dc..6095bdf 100755
--- a/tests/Annotation/Requirement/TarantoolVersionRequirementTest.php
+++ b/tests/Attribute/Requirement/TarantoolRequirementTest.php
@@ -11,21 +11,23 @@
declare(strict_types=1);
-namespace Tarantool\PhpUnit\Tests\Annotation\Requirement;
+namespace Tarantool\PhpUnit\Tests\Attribute\Requirement;
+use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
+use PHPUnitExtras\Attribute\PlaceholderResolver\PlaceholderResolver;
+use PHPUnitExtras\Attribute\Target;
use Tarantool\Client\Request\CallRequest;
-use Tarantool\PhpUnit\Annotation\Requirement\TarantoolVersionRequirement;
+use Tarantool\PhpUnit\Attribute\Requirement\TarantoolRequirement;
+use Tarantool\PhpUnit\Attribute\RequiresTarantool;
use Tarantool\PhpUnit\Client\TestDoubleClient;
use Tarantool\PhpUnit\Client\TestDoubleFactory;
-final class TarantoolVersionRequirementTest extends TestCase
+final class TarantoolRequirementTest extends TestCase
{
use TestDoubleClient;
- /**
- * @dataProvider provideCheckPassesForValidConstraintsData()
- */
+ #[DataProvider('provideCheckPassesForValidConstraintsData')]
public function testCheckPassesForValidConstraints(string $serverVersion, string $constraints) : void
{
$mockClient = $this->getTestDoubleClientBuilder()
@@ -34,12 +36,12 @@ public function testCheckPassesForValidConstraints(string $serverVersion, string
TestDoubleFactory::createResponseFromData([['version' => $serverVersion]]))
->build();
- $requirement = new TarantoolVersionRequirement($mockClient);
+ $requirement = new TarantoolRequirement($mockClient);
- self::assertNull($requirement->check($constraints));
+ self::assertNull($requirement->check(new RequiresTarantool($constraints), new Target(self::class), self::resolver()));
}
- public function provideCheckPassesForValidConstraintsData() : iterable
+ public static function provideCheckPassesForValidConstraintsData() : iterable
{
$v2_3_1_3 = '2.3.1-3-g878e2a42c';
@@ -95,9 +97,7 @@ public function provideCheckPassesForValidConstraintsData() : iterable
];
}
- /**
- * @dataProvider provideCheckFailsForInvalidConstraintsData()
- */
+ #[DataProvider('provideCheckFailsForInvalidConstraintsData')]
public function testCheckFailsForInvalidConstraints(string $serverVersion, string $constraints) : void
{
$mockClient = $this->getTestDoubleClientBuilder()
@@ -106,13 +106,13 @@ public function testCheckFailsForInvalidConstraints(string $serverVersion, strin
TestDoubleFactory::createResponseFromData([['version' => $serverVersion]]))
->build();
- $requirement = new TarantoolVersionRequirement($mockClient);
- $errorMessage = sprintf('Tarantool version %s is required', $constraints);
+ $requirement = new TarantoolRequirement($mockClient);
+ $errorMessage = \sprintf('Tarantool version %s is required', $constraints);
- self::assertSame($errorMessage, $requirement->check($constraints));
+ self::assertSame($errorMessage, $requirement->check(new RequiresTarantool($constraints), new Target(self::class), self::resolver()));
}
- public function provideCheckFailsForInvalidConstraintsData() : iterable
+ public static function provideCheckFailsForInvalidConstraintsData() : iterable
{
$v2_3_1_3 = '2.3.1-3-g878e2a42c';
@@ -148,4 +148,19 @@ public function provideCheckFailsForInvalidConstraintsData() : iterable
[$v2_3_1_3, '< 2'],
];
}
+
+ private static function resolver() : PlaceholderResolver
+ {
+ return new class implements PlaceholderResolver {
+ public function getName() : string
+ {
+ return 'identity';
+ }
+
+ public function resolve(string $value, Target $target) : string
+ {
+ return $value;
+ }
+ };
+ }
}
diff --git a/tests/Expectation/RequestExpectationsTest.php b/tests/Expectation/RequestExpectationsTest.php
index 3453ec6..160b194 100755
--- a/tests/Expectation/RequestExpectationsTest.php
+++ b/tests/Expectation/RequestExpectationsTest.php
@@ -13,6 +13,7 @@
namespace Tarantool\PhpUnit\Tests\Expectation;
+use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\ExpectationFailedException;
use PHPUnitExtras\TestCase;
use Tarantool\Client\Client;
@@ -33,7 +34,7 @@ protected function getClient() : Client
{
// increase values for eval requests
// to eliminate RequestCounter's count adjustments
- if ('Eval' === $this->getProvidedData()[0]) {
+ if ('Eval' === $this->providedData()[0]) {
++$this->oldValue;
$this->newValue += 2;
}
@@ -47,7 +48,7 @@ protected function getClient() : Client
->build();
}
- public function provideRequestNames() : iterable
+ public static function provideRequestNames() : iterable
{
return [
['Auth'],
@@ -63,9 +64,7 @@ public function provideRequestNames() : iterable
];
}
- /**
- * @dataProvider provideRequestNames
- */
+ #[DataProvider('provideRequestNames')]
public function testExpectToBeCalledSucceeds(string $requestName) : void
{
$this->oldValue = 1;
@@ -74,9 +73,7 @@ public function testExpectToBeCalledSucceeds(string $requestName) : void
$this->verifyExpectations();
}
- /**
- * @dataProvider provideRequestNames
- */
+ #[DataProvider('provideRequestNames')]
public function testExpectToBeCalledFails(string $requestName) : void
{
$this->oldValue = 1;
@@ -87,9 +84,7 @@ public function testExpectToBeCalledFails(string $requestName) : void
$this->verifyExpectations();
}
- /**
- * @dataProvider provideRequestNames
- */
+ #[DataProvider('provideRequestNames')]
public function testExpectToBeCalledAtLeastSucceeds(string $requestName) : void
{
$this->oldValue = 1;
@@ -98,9 +93,7 @@ public function testExpectToBeCalledAtLeastSucceeds(string $requestName) : void
$this->verifyExpectations();
}
- /**
- * @dataProvider provideRequestNames
- */
+ #[DataProvider('provideRequestNames')]
public function testExpectToBeCalledAtLeastFails(string $requestName) : void
{
$this->oldValue = 1;
@@ -111,9 +104,7 @@ public function testExpectToBeCalledAtLeastFails(string $requestName) : void
$this->verifyExpectations();
}
- /**
- * @dataProvider provideRequestNames
- */
+ #[DataProvider('provideRequestNames')]
public function testExpectToBeCalledAtMostSucceeds(string $requestName) : void
{
$this->oldValue = 1;
@@ -122,9 +113,7 @@ public function testExpectToBeCalledAtMostSucceeds(string $requestName) : void
$this->verifyExpectations();
}
- /**
- * @dataProvider provideRequestNames
- */
+ #[DataProvider('provideRequestNames')]
public function testExpectToBeCalledAtMostFails(string $requestName) : void
{
$this->oldValue = 1;
@@ -135,9 +124,7 @@ public function testExpectToBeCalledAtMostFails(string $requestName) : void
$this->verifyExpectations();
}
- /**
- * @dataProvider provideRequestNames
- */
+ #[DataProvider('provideRequestNames')]
public function testExpectToBeCalledOnceSucceeds(string $requestName) : void
{
$this->oldValue = 1;
@@ -146,9 +133,7 @@ public function testExpectToBeCalledOnceSucceeds(string $requestName) : void
$this->verifyExpectations();
}
- /**
- * @dataProvider provideRequestNames
- */
+ #[DataProvider('provideRequestNames')]
public function testExpectToBeCalledOnceFails(string $requestName) : void
{
$this->oldValue = 1;
@@ -159,9 +144,7 @@ public function testExpectToBeCalledOnceFails(string $requestName) : void
$this->verifyExpectations();
}
- /**
- * @dataProvider provideRequestNames
- */
+ #[DataProvider('provideRequestNames')]
public function testExpectToBeNeverCalledSucceeds(string $requestName) : void
{
$this->oldValue = 1;
@@ -170,9 +153,7 @@ public function testExpectToBeNeverCalledSucceeds(string $requestName) : void
$this->verifyExpectations();
}
- /**
- * @dataProvider provideRequestNames
- */
+ #[DataProvider('provideRequestNames')]
public function testExpectToBeNeverCalledFails(string $requestName) : void
{
$this->oldValue = 1;
@@ -183,9 +164,7 @@ public function testExpectToBeNeverCalledFails(string $requestName) : void
$this->verifyExpectations();
}
- /**
- * @dataProvider provideRequestNames
- */
+ #[DataProvider('provideRequestNames')]
public function testExpectToBeCalledAtLeastOnceSucceeds(string $requestName) : void
{
$this->oldValue = 1;
@@ -194,9 +173,7 @@ public function testExpectToBeCalledAtLeastOnceSucceeds(string $requestName) : v
$this->verifyExpectations();
}
- /**
- * @dataProvider provideRequestNames
- */
+ #[DataProvider('provideRequestNames')]
public function testExpectToBeCalledAtLeastOnceFails(string $requestName) : void
{
$this->oldValue = 1;
@@ -207,9 +184,7 @@ public function testExpectToBeCalledAtLeastOnceFails(string $requestName) : void
$this->verifyExpectations();
}
- /**
- * @dataProvider provideRequestNames
- */
+ #[DataProvider('provideRequestNames')]
public function testExpectToBeCalledAtMostOnceSucceeds(string $requestName) : void
{
$this->oldValue = 1;
@@ -218,9 +193,7 @@ public function testExpectToBeCalledAtMostOnceSucceeds(string $requestName) : vo
$this->verifyExpectations();
}
- /**
- * @dataProvider provideRequestNames
- */
+ #[DataProvider('provideRequestNames')]
public function testExpectToBeCalledAtMostOnceFails(string $requestName) : void
{
$this->oldValue = 1;