import { describe, expect, it } from "bun:test"; import type { ContentExpectations } from "../../../../../src/server/checker/expect/types"; import { checkAnswerCount, checkDnsValues, checkFlag, checkRcode, checkResponded, checkResult, checkTtlMax, checkTtlMin, checkValueCount, } from "../../../../../src/server/checker/runner/dns/expect"; describe("checkResponded", () => { it("responded=true 期望 true → 匹配", () => { const result = checkResponded(true, true); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); it("responded=false 期望 true → 不匹配", () => { const result = checkResponded(false, true); expect(result.matched).toBe(false); expect(result.failure!.kind).toBe("mismatch"); expect(result.failure!.phase).toBe("responded"); expect(result.failure!.message).toContain("未收到"); }); it("responded=true 期望 false → 不匹配", () => { const result = checkResponded(true, false); expect(result.matched).toBe(false); expect(result.failure!.kind).toBe("mismatch"); expect(result.failure!.phase).toBe("responded"); expect(result.failure!.message).toContain("收到响应"); }); it("responded=false 期望 false → 匹配", () => { const result = checkResponded(false, false); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); }); describe("checkRcode", () => { it("NOERROR 在 [NOERROR] → 匹配", () => { const result = checkRcode("NOERROR", ["NOERROR"]); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); it("NXDOMAIN 在 [NOERROR] → 不匹配", () => { const result = checkRcode("NXDOMAIN", ["NOERROR"]); expect(result.matched).toBe(false); expect(result.failure!.kind).toBe("mismatch"); expect(result.failure!.phase).toBe("rcode"); }); it("NXDOMAIN 在 [NXDOMAIN, SERVFAIL] → 匹配", () => { const result = checkRcode("NXDOMAIN", ["NXDOMAIN", "SERVFAIL"]); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); }); describe("checkDnsValues", () => { it("exact: 相同集合不同顺序 → 匹配", () => { const result = checkDnsValues(["2.2.2.2", "1.1.1.1"], { exact: ["1.1.1.1", "2.2.2.2"] }); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); it("exact: 不同集合 → 不匹配", () => { const result = checkDnsValues(["1.1.1.1"], { exact: ["2.2.2.2"] }); expect(result.matched).toBe(false); expect(result.failure!.kind).toBe("mismatch"); expect(result.failure!.phase).toBe("values"); }); it("exact: 数量不同 → 不匹配", () => { const result = checkDnsValues(["1.1.1.1", "2.2.2.2"], { exact: ["1.1.1.1"] }); expect(result.matched).toBe(false); }); it("include: 全部存在 → 匹配", () => { const result = checkDnsValues(["1.1.1.1", "2.2.2.2"], { include: ["1.1.1.1"] }); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); it("include: 缺少一个 → 不匹配", () => { const result = checkDnsValues(["1.1.1.1"], { include: ["3.3.3.3"] }); expect(result.matched).toBe(false); expect(result.failure!.message).toContain("3.3.3.3"); }); it("exclude: 全不存在 → 匹配", () => { const result = checkDnsValues(["1.1.1.1"], { exclude: ["3.3.3.3"] }); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); it("exclude: 存在一个 → 不匹配", () => { const result = checkDnsValues(["1.1.1.1", "2.2.2.2"], { exclude: ["2.2.2.2"] }); expect(result.matched).toBe(false); expect(result.failure!.message).toContain("2.2.2.2"); }); it("include + exclude 组合:全部满足 → 匹配", () => { const result = checkDnsValues(["1.1.1.1", "2.2.2.2"], { exclude: ["3.3.3.3"], include: ["1.1.1.1"] }); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); it("include + exclude 组合:include 失败 → 不匹配", () => { const result = checkDnsValues(["1.1.1.1"], { exclude: ["3.3.3.3"], include: ["4.4.4.4"] }); expect(result.matched).toBe(false); }); it("空 expectation → 匹配", () => { const result = checkDnsValues(["1.1.1.1"], {}); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); }); describe("checkValueCount", () => { it("count=3 gte=1 → 匹配", () => { const result = checkValueCount(3, { gte: 1 }); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); it("count=0 gte=1 → 不匹配", () => { const result = checkValueCount(0, { gte: 1 }); expect(result.matched).toBe(false); expect(result.failure!.kind).toBe("mismatch"); expect(result.failure!.phase).toBe("valueCount"); }); }); describe("checkAnswerCount", () => { it("count=2 gte=2 → 匹配", () => { const result = checkAnswerCount(2, { gte: 2 }); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); it("count=1 gte=2 → 不匹配", () => { const result = checkAnswerCount(1, { gte: 2 }); expect(result.matched).toBe(false); expect(result.failure!.kind).toBe("mismatch"); expect(result.failure!.phase).toBe("answerCount"); }); }); describe("checkTtlMin", () => { it("ttl=300 gte=60 → 匹配", () => { const result = checkTtlMin(300, { gte: 60 }); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); it("ttl=30 gte=60 → 不匹配", () => { const result = checkTtlMin(30, { gte: 60 }); expect(result.matched).toBe(false); expect(result.failure!.kind).toBe("mismatch"); expect(result.failure!.phase).toBe("ttlMin"); }); }); describe("checkTtlMax", () => { it("ttl=100 lte=3600 → 匹配", () => { const result = checkTtlMax(100, { lte: 3600 }); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); it("ttl=5000 lte=3600 → 不匹配", () => { const result = checkTtlMax(5000, { lte: 3600 }); expect(result.matched).toBe(false); expect(result.failure!.kind).toBe("mismatch"); expect(result.failure!.phase).toBe("ttlMax"); }); }); describe("checkFlag", () => { it("匹配 → matched", () => { const result = checkFlag(true, true, "authoritative"); expect(result!.matched).toBe(true); expect(result!.failure).toBeNull(); }); it("不匹配 → mismatch", () => { const result = checkFlag(false, true, "authoritative"); expect(result!.matched).toBe(false); expect(result!.failure!.kind).toBe("mismatch"); expect(result!.failure!.phase).toBe("authoritative"); }); it("undefined 期望 → 跳过返回 null", () => { const result = checkFlag(true, undefined, "authoritative"); expect(result).toBeNull(); }); }); describe("checkResult", () => { it("单条 contains 匹配 JSON 字符串", () => { const observation = { answers: ["1.1.1.1"], rcode: "NOERROR" }; const expectations: ContentExpectations = [{ kind: "value", matcher: { contains: "NOERROR" } }]; const result = checkResult(observation, expectations); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); it("单条 contains 不匹配 → 不匹配", () => { const observation = { rcode: "SERVFAIL" }; const expectations: ContentExpectations = [{ kind: "value", matcher: { contains: "NOERROR" } }]; const result = checkResult(observation, expectations); expect(result.matched).toBe(false); expect(result.failure!.kind).toBe("mismatch"); expect(result.failure!.phase).toBe("result"); }); });