1
0
Files
DiAL/tests/server/checker/command-runner.test.ts
lanyuanxiaoyao b8810f1182 feat: 重构为多类型 checker 通用框架,支持 HTTP 与命令检查
- 引入 typed target 判别联合,支持 http 与 command 两种 checker
- expect 重构为有序规则数组,按配置顺序快速失败并生成结构化 failure
- 新增 command runner,支持 exec + args 本地命令执行
- 引入全局并发限制 maxConcurrentChecks 和 size 解析 (KB/MB/GB)
- HTTP/command 各自独立 expect pipeline,应用领域默认成功语义
- SQLite schema、API、Dashboard 全链路调整为 checker 通用契约
- 补充完整测试覆盖(192 tests),更新 README 与示例配置
2026-05-10 22:25:21 +08:00

132 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, test } from "bun:test";
import { runCommandCheck } from "../../../src/server/checker/command-runner";
import type { ResolvedCommandTarget } from "../../../src/server/checker/types";
function makeTarget(
command: Partial<ResolvedCommandTarget["command"]>,
overrides?: Partial<ResolvedCommandTarget>,
): ResolvedCommandTarget {
return {
type: "command",
name: "test-cmd",
command: {
exec: "echo",
args: ["hello"],
cwd: "/tmp",
env: {},
maxOutputBytes: 1024 * 1024,
...command,
},
intervalMs: 60000,
timeoutMs: 5000,
...overrides,
};
}
describe("runCommandCheck", () => {
test("exitCode=0 成功", async () => {
const result = await runCommandCheck(makeTarget({ exec: "true", args: [] }));
expect(result.success).toBe(true);
expect(result.matched).toBe(true);
expect(result.statusDetail).toBe("exitCode=0");
expect(result.failure).toBeNull();
});
test("exitCode=1 不匹配默认 [0]", async () => {
const result = await runCommandCheck(makeTarget({ exec: "false", args: [] }));
expect(result.success).toBe(false);
expect(result.matched).toBe(false);
expect(result.statusDetail).toBe("exitCode=1");
expect(result.failure).not.toBeNull();
expect(result.failure!.phase).toBe("exitCode");
});
test("exitCode=1 匹配自定义 [1]", async () => {
const result = await runCommandCheck(makeTarget({ exec: "false", args: [] }, { expect: { exitCode: [1] } }));
expect(result.success).toBe(true);
expect(result.matched).toBe(true);
expect(result.statusDetail).toBe("exitCode=1");
});
test("命令不存在返回 spawn 错误", async () => {
const result = await runCommandCheck(makeTarget({ exec: "/nonexistent/command/xyz" }));
expect(result.success).toBe(false);
expect(result.failure).not.toBeNull();
expect(result.failure!.phase).toBe("exitCode");
expect(result.failure!.message).toBeTruthy();
});
test("超时返回错误", async () => {
const result = await runCommandCheck(makeTarget({ exec: "sleep", args: ["10"] }, { timeoutMs: 100 }));
expect(result.success).toBe(false);
expect(result.failure).not.toBeNull();
expect(result.failure!.message).toContain("超时");
});
test("stdout 输出捕获", async () => {
const result = await runCommandCheck(makeTarget({ exec: "echo", args: ["hello world"] }));
expect(result.success).toBe(true);
});
test("stdout 匹配 expect", async () => {
const result = await runCommandCheck(
makeTarget({ exec: "echo", args: ["hello"] }, { expect: { stdout: [{ contains: "hello" }] } }),
);
expect(result.success).toBe(true);
expect(result.matched).toBe(true);
});
test("stdout 不匹配 expect", async () => {
const result = await runCommandCheck(
makeTarget({ exec: "echo", args: ["hello"] }, { expect: { stdout: [{ contains: "nonexistent" }] } }),
);
expect(result.success).toBe(false);
expect(result.failure!.phase).toBe("stdout");
});
test("stderr 匹配 expect", async () => {
const result = await runCommandCheck(
makeTarget({ exec: "bash", args: ["-c", "echo error >&2"] }, { expect: { stderr: [{ contains: "error" }] } }),
);
expect(result.success).toBe(true);
expect(result.matched).toBe(true);
});
test("输出超过 maxOutputBytes", async () => {
const result = await runCommandCheck(
makeTarget({
exec: "bash",
args: ["-c", "yes | head -1000"],
maxOutputBytes: 10,
}),
);
expect(result.success).toBe(false);
expect(result.failure).not.toBeNull();
expect(result.failure!.message).toContain("超过限制");
});
test("durationMs 非空", async () => {
const result = await runCommandCheck(makeTarget({ exec: "true", args: [] }));
expect(result.durationMs).not.toBeNull();
expect(result.durationMs!).toBeGreaterThanOrEqual(0);
});
test("ls 命令执行成功", async () => {
const result = await runCommandCheck(makeTarget({ exec: "ls", args: ["/tmp"] }));
expect(result.success).toBe(true);
expect(result.statusDetail).toBe("exitCode=0");
});
test("不使用 shell通配符不被展开", async () => {
const result = await runCommandCheck(
makeTarget({ exec: "echo", args: ["*"] }, { expect: { stdout: [{ contains: "*" }] } }),
);
expect(result.success).toBe(true);
});
test("不提供 stdin等待输入的命令会阻塞超时", async () => {
const result = await runCommandCheck(makeTarget({ exec: "bash", args: ["-c", "read line"] }, { timeoutMs: 500 }));
expect(result.success).toBe(false);
});
});