- 重命名 ContentRules→ContentExpectations, KeyValueExpect→KeyedExpectations - 新增 Raw/Resolved 双层模型:resolve 阶段物化为执行计划,store 持久化 Raw 快照 - HTTP body 按需读取:status/headers 失败或无 body expectation 时不读取 body - 新增 displayValueExpectation() 解包 failure.expected 用户可读展示 - 修复 checkEarlyTimeout 独立 lte/lt 检查,修复 KeyedExpectations JSON Schema - 新增 expect/value.ts(resolve/check/display)、keyed.ts、content.ts、headers.ts、status.ts - 删除旧 normalize.ts/matcher.ts/validate-matcher.ts/key-value.ts - 更新 DEVELOPMENT.md:expect 五层管线表、displayValueExpectation、1.7↔1.10 交叉引用 - 同步 13 个 main specs,归档 refactor-expect-type-model 变更(62/62 tasks)
12 KiB
Purpose
定义 UDP checker 的 target 配置、defaults、执行语义、响应编码、expect 校验、失败结构和状态摘要。
Requirements
Requirement: udp target 配置
系统 SHALL 支持 type: udp 的 target 配置,通过 udp.host 和 udp.port 描述目标 UDP 地址,并通过可选字段控制 payload、编码和响应大小限制。
Scenario: 解析最简 udp target
- WHEN YAML 中 target 配置
type: udp、udp.host: "127.0.0.1"和udp.port: 9000 - THEN 系统 SHALL 将其解析为 udp checker,并填充
payload=""、encoding="text"、responseEncoding="text"、maxResponseBytes=4096、interval、timeout、group 和 expect 配置
Scenario: udp target 缺少 host
- WHEN YAML 中 target 配置
type: udp但缺少udp.host - THEN 系统 SHALL 以配置错误退出,并提示该 target 缺少 udp.host 字段
Scenario: udp target 缺少 port
- WHEN YAML 中 target 配置
type: udp但缺少udp.port - THEN 系统 SHALL 以配置错误退出,并提示该 target 缺少 udp.port 字段
Scenario: udp port 范围非法
- WHEN YAML 中 udp target 的
udp.port不是 1 到 65535 之间的整数 - THEN 系统 SHALL 以配置错误退出,并提示 udp.port 必须为合法 UDP 端口
Scenario: 省略 payload 发送空 datagram
- WHEN YAML 中 udp target 未配置
udp.payload - THEN 系统 SHALL 使用空字符串作为 payload,并在执行时发送零长度 UDP datagram
Scenario: udp defaults 覆盖通用 UDP 参数
- WHEN YAML 中配置
defaults.udp.encoding: "hex"、defaults.udp.responseEncoding: "hex"和defaults.udp.maxResponseBytes: "8KB" - THEN 未显式配置对应字段的 udp target SHALL 使用 defaults.udp 中的值
Scenario: per-target UDP 参数覆盖 defaults
- WHEN defaults.udp 配置了 encoding、responseEncoding 或 maxResponseBytes,且某个 udp target 显式配置对应字段
- THEN 该 target SHALL 使用自身 udp 分组中的值
Scenario: udp 分组未知字段失败
- WHEN YAML 中 udp target 的
udp分组包含dnsQuery、expectResponse或其他未知字段 - THEN 系统 SHALL 以配置错误退出,提示 udp 分组包含未知字段
Scenario: udp 序列化展示摘要
- WHEN 系统同步 udp target 到 targets 表
- THEN
target展示摘要 SHALL 为udp <host>:<port>,configJSON SHALL 包含 resolved 后的 host、port、payload、encoding、responseEncoding 和 maxResponseBytes
Requirement: udp payload 编码
系统 SHALL 支持将 udp.payload 按 udp.encoding 解码为发送字节,编码类型限定为 text、hex 和 base64。
Scenario: text payload 编码
- WHEN udp target 配置
udp.payload: "PING"且udp.encoding未配置或为text - THEN 系统 SHALL 以 UTF-8 字节发送
PING
Scenario: hex payload 编码
- WHEN udp target 配置
udp.payload: "50494e47"和udp.encoding: "hex" - THEN 系统 SHALL 解码 hex 后发送字节内容
PING
Scenario: base64 payload 编码
- WHEN udp target 配置
udp.payload: "UElORw=="和udp.encoding: "base64" - THEN 系统 SHALL 解码 base64 后发送字节内容
PING
Scenario: 非法 encoding 失败
- WHEN YAML 中 udp target 配置
udp.encoding: "json" - THEN 系统 SHALL 以配置错误退出,提示 udp.encoding 必须为
text、hex或base64
Scenario: 非法 responseEncoding 失败
- WHEN YAML 中 udp target 配置
udp.responseEncoding: "json" - THEN 系统 SHALL 以配置错误退出,提示 udp.responseEncoding 必须为
text、hex或base64
Scenario: 非法 hex payload 失败
- WHEN YAML 中 udp target 配置
udp.encoding: "hex"但udp.payload不是合法 hex 字符串 - THEN 系统 SHALL 以配置错误退出,提示 udp.payload 与 udp.encoding 不匹配
Scenario: 非法 base64 payload 失败
- WHEN YAML 中 udp target 配置
udp.encoding: "base64"但udp.payload不是合法 base64 字符串 - THEN 系统 SHALL 以配置错误退出,提示 udp.payload 与 udp.encoding 不匹配
Requirement: udp checker 执行
系统 SHALL 使用 Bun connected UDP socket 向目标发送单个 datagram,等待第一个 UDP 响应 datagram,记录完整执行耗时和 UDP observation,并在发送失败、超时、资源超限或底层 socket 错误时产生结构化失败信息。
Scenario: UDP 请求响应成功
- WHEN udp target 指向会返回
PONG的 UDP 服务,且未配置 expect 或expect.responded为true - THEN 系统 SHALL 记录
matched=true、durationMs和包含响应大小的 observation,并关闭 socket
Scenario: 使用 hostname 执行 UDP 探测
- WHEN udp target 的
udp.host为可解析域名或localhost - THEN 系统 SHALL 使用 Bun connected UDP socket 完成发送和接收,不要求配置 IP 地址
Scenario: 只处理第一个响应 datagram
- WHEN UDP 服务对一次请求返回多个 datagram
- THEN 系统 SHALL 仅使用第一个收到的 UDP datagram 执行 expect 校验,并关闭 socket
Scenario: UDP 无响应且默认期望响应
- WHEN udp target 指向在 timeout 内不返回 UDP datagram 的服务,且未配置 expect 或
expect.responded为true - THEN 系统 SHALL 在
ctx.signalabort 后记录matched=false,observation SHALL 包含 responded=false 和 error,failure 的 kind 为error,phase 为response,message 包含超时或未响应信息
Scenario: 期望无响应且实际无响应
- WHEN udp target 配置
expect.responded: false,且 timeout 内未收到 UDP datagram - THEN 系统 SHALL 记录
matched=true,observation SHALL 包含 responded=false,API detail SHALL 表示未收到响应
Scenario: 期望无响应但实际收到响应
- WHEN udp target 配置
expect.responded: false,但收到了 UDP datagram - THEN 系统 SHALL 记录
matched=false,observation SHALL 包含 responded=true 和响应摘要,failure 的 kind 为mismatch,phase 为responded
Scenario: UDP socket 底层错误
- WHEN Bun UDP socket 在发送或接收过程中触发 error 事件
- THEN 系统 SHALL best-effort 关闭 socket,并记录
matched=false、failure.kind=error和可读错误信息,并在可收集时记录 observation
Scenario: ICMP unreachable 不作为 UDP 响应
- WHEN 底层系统因目标端口不可达产生 ICMP unreachable
- THEN 系统 SHALL NOT 将其视为
responded=true的 UDP datagram 响应
Scenario: UDP 执行超时关闭 socket
- WHEN 引擎注入的
ctx.signal在 UDP 发送或等待响应过程中 abort - THEN 系统 SHALL best-effort 关闭 UDP socket,并记录结构化超时或未响应结果
Requirement: udp 响应大小限制
系统 SHALL 使用 udp.maxResponseBytes 限制单个 UDP 响应 datagram 的可处理字节数,默认值为 4096,支持数字或 size string。
Scenario: 响应大小未超过限制
- WHEN udp target 配置
udp.maxResponseBytes: 4096,且实际响应为 16 字节 - THEN 系统 SHALL 允许后续 expect 校验继续执行
Scenario: 响应大小超过限制
- WHEN udp target 配置
udp.maxResponseBytes: 4,且实际响应为 16 字节 - THEN 系统 SHALL 返回
matched=false,failure 的 kind 为error,phase 为response,message 包含响应超过大小限制的信息
Scenario: Bun 标记 datagram 被截断
- WHEN Bun UDP data 回调中的
flags.truncated为true - THEN 系统 SHALL 返回
matched=false,failure 的 kind 为error,phase 为response,message 包含响应被截断的信息
Scenario: maxResponseBytes 格式非法
- WHEN YAML 中 udp target 或 defaults.udp 的
maxResponseBytes不是非负整数或合法 size string - THEN 系统 SHALL 以配置错误退出,提示 maxResponseBytes 格式错误
Requirement: udp expect 校验
系统 SHALL 支持 udp 专属 expect,包括 responded、response、responseSize、sourceHost、sourcePort 和 durationMs,并按 responded、responseSize、response、sourceHost、sourcePort、durationMs 的阶段顺序快速失败。responded SHALL 保持布尔状态语义,未配置时在 Resolved expect 中默认 true。response MUST 使用共享 RawContentExpectations 数组输入并在运行期使用 ContentExpectations,且作用于按 udp.responseEncoding 转换后的响应文本。responseSize、sourceHost、sourcePort 和 durationMs SHALL 使用共享 RawValueExpectation 输入并在运行期使用 ValueExpectation。
Scenario: 默认 responded 成功语义
- WHEN udp target 未显式配置
expect.responded - THEN 系统 SHALL 在 Resolved udp expect 中使用默认
responded: true进行校验
Scenario: response ContentExpectations 校验通过
- WHEN udp target 配置
expect.response: [{ contains: "PONG" }],且按responseEncoding转换后的响应文本包含PONG - THEN 系统 SHALL 判定 response 阶段通过
Scenario: response JSON 校验通过
- WHEN udp target 收到文本响应
{"status":"ok"}且配置expect.response: [{json: {path: "$.status", equals: "ok"}}] - THEN 系统 SHALL 判定 response 阶段通过
Scenario: response ContentExpectations 校验失败
- WHEN udp target 配置
expect.response: [{ contains: "PONG" }],但按responseEncoding转换后的响应文本不包含PONG - THEN 系统 SHALL 返回
matched=false,failure 的 kind 为mismatch,phase 为response,path 指向失败的 response expectation
Scenario: responseEncoding 为 hex
- WHEN udp target 配置
udp.responseEncoding: "hex"且收到字节内容PONG - THEN 系统 SHALL 将响应转换为小写 hex 字符串
504f4e47后执行expect.responseexpectation
Scenario: responseSize matcher 校验通过
- WHEN udp target 配置
expect.responseSize: { gte: 4 },且实际响应为 4 字节 - THEN 系统 SHALL 判定 responseSize 阶段通过
Scenario: responseSize matcher 校验失败
- WHEN udp target 配置
expect.responseSize: { gte: 4 },但实际响应为 2 字节 - THEN 系统 SHALL 返回
matched=false,failure 的 kind 为mismatch,phase 为responseSize
Scenario: sourceHost matcher 校验
- WHEN udp target 配置
expect.sourceHost: { equals: "127.0.0.1" },且 Bun 回调中的来源地址为127.0.0.1 - THEN 系统 SHALL 判定 sourceHost 阶段通过
Scenario: sourcePort matcher 校验
- WHEN udp target 配置
expect.sourcePort: { equals: 9000 },且 Bun 回调中的来源端口为9000 - THEN 系统 SHALL 判定 sourcePort 阶段通过
Scenario: durationMs 校验
- WHEN udp target 配置
expect.durationMs: {lte: 100},且完整执行耗时超过 100ms - THEN 系统 SHALL 返回
matched=false,failure 的 phase 为duration
Scenario: response 断言要求实际有响应
- WHEN udp target 配置了
expect.response或expect.responseSize,但同时配置expect.responded: false - THEN 系统 SHALL 在启动期配置校验失败,提示响应内容或大小断言需要
expect.responded为 true
Scenario: source 断言要求实际有响应
- WHEN udp target 配置了
expect.sourceHost或expect.sourcePort,但同时配置expect.responded: false - THEN 系统 SHALL 在启动期配置校验失败,提示响应来源断言需要
expect.responded为 true
Scenario: udp expect 未知字段失败
- WHEN YAML 中 udp target 的 expect 包含
status: [200]、maxDurationMs: 1000或其他非 udp expect 字段 - THEN 系统 SHALL 以配置错误退出,提示 expect 包含未知字段
Requirement: udp detail 摘要
系统 SHALL 在 udp API 序列化时从 observation 动态生成简短 detail 摘要,展示关键结果和执行耗时并避免返回过长响应内容。UDP observation SHALL 包含 durationMs 以支持 detail 构造。
Scenario: 收到响应的摘要
- WHEN udp target 收到 4 字节响应且完整执行耗时为 12ms
- THEN detail SHALL 包含
responded in 12ms和4 bytes
Scenario: 未收到响应的摘要
- WHEN udp target 配置
expect.responded: false且 timeout 内未收到 UDP datagram - THEN detail SHALL 包含
no response和执行耗时
Scenario: 响应内容摘要截断
- WHEN udp target 收到较长响应内容
- THEN detail SHALL 只展示按
responseEncoding转换并截断后的响应摘要