1
0
Files
DiAL/tests/server/checker/runner/db/expect.test.ts
lanyuanxiaoyao 7a635a0a9f refactor: 统一 expect 断言体系,引入共享 ValueMatcher/ContentRules/KeyValueExpect 模型
- 引入共享 ValueMatcher(equals/contains/regex/exists/empty/gt/gte/lt/lte)
- 引入共享 ContentRules 数组(direct/json/css/xpath 提取器)
- 引入共享 KeyValueExpect(动态键值断言,字面量等价 equals)
- maxDurationMs → durationMs: ValueMatcher(所有 checker)
- match → regex(固定无 flags)
- Ping max* → packetLossPercent/avgLatencyMs/maxLatencyMs(ValueMatcher)
- LLM finishReason/rawFinishReason → ValueMatcher
- DB 新增 result: ContentRules
- TCP banner → ContentRules 数组
- 删除旧模块:operator.ts、validate-operator.ts、duration.ts、body.ts、text.ts、output.ts
- 更新全部 checker schema/validate/expect/execute
- 更新 probe-config.schema.json、probes.example.yaml
- 更新 README.md、DEVELOPMENT.md(含 expect 字段选择规范)
- 同步 10 个 delta specs 到主 specs,归档 change
2026-05-19 14:24:27 +08:00

135 lines
4.2 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 { checkRowCount, checkRows } from "../../../../../src/server/checker/runner/db/expect";
describe("checkRowCount", () => {
test("空数组通过 rowCount gte 0", () => {
const result = checkRowCount(0, { gte: 0 });
expect(result.matched).toBe(true);
expect(result.failure).toBeNull();
});
test("0 行通过 gte 0", () => {
const result = checkRowCount(0, { gte: 0 });
expect(result.matched).toBe(true);
});
test("rowCount gte 通过", () => {
const result = checkRowCount(3, { gte: 3 });
expect(result.matched).toBe(true);
});
test("rowCount gte 失败", () => {
const result = checkRowCount(2, { gte: 3 });
expect(result.matched).toBe(false);
expect(result.failure!.phase).toBe("rowCount");
expect(result.failure!.path).toBe("rowCount");
});
test("rowCount equals 通过", () => {
const result = checkRowCount(3, { equals: 3 });
expect(result.matched).toBe(true);
});
test("rowCount equals 失败", () => {
const result = checkRowCount(3, { equals: 5 });
expect(result.matched).toBe(false);
});
});
describe("checkRows", () => {
test("非数组返回失败", () => {
const result = checkRows(null, [{ col: 1 }]);
expect(result.matched).toBe(false);
expect(result.failure!.phase).toBe("row");
expect(result.failure!.path).toBe("rows");
});
test("空规则通过", () => {
const result = checkRows([], []);
expect(result.matched).toBe(true);
});
test("单行单列匹配(字面量)", () => {
const result = checkRows([{ col: "value" }], [{ col: "value" }]);
expect(result.matched).toBe(true);
});
test("单行单列匹配operator", () => {
const result = checkRows([{ col: 100 }], [{ col: { gte: 50 } }]);
expect(result.matched).toBe(true);
});
test("单行单列不匹配", () => {
const result = checkRows([{ col: 10 }], [{ col: { gte: 50 } }]);
expect(result.matched).toBe(false);
expect(result.failure!.phase).toBe("row");
expect(result.failure!.path).toBe("rows[0].col");
});
test("多行多列全部匹配", () => {
const result = checkRows(
[
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
],
[{ id: { gte: 1 } }, { name: "Bob" }],
);
expect(result.matched).toBe(true);
});
test("多行中有一行不匹配", () => {
const result = checkRows([{ col: 1 }, { col: 2 }], [{ col: { gte: 2 } }, { col: { gte: 3 } }]);
expect(result.matched).toBe(false);
// 第一行 { col: 1 } 不满足 { gte: 2 },所以失败在第一行
expect(result.failure!.path).toBe("rows[0].col");
});
test("结果行数不足", () => {
const result = checkRows([{ col: 1 }], [{ col: 1 }, { col: 2 }]);
expect(result.matched).toBe(false);
expect(result.failure!.message).toContain("行数不足");
});
test("只检查声明的列", () => {
const result = checkRows([{ col: 1, other: "ignored" }], [{ col: { gte: 0 } }]);
expect(result.matched).toBe(true);
});
test("行不是对象返回失败", () => {
const result = checkRows(["not-an-object"] as unknown[], [{ col: 1 }]);
expect(result.matched).toBe(false);
expect(result.failure!.path).toBe("rows[0]");
});
test("列不存在视为 undefined", () => {
const result = checkRows([{}], [{ col: { exists: false } }]);
expect(result.matched).toBe(true);
});
test("列存在且值为 null", () => {
const result = checkRows([{ col: null }], [{ col: { empty: true } }]);
expect(result.matched).toBe(true);
});
test("contains 匹配字符串", () => {
const result = checkRows([{ text: "hello world" }], [{ text: { contains: "hello" } }]);
expect(result.matched).toBe(true);
});
test("regex 正则匹配", () => {
const result = checkRows([{ code: "ABC-123" }], [{ code: { regex: "^ABC-" } }]);
expect(result.matched).toBe(true);
});
test("多个断言同时满足", () => {
const result = checkRows([{ val: 50 }], [{ val: { gte: 10, lte: 100 } }]);
expect(result.matched).toBe(true);
});
test("多个断言中有一个不满足", () => {
const result = checkRows([{ val: 50 }], [{ val: { gte: 10, lte: 30 } }]);
expect(result.matched).toBe(false);
});
});