From 3bedb9719086e351bfcdc7b91b3d39ebebd4bd9b Mon Sep 17 00:00:00 2001 From: Demin Yin Date: Sat, 29 Aug 2026 12:33:19 -0700 Subject: [PATCH 1/2] Replace PHPUnit with deminy/counit for unit tests Switch the test runner from a hand-rolled coroutine wrapper around PHPUnit (tests/co-phpunit) to deminy/counit, which provides the same per-test Swoole coroutine execution as a maintained, versioned dependency with more correct reporting (accurate timing/assertion counts and late-failure handling via CounitExtension). - composer.json: require-dev deminy/counit ^0.3 (matches the existing phpunit/phpunit ~8.0/~9.0 usage) instead of phpunit/phpunit directly; "test" script now runs ./vendor/bin/counit. - phpunit.xml.dist: register Deminy\Counit\CounitExtension. - All test classes now extend Deminy\Counit\TestCase instead of PHPUnit\Framework\TestCase; the four classes overriding setUpBeforeClass()/tearDownAfterClass() call the parent methods, as required by TestCase. - Remove tests/co-phpunit, superseded by vendor/bin/counit. Verified: full suite (49 tests, incl. live-broker WebSocket tests) and static analysis (phpstan) both pass. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_017FqMMVcHcgGongoKm1WrfX --- composer.json | 4 +-- phpunit.xml.dist | 3 ++ tests/Unit/ClientConfigTest.php | 2 +- tests/Unit/ClientTest.php | 2 +- tests/Unit/MessageTest.php | 2 +- tests/Unit/ToolsTest.php | 2 +- tests/V3/PacketTest.php | 4 ++- tests/V3/WebSocketTest.php | 4 ++- tests/V5/PacketTest.php | 4 ++- tests/V5/WebSocketTest.php | 4 ++- tests/co-phpunit | 64 --------------------------------- 11 files changed, 21 insertions(+), 74 deletions(-) delete mode 100755 tests/co-phpunit diff --git a/composer.json b/composer.json index 6ae2bff..4667b29 100644 --- a/composer.json +++ b/composer.json @@ -25,8 +25,8 @@ "ext-mbstring": "*" }, "require-dev": { + "deminy/counit": "^0.3", "friendsofphp/php-cs-fixer": "^3.0", - "phpunit/phpunit": "^8.5", "swoole/ide-helper": ">=4.4.20", "simps/mqtt-cli": "*", "phpstan/phpstan": "^2.0" @@ -50,7 +50,7 @@ "scripts": { "cs-check": "/usr/bin/env php ./vendor/bin/php-cs-fixer fix --dry-run", "cs-fix": "/usr/bin/env php ./vendor/bin/php-cs-fixer fix", - "test": "./tests/co-phpunit --colors=always", + "test": "./vendor/bin/counit --colors=always", "analyse": "phpstan analyse --memory-limit 4096M -c phpstan.neon" }, "extra": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index adba018..d2b0fca 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -8,4 +8,7 @@ + + + diff --git a/tests/Unit/ClientConfigTest.php b/tests/Unit/ClientConfigTest.php index 58602d1..6723371 100644 --- a/tests/Unit/ClientConfigTest.php +++ b/tests/Unit/ClientConfigTest.php @@ -12,7 +12,7 @@ */ namespace SimpsTest\MQTT\Unit; -use PHPUnit\Framework\TestCase; +use Deminy\Counit\TestCase; use Simps\MQTT\Client; use Simps\MQTT\Config\ClientConfig; use Simps\MQTT\Protocol\ProtocolInterface; diff --git a/tests/Unit/ClientTest.php b/tests/Unit/ClientTest.php index b413d33..8283036 100644 --- a/tests/Unit/ClientTest.php +++ b/tests/Unit/ClientTest.php @@ -12,7 +12,7 @@ */ namespace SimpsTest\MQTT\Unit; -use PHPUnit\Framework\TestCase; +use Deminy\Counit\TestCase; use Simps\MQTT\Client as MQTTClient; use Simps\MQTT\Exception\ConnectException; use Simps\MQTT\Exception\ProtocolException; diff --git a/tests/Unit/MessageTest.php b/tests/Unit/MessageTest.php index f1178b5..95b7041 100644 --- a/tests/Unit/MessageTest.php +++ b/tests/Unit/MessageTest.php @@ -12,7 +12,7 @@ */ namespace SimpsTest\MQTT\Unit; -use PHPUnit\Framework\TestCase; +use Deminy\Counit\TestCase; use Simps\MQTT\Message; use Simps\MQTT\Protocol\ProtocolInterface; use Simps\MQTT\Protocol\Types; diff --git a/tests/Unit/ToolsTest.php b/tests/Unit/ToolsTest.php index 9747761..1692eec 100644 --- a/tests/Unit/ToolsTest.php +++ b/tests/Unit/ToolsTest.php @@ -12,7 +12,7 @@ */ namespace SimpsTest\MQTT\Unit; -use PHPUnit\Framework\TestCase; +use Deminy\Counit\TestCase; use Simps\MQTT\Exception\InvalidArgumentException; use Simps\MQTT\Protocol\ProtocolInterface; use Simps\MQTT\Tools\Debug; diff --git a/tests/V3/PacketTest.php b/tests/V3/PacketTest.php index c6123af..a07e186 100644 --- a/tests/V3/PacketTest.php +++ b/tests/V3/PacketTest.php @@ -12,7 +12,7 @@ */ namespace SimpsTest\MQTT\V3; -use PHPUnit\Framework\TestCase; +use Deminy\Counit\TestCase; use Simps\MQTT\Client; use Simps\MQTT\Exception\ProtocolException; use Simps\MQTT\Hex\ReasonCode; @@ -30,6 +30,7 @@ class PacketTest extends TestCase public static function setUpBeforeClass(): void { + parent::setUpBeforeClass(); self::$topic = 'testtopic/simps-' . rand(100, 999); self::$client = new Client(SIMPS_MQTT_REMOTE_HOST, SIMPS_MQTT_PORT, getTestConnectConfig()); } @@ -38,6 +39,7 @@ public static function tearDownAfterClass(): void { self::$topic = ''; self::$client = null; + parent::tearDownAfterClass(); } public function testConnect() diff --git a/tests/V3/WebSocketTest.php b/tests/V3/WebSocketTest.php index a707b2f..4b14ae9 100644 --- a/tests/V3/WebSocketTest.php +++ b/tests/V3/WebSocketTest.php @@ -12,7 +12,7 @@ */ namespace SimpsTest\MQTT\V3; -use PHPUnit\Framework\TestCase; +use Deminy\Counit\TestCase; use Simps\MQTT\Exception\ProtocolException; use Simps\MQTT\Hex\ReasonCode; use Simps\MQTT\Protocol\Types; @@ -30,6 +30,7 @@ class WebSocketTest extends TestCase public static function setUpBeforeClass(): void { + parent::setUpBeforeClass(); self::$topic = 'testtopic/simps-' . rand(100, 999); self::$client = new WebSocketClient(SIMPS_MQTT_REMOTE_HOST, SIMPS_MQTT_OVER_WEBSOCKET_PORT, getTestConnectConfig()); } @@ -38,6 +39,7 @@ public static function tearDownAfterClass(): void { self::$topic = ''; self::$client = null; + parent::tearDownAfterClass(); } public function testConnect() diff --git a/tests/V5/PacketTest.php b/tests/V5/PacketTest.php index 89a45e6..028e024 100644 --- a/tests/V5/PacketTest.php +++ b/tests/V5/PacketTest.php @@ -12,7 +12,7 @@ */ namespace SimpsTest\MQTT\V5; -use PHPUnit\Framework\TestCase; +use Deminy\Counit\TestCase; use Simps\MQTT\Client; use Simps\MQTT\Exception\ProtocolException; use Simps\MQTT\Hex\ReasonCode; @@ -31,6 +31,7 @@ class PacketTest extends TestCase public static function setUpBeforeClass(): void { + parent::setUpBeforeClass(); self::$topic = 'testtopic/simps-' . rand(100, 999); self::$client = new Client(SIMPS_MQTT_REMOTE_HOST, SIMPS_MQTT_PORT, getTestMQTT5ConnectConfig()); } @@ -39,6 +40,7 @@ public static function tearDownAfterClass(): void { self::$topic = ''; self::$client = null; + parent::tearDownAfterClass(); } public function testConnect() diff --git a/tests/V5/WebSocketTest.php b/tests/V5/WebSocketTest.php index 4c48575..3ef93c5 100644 --- a/tests/V5/WebSocketTest.php +++ b/tests/V5/WebSocketTest.php @@ -12,7 +12,7 @@ */ namespace SimpsTest\MQTT\V5; -use PHPUnit\Framework\TestCase; +use Deminy\Counit\TestCase; use Simps\MQTT\Exception\ProtocolException; use Simps\MQTT\Hex\ReasonCode; use Simps\MQTT\Protocol\Types; @@ -31,6 +31,7 @@ class WebSocketTest extends TestCase public static function setUpBeforeClass(): void { + parent::setUpBeforeClass(); self::$topic = 'testtopic/simps-' . rand(100, 999); self::$client = new WebSocketClient(SIMPS_MQTT_REMOTE_HOST, SIMPS_MQTT_OVER_WEBSOCKET_PORT, getTestMQTT5ConnectConfig()); } @@ -39,6 +40,7 @@ public static function tearDownAfterClass(): void { self::$topic = ''; self::$client = null; + parent::tearDownAfterClass(); } public function testConnect() diff --git a/tests/co-phpunit b/tests/co-phpunit deleted file mode 100755 index b22aa57..0000000 --- a/tests/co-phpunit +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env php - SWOOLE_HOOK_ALL, - 'exit_condition' => function(){ - return Swoole\Coroutine::stats()['coroutine_num'] === 0; - } -]); -Swoole\Coroutine\Run(function () use (&$code) { - if (version_compare('7.1.0', PHP_VERSION, '>')) { - fwrite( - STDERR, - sprintf( - 'This version of PHPUnit is supported on PHP 7.1 and PHP 7.2.' . PHP_EOL . - 'You are using PHP %s (%s).' . PHP_EOL, - PHP_VERSION, - PHP_BINARY - ) - ); - - die(1); - } - - if (! ini_get('date.timezone')) { - ini_set('date.timezone', 'UTC'); - } - - foreach ([__DIR__ . '/../../autoload.php', __DIR__ . '/../vendor/autoload.php', __DIR__ . '/vendor/autoload.php'] as $file) { - if (file_exists($file)) { - define('PHPUNIT_COMPOSER_INSTALL', $file); - - break; - } - } - - unset($file); - - if (! defined('PHPUNIT_COMPOSER_INSTALL')) { - fwrite( - STDERR, - 'You need to set up the project dependencies using Composer:' . PHP_EOL . PHP_EOL . - ' composer install' . PHP_EOL . PHP_EOL . - 'You can learn all about Composer on https://getcomposer.org/.' . PHP_EOL - ); - - die(1); - } - - $options = getopt('', ['prepend:']); - - if (isset($options['prepend'])) { - require $options['prepend']; - } - - unset($options); - - require PHPUNIT_COMPOSER_INSTALL; - - $code = PHPUnit\TextUI\Command::main(false); -}); - -exit($code); From 383912b4970a376f2e9ecf3560603d266dced813 Mon Sep 17 00:00:00 2001 From: Demin Yin Date: Sat, 29 Aug 2026 12:58:33 -0700 Subject: [PATCH 2/2] Fix php-cs-fixer CI failure by pinning version and fixing config composer.json pinned friendsofphp/php-cs-fixer to an open ^3.0 range with no committed composer.lock, so CI always resolved to whatever was newest on Packagist. That silently drifted the tool from 2021's ~3.x to the current 3.95.23, which broke cs-check two ways: - '@Symfony'/'@PhpCsFixer' rule-set aliases absorbed many new fixers over that span, so the currently-formatted code now differs from what the latest version wants in 51 of 53 files. - 'increment_style' => [] was valid/no-op on old cs-fixer but is rejected by newer versions ("Configuration must be an array and may not be empty"), which is the crash CI actually hit. Fix: - .php-cs-fixer.php: set increment_style explicitly to ['style' => 'post'], matching the codebase's existing postfix (++/--) convention throughout, instead of the invalid empty array. - src/Tools/UnPackTool.php: fix the one spot using prefix increment (++$headBytes), inconsistent with the rest of the codebase, which the corrected rule now catches. - composer.json: pin friendsofphp/php-cs-fixer to the exact 3.7.0 (bisected under PHP 8.1 in Docker, matching the CI job's runtime, to confirm it's a version the current source needs zero changes against) instead of the open ^3.0 range, so this can't silently drift and break again on a future cs-fixer release. Verified with a from-scratch composer install (no cached vendor/ composer.lock) under PHP 8.1 in Docker: cs-check exits 0 with no files needing fixes, phpstan analyse reports no errors, and the counit unit suite passes. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_017FqMMVcHcgGongoKm1WrfX --- .php-cs-fixer.php | 4 +++- composer.json | 2 +- src/Tools/UnPackTool.php | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 722cf2b..1a89547 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -96,7 +96,9 @@ 'phpdoc_separation' => false, 'phpdoc_summary' => false, 'single_quote' => true, - 'increment_style' => [], + 'increment_style' => [ + 'style' => 'post', + ], 'standardize_increment' => false, 'standardize_not_equals' => true, 'multiline_comment_opening_closing' => true, diff --git a/composer.json b/composer.json index 4667b29..ef62f94 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ }, "require-dev": { "deminy/counit": "^0.3", - "friendsofphp/php-cs-fixer": "^3.0", + "friendsofphp/php-cs-fixer": "3.7.0", "swoole/ide-helper": ">=4.4.20", "simps/mqtt-cli": "*", "phpstan/phpstan": "^2.0" diff --git a/src/Tools/UnPackTool.php b/src/Tools/UnPackTool.php index 3896dab..45f2bd7 100644 --- a/src/Tools/UnPackTool.php +++ b/src/Tools/UnPackTool.php @@ -86,7 +86,7 @@ protected static function getRemainingLength(string $data, ?int &$headBytes): in $digit = ord($data[$headBytes]); $value += ($digit & 127) * $multiplier; $multiplier *= 128; - ++$headBytes; + $headBytes++; } while (($digit & 128) != 0); return $value;