1
0
Files
DiAL/openspec/specs/icmp-checker/spec.md
lanyuanxiaoyao 60a54b483f refactor: expect 类型模型重构,Raw/Resolved 双层分离与断言基础设施内聚
- 重命名 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)
2026-05-20 16:12:48 +08:00

12 KiB
Raw Blame History

Purpose

定义 ICMP checker 的配置格式、命令执行、跨平台输出解析、expect 校验、失败结构和状态摘要。

Requirements

Requirement: icmp target 配置

系统 SHALL 支持 type: icmp 的 target 配置,通过 icmp.host 描述目标主机地址,并通过可选字段控制探测行为。

Scenario: 解析最简 icmp target

  • WHEN YAML 中 target 配置 type: icmpicmp.host: "10.0.0.1"
  • THEN 系统 SHALL 将其解析为 icmp checker并填充 count=3packetSize=56、interval、timeout、group 和 expect 配置

Scenario: icmp target 缺少 host

  • WHEN YAML 中 target 配置 type: icmp 但缺少 icmp.host
  • THEN 系统 SHALL 以配置错误退出,并提示该 target 缺少 icmp.host 字段

Scenario: icmp host 类型非法

  • WHEN YAML 中 icmp target 的 icmp.host 不是非空字符串
  • THEN 系统 SHALL 以配置错误退出,提示 icmp.host 必须为非空字符串

Scenario: icmp count 配置

  • WHEN YAML 中 icmp target 配置 icmp.count: 5
  • THEN 系统 SHALL 使用 5 作为 ICMP 包发送数量

Scenario: icmp count 非法

  • WHEN YAML 中 icmp target 的 icmp.count 不是 1 到 100 之间的正整数
  • THEN 系统 SHALL 以配置错误退出,提示 icmp.count 必须为 1-100 的正整数

Scenario: icmp packetSize 配置

  • WHEN YAML 中 icmp target 配置 icmp.packetSize: 1472
  • THEN 系统 SHALL 使用 1472 作为 ICMP 包大小bytes

Scenario: icmp packetSize 非法

  • WHEN YAML 中 icmp target 的 icmp.packetSize 不是 1 到 65500 之间的正整数
  • THEN 系统 SHALL 以配置错误退出,提示 icmp.packetSize 必须为 1-65500 的正整数

Scenario: icmp 分组未知字段失败

  • WHEN YAML 中 icmp target 的 icmp 分组包含 timeout: 5 等未知字段
  • THEN 系统 SHALL 以配置错误退出,提示 icmp 分组包含未知字段

Scenario: icmp 序列化展示摘要

  • WHEN 系统同步 icmp target 到 targets 表
  • THEN target 展示摘要 SHALL 为 icmp <host>config JSON SHALL 包含 resolved 后的 host、count 和 packetSize

Requirement: icmp checker 执行

系统 SHALL 通过调用系统 ping 命令执行 ICMP 探测,记录完整执行耗时,并在命令不可用、超时或解析失败时产生结构化失败信息。IcmpChecker SHALL 通过构造函数参数支持 platform 注入,默认使用 process.platform

Scenario: ping 命令构建Linux

  • WHEN 系统平台为 linuxicmp target 配置 host="10.0.0.1"、count=3、packetSize=56且外层 timeoutMs=10000
  • THEN 系统 SHALL 执行 ping -c 3 -s 56 -W 10 10.0.0.1-W 单位为秒,向上取整)

Scenario: ping 命令构建macOS

  • WHEN 系统平台为 darwinicmp target 配置 host="10.0.0.1"、count=3、packetSize=56且外层 timeoutMs=10000
  • THEN 系统 SHALL 执行 ping -c 3 -s 56 -W 10000 10.0.0.1-W 单位为毫秒)

Scenario: ping 命令构建Windows

  • WHEN 系统平台为 win32icmp target 配置 host="10.0.0.1"、count=3、packetSize=56且外层 timeoutMs=10000
  • THEN 系统 SHALL 执行 ping -n 3 -l 56 -w 10000 10.0.0.1-w 单位为毫秒)

Scenario: ping 命令不存在

  • WHEN 系统未安装 ping 命令spawn 抛出 ENOENT
  • THEN 系统 SHALL 记录 matched=falsefailure 的 kind 为 errorphase 为 icmppath 为 spawnmessage 包含 "icmp 命令不可用" 和原始错误信息

Scenario: ping 执行超时

  • WHEN 引擎注入的 ctx.signal 在 ping 命令执行过程中 abort
  • THEN 系统 SHALL 调用 proc.kill() 终止子进程,记录 matched=falsefailure 的 kind 为 errorphase 为 icmpmessage 包含超时信息

Scenario: ping 目标可达

  • WHEN icmp target 指向可达主机,且 ping 命令正常返回
  • THEN 系统 SHALL 解析 stdout 获取统计数据,并按断言链执行 expect 校验

Scenario: ping 目标不可达

  • WHEN icmp target 指向不可达主机,且 ping 命令返回 100% packet loss
  • THEN 系统 SHALL 解析 stdout 获取统计数据,alive 为 false延迟字段为 null

Scenario: duration 覆盖完整执行

  • WHEN ping 命令执行完成
  • THEN 结果中的 durationMs SHALL 覆盖从 spawn 到进程退出的完整耗时

Scenario: platform 注入用于测试

  • WHEN 构造 new IcmpChecker("linux")
  • THEN execute 方法 SHALL 使用注入的 "linux" 作为平台参数,而非 process.platform

Requirement: 跨平台 icmp 输出解析

系统 SHALL 实现跨平台 ping 输出解析器,支持 Linux、macOS 和 Windows含多语言 locale从 stdout 中提取 transmitted、received、packetLoss、minLatencyMs、avgLatencyMs、maxLatencyMs。

Scenario: 解析 Linux ping 输出

  • WHEN 平台为 linuxstdout 包含 "3 packets transmitted, 3 received, 0% packet loss" 和 "rtt min/avg/max/mdev = 1.234/2.345/3.456/0.567 ms"
  • THEN 系统 SHALL 解析为 transmitted=3, received=3, packetLoss=0, minLatencyMs=1.234, avgLatencyMs=2.345, maxLatencyMs=3.456

Scenario: 解析 macOS ping 输出

  • WHEN 平台为 darwinstdout 包含 "3 packets transmitted, 3 packets received, 0.0% packet loss" 和 "round-trip min/avg/max/stddev = 1.234/2.345/3.456/0.567 ms"
  • THEN 系统 SHALL 解析为 transmitted=3, received=3, packetLoss=0, minLatencyMs=1.234, avgLatencyMs=2.345, maxLatencyMs=3.456

Scenario: 解析 Windows 英文 ping 输出

  • WHEN 平台为 win32stdout 包含 "Packets: Sent = 3, Received = 3, Lost = 0 (0% loss)" 和 "Minimum = 1ms, Maximum = 3ms, Average = 2ms"
  • THEN 系统 SHALL 解析为 transmitted=3, received=3, packetLoss=0, minLatencyMs=1, avgLatencyMs=2, maxLatencyMs=3

Scenario: 解析 Windows 中文 ping 输出

  • WHEN 平台为 win32stdout 包含 "数据包: 已发送 = 3已接收 = 3丢失 = 0 (0% 丢失)" 和 "最短 = 1ms最长 = 3ms平均 = 2ms"
  • THEN 系统 SHALL 解析为 transmitted=3, received=3, packetLoss=0, minLatencyMs=1, avgLatencyMs=2, maxLatencyMs=3

Scenario: 解析全部丢包(无延迟行)

  • WHEN stdout 包含丢包统计行但无延迟统计行100% packet loss
  • THEN 系统 SHALL 解析为 alive=false延迟字段min/avg/max均为 null

Scenario: 输出无法解析

  • WHEN stdout 不匹配任何已知的统计行格式
  • THEN 系统 SHALL 记录 matched=falsefailure 的 kind 为 errorphase 为 icmppath 为 parsemessage 包含 "无法解析 icmp 输出"

Requirement: icmp expect 校验

系统 SHALL 支持 icmp 专属 expect包括 alivepacketLossPercentavgLatencyMsmaxLatencyMsdurationMs,并按 alive、packetLossPercent、avgLatencyMs、maxLatencyMs、durationMs 的阶段顺序快速失败。alive SHALL 保持布尔状态语义,未配置时在 Resolved expect 中默认 truepacketLossPercent SHALL 表示 0 到 100 的丢包率百分比,并使用共享 RawValueExpectation 输入、运行期 ValueExpectation 执行。avgLatencyMsmaxLatencyMsdurationMs SHALL 使用共享 RawValueExpectation 输入、运行期 ValueExpectation 执行。

Scenario: 默认 alive 成功语义

  • WHEN icmp target 未显式配置 expect.alive
  • THEN 系统 SHALL 在 Resolved icmp expect 中使用默认 alive: true 进行校验

Scenario: alive 校验通过

  • WHEN icmp target 配置 expect.alive: true,且目标主机可达
  • THEN 系统 SHALL 判定 alive 阶段通过

Scenario: alive 校验失败

  • WHEN icmp target 配置 expect.alive: true,且目标主机不可达
  • THEN 系统 SHALL 返回 matched=falsefailure 的 kind 为 mismatchphase 为 alive

Scenario: 反向 alive 断言

  • WHEN icmp target 配置 expect.alive: false,且目标主机不可达
  • THEN 系统 SHALL 判定 alive 阶段通过(matched=true

Scenario: packetLossPercent 校验通过

  • WHEN icmp target 配置 expect.packetLossPercent: {lte: 10},且实际丢包率为 0%
  • THEN 系统 SHALL 判定 packetLossPercent 阶段通过

Scenario: packetLossPercent 校验失败

  • WHEN icmp target 配置 expect.packetLossPercent: {lte: 10},且实际丢包率为 33%
  • THEN 系统 SHALL 返回 matched=falsefailure 的 kind 为 mismatchphase 为 packetLoss

Scenario: avgLatencyMs 校验通过

  • WHEN icmp target 配置 expect.avgLatencyMs: {lte: 200},且实际平均延迟为 12ms
  • THEN 系统 SHALL 判定 avgLatency 阶段通过

Scenario: avgLatencyMs 校验失败

  • WHEN icmp target 配置 expect.avgLatencyMs: {lte: 100},且实际平均延迟为 156ms
  • THEN 系统 SHALL 返回 matched=falsefailure 的 kind 为 mismatchphase 为 avgLatency

Scenario: maxLatencyMs 校验通过

  • WHEN icmp target 配置 expect.maxLatencyMs: {lte: 500},且实际最大延迟为 340ms
  • THEN 系统 SHALL 判定 maxLatency 阶段通过

Scenario: maxLatencyMs 校验失败

  • WHEN icmp target 配置 expect.maxLatencyMs: {lte: 200},且实际最大延迟为 340ms
  • THEN 系统 SHALL 返回 matched=falsefailure 的 kind 为 mismatchphase 为 maxLatency

Scenario: durationMs 校验

  • WHEN icmp target 配置 expect.durationMs: {lte: 5000},且完整执行耗时超过 5000ms
  • THEN 系统 SHALL 返回 matched=falsefailure 的 phase 为 duration

Scenario: alive=false 时跳过延迟断言

  • WHEN icmp target 配置 expect.alive: trueexpect.avgLatencyMs: {lte: 100},且目标不可达
  • THEN 系统 SHALL 在 alive 阶段即返回失败,不执行后续延迟断言

Scenario: icmp expect 未知字段失败

  • WHEN YAML 中 icmp target 的 expect 包含 status: [200]maxPacketLossmaxAvgLatencyMsmaxMaxLatencyMsmaxDurationMs 或其他非 icmp expect 字段
  • THEN 系统 SHALL 以配置错误退出,提示 expect 包含未知字段

Scenario: packetLossPercent 类型非法

  • WHEN YAML 中 icmp target 的 expect.packetLossPercent 不是合法 RawValueExpectation,或其数值范围无法用于 0 到 100 的百分比断言
  • THEN 系统 SHALL 以配置错误退出,提示 expect.packetLossPercent 格式错误

Scenario: avgLatencyMs 类型非法

  • WHEN YAML 中 icmp target 的 expect.avgLatencyMs 不是合法 RawValueExpectation
  • THEN 系统 SHALL 以配置错误退出,提示 expect.avgLatencyMs 格式错误

Scenario: maxLatencyMs 类型非法

  • WHEN YAML 中 icmp target 的 expect.maxLatencyMs 不是合法 RawValueExpectation
  • THEN 系统 SHALL 以配置错误退出,提示 expect.maxLatencyMs 格式错误

Scenario: Raw icmp expect 不被校验阶段修改

  • WHEN YAML 中 icmp target 配置 expect.durationMs: 5000
  • THEN 语义校验 SHALL 接受该 Raw primitive 简写且 MUST NOT 将输入对象原地改写为 {equals: 5000}

Requirement: icmp detail 摘要

系统 SHALL 在 icmp API 序列化时从 observation 动态生成结构化 detail 摘要展示关键指标。API registry type SHALL 仍为 icmp

Scenario: 目标可达无丢包

  • WHEN icmp observation 为 alive=true, avgLatencyMs=12, packetLoss=0%, transmitted=3, received=3
  • THEN detail SHALL 为 alive, avg 12ms, loss 0% (3/3)

Scenario: 目标可达有丢包

  • WHEN icmp observation 为 alive=true, avgLatencyMs=156, maxLatencyMs=340, packetLoss=33%, transmitted=3, received=2
  • THEN detail SHALL 包含 avg、max 和 loss 信息

Scenario: 目标不可达

  • WHEN icmp observation 为 alive=false, transmitted=3, received=0
  • THEN detail SHALL 为 unreachable (0/3 received)