From 46df02dc286dc306fbb8162d47402d026addfba1 Mon Sep 17 00:00:00 2001 From: Lazizbek Ergashev Date: Wed, 26 Aug 2026 13:36:49 +0500 Subject: [PATCH] fix: key Tia worker partials per process to survive batch recycling (#1782) * fix: key Tia worker partials per process to survive batch recycling * test(tia): refresh visual snapshots for the worker token test --------- Co-authored-by: Punyapal Shah <53343069+MrPunyapal@users.noreply.github.com> --- src/Plugins/Tia.php | 3 +- tests/.snapshots/success.txt | 6 +++- tests/Unit/Plugins/Tia/WorkerToken.php | 39 ++++++++++++++++++++++++++ tests/Visual/Parallel.php | 2 +- 4 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 tests/Unit/Plugins/Tia/WorkerToken.php diff --git a/src/Plugins/Tia.php b/src/Plugins/Tia.php index 3e03f156..be761fc7 100644 --- a/src/Plugins/Tia.php +++ b/src/Plugins/Tia.php @@ -1505,7 +1505,8 @@ final class Tia implements AddsOutput, HandlesArguments, HandlesOriginalArgument private function workerToken(): string { - $raw = $_SERVER['TEST_TOKEN'] ?? $_ENV['TEST_TOKEN'] ?? null; + $raw = $_SERVER['UNIQUE_TEST_TOKEN'] ?? $_ENV['UNIQUE_TEST_TOKEN'] + ?? $_SERVER['TEST_TOKEN'] ?? $_ENV['TEST_TOKEN'] ?? null; $token = is_scalar($raw) ? (string) $raw : (string) getmypid(); $token = preg_replace('/[^A-Za-z0-9_-]/', '', $token); diff --git a/tests/.snapshots/success.txt b/tests/.snapshots/success.txt index d845a701..deecf6f3 100644 --- a/tests/.snapshots/success.txt +++ b/tests/.snapshots/success.txt @@ -2061,6 +2061,10 @@ ✓ it accepts a page directory candidate only when it matches the casing on disk with ('wrong parent') ✓ it accepts a page directory candidate only when it matches the casing on disk with ('absent') + PASS Tests\Unit\Plugins\Tia\WorkerToken + ✓ prefers the per-process UNIQUE_TEST_TOKEN over the per-slot TEST_TOKEN, so two workers recycled into the same slot get different tokens + ✓ falls back to TEST_TOKEN when UNIQUE_TEST_TOKEN is absent + PASS Tests\Unit\Preset ✓ preset invalid name ✓ preset → myFramework @@ -2251,4 +2255,4 @@ ✓ pass with dataset with ('my-datas-set-value') ✓ within describe → pass with dataset with ('my-datas-set-value') - Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 40 todos, 35 skipped, 1596 passed (3481 assertions) \ No newline at end of file + Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 40 todos, 35 skipped, 1598 passed (3485 assertions) \ No newline at end of file diff --git a/tests/Unit/Plugins/Tia/WorkerToken.php b/tests/Unit/Plugins/Tia/WorkerToken.php new file mode 100644 index 00000000..7d36623e --- /dev/null +++ b/tests/Unit/Plugins/Tia/WorkerToken.php @@ -0,0 +1,39 @@ +newInstanceWithoutConstructor(); + + return new ReflectionMethod($tia, 'workerToken')->invoke($tia); +} + +beforeEach(function (): void { + unset( + $_SERVER['TEST_TOKEN'], + $_ENV['TEST_TOKEN'], + $_SERVER['UNIQUE_TEST_TOKEN'], + $_ENV['UNIQUE_TEST_TOKEN'], + ); +}); + +test('prefers the per-process UNIQUE_TEST_TOKEN over the per-slot TEST_TOKEN, so two workers recycled into the same slot get different tokens', function (): void { + $_SERVER['TEST_TOKEN'] = '2'; + + $_SERVER['UNIQUE_TEST_TOKEN'] = '2_6a690d236824c'; + $processA = tiaWorkerToken(); + + $_SERVER['UNIQUE_TEST_TOKEN'] = '2_9f31be04117a'; + $processB = tiaWorkerToken(); + + expect($processA)->toBe('2_6a690d236824c') + ->and($processB)->toBe('2_9f31be04117a') + ->and($processA)->not->toBe($processB); +}); + +test('falls back to TEST_TOKEN when UNIQUE_TEST_TOKEN is absent', function (): void { + $_SERVER['TEST_TOKEN'] = '3'; + + expect(tiaWorkerToken())->toBe('3'); +}); diff --git a/tests/Visual/Parallel.php b/tests/Visual/Parallel.php index fa4af783..688475f7 100644 --- a/tests/Visual/Parallel.php +++ b/tests/Visual/Parallel.php @@ -20,7 +20,7 @@ test('parallel', function () use ($run): void { $output = $run('--exclude-group=integration'); $output = implode("\n", array_slice(explode("\n", (string) $output), -10)); - $expected = '2 deprecated, 4 warnings, 5 incomplete, 3 notices, 40 todos, 27 skipped, 1578 passed (3426 assertions)'; + $expected = '2 deprecated, 4 warnings, 5 incomplete, 3 notices, 40 todos, 27 skipped, 1580 passed (3430 assertions)'; expect($output) ->toContain("Tests: {$expected}")