1
0
Files
DiAL/tests/server/checker/runner/command/runner.test.ts
lanyuanxiaoyao a5cf6065c2 chore: 强化代码质量与风格检查体系
ESLint 升级到 recommended-type-checked + stylistic-type-checked,
引入 perfectionist 导入排序和 import 插件导入验证。

Prettier 显式声明全部格式化参数,消除跨环境差异。
TypeScript 启用 noUnusedLocals 和 noPropertyAccessFromIndexSignature。
完善 ignore 列表,排除 .agents/、bun.lock、data/ 等。
引入 husky + lint-staged(pre-commit)+ commitlint(commit-msg)。
更新 DEVELOPMENT.md 代码质量章节。
修复所有新增规则检测到的类型和风格违规。
2026-05-12 18:44:59 +08:00

137 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 type { CheckerContext } from "../../../../../src/server/checker/runner/types";
import type { ResolvedCommandTarget } from "../../../../../src/server/checker/types";
import { CommandChecker } from "../../../../../src/server/checker/runner/command/runner";
const checker = new CommandChecker();
function makeCtx(timeoutMs = 5000): CheckerContext {
const controller = new AbortController();
setTimeout(() => controller.abort(), timeoutMs);
return { signal: controller.signal };
}
function makeTarget(
command: Partial<ResolvedCommandTarget["command"]>,
overrides?: Partial<ResolvedCommandTarget>,
): ResolvedCommandTarget {
return {
command: {
args: ["hello"],
cwd: "/tmp",
env: {},
exec: "echo",
maxOutputBytes: 1024 * 1024,
...command,
},
group: "default",
intervalMs: 60000,
name: "test-cmd",
timeoutMs: 5000,
type: "command",
...overrides,
};
}
describe("CommandChecker", () => {
test("exitCode=0 成功", async () => {
const result = await checker.execute(makeTarget({ args: [], exec: "true" }), makeCtx());
expect(result.matched).toBe(true);
expect(result.statusDetail).toBe("exitCode=0");
expect(result.failure).toBeNull();
});
test("exitCode=1 不匹配默认 [0]", async () => {
const result = await checker.execute(makeTarget({ args: [], exec: "false" }), makeCtx());
expect(result.matched).toBe(false);
expect(result.statusDetail).toBe("exitCode=1");
expect(result.failure!.phase).toBe("exitCode");
});
test("exitCode=1 匹配自定义 [1]", async () => {
const result = await checker.execute(
makeTarget({ args: [], exec: "false" }, { expect: { exitCode: [1] } }),
makeCtx(),
);
expect(result.matched).toBe(true);
expect(result.statusDetail).toBe("exitCode=1");
});
test("命令不存在返回 spawn 错误", async () => {
const result = await checker.execute(makeTarget({ exec: "/nonexistent/command/xyz" }), makeCtx());
expect(result.matched).toBe(false);
expect(result.failure!.phase).toBe("exitCode");
expect(result.failure!.message).toBeTruthy();
});
test("超时返回错误", async () => {
const result = await checker.execute(makeTarget({ args: ["10"], exec: "sleep" }, { timeoutMs: 100 }), makeCtx(100));
expect(result.matched).toBe(false);
expect(result.failure!.message).toContain("超时");
});
test("stdout 输出捕获", async () => {
const result = await checker.execute(makeTarget({ args: ["hello world"], exec: "echo" }), makeCtx());
expect(result.matched).toBe(true);
});
test("stdout 匹配 expect", async () => {
const result = await checker.execute(
makeTarget({ args: ["hello"], exec: "echo" }, { expect: { stdout: [{ contains: "hello" }] } }),
makeCtx(),
);
expect(result.matched).toBe(true);
});
test("stdout 不匹配 expect", async () => {
const result = await checker.execute(
makeTarget({ args: ["hello"], exec: "echo" }, { expect: { stdout: [{ contains: "nonexistent" }] } }),
makeCtx(),
);
expect(result.matched).toBe(false);
expect(result.failure!.phase).toBe("stdout");
});
test("stderr 匹配 expect", async () => {
const result = await checker.execute(
makeTarget({ args: ["-c", "echo error >&2"], exec: "bash" }, { expect: { stderr: [{ contains: "error" }] } }),
makeCtx(),
);
expect(result.matched).toBe(true);
});
test("输出超过 maxOutputBytes", async () => {
const result = await checker.execute(
makeTarget({ args: ["-c", "yes | head -1000"], exec: "bash", maxOutputBytes: 10 }),
makeCtx(),
);
expect(result.matched).toBe(false);
expect(result.failure!.message).toContain("超过限制");
});
test("durationMs 非空", async () => {
const result = await checker.execute(makeTarget({ args: [], exec: "true" }), makeCtx());
expect(result.durationMs).not.toBeNull();
expect(result.durationMs!).toBeGreaterThanOrEqual(0);
});
test("不使用 shell通配符不被展开", async () => {
const result = await checker.execute(
makeTarget({ args: ["*"], exec: "echo" }, { expect: { stdout: [{ contains: "*" }] } }),
makeCtx(),
);
expect(result.matched).toBe(true);
});
test("serialize 返回命令摘要和 config JSON", () => {
const target = makeTarget({ args: ["hello"], exec: "echo" });
const s = checker.serialize(target);
expect(s.target).toBe("exec echo hello");
const config = JSON.parse(s.config) as { args: string[]; exec: string };
expect(config.exec).toBe("echo");
expect(config.args).toEqual(["hello"]);
});
});