2026-08-04 18:08:08 +08:00
|
|
|
|
#requires -Version 5.1
|
2026-07-31 13:53:49 +08:00
|
|
|
|
<#
|
|
|
|
|
|
.SYNOPSIS
|
|
|
|
|
|
userapps-matrix — 用户态程序功能矩阵(docs/RE/test-cases/userapps-matrix.md)
|
|
|
|
|
|
|
|
|
|
|
|
.DESCRIPTION
|
2026-08-04 18:08:08 +08:00
|
|
|
|
dev_mode 单会话覆盖 shell 内建命令与工具程序(串口镜像开启,全程可断言)。
|
2026-07-31 13:53:49 +08:00
|
|
|
|
|
2026-08-04 18:08:08 +08:00
|
|
|
|
会话 A(唯一):dev_tests 硬编码序列 → help → id → pci 存活 →
|
|
|
|
|
|
ping(PATH 加载 → 10.0.2.2 四报文 → Esc 退出)→
|
|
|
|
|
|
run EDITOR.ELF / FILEMAN.ELF / BROWSER.ELF(加载 + 按键 + Esc 退出)→
|
|
|
|
|
|
Esc 回 DSK → cmd(AUTOEXEC) → desktop
|
2026-07-31 13:53:49 +08:00
|
|
|
|
|
2026-08-04 18:08:08 +08:00
|
|
|
|
历史背景(详见 docs/RE/Bug记录.txt,均已 FIXED,相关降级已全部回收):
|
2026-07-31 13:53:49 +08:00
|
|
|
|
|
2026-08-04 18:08:08 +08:00
|
|
|
|
BUG-20260801-001 [shell] y/i/0 吞键(未跟踪 Ctrl 修饰键):
|
|
|
|
|
|
已修复(0x1D/0x9D 跟踪 Ctrl,快捷键仅在 Ctrl 按下时生效)
|
|
|
|
|
|
→ id/ping 等含 i 命令恢复自动化断言。
|
|
|
|
|
|
|
|
|
|
|
|
BUG-20260801-002 [shell] g_run_image 仅 256KB,editor(496KB) 拒绝加载:
|
|
|
|
|
|
已修复(g_run_image 扩至 1MB,与 desktop 宿主对齐)
|
|
|
|
|
|
→ run EDITOR.ELF 断言升级为 [editor] boot + [editor] exit。
|
|
|
|
|
|
|
|
|
|
|
|
BUG-20260801-003 [desktop_app.h] da_mouse_poll 吞键盘扫描码 +
|
|
|
|
|
|
BUG-20260801-008 [desktop_app.h] da_mouse_init 配置字污染:
|
|
|
|
|
|
均已修复(先判 AUX 位再读 0x60;init 首尾 da_ps2_drain + 读全响应)
|
|
|
|
|
|
→ fileman/editor/browser 键盘路径恢复,Esc 退出断言全部自动化;
|
|
|
|
|
|
工具不再占住会话,三会合并为单会话顺序执行。
|
2026-07-31 13:53:49 +08:00
|
|
|
|
|
|
|
|
|
|
退出码:全部通过 0,任一 FAIL 1。
|
|
|
|
|
|
#>
|
|
|
|
|
|
param([switch]$Build)
|
|
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
|
|
. (Join-Path $PSScriptRoot 'lib\QemuTest.ps1')
|
|
|
|
|
|
|
|
|
|
|
|
Initialize-QemuTest -Build:$Build
|
|
|
|
|
|
$result = New-TestCaseResult 'userapps-matrix'
|
|
|
|
|
|
|
2026-08-04 18:08:08 +08:00
|
|
|
|
# ----------------------------------------------------------------
|
|
|
|
|
|
# monitor sendkey 在 guest 重负载(AHCI 读盘刷屏、帧缓冲重绘)下会丢扫描码。
|
|
|
|
|
|
# 对策:每键 150ms + "发送→等锚点→重试 ≤3 次",重试前先 backspace 清行。
|
|
|
|
|
|
# 注意:backspace(0x0E) 不在 shell Ctrl+U/W/K 快捷键扫描码列表内,清行可靠。
|
|
|
|
|
|
# ----------------------------------------------------------------
|
|
|
|
|
|
function Invoke-ShellCmdRetry {
|
|
|
|
|
|
param(
|
|
|
|
|
|
[Parameter(Mandatory)]$Session,
|
|
|
|
|
|
[Parameter(Mandatory)][string]$Text,
|
|
|
|
|
|
[Parameter(Mandatory)][string[]]$Anchors,
|
|
|
|
|
|
[int]$TimeoutSeconds = 20,
|
|
|
|
|
|
[int]$MaxAttempts = 3
|
|
|
|
|
|
)
|
|
|
|
|
|
for ($a = 1; $a -le $MaxAttempts; $a++) {
|
|
|
|
|
|
if ($a -gt 1) {
|
|
|
|
|
|
$bk = @(); for ($i = 0; $i -lt 24; $i++) { $bk += 'backspace' }
|
|
|
|
|
|
Send-QemuKeys -Session $Session -Keys $bk -DelayMs 50
|
|
|
|
|
|
Start-Sleep -Milliseconds 400
|
|
|
|
|
|
Add-TestNote $result "输入 '$Text' 第 $($a-1) 次未命中锚点,清行重试"
|
|
|
|
|
|
}
|
|
|
|
|
|
Send-QemuText -Session $Session -Text $Text -Enter -DelayMs 150
|
|
|
|
|
|
$h = Wait-QemuLog -Session $Session -Patterns $Anchors -TimeoutSeconds $TimeoutSeconds
|
|
|
|
|
|
if ($h) { return $h }
|
|
|
|
|
|
}
|
|
|
|
|
|
return $null
|
|
|
|
|
|
}
|
2026-07-31 13:53:49 +08:00
|
|
|
|
|
2026-08-04 18:08:08 +08:00
|
|
|
|
# Esc 退出重试:只在锚点未出现时补发,锚点出现即停(避免多余 Esc 漏进 shell/cmd)
|
|
|
|
|
|
function Send-EscRetry {
|
|
|
|
|
|
param(
|
|
|
|
|
|
[Parameter(Mandatory)]$Session,
|
|
|
|
|
|
[Parameter(Mandatory)][string[]]$Anchors,
|
|
|
|
|
|
[int]$TimeoutSeconds = 15,
|
|
|
|
|
|
[int]$MaxAttempts = 2
|
|
|
|
|
|
)
|
|
|
|
|
|
for ($a = 1; $a -le $MaxAttempts; $a++) {
|
|
|
|
|
|
Send-QemuKeys -Session $Session -Keys @('esc')
|
|
|
|
|
|
$h = Wait-QemuLog -Session $Session -Patterns $Anchors -TimeoutSeconds $TimeoutSeconds
|
|
|
|
|
|
if ($h) { return $h }
|
|
|
|
|
|
if ($a -lt $MaxAttempts) { Add-TestNote $result "Esc 第 $a 次未命中($($Anchors -join ' | ')),补发" }
|
2026-07-31 13:53:49 +08:00
|
|
|
|
}
|
2026-08-04 18:08:08 +08:00
|
|
|
|
return $null
|
|
|
|
|
|
}
|
2026-07-31 13:53:49 +08:00
|
|
|
|
|
2026-08-04 18:08:08 +08:00
|
|
|
|
try {
|
|
|
|
|
|
# ================================================================
|
|
|
|
|
|
# 会话 A(唯一):shell 内建命令 + ping/editor/fileman/browser
|
|
|
|
|
|
# 工具链全交互 + Esc→cmd→desktop 链路
|
|
|
|
|
|
# ================================================================
|
|
|
|
|
|
Set-DeshabFirstInit -First 1 -DevMode 1
|
|
|
|
|
|
Set-DeshabAutoexec -Lines @('ver', 'exit')
|
|
|
|
|
|
|
|
|
|
|
|
$s = Start-QemuSession -Name 'userapps-matrix' -MonitorPort 45505
|
|
|
|
|
|
try {
|
|
|
|
|
|
$hit = Wait-QemuLog -Session $s -Patterns @('=== 自动测试完成 ===', '[PANIC]') -TimeoutSeconds 240
|
|
|
|
|
|
$log = Read-QemuLogText $s.LogPath
|
|
|
|
|
|
$result.LogPath = $s.LogPath
|
|
|
|
|
|
|
|
|
|
|
|
Assert-QemuLog $result $log -Ordered @(
|
|
|
|
|
|
'[DSK:SCHED] decision: dev_mode -> shell.elf',
|
|
|
|
|
|
'[shell] boot',
|
|
|
|
|
|
'[shell] test.bas not found, fallback to hardcoded',
|
|
|
|
|
|
'[1] ls',
|
|
|
|
|
|
'[2] echo "Deshab dev test" > TEST.TXT',
|
|
|
|
|
|
'[3] cat TEST.TXT',
|
|
|
|
|
|
'[4] cp TEST.TXT COPY.TXT',
|
|
|
|
|
|
'[6] mv COPY.TXT MOVED.TXT',
|
|
|
|
|
|
'[8] rm TEST.TXT',
|
|
|
|
|
|
'[10] ls'
|
|
|
|
|
|
) -MustNotContain @('[PANIC]')
|
|
|
|
|
|
if ($hit -eq '=== 自动测试完成 ===') {
|
|
|
|
|
|
Add-TestCheck $result 'shell: dev_tests 完成(ls/echo/cat/cp/mv/rm)' 'PASS'
|
2026-07-31 13:53:49 +08:00
|
|
|
|
} else {
|
2026-08-04 18:08:08 +08:00
|
|
|
|
Add-TestCheck $result 'shell: dev_tests 完成(ls/echo/cat/cp/mv/rm)' 'FAIL' "hit=$hit"
|
2026-07-31 13:53:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-04 18:08:08 +08:00
|
|
|
|
if ($hit -eq '=== 自动测试完成 ===') {
|
|
|
|
|
|
# --- help ---
|
|
|
|
|
|
Start-Sleep -Seconds 1
|
|
|
|
|
|
$h = Invoke-ShellCmdRetry -Session $s -Text 'help' -Anchors @('dsl push <') -TimeoutSeconds 20
|
|
|
|
|
|
if ($h) { Add-TestCheck $result 'shell: help 命令列表' 'PASS' }
|
|
|
|
|
|
else { Add-TestCheck $result 'shell: help 命令列表' 'FAIL' 'missing help output' }
|
|
|
|
|
|
|
|
|
|
|
|
# --- id(BUG-001 修复回归守护:i 不再被吞,输出上串口) ---
|
|
|
|
|
|
$h = Invoke-ShellCmdRetry -Session $s -Text 'id' -Anchors @('uid=0(root) gid=0(root)') -TimeoutSeconds 20
|
|
|
|
|
|
if ($h) { Add-TestCheck $result 'shell: id 用户查询(BUG-001 修复后 i 可键入)' 'PASS' }
|
|
|
|
|
|
else { Add-TestCheck $result 'shell: id 用户查询(BUG-001 修复后 i 可键入)' 'FAIL' 'missing uid=0(root) output' }
|
|
|
|
|
|
|
|
|
|
|
|
# --- pci(验证存活:pci 后 ver 仍有响应,锚点取 ver 独有行) ---
|
|
|
|
|
|
Send-QemuText -Session $s -Text 'pci' -Enter -DelayMs 150
|
|
|
|
|
|
Start-Sleep -Seconds 3
|
|
|
|
|
|
$h = Invoke-ShellCmdRetry -Session $s -Text 'ver' -Anchors @('Architecture: x86_64') -TimeoutSeconds 20
|
|
|
|
|
|
if ($h) { Add-TestCheck $result 'shell: pci 枚举后 shell 存活' 'PASS' }
|
|
|
|
|
|
else { Add-TestCheck $result 'shell: pci 枚举后 shell 存活' 'FAIL' 'no response after pci' }
|
|
|
|
|
|
|
|
|
|
|
|
# --- ping:BUG-001 修复后可键入;PATH → /bin/PING.ELF → 10.0.2.2 四报文 → Esc 退出 ---
|
|
|
|
|
|
$h = Invoke-ShellCmdRetry -Session $s -Text 'ping' -Anchors @('[ping] boot') -TimeoutSeconds 30
|
|
|
|
|
|
if ($h) {
|
|
|
|
|
|
Add-TestCheck $result 'ping.elf: PATH 加载启动([ping] boot)' 'PASS'
|
|
|
|
|
|
Start-Sleep -Milliseconds 800
|
|
|
|
|
|
# 4 个 ICMP Echo(每报文超时上限 2s);reply/统计仅帧缓冲,串口无锚点
|
|
|
|
|
|
Send-QemuText -Session $s -Text '10.0.2.2' -Enter -DelayMs 150
|
|
|
|
|
|
Start-Sleep -Seconds 10
|
|
|
|
|
|
$h2 = Send-EscRetry -Session $s -Anchors @('[ping] exit') -TimeoutSeconds 15 -MaxAttempts 2
|
|
|
|
|
|
$logp = Read-QemuLogText $s.LogPath
|
|
|
|
|
|
if ($h2 -and $logp.Contains('[shell] path: tool returned')) {
|
|
|
|
|
|
Add-TestCheck $result 'ping.elf: Esc 退出返回 shell' 'PASS'
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Add-TestCheck $result 'ping.elf: Esc 退出返回 shell' 'FAIL' 'missing [ping] exit / path: tool returned'
|
|
|
|
|
|
}
|
2026-07-31 13:53:49 +08:00
|
|
|
|
} else {
|
2026-08-04 18:08:08 +08:00
|
|
|
|
Add-TestCheck $result 'ping.elf: PATH 加载启动([ping] boot)' 'FAIL' 'missing [ping] boot'
|
2026-07-31 13:53:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-04 18:08:08 +08:00
|
|
|
|
# --- editor:BUG-002 已修复(g_run_image 扩至 1MB),run 加载 → 按键插入 → Esc 退出 ---
|
|
|
|
|
|
$h = Invoke-ShellCmdRetry -Session $s -Text 'run EDITOR.ELF' -Anchors @('[editor] boot') -TimeoutSeconds 30
|
|
|
|
|
|
if ($h) {
|
|
|
|
|
|
Add-TestCheck $result 'editor.elf: run 加载启动([editor] boot,BUG-002 修复后行为)' 'PASS'
|
|
|
|
|
|
Start-Sleep -Seconds 1
|
|
|
|
|
|
Send-QemuText -Session $s -Text 'abc' -DelayMs 150 # 编辑模式按键插入(驱动键盘路径,无串口锚点)
|
|
|
|
|
|
$h2 = Send-EscRetry -Session $s -Anchors @('[editor] exit') -TimeoutSeconds 15 -MaxAttempts 2
|
|
|
|
|
|
$loge = Read-QemuLogText $s.LogPath
|
|
|
|
|
|
if ($h2 -and $loge.Contains('[shell] run: tool returned')) {
|
|
|
|
|
|
Add-TestCheck $result 'editor.elf: Esc 退出返回 shell([editor] exit)' 'PASS'
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Add-TestCheck $result 'editor.elf: Esc 退出返回 shell([editor] exit)' 'FAIL' 'missing [editor] exit / run: tool returned'
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Add-TestCheck $result 'editor.elf: run 加载启动([editor] boot,BUG-002 修复后行为)' 'FAIL' 'missing [editor] boot'
|
|
|
|
|
|
}
|
2026-07-31 13:53:49 +08:00
|
|
|
|
|
2026-08-04 18:08:08 +08:00
|
|
|
|
# --- fileman:BUG-003/008 修复后键盘可用;方向键移动选区 + Esc 退出 ---
|
|
|
|
|
|
$h = Invoke-ShellCmdRetry -Session $s -Text 'run FILEMAN.ELF' -Anchors @('[fileman] boot') -TimeoutSeconds 30
|
|
|
|
|
|
if ($h) {
|
|
|
|
|
|
Add-TestCheck $result 'fileman.elf: run 加载启动(未复现 QEMU 退出)' 'PASS'
|
|
|
|
|
|
Start-Sleep -Seconds 2 # 等 da_mouse_init + 目录加载 + 首帧渲染
|
|
|
|
|
|
Send-QemuKeys -Session $s -Keys @('down', 'down', 'up') -DelayMs 200 # 选区移动(仅帧缓冲,驱动键盘路径)
|
|
|
|
|
|
$h2 = Send-EscRetry -Session $s -Anchors @('[fileman] exit') -TimeoutSeconds 15 -MaxAttempts 2
|
|
|
|
|
|
$logfm = Read-QemuLogText $s.LogPath
|
|
|
|
|
|
if ($h2 -and $logfm.Contains('[shell] run: tool returned')) {
|
|
|
|
|
|
Add-TestCheck $result 'fileman.elf: 方向键 + Esc 退出返回 shell(BUG-003/008 修复后键盘路径)' 'PASS'
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Add-TestCheck $result 'fileman.elf: 方向键 + Esc 退出返回 shell(BUG-003/008 修复后键盘路径)' 'FAIL' 'missing [fileman] exit / run: tool returned'
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Add-TestCheck $result 'fileman.elf: run 加载启动(未复现 QEMU 退出)' 'FAIL' 'missing [fileman] boot'
|
|
|
|
|
|
}
|
2026-07-31 13:53:49 +08:00
|
|
|
|
|
2026-08-04 18:08:08 +08:00
|
|
|
|
# --- browser:启动 + Esc 退出 ---
|
|
|
|
|
|
$h = Invoke-ShellCmdRetry -Session $s -Text 'run BROWSER.ELF' -Anchors @('[browser] boot') -TimeoutSeconds 30
|
|
|
|
|
|
if ($h) {
|
|
|
|
|
|
Add-TestCheck $result 'browser.elf: run 加载启动' 'PASS'
|
|
|
|
|
|
Start-Sleep -Seconds 2
|
|
|
|
|
|
$h2 = Send-EscRetry -Session $s -Anchors @('[browser] exit') -TimeoutSeconds 15 -MaxAttempts 2
|
|
|
|
|
|
$logbr = Read-QemuLogText $s.LogPath
|
|
|
|
|
|
if ($h2 -and $logbr.Contains('[shell] run: tool returned')) {
|
|
|
|
|
|
Add-TestCheck $result 'browser.elf: Esc 退出返回 shell([browser] exit)' 'PASS'
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Add-TestCheck $result 'browser.elf: Esc 退出返回 shell([browser] exit)' 'FAIL' 'missing [browser] exit / run: tool returned'
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Add-TestCheck $result 'browser.elf: run 加载启动' 'FAIL' 'missing [browser] boot'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# --- Esc 回 DSK → cmd(AUTOEXEC) → desktop ---
|
|
|
|
|
|
# 只重试到中间锚点 '[shell] esc -> return to DSK' 出现即停,
|
|
|
|
|
|
# 避免多余 Esc 漏进 cmd/desktop;desktop ready 纯被动等待。
|
|
|
|
|
|
$h = Send-EscRetry -Session $s -Anchors @('[shell] esc -> return to DSK') -TimeoutSeconds 20 -MaxAttempts 2
|
|
|
|
|
|
$hitDesk = Wait-QemuLog -Session $s -Patterns @('desktop ready') -TimeoutSeconds 150
|
|
|
|
|
|
$logf = Read-QemuLogText $s.LogPath
|
|
|
|
|
|
Assert-QemuLog $result $logf -Ordered @(
|
|
|
|
|
|
'[shell] esc -> return to DSK',
|
|
|
|
|
|
'[DSK] shell auto-test returned'
|
|
|
|
|
|
) -MustNotContain @('[PANIC]')
|
|
|
|
|
|
if ($hitDesk) { Add-TestCheck $result '链路: Esc → cmd → desktop ready' 'PASS' }
|
|
|
|
|
|
else { Add-TestCheck $result '链路: Esc → cmd → desktop ready' 'FAIL' 'no desktop ready' }
|
|
|
|
|
|
}
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
Stop-QemuSession $s
|
2026-07-31 13:53:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# ================= MANUAL / 引用项 =================
|
2026-08-04 18:08:08 +08:00
|
|
|
|
Add-TestCheck $result 'ping.elf: ICMP reply/RTT 与四报文统计' 'MANUAL' 'reply/统计输出仅帧缓冲(无串口锚点);10.0.2.2 输入与 [ping] boot/exit 链已自动化'
|
|
|
|
|
|
Add-TestCheck $result 'editor.elf: 编辑内容渲染与保存' 'MANUAL' '编辑区/保存结果仅帧缓冲与磁盘(无串口锚点);boot/按键插入/exit 链已自动化'
|
|
|
|
|
|
Add-TestCheck $result 'fileman 浏览内容(列表渲染/进入子目录)' 'MANUAL' '列表渲染仅帧缓冲(无串口锚点);方向键/Esc 键盘路径已自动化'
|
2026-07-31 13:53:49 +08:00
|
|
|
|
Add-TestCheck $result 'FirstInit 向导(程序 1)' 'MANUAL' '由 boot-regression.ps1 B1 自动化覆盖(monitor 按键填表)'
|
|
|
|
|
|
Add-TestCheck $result 'login(程序 2)' 'SKIP' 'FUCK [dsk] skip_login=1 跳过;USER.CONF 解密路径需人工验证'
|
|
|
|
|
|
Add-TestCheck $result 'desktop 双击/窗口拖动/任务栏(程序 3)' 'MANUAL' '无串口锚点,需人工或 screendump 验证'
|
|
|
|
|
|
Add-TestCheck $result 'cmd pe 兼容(程序 5)' 'MANUAL' '由 pe-compat.ps1 自动化覆盖'
|
|
|
|
|
|
Add-TestCheck $result 'netman(程序 6)' 'MANUAL' '由 network-e2e.ps1 场景 N-A 自动化覆盖(netman 仅首启调度)'
|
|
|
|
|
|
Add-TestCheck $result 'mouseInit(程序 7)' 'MANUAL' '由 boot-regression.ps1 B1 首启链路覆盖'
|
|
|
|
|
|
Add-TestCheck $result 'curl.elf HTTP(程序 11)' 'MANUAL' '由 network-e2e.ps1 场景 N-B 自动化覆盖(主机侧 HTTP 服务器断言)'
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
Restore-DeshabScenario
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Write-TestCaseResult $result
|
|
|
|
|
|
if ($result.Status -eq 'FAIL') { exit 1 } else { exit 0 }
|