From 8e7d69be11d0cf3feb6e0c959d5a21d958b9f9c2 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Fri, 9 Oct 2026 23:13:58 +0400 Subject: [PATCH 1/2] feat: require PHP 8.2 build: bump vimeo/psalm to ^6 || ^7 Testo needs PHP 8.2. Psalm 5 does not install on PHP above 8.3, which kept the security audit on PHP 8.5 red. The new Psalm reports for #[\Override] (a PHP 8.3 attribute) and an int|float operand in the TTL conversion are suppressed in psalm.xml until the static analysis pass. Assisted-By: Claude Opus 5.5 --- README.md | 2 +- composer.json | 4 ++-- psalm.xml | 10 ++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1e078c5..e868ff4 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ processes connected to the RoadRunner server. Make sure that your server is configured with following PHP version and extensions: -- PHP 8.1+ +- PHP 8.2+ ### Installation diff --git a/composer.json b/composer.json index 02bff03..9f9298e 100644 --- a/composer.json +++ b/composer.json @@ -44,7 +44,7 @@ } ], "require": { - "php": "^8.1", + "php": "^8.2", "ramsey/uuid": "^4.7", "roadrunner-php/roadrunner-api-dto": "^1.0", "spiral/goridge": "^4.0" @@ -52,7 +52,7 @@ "require-dev": { "mockery/mockery": "^1.5", "phpunit/phpunit": "^10.0", - "vimeo/psalm": "^5.9" + "vimeo/psalm": "^6 || ^7" }, "autoload": { "psr-4": { diff --git a/psalm.xml b/psalm.xml index 7e98f69..e1f086b 100644 --- a/psalm.xml +++ b/psalm.xml @@ -13,4 +13,14 @@ + + + + + + + + + + From 4ba86df7005a1fb7505156d43674e3e081511938 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Fri, 9 Oct 2026 23:13:59 +0400 Subject: [PATCH 2/2] test: migrate from PHPUnit to Testo ci: run tests via the shared testo workflow Mockery stays as the mocking library: Double requires PHP 8.3. Push triggers now target 1.x, since the old *.* pattern never matched the default branch. Assisted-By: Claude Opus 5.5 --- .gitattributes | 2 +- .github/workflows/phpunit.yml | 16 --------- .github/workflows/psalm.yml | 2 +- .github/workflows/testo.yml | 16 +++++++++ .gitignore | 1 - composer.json | 7 ++-- phpunit.xml | 34 ------------------- testo.php | 20 ++++++++++++ tests/src/LockTest.php | 61 ++++++++++++++++------------------- tests/src/TestCase.php | 10 ------ 10 files changed, 69 insertions(+), 100 deletions(-) delete mode 100644 .github/workflows/phpunit.yml create mode 100644 .github/workflows/testo.yml delete mode 100644 phpunit.xml create mode 100644 testo.php delete mode 100644 tests/src/TestCase.php diff --git a/.gitattributes b/.gitattributes index b7404a3..9365305 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,7 @@ /.github export-ignore /.gitattributes export-ignore /.gitignore export-ignore -/phpunit.xml.dist export-ignore +/testo.php export-ignore /tests export-ignore /.editorconfig export-ignore /.php_cs.dist.php export-ignore diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml deleted file mode 100644 index 3b86822..0000000 --- a/.github/workflows/phpunit.yml +++ /dev/null @@ -1,16 +0,0 @@ -on: - pull_request: null - push: - branches: - - '*.*' - -name: phpunit - -jobs: - phpunit: - uses: spiral/gh-actions/.github/workflows/phpunit.yml@master - with: - os: >- - ['ubuntu-latest'] - stability: >- - ['prefer-lowest', 'prefer-stable'] diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml index eea1d20..901c593 100644 --- a/.github/workflows/psalm.yml +++ b/.github/workflows/psalm.yml @@ -2,7 +2,7 @@ on: pull_request: null push: branches: - - '*.*' + - '1.x' name: static analysis diff --git a/.github/workflows/testo.yml b/.github/workflows/testo.yml new file mode 100644 index 0000000..174bb5a --- /dev/null +++ b/.github/workflows/testo.yml @@ -0,0 +1,16 @@ +on: + pull_request: null + push: + branches: + - '1.x' + +name: testo + +jobs: + testo: + uses: spiral/gh-actions/.github/workflows/testo.yml@master + with: + os: >- + ['ubuntu-latest'] + dependencies: >- + ['lowest', 'highest'] diff --git a/.gitignore b/.gitignore index 1a6ed30..78d21b7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ .idea .php_cs .php_cs.cache -.phpunit.result.cache build composer.lock coverage diff --git a/composer.json b/composer.json index 9f9298e..1a8b7da 100644 --- a/composer.json +++ b/composer.json @@ -50,8 +50,9 @@ "spiral/goridge": "^4.0" }, "require-dev": { - "mockery/mockery": "^1.5", - "phpunit/phpunit": "^10.0", + "mockery/mockery": "^1.6", + "testo/bridge-mockery": "^0.1.2", + "testo/testo": "^0.10.55", "vimeo/psalm": "^6 || ^7" }, "autoload": { @@ -65,7 +66,7 @@ } }, "scripts": { - "test": "vendor/bin/phpunit", + "test": "vendor/bin/testo", "psalm": "vendor/bin/psalm --config=psalm.xml ./src --show-info=true" }, "config": { diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100644 index 6b82af7..0000000 --- a/phpunit.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - tests - - - - - ./src - - - - - - - - - - - diff --git a/testo.php b/testo.php new file mode 100644 index 0000000..1d387a7 --- /dev/null +++ b/testo.php @@ -0,0 +1,20 @@ +rpc = m::mock(RPCInterface::class); $this->rpc->shouldReceive('withCodec') @@ -34,9 +39,7 @@ protected function setUp(): void $this->lock = new Lock($this->rpc, $this->idGenerator); } - /** - * @dataProvider lockTypeDataProvider - */ + #[DataProvider('lockTypeDataProvider')] public function testLock( string $method, string $callMethod, @@ -69,15 +72,13 @@ public function testLock( $result = $this->lock->$method(resource: 'resource', id: $id, ttl: $ttl, waitTTL: $wait); if ($expectedResult) { - $this->assertSame(($id === null ? 'some-id' : $id), $result); + Assert::same($result, ($id === null ? 'some-id' : $id)); } else { - $this->assertFalse($result); + Assert::false($result); } } - /** - * @dataProvider resultDataProvider - */ + #[DataProvider('resultDataProvider')] public function testRelease(bool $result): void { $this->rpc->shouldReceive('call') @@ -90,12 +91,10 @@ public function testRelease(bool $result): void }) ->andReturn(new Response(['ok' => $result])); - $this->assertSame($result, $this->lock->release('resource', 'some-id')); + Assert::same($this->lock->release('resource', 'some-id'), $result); } - /** - * @dataProvider resultDataProvider - */ + #[DataProvider('resultDataProvider')] public function testForceRelease(bool $result): void { $this->rpc->shouldReceive('call') @@ -108,12 +107,10 @@ public function testForceRelease(bool $result): void }) ->andReturn(new Response(['ok' => $result])); - $this->assertSame($result, $this->lock->forceRelease('resource')); + Assert::same($this->lock->forceRelease('resource'), $result); } - /** - * @dataProvider resultDataProvider - */ + #[DataProvider('resultDataProvider')] public function testExists(bool $result): void { $this->rpc->shouldReceive('call') @@ -126,12 +123,10 @@ public function testExists(bool $result): void }) ->andReturn(new Response(['ok' => $result])); - $this->assertSame($result, $this->lock->exists('resource')); + Assert::same($this->lock->exists('resource'), $result); } - /** - * @dataProvider updateTTLDataProvider - */ + #[DataProvider('updateTTLDataProvider')] public function testUpdateTTL($ttl, int $expectedTtl, bool $result): void { $this->rpc->shouldReceive('call') @@ -145,12 +140,10 @@ public function testUpdateTTL($ttl, int $expectedTtl, bool $result): void }) ->andReturn(new Response(['ok' => $result])); - $this->assertSame($result, $this->lock->updateTTL('resource', 'some-id', $ttl)); + Assert::same($this->lock->updateTTL('resource', 'some-id', $ttl), $result); } - /** - * @dataProvider resultDataProvider - */ + #[DataProvider('resultDataProvider')] public function testExistsWithId(bool $result): void { $this->rpc->shouldReceive('call') @@ -163,7 +156,7 @@ public function testExistsWithId(bool $result): void }) ->andReturn(new Response(['ok' => $result])); - $this->assertSame($result, $this->lock->exists('resource', 'some-id')); + Assert::same($this->lock->exists('resource', 'some-id'), $result); } public static function lockTypeDataProvider(): \Generator @@ -220,33 +213,33 @@ public static function resultDataProvider(): \Traversable yield [false]; } + #[ExpectException(\LogicException::class)] public function testLockNegativeTtl(): void { - self::expectException(\LogicException::class); $this->lock->lock('resource', 'uuid', -300); } + #[ExpectException(\LogicException::class)] public function testLockNegativeWaitTtl(): void { - self::expectException(\LogicException::class); $this->lock->lock('resource', 'uuid', 0, -300); } + #[ExpectException(\LogicException::class)] public function testLockReadNegativeTtl(): void { - self::expectException(\LogicException::class); $this->lock->lock('resource', 'uuid', -300); } + #[ExpectException(\LogicException::class)] public function testLockReadNegativeWaitTtl(): void { - self::expectException(\LogicException::class); $this->lock->lockRead('resource', 'uuid', 0, -300); } + #[ExpectException(\LogicException::class)] public function testUpdateNegativeWaitTtl(): void { - self::expectException(\LogicException::class); $this->lock->updateTTL('resource', 'uuid', -300); } } diff --git a/tests/src/TestCase.php b/tests/src/TestCase.php deleted file mode 100644 index 08e12bb..0000000 --- a/tests/src/TestCase.php +++ /dev/null @@ -1,10 +0,0 @@ -