feat: B7 APIC/IOAPIC接管 + NVMe写路径 + virtio_net virtqueue + PE兼容层修复 + QEMU测试套件全自动化
中断路由 (B7): - apic.drv: LAPIC enable + IOAPIC重定向表编程(MADT ISO感知) + apic_route/apic_route_legacy/apic_diag开关 - UTSM: LAPIC EOI钩子(register_apic_eoi, ABI尾部追加) + IDT 0-255全覆盖 + spurious 0xFF特判 - FUCK: apic_route=0默认PIC(零回归) / =1 IOAPIC->LAPIC接管(失败完整降级) / legacy放开IRQ1/12/11 存储: - nvme.drv: 写路径 + PRP list + 读回校验 + MSI/MSI-X中断驱动(nvme_msi开关, 回退纯轮询) - build.ps1: apic.drv纳入构建(原为预置二进制) 网络: - virtio_net: virtqueue RX/TX + netdev注册 + DHCP自测(slirp真实OFFER) PE兼容层: - pe_shim: guest->host指针转换(g_emu_mem_base + gp()) + shim fn32列补齐 - gen_pe.py: PE32+ RVA偏置修复(BUG-004) + cmd.exe生成 - desktop_app.h: da_mouse_poll先判AUX位 + da_mouse_init冲刷残留(BUG-003/008) - shell: Ctrl修饰键跟踪(BUG-001) + g_run_image扩至1MB(BUG-002) QEMU测试套件: - 9用例全自动化(Run-All.ps1): boot-regression/driver-matrix/linux-compat/pe-compat/deaicup-e2e/userapps-matrix/network-e2e/performance-baseline/x86emu32-coverage - QemuTest.ps1公共库: 串口断言/monitor sendkey/screendump/HTTP服务器/并发隔离 文档: - CLAUDE.md: APIC/IOAPIC能力 + kernel_api暴露 + IRQ后端升级状态 - LESSONS_LEARNED.md: B7 LAPIC/IOAPIC经验教训(2条) - Bug记录.txt: BUG-20260801-001~008 + BUG-20260803-009(9条) - test-cases/*.md: 全部补充自动化脚本小节 - 桌面设计.md: .lnk快捷方式 + LINUXAPP.CNF Linux应用图标 - 系统开发策划.md: NVMe/virtio_net标完成 + B2/B7标已解决 + M2进度列
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
#requires -Version 5.1
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Run-All — Deshab QEMU 自动化测试套件总运行器
|
||||
|
||||
.DESCRIPTION
|
||||
顺序执行 tests/qemu 下全部 9 个用例脚本,每用例独立 powershell 子进程
|
||||
(独立 QEMU 会话 + firstInit/AUTOEXEC 场景隔离),汇总 PASS/FAIL/耗时。
|
||||
|
||||
用例顺序(依赖与耗时综合考虑,快用例靠后):
|
||||
1. boot-regression.ps1 B1 首启向导 / B2 正常 / B3 dev_mode / B4 无盘 / B5 无 NIC
|
||||
2. driver-matrix.ps1 16 清单驱动加载矩阵 + NVMe 写路径回归
|
||||
3. linux-compat.ps1 VMM 分流(QEMU 走 VMM unavailable 优雅降级路径)
|
||||
4. pe-compat.ps1 PE32+ 原生 + PE32 x86emu32 + 错误路径
|
||||
5. deaicup-e2e.ps1 Deaicup GUI PE 端到端(首帧像素/键鼠消息/Esc 退出链)
|
||||
6. userapps-matrix.ps1 shell dev_tests + ping/editor/fileman/browser 工具链
|
||||
7. network-e2e.ps1 N-A netman 全链路 + N-B curl 主机侧端到端
|
||||
8. performance-baseline.ps1
|
||||
启动阶段墙上计时 → .build_tmp/perf_baseline.json
|
||||
9. x86emu32-coverage.ps1 x86emu32 静态枚举 + hello32 动态解释执行
|
||||
|
||||
.PARAMETER Only
|
||||
只跑指定用例(逗号分隔的脚本基名,大小写不敏感):
|
||||
.\Run-All.ps1 -Only network-e2e,x86emu32-coverage
|
||||
|
||||
.PARAMETER Build
|
||||
先执行一次 build.ps1(全量编译+打包镜像)再跑用例。
|
||||
|
||||
.NOTES
|
||||
退出码:全部用例 PASS → 0;任一 FAIL → 1。
|
||||
每用例完整输出存档 .build_tmp\tests\runall\<case>.log。
|
||||
#>
|
||||
param(
|
||||
[string[]]$Only = @(),
|
||||
[switch]$Build
|
||||
)
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$suiteRoot = $PSScriptRoot
|
||||
$repoRoot = [System.IO.Path]::GetFullPath((Join-Path $suiteRoot '..\..'))
|
||||
$outDir = Join-Path $repoRoot '.build_tmp\tests\runall'
|
||||
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
|
||||
|
||||
# ---- 跑前清理:只杀本套件历史会话残留的 QEMU(-name deshabtest- 标记)。
|
||||
# 绝不全局清理——可能有其他代理/人工在并发跑 QEMU(如 monitor 45454 的调试会话)。
|
||||
# 本套件所有会话默认 -snapshot(镜像只读),无需靠杀进程解决镜像锁。 ----
|
||||
. (Join-Path $suiteRoot 'lib\QemuTest.ps1')
|
||||
Stop-ResidualQemu
|
||||
|
||||
# ---- 可选:先构建一次 ----
|
||||
if ($Build) {
|
||||
Write-Host '[runall] running build.ps1 ...'
|
||||
& powershell -ExecutionPolicy Bypass -File (Join-Path $repoRoot 'build.ps1')
|
||||
if ($LASTEXITCODE -ne 0) { Write-Host "[runall] build.ps1 FAILED (exit $LASTEXITCODE)"; exit 1 }
|
||||
}
|
||||
|
||||
$cases = @(
|
||||
'boot-regression',
|
||||
'driver-matrix',
|
||||
'linux-compat',
|
||||
'pe-compat',
|
||||
'deaicup-e2e',
|
||||
'userapps-matrix',
|
||||
'network-e2e',
|
||||
'performance-baseline',
|
||||
'x86emu32-coverage'
|
||||
)
|
||||
if ($Only.Count -gt 0) {
|
||||
# -File 调用下逗号列表常作为单个字符串传入,统一按逗号再切一次
|
||||
$want = @($Only | ForEach-Object { $_ -split ',' } | ForEach-Object { $_.Trim().ToLower() } | Where-Object { $_ })
|
||||
$cases = @($cases | Where-Object { $want -contains $_.ToLower() })
|
||||
if ($cases.Count -eq 0) { Write-Host "[runall] -Only 过滤后无用例可跑: $($Only -join ',')"; exit 1 }
|
||||
}
|
||||
|
||||
$rows = New-Object System.Collections.ArrayList
|
||||
$suiteStart = Get-Date
|
||||
foreach ($case in $cases) {
|
||||
$script = Join-Path $suiteRoot "$case.ps1"
|
||||
$log = Join-Path $outDir "$case.log"
|
||||
Write-Host ''
|
||||
Write-Host ("================ [runall] {0} ================" -f $case)
|
||||
$t0 = Get-Date
|
||||
& powershell -ExecutionPolicy Bypass -File $script 2>&1 | Tee-Object -FilePath $log | Out-Host
|
||||
$rc = $LASTEXITCODE
|
||||
$dur = [math]::Round(((Get-Date) - $t0).TotalSeconds, 1)
|
||||
|
||||
$outText = ''
|
||||
if (Test-Path $log) { $outText = Get-Content $log -Raw }
|
||||
$manualCount = ([regex]::Matches($outText, '\[MANUAL\]')).Count
|
||||
$skipCount = ([regex]::Matches($outText, '\[SKIP\]')).Count
|
||||
$status = 'PASS'
|
||||
if ($rc -ne 0) { $status = 'FAIL' }
|
||||
|
||||
[void]$rows.Add([pscustomobject]@{
|
||||
Case = $case
|
||||
Status = $status
|
||||
Duration = "${dur}s"
|
||||
Manual = $manualCount
|
||||
Skip = $skipCount
|
||||
ExitCode = $rc
|
||||
Log = $log
|
||||
})
|
||||
}
|
||||
|
||||
# ---- 汇总表 ----
|
||||
$totalDur = [math]::Round(((Get-Date) - $suiteStart).TotalMinutes, 1)
|
||||
Write-Host ''
|
||||
Write-Host ("================ 测试套件汇总 ({0} min) ================" -f $totalDur)
|
||||
$rows | Format-Table Case, Status, Duration, Manual, Skip, ExitCode -AutoSize | Out-Host
|
||||
|
||||
$failCount = @($rows | Where-Object { $_.Status -eq 'FAIL' }).Count
|
||||
$passCount = @($rows | Where-Object { $_.Status -eq 'PASS' }).Count
|
||||
Write-Host ("PASS: {0} FAIL: {1} TOTAL: {2}" -f $passCount, $failCount, $rows.Count)
|
||||
Write-Host ("日志目录: {0}" -f $outDir)
|
||||
|
||||
if ($failCount -gt 0) { exit 1 } else { exit 0 }
|
||||
Reference in New Issue
Block a user