CAPL Script

CAPL 测试模块:有界等待与超时检查

只验证一个明确的承诺

本例的承诺是:开始等待后 500 ms 内,观察到 CAN1 上 ID 0x200 的接收数据帧,至少两个字节,首字节为 0xAA。它验证的是周期心跳的可用性和最小载荷约定,不验证门锁动作、请求响应因果关系或每次发送间隔。

发送端可使用周期定时器教程。建立支持 Test Feature Set 的 CAPL 测试模块,并限制为单 CAN 通道配置,避免其他通道同 ID 的事件提前解除等待。下面代码包含一个 testcase 和入口 MainTest;不要放入普通仿真节点当作定时器程序。请先核实许可、模块类型、通道上下文和已安装版本 API。

有界等待必须检查返回值

TestWaitForMessage 返回值 含义 本例处理
1 匹配消息事件发生 读取触发本次等待的帧,再检查内容
0 超时 记录未在期限内观察到事件
-2 约束违规导致恢复执行 单独记录中断原因,不归为普通超时
-1 或其他异常值 错误或功能不可用等 记录返回码,不继续读取旧数据

等待参数是毫秒。参考资料说明,传入 0 表示不进行超时控制;这里必须使用有界的 500。收到消息后,用 TestGetWaitEventMsgData 获取刚刚解除等待的消息。该函数返回 0 才表示读取成功;不要把这两个 API 的成功返回值混用。

示例测试模块

源代码已对照可用参考资料,尚未在 CANoe 中编译或执行。本例的通过步骤只代表被观察帧满足这里列出的条件。

testcase TC_HeartbeatAvailability()
{
  long waitResult;
  long dataResult;
  message CAN1.0x200 observed;

  TestCaseTitle("HB-01", "Observe a valid heartbeat within 500 ms");
  TestStep("1", "Wait for ID 0x200 in the single-channel test setup");
  waitResult = TestWaitForMessage(0x200, 500);

  if (waitResult == 0)
  {
    TestStepFail("2", "Timeout: no matching message observed within 500 ms");
    return;
  }
  if (waitResult == -2)
  {
    TestStepFail("2", "Wait interrupted by a constraint violation");
    return;
  }
  if (waitResult != 1)
  {
    TestStepFail("2", "Wait failed or is unavailable: result=%d", waitResult);
    return;
  }

  dataResult = TestGetWaitEventMsgData(observed);
  if (dataResult != 0)
  {
    TestStepFail("3", "Could not retrieve the triggering frame: result=%d", dataResult);
    return;
  }
  if (observed.CAN != 1 || observed.DIR != Rx || observed.RTR != 0)
  {
    TestStepFail("3", "Unexpected channel, direction or frame type");
    return;
  }
  if (observed.DLC < 2)
  {
    TestStepFail("3", "Heartbeat payload is shorter than two bytes");
    return;
  }
  if (observed.byte(0) != 0xAA)
  {
    TestStepFail("4", "Wrong marker: expected 0xAA, got 0x%02X", observed.byte(0));
    return;
  }
  TestStepPass("4", "Observed a two-byte heartbeat with marker 0xAA");
}

void MainTest()
{
  TC_HeartbeatAvailability();
}

先检查数据获取结果、通道、方向、帧类型和 DLC,再读载荷,可以避免把缓存旧值或长度不足的帧当成正确响应。这里没有使用另一个 on message 处理函数中的全局 doorStatus,因此不依赖两个处理路径之间的数据更新时间。

同时验证失败路径

下面是一份待执行矩阵,不是通过报告。每次运行前只保留本场景的受控发送源,并重置测试环境。

场景 操作 应检查的结果
正常心跳 运行两字节 AA 心跳发送节点 最终内容检查步骤通过
无心跳 发送节点按 x 停止,等已提交流量结束,再启动用例 500 ms 后走超时分支
长度不足 独立发送源用相同 ID 发送 DLC 1 长度检查失败,不能读第二字节
标记错误 DLC 2,首字节改为 AB 内容检查失败,报文到达本身不能让测试通过
配置错误 核实模块支持或约束触发情况 按实际返回码记录,不能伪造为超时

如果错误帧先到、正确帧稍后到,本例会在第一帧处失败。若需求允许重试,应另外定义一个总截止时间;不要每次循环都重新等待完整的 500 ms,否则总等待时间会超过承诺。

接收可用性不等于功能正确

一条心跳可能与刚发送的命令无关。真正的请求响应测试需要明确的关联字段、状态转换或请求序号,还要处理旧响应和无关周期消息。不要在 output 调用后直接写“发送成功”,也不要仅因 TestWaitForMessage 返回 1 就判定门锁已经锁上。

周期稳定性请用时间戳教程和间隔工具检查。单次 500 ms 等待不能替代多帧周期统计。

记录执行版本、测试台架、源文件、配置、期望值与完整测试报告,再谈实测结果。API 依据为获授权参考资料中的 TestWaitForMessage、TestGetWaitEventMsgData 和 TestStep;可对照 Vector Test Feature Set 教程,该链接可能需要登录。本站未以官方示例的运行结果替代本例验证。