import { afterAll, beforeAll, describe, expect, test } from "bun:test"; import { ProbeStore } from "../../../src/server/checker/store"; import { ProbeEngine } from "../../../src/server/checker/engine"; import type { ResolvedTarget } from "../../../src/server/checker/types"; import { mkdir, rm } from "node:fs/promises"; import { join } from "node:path"; import { tmpdir } from "node:os"; describe("ProbeEngine", () => { let tempDir: string; let store: ProbeStore; const target: ResolvedTarget = { name: "httpbin", url: "https://httpbin.org/get", method: "GET", headers: {}, intervalMs: 60000, timeoutMs: 10000, }; beforeAll(async () => { tempDir = join(tmpdir(), `gc-engine-test-${Date.now()}`); await mkdir(tempDir, { recursive: true }); store = new ProbeStore(join(tempDir, "test.db")); store.syncTargets([target]); }); afterAll(async () => { store.close(); await rm(tempDir, { recursive: true, force: true }); }); test("groupByInterval 分组逻辑", () => { const targets: ResolvedTarget[] = [ { name: "a", url: "http://a.com", method: "GET", headers: {}, intervalMs: 30000, timeoutMs: 10000 }, { name: "b", url: "http://b.com", method: "GET", headers: {}, intervalMs: 30000, timeoutMs: 10000 }, { name: "c", url: "http://c.com", method: "GET", headers: {}, intervalMs: 60000, timeoutMs: 10000 }, ]; const engine = new ProbeEngine(store, targets); engine.start(); engine.stop(); // 只要能启动和停止不出错就行 expect(true).toBe(true); }); test("engine start/stop 不抛错", () => { const engine = new ProbeEngine(store, [target]); engine.start(); engine.stop(); expect(true).toBe(true); }); test("单次拨测写入数据库", async () => { const engine = new ProbeEngine(store, [target]); // 手动调用 probeGroup 不启动 timer const probeGroup = (engine as unknown as { probeGroup: (t: ResolvedTarget[]) => Promise }).probeGroup.bind(engine); await probeGroup([target]); const dbTargets = store.getTargets(); const latest = store.getLatestCheck(dbTargets[0]!.id); expect(latest).not.toBeNull(); expect(latest!.success === 1 || latest!.success === 0).toBe(true); }); test("单目标失败隔离", async () => { const badTarget: ResolvedTarget = { name: "bad-target", url: "http://127.0.0.1:1/impossible", method: "GET", headers: {}, intervalMs: 60000, timeoutMs: 2000, }; store.syncTargets([target, badTarget]); const engine = new ProbeEngine(store, [target, badTarget]); const probeGroup = (engine as unknown as { probeGroup: (t: ResolvedTarget[]) => Promise }).probeGroup.bind(engine); await probeGroup([target, badTarget]); const dbTargets = store.getTargets(); const goodResult = store.getLatestCheck(dbTargets.find((t) => t.name === "httpbin")!.id); const badResult = store.getLatestCheck(dbTargets.find((t) => t.name === "bad-target")!.id); expect(goodResult).not.toBeNull(); expect(badResult).not.toBeNull(); expect(badResult!.success).toBe(0); }); });