import { describe, expect, it } from "bun:test"; import type { CheckerValidationInput } from "../../../../../src/server/checker/runner/types"; import { validateUdpConfig } from "../../../../../src/server/checker/runner/udp/validate"; describe("validateUdpConfig", () => { const makeInput = (overrides: { defaults?: Record; targets?: Array>; }): CheckerValidationInput => ({ defaults: overrides.defaults ?? {}, targets: (overrides.targets ?? []) as CheckerValidationInput["targets"], }); it("accepts minimal valid UDP target", () => { const issues = validateUdpConfig( makeInput({ targets: [{ id: "test", type: "udp", udp: { host: "127.0.0.1", port: 53 } }], }), ); expect(issues).toHaveLength(0); }); it("reports required when udp.host is missing", () => { const issues = validateUdpConfig( makeInput({ targets: [{ id: "test", type: "udp", udp: { port: 53 } }], }), ); expect(issues).toHaveLength(1); expect(issues[0]!.code).toBe("required"); expect(issues[0]!.path).toContain("host"); }); it("reports required when udp.port is missing", () => { const issues = validateUdpConfig( makeInput({ targets: [{ id: "test", type: "udp", udp: { host: "127.0.0.1" } }], }), ); expect(issues).toHaveLength(1); expect(issues[0]!.code).toBe("required"); expect(issues[0]!.path).toContain("port"); }); it("rejects invalid port values", () => { for (const port of [0, -1, 65536, 1.5]) { const issues = validateUdpConfig( makeInput({ targets: [{ id: "test", type: "udp", udp: { host: "127.0.0.1", port } }], }), ); expect(issues.length).toBeGreaterThanOrEqual(1); expect(issues.some((i) => i.code === "invalid-value" && i.path.includes("port"))).toBe(true); } }); it("reports required when udp section is missing", () => { const issues = validateUdpConfig( makeInput({ targets: [{ id: "test", type: "udp" }], }), ); expect(issues).toHaveLength(1); expect(issues[0]!.code).toBe("required"); expect(issues[0]!.path).toContain("udp"); }); it("accepts valid defaults.udp with encoding, responseEncoding, maxResponseBytes", () => { const issues = validateUdpConfig( makeInput({ defaults: { udp: { encoding: "hex", maxResponseBytes: 1024, responseEncoding: "text" }, }, targets: [{ id: "test", type: "udp", udp: { host: "127.0.0.1", port: 53 } }], }), ); expect(issues).toHaveLength(0); }); it("reports unknown-field in defaults.udp", () => { const issues = validateUdpConfig( makeInput({ defaults: { udp: { unknownField: true } }, targets: [{ id: "test", type: "udp", udp: { host: "127.0.0.1", port: 53 } }], }), ); expect(issues).toHaveLength(1); expect(issues[0]!.code).toBe("unknown-field"); }); it("reports invalid-value for udp.encoding with bad value", () => { const issues = validateUdpConfig( makeInput({ targets: [ { id: "test", type: "udp", udp: { encoding: "json", host: "127.0.0.1", port: 53 }, }, ], }), ); expect(issues.some((i) => i.code === "invalid-value" && i.path.includes("encoding"))).toBe(true); }); it("reports invalid-value for udp.responseEncoding with bad value", () => { const issues = validateUdpConfig( makeInput({ targets: [ { id: "test", type: "udp", udp: { host: "127.0.0.1", port: 53, responseEncoding: "binary" }, }, ], }), ); expect(issues.some((i) => i.code === "invalid-value" && i.path.includes("responseEncoding"))).toBe(true); }); it("reports invalid-value for hex payload that is not valid hex", () => { const issues = validateUdpConfig( makeInput({ targets: [ { id: "test", type: "udp", udp: { encoding: "hex", host: "127.0.0.1", payload: "ZZZZ", port: 53 }, }, ], }), ); expect(issues.some((i) => i.code === "invalid-value" && i.path.includes("payload"))).toBe(true); }); it("reports invalid-value for base64 payload that is not valid base64", () => { const issues = validateUdpConfig( makeInput({ targets: [ { id: "test", type: "udp", udp: { encoding: "base64", host: "127.0.0.1", payload: "!!!notbase64", port: 53 }, }, ], }), ); expect(issues.some((i) => i.code === "invalid-value" && i.path.includes("payload"))).toBe(true); }); it("reports unknown-field for unknown key in udp group", () => { const issues = validateUdpConfig( makeInput({ targets: [ { id: "test", type: "udp", udp: { bogus: true, host: "127.0.0.1", port: 53 }, }, ], }), ); expect(issues.some((i) => i.code === "unknown-field" && i.path.includes("bogus"))).toBe(true); }); it("reports unknown-field for unknown key in expect", () => { const issues = validateUdpConfig( makeInput({ targets: [ { expect: { unknownExpect: true }, id: "test", type: "udp", udp: { host: "127.0.0.1", port: 53 }, }, ], }), ); expect(issues.some((i) => i.code === "unknown-field" && i.path.includes("unknownExpect"))).toBe(true); }); it("reports conflict when expect.responded=false with expect.response", () => { const issues = validateUdpConfig( makeInput({ targets: [ { expect: { responded: false, response: [{ type: "contains", value: "ok" }] }, id: "test", type: "udp", udp: { host: "127.0.0.1", port: 53 }, }, ], }), ); expect(issues.some((i) => i.path.includes("responded") && i.message.includes("响应内容"))).toBe(true); }); it("reports conflict when expect.responded=false with expect.sourceHost", () => { const issues = validateUdpConfig( makeInput({ targets: [ { expect: { responded: false, sourceHost: { eq: "1.2.3.4" } }, id: "test", type: "udp", udp: { host: "127.0.0.1", port: 53 }, }, ], }), ); expect(issues.some((i) => i.path.includes("responded") && i.message.includes("响应来源"))).toBe(true); }); it("reports invalid-type for negative expect.maxDurationMs", () => { const issues = validateUdpConfig( makeInput({ targets: [ { expect: { maxDurationMs: -100 }, id: "test", type: "udp", udp: { host: "127.0.0.1", port: 53 }, }, ], }), ); expect(issues.some((i) => i.code === "invalid-type" && i.path.includes("maxDurationMs"))).toBe(true); }); it("reports invalid-type for non-boolean expect.responded", () => { const issues = validateUdpConfig( makeInput({ targets: [ { expect: { responded: "yes" }, id: "test", type: "udp", udp: { host: "127.0.0.1", port: 53 }, }, ], }), ); expect(issues.some((i) => i.code === "invalid-type" && i.path.includes("responded"))).toBe(true); }); it("reports invalid-value for negative maxResponseBytes", () => { const issues = validateUdpConfig( makeInput({ targets: [ { id: "test", type: "udp", udp: { host: "127.0.0.1", maxResponseBytes: -1, port: 53 }, }, ], }), ); expect(issues.some((i) => i.code === "invalid-value" && i.path.includes("maxResponseBytes"))).toBe(true); }); });