Skip to content

Support ordered shell initialization steps across terminal conte #169

Description

@YanLien

问题

目前 ostool 只支持一组顶层 shell 初始化配置:

shell_prefix = "root@starry:/root #"
shell_init_cmd = "echo pass"
success_regex = ["(?m)^pass\\s*$"]

这种配置要求 runner 启动后已经位于目标 shell。

Axvisor 引入 guest console 隔离后,物理终端默认停留在 Axvisor shell,guest 串口日志由 Axvisor 缓存。测试需要按下面的顺序操作:

Axvisor shell
    -> vm console 1
    -> guest shell
    -> guest test command

现有的单组 shell_prefixshell_init_cmd 无法表达这个过程。

实际失败日志中,Axvisor 已经成功启动 guest,但 ostool 一直停留在 Axvisor shell,最终等待 guest 成功标记超时:

axvisor:/$
kernel boot timed out after 300s

手动输入 vm console 1 后,可以看到 guest 日志并继续测试。

建议方案

为 QEMU、U-Boot 和 board 配置增加显式有序数组 shell_init_steps

shell_check_steps = [
  {
    name = "attach guest",
    shell_prefix = "axvisor:/$",
    shell_cmd = "vm console 1"
  },
  {
    name = "run guest test",
    shell_prefix = "root@starry:/root #",
    shell_cmd = "pwd && echo 'starry guest test pass'",
    success_regex = ["(?m)^starry guest test pass\\s*$"],
    fail_regex = ["(?i)failed", "(?i)panic"],
    timeout = 30
  },
]

数组下标就是执行顺序。

每一步支持:

pub struct ShellCheckStep {
    pub name: Option<String>,
    pub shell_prefix: Option<String>,
    pub shell_cmd: String,
    pub success_regex: Option<Vec<String>>,
    pub fail_regex: Option<Vec<String>>,
    pub timeout: Option<u64>,
}

配置语义

shell prefix

  • 第一步必须配置非空的 shell_prefix
  • 后续步骤省略 shell_prefix 时,继承前一步。
  • 显式配置空字符串时报错。
  • shell_prefix 使用普通字符串匹配,不作为正则处理。

例如:

shell_check_steps = [
  { shell_prefix = "root#", shell_cmd = "cd /tmp" },
  { shell_cmd = "./test", success_regex = ["PASS"] },
]

第二步继承 root#

success 和 fail

  • shell_check_steps 之间严格按数组顺序执行。只有当前步骤完成后,才会进入下一步;不能跨步骤匹配,也不能跳过中间步骤。
  • 单个步骤内部可以配置多个 success_regex。当前步骤的任意一个 success 匹配后,该步骤完成并进入下一步。
  • 单个步骤内部也可以配置多个 fail_regex。当前步骤的任意一个 fail 匹配后,该步骤立即失败,整个测试结束。
  • 当前步骤的同一批输出同时匹配 success 和 fail 时,fail 优先。
  • 不允许只配置 fail_regex 而没有 success_regex,因为这种步骤没有明确的成功条件。

可以概括为:步骤之间是顺序 AND;单个步骤内部的 success_regex 是 OR,fail_regex 也是 OR。

没有结果表达式的步骤

如果某一步没有配置 success_regexfail_regex,命令完成 write/flush 后直接进入下一步:

{ shell_prefix = "axvisor:/$", shell_cmd = "vm console 1" }

这只能证明命令已经送入终端,不能单独证明命令执行成功。通常由下一步 guest prefix 证明 console 切换已经生效。

timeout

  • 步骤 timeout 从命令完成 write/flush 后开始。
  • 它只覆盖该步骤等待结果的阶段。
  • 顶层 timeout 继续作为整个运行过程的总超时。
  • timeout 和成功匹配必须是互斥的状态转换,不能在截止时间附近同时把测试标记为成功和失败。

只读取 guest 启动结果

有些测试不需要在 guest shell 执行命令,但成功标记只存在于 guest console。只有当前 Axvisor 输出流确实看不到该标记时,才需要 attach。

这种情况只需要一个步骤:

success_regex = []
fail_regex = [
  "(?i)kernel panic",
  "(?m)^AXVISOR_X86_ACPI_FAILED\\s*$",
]

shell_check_steps = [
  {
    shell_prefix = "axvisor:/$",
    shell_cmd = "vm console 1",
    success_regex = ["(?m)^AXVISOR_GUEST_PASSED\\s*$"],
    fail_regex = ["(?i)kernel panic"]
  },
]

ostool 发送 vm console 1 后,由当前步骤从 Axvisor 回放的 guest 日志中匹配结果。若 ACPI、timer 等测例的成功标记本来就在当前流中,则应保持原配置,不添加步骤。

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions