From 0d990c090a6b7d6cc7cea1a02abb6dd00551fdf4 Mon Sep 17 00:00:00 2001 From: hided62 Date: Wed, 12 Aug 2026 15:40:07 +0000 Subject: [PATCH] test(compare): enforce invader resume watchdog --- hwe/compare/monthly_event_trace.php | 22 ++++++++++++ tests/AutoResetProgressTest.php | 53 +++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 tests/AutoResetProgressTest.php diff --git a/hwe/compare/monthly_event_trace.php b/hwe/compare/monthly_event_trace.php index 2c100cc3..cb44f003 100644 --- a/hwe/compare/monthly_event_trace.php +++ b/hwe/compare/monthly_event_trace.php @@ -886,6 +886,15 @@ function comparisonUnificationInvaderResumeTrace(array $request, array $environm 'autoresetAnchor' => $gameStorage->autoreset_united_wall_anchor, 'autoresetAnchorRefreshed' => $gameStorage->autoreset_united_wall_anchor !== $pausedAnchor, ]; + if ( + $decisionResult !== RaiseInvaderMessage::ACCEPTED + || $afterSummon['isunited'] !== 1 + || $afterSummon['plock'] !== 0 + || $afterSummon['invaderNationCount'] !== 7 + || $afterSummon['autoresetAnchorRefreshed'] !== true + ) { + throw new \RuntimeException('invader choice did not start an unlocked, watchdog-active event game'); + } $resumeBoundary = addTurn( cutTurn(Util::toInt($gameStorage->turntime), Util::toInt($gameStorage->turnterm)), @@ -938,6 +947,19 @@ function comparisonUnificationInvaderResumeTrace(array $request, array $environm 'autoresetAnchor' => $gameStorage->autoreset_united_wall_anchor, 'autoresetAnchorRefreshed' => $gameStorage->autoreset_united_wall_anchor !== $stalledAnchor, ]; + $expectedYear = $month === 12 ? $year + 1 : $year; + $expectedMonth = $month === 12 ? 1 : $month + 1; + if ( + $afterResume['turntime'] < $resumeBoundary + || $afterResume['year'] !== $expectedYear + || $afterResume['month'] !== $expectedMonth + || $afterResume['isunited'] !== 1 + || $afterResume['lockedCalls'] !== 0 + || $afterResume['plock'] !== 0 + || $afterResume['autoresetAnchorRefreshed'] !== true + ) { + throw new \RuntimeException('invader event game did not advance through the next monthly boundary'); + } return [ 'schemaVersion' => 1, diff --git a/tests/AutoResetProgressTest.php b/tests/AutoResetProgressTest.php new file mode 100644 index 00000000..31d7b1bb --- /dev/null +++ b/tests/AutoResetProgressTest.php @@ -0,0 +1,53 @@ +createMock(KVStorage::class); + $storage->expects(self::once()) + ->method('setValue') + ->with( + AutoResetProgress::STORAGE_KEY, + '2026-08-12 15:40:12.345678', + ) + ->willReturnSelf(); + + AutoResetProgress::record( + $storage, + new \DateTimeImmutable('2026-08-12 15:40:12.345678 UTC'), + ); + } + + public function testRecordIfAdvancedIgnoresEqualOrRegressiveTicks(): void + { + $storage = $this->createMock(KVStorage::class); + $storage->expects(self::never())->method('setValue'); + + self::assertFalse(AutoResetProgress::recordIfAdvanced($storage, 100, 100)); + self::assertFalse(AutoResetProgress::recordIfAdvanced($storage, 100, 99)); + } + + public function testRecordIfAdvancedRefreshesTheWatchdogAnchor(): void + { + $storage = $this->createMock(KVStorage::class); + $storage->expects(self::once()) + ->method('setValue') + ->with( + AutoResetProgress::STORAGE_KEY, + '2026-08-12 15:41:00.000001', + ) + ->willReturnSelf(); + + self::assertTrue(AutoResetProgress::recordIfAdvanced( + $storage, + 100, + 101, + new \DateTimeImmutable('2026-08-12 15:41:00.000001 UTC'), + )); + } +}