feat: 新增 ICMP/Ping checker,支持跨平台主机存活检测与延迟监控
实现 type: ping checker,通过 Bun.spawn 调用系统 ping 命令,自行实现跨平台 输出解析器(Linux/macOS/Windows 含中文 locale),支持 alive、丢包率、延迟、 耗时等 expect 断言,复用现有 checker 架构零外部依赖。 包含完整的类型定义、TypeBox schema、语义校验、命令构建、解析、断言、执行、 注册、配置加载测试,以及 probe-config.schema.json 更新和文档更新。 审查修复:提取 buildPingCommand 为独立纯函数并补充跨平台单测,补充 maxDurationMs/maxAvgLatencyMs 类型非法和空字符串 host 边界测试用例。 变更已归档,delta specs 已同步至 main specs。
This commit is contained in:
@@ -5,6 +5,7 @@ import { join } from "node:path";
|
||||
|
||||
import type { ResolvedCommandTarget } from "../../../src/server/checker/runner/cmd/types";
|
||||
import type { ResolvedHttpTarget } from "../../../src/server/checker/runner/http/types";
|
||||
import type { ResolvedPingTarget } from "../../../src/server/checker/runner/icmp/types";
|
||||
import type { ResolvedTcpTarget } from "../../../src/server/checker/runner/tcp/types";
|
||||
|
||||
import { loadConfig, parseDuration } from "../../../src/server/checker/config-loader";
|
||||
@@ -1974,4 +1975,99 @@ targets:
|
||||
expect(t.expect?.connected).toBe(false);
|
||||
expect(t.expect?.maxDurationMs).toBe(5000);
|
||||
});
|
||||
|
||||
test("解析最简 ping 配置", async () => {
|
||||
const configPath = join(tempDir, "minimal-ping.yaml");
|
||||
await writeFile(
|
||||
configPath,
|
||||
`targets:
|
||||
- id: "gateway"
|
||||
type: ping
|
||||
ping:
|
||||
host: "10.0.0.1"
|
||||
`,
|
||||
);
|
||||
|
||||
const config = await loadConfig(configPath);
|
||||
expect(config.targets).toHaveLength(1);
|
||||
const t = config.targets[0]! as ResolvedPingTarget;
|
||||
expect(t.type).toBe("ping");
|
||||
expect(t.ping).toEqual({ count: 3, host: "10.0.0.1", packetSize: 56 });
|
||||
expect(t.group).toBe("default");
|
||||
expect(t.intervalMs).toBe(30000);
|
||||
expect(t.timeoutMs).toBe(10000);
|
||||
});
|
||||
|
||||
test("解析 ping expect 配置", async () => {
|
||||
const configPath = join(tempDir, "ping-expect.yaml");
|
||||
await writeFile(
|
||||
configPath,
|
||||
`targets:
|
||||
- id: "gateway"
|
||||
type: ping
|
||||
ping:
|
||||
host: "10.0.0.1"
|
||||
count: 5
|
||||
packetSize: 1472
|
||||
expect:
|
||||
alive: true
|
||||
maxPacketLoss: 10
|
||||
maxAvgLatencyMs: 200
|
||||
maxMaxLatencyMs: 500
|
||||
maxDurationMs: 5000
|
||||
`,
|
||||
);
|
||||
|
||||
const config = await loadConfig(configPath);
|
||||
const t = config.targets[0]! as ResolvedPingTarget;
|
||||
expect(t.ping).toEqual({ count: 5, host: "10.0.0.1", packetSize: 1472 });
|
||||
expect(t.expect).toEqual({
|
||||
alive: true,
|
||||
maxAvgLatencyMs: 200,
|
||||
maxDurationMs: 5000,
|
||||
maxMaxLatencyMs: 500,
|
||||
maxPacketLoss: 10,
|
||||
});
|
||||
});
|
||||
|
||||
test("ping 缺少 host 抛出错误", async () => {
|
||||
await expectConfigError(
|
||||
"ping-no-host.yaml",
|
||||
`targets:
|
||||
- id: "gateway"
|
||||
type: ping
|
||||
ping: {}
|
||||
`,
|
||||
"ping.host",
|
||||
);
|
||||
});
|
||||
|
||||
test("ping count 非法抛出错误", async () => {
|
||||
await expectConfigError(
|
||||
"ping-bad-count.yaml",
|
||||
`targets:
|
||||
- id: "gateway"
|
||||
type: ping
|
||||
ping:
|
||||
host: "10.0.0.1"
|
||||
count: 0
|
||||
`,
|
||||
"ping.count",
|
||||
);
|
||||
});
|
||||
|
||||
test("ping expect 未知字段抛出错误", async () => {
|
||||
await expectConfigError(
|
||||
"ping-unknown-expect.yaml",
|
||||
`targets:
|
||||
- id: "gateway"
|
||||
type: ping
|
||||
ping:
|
||||
host: "10.0.0.1"
|
||||
expect:
|
||||
status: [200]
|
||||
`,
|
||||
"expect.status 是未知字段",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user