import { describe, expect, test } from "bun:test"; import type { CheckerValidationInput } from "../../../../../src/server/checker/runner/types"; import { validateTcpConfig } from "../../../../../src/server/checker/runner/tcp/validate"; function makeInput(targets: unknown[], defaults?: Record): CheckerValidationInput { return { defaults: defaults ?? {}, targets: targets as CheckerValidationInput["targets"], }; } describe("validateTcpConfig", () => { test("合法 tcp target 无错误", () => { const issues = validateTcpConfig(makeInput([{ id: "t1", tcp: { host: "127.0.0.1", port: 80 }, type: "tcp" }])); expect(issues).toHaveLength(0); }); test("缺少 tcp 分组", () => { const issues = validateTcpConfig(makeInput([{ id: "t1", type: "tcp" }])); expect(issues.length).toBeGreaterThan(0); expect(issues.some((i) => i.message.includes("tcp"))).toBe(true); }); test("缺少 host", () => { const issues = validateTcpConfig(makeInput([{ id: "t1", tcp: { port: 80 }, type: "tcp" }])); expect(issues.some((i) => i.path.includes("host"))).toBe(true); }); test("缺少 port", () => { const issues = validateTcpConfig(makeInput([{ id: "t1", tcp: { host: "127.0.0.1" }, type: "tcp" }])); expect(issues.some((i) => i.path.includes("port"))).toBe(true); }); test("端口超范围", () => { const issues = validateTcpConfig(makeInput([{ id: "t1", tcp: { host: "127.0.0.1", port: 99999 }, type: "tcp" }])); expect(issues.some((i) => i.path.includes("port"))).toBe(true); }); test("端口为 0", () => { const issues = validateTcpConfig(makeInput([{ id: "t1", tcp: { host: "127.0.0.1", port: 0 }, type: "tcp" }])); expect(issues.some((i) => i.path.includes("port"))).toBe(true); }); test("readBanner 非布尔值", () => { const issues = validateTcpConfig( makeInput([{ id: "t1", tcp: { host: "127.0.0.1", port: 80, readBanner: "yes" }, type: "tcp" }]), ); expect(issues.some((i) => i.path.includes("readBanner"))).toBe(true); }); test("bannerReadTimeout 非数字", () => { const issues = validateTcpConfig( makeInput([{ id: "t1", tcp: { bannerReadTimeout: "slow", host: "127.0.0.1", port: 80 }, type: "tcp" }]), ); expect(issues.some((i) => i.path.includes("bannerReadTimeout"))).toBe(true); }); test("tcp 分组未知字段", () => { const issues = validateTcpConfig( makeInput([{ id: "t1", tcp: { host: "127.0.0.1", port: 80, tls: true }, type: "tcp" }]), ); expect(issues.some((i) => i.message.includes("未知字段"))).toBe(true); }); test("expect.banner 未开启 readBanner", () => { const issues = validateTcpConfig( makeInput([ { expect: { banner: [{ contains: "ESMTP" }] }, id: "t1", tcp: { host: "127.0.0.1", port: 25 }, type: "tcp", }, ]), ); expect(issues.some((i) => i.message.includes("readBanner"))).toBe(true); }); test("expect.banner 开启 readBanner 无错误", () => { const issues = validateTcpConfig( makeInput([ { expect: { banner: [{ contains: "ESMTP" }] }, id: "t1", tcp: { host: "127.0.0.1", port: 25, readBanner: true }, type: "tcp", }, ]), ); expect(issues).toHaveLength(0); }); test("expect connected 非布尔值", () => { const issues = validateTcpConfig( makeInput([ { expect: { connected: "yes" }, id: "t1", tcp: { host: "127.0.0.1", port: 80 }, type: "tcp", }, ]), ); expect(issues.some((i) => i.path.includes("connected"))).toBe(true); }); test("expect durationMs 非 matcher", () => { const issues = validateTcpConfig( makeInput([ { expect: { durationMs: "slow" }, id: "t1", tcp: { host: "127.0.0.1", port: 80 }, type: "tcp", }, ]), ); expect(issues.some((i) => i.path.includes("durationMs"))).toBe(true); }); test("expect 未知字段", () => { const issues = validateTcpConfig( makeInput([ { expect: { status: [200] }, id: "t1", tcp: { host: "127.0.0.1", port: 80 }, type: "tcp", }, ]), ); expect(issues.some((i) => i.message.includes("未知字段"))).toBe(true); }); test("expect.banner regex 正则非法", () => { const issues = validateTcpConfig( makeInput([ { expect: { banner: [{ regex: "[invalid" }] }, id: "t1", tcp: { host: "127.0.0.1", port: 25, readBanner: true }, type: "tcp", }, ]), ); expect(issues.some((i) => i.message.includes("正则"))).toBe(true); }); test("非 tcp 类型 target 跳过", () => { const issues = validateTcpConfig(makeInput([{ http: { url: "http://example.com" }, id: "t1", type: "http" }])); expect(issues).toHaveLength(0); }); test("defaults.tcp 合法字段无错误", () => { const issues = validateTcpConfig( makeInput([{ id: "t1", tcp: { host: "127.0.0.1", port: 80 }, type: "tcp" }], { tcp: { bannerReadTimeout: 1000, maxBannerBytes: "8KB" }, }), ); expect(issues).toHaveLength(0); }); test("defaults.tcp 未知字段", () => { const issues = validateTcpConfig( makeInput([{ id: "t1", tcp: { host: "127.0.0.1", port: 80 }, type: "tcp" }], { tcp: { bannerReadTimeout: 1000, host: "127.0.0.1" }, }), ); expect(issues.some((i) => i.message.includes("未知字段"))).toBe(true); }); test("defaults.tcp bannerReadTimeout 非法", () => { const issues = validateTcpConfig( makeInput([{ id: "t1", tcp: { host: "127.0.0.1", port: 80 }, type: "tcp" }], { tcp: { bannerReadTimeout: "slow" }, }), ); expect(issues.some((i) => i.path.includes("bannerReadTimeout"))).toBe(true); }); test("defaults.tcp maxBannerBytes 非法", () => { const issues = validateTcpConfig( makeInput([{ id: "t1", tcp: { host: "127.0.0.1", port: 80 }, type: "tcp" }], { tcp: { maxBannerBytes: true }, }), ); expect(issues.some((i) => i.path.includes("maxBannerBytes"))).toBe(true); }); });