From fab128943c61e5313c77dab98336f52ea5d808c0 Mon Sep 17 00:00:00 2001 From: Hide_D Date: Sun, 28 Dec 2025 14:24:30 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20TurnDaemonLifecycle=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/turnDaemonLifecycle.test.ts | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 app/game-engine/test/turnDaemonLifecycle.test.ts diff --git a/app/game-engine/test/turnDaemonLifecycle.test.ts b/app/game-engine/test/turnDaemonLifecycle.test.ts new file mode 100644 index 00000000..22bf7b7a --- /dev/null +++ b/app/game-engine/test/turnDaemonLifecycle.test.ts @@ -0,0 +1,65 @@ +import { describe, expect, it, vi } from 'vitest'; + +import { + FixedIntervalSchedule, + InMemoryControlQueue, + ManualClock, + TurnDaemonLifecycle, + type TurnProcessor, + type TurnRunResult, + type TurnStateStore, +} from '../src/index.js'; + +describe('TurnDaemonLifecycle', () => { + it('runs once when requestRun is enqueued', async () => { + const clock = new ManualClock(0); + const controlQueue = new InMemoryControlQueue(); + const schedule = new FixedIntervalSchedule(1000); + + const stateStore: TurnStateStore = { + loadLastTurnTime: async () => new Date(0), + saveLastTurnTime: async () => {}, + loadCheckpoint: async () => undefined, + saveCheckpoint: async () => {}, + }; + + let resolveRun: (() => void) | null = null; + const runCalled = new Promise((resolve) => { + resolveRun = resolve; + }); + const processor: TurnProcessor = { + run: vi.fn(async (): Promise => { + resolveRun?.(); + return { + lastTurnTime: new Date(0).toISOString(), + processedGenerals: 0, + processedTurns: 1, + durationMs: 0, + partial: false, + }; + }), + }; + + const lifecycle = new TurnDaemonLifecycle( + { clock, controlQueue, schedule, stateStore, processor }, + { + profile: 'test', + defaultBudget: { budgetMs: 1000, maxGenerals: 10, catchUpCap: 1 }, + }, + ); + + const loop = lifecycle.start(); + lifecycle.requestRun('manual'); + await Promise.race([ + runCalled, + new Promise((_, reject) => { + setTimeout(() => reject(new Error('run was not called')), 50); + }), + ]); + + expect(processor.run).toHaveBeenCalledTimes(1); + + await lifecycle.stop('test done'); + await loop; + }); +});