test: add reproducible Windows VM bundle harness

This commit is contained in:
2026-09-09 06:44:54 +00:00
parent 2abf0bf19b
commit a9aec8d9a8
7 changed files with 685 additions and 55 deletions
+46 -19
View File
@@ -190,7 +190,9 @@ scripts/test-unit [--package PATTERN] [--run REGEXP] [--race]
scripts/test-integration [--suite NAME|all] [--run-id ID] [--resume]
scripts/test-e2e [--scenario NAME|all] [--run-id ID] [--resume]
scripts/test-env doctor|coverage|status|logs|collect|recover|reuse|stop|reset|purge|gc ...
scripts/windows/test-host.ps1 Prepare|Status|Run|Collect|Stop|Reset
scripts/build build|verify (pinned toolchain; host-safe)
scripts/windows/build-test-bundle --run-id ID --config FILE [--ca FILE]
scripts/windows/test-host status|prepare|stage|run|collect|stop|reset|recover
```
Scripts are thin, reviewed orchestration wrappers. `scripts/test-unit` invokes
@@ -199,6 +201,13 @@ commands call a shared Go harness under `test/harness` so manifest parsing,
timeouts, process control, reporting, and cleanup logic are not reimplemented in
shell and PowerShell. The harness itself is built in the toolchain container;
no Go/Buf/protoc/SQLite SDK or package manager is installed on the host.
`scripts/build` is the corresponding host-safe wrapper around the established
containerized `make build`/`make verify` targets. A native run uses
`scripts/windows/build-test-bundle` to make one non-secret bundle below its
exact `.test-runs/<run-id>` directory, with source-commit and SHA-256 manifest;
it refuses replacement rather than overwriting an earlier bundle. This is not a
release publisher: signing, version resources, and public checksum publication
remain Phase 8 gates.
The first integration/E2E invocation creates a filesystem-safe random run ID,
or validates an explicitly supplied one, and records
@@ -257,12 +266,14 @@ copies prior mutable test state.
The Linux controller exposes bounded fault controls for frame drop/delay,
listener interruption, process termination at named durability checkpoints,
filesystem quota/error simulation, and monotonic/wall-clock advancement in the
deterministic peer. Native Windows `test-host.ps1` validates administrator state,
OS build, UAC/policy fixture, active sessions, service identity, and test-root
ownership before running. It uses a test-specific ProgramData root and an
exclusive host lease; production-name SCM/Run-key installation tests run only in
a resettable VM snapshot. Passwords and VM access credentials come from the CI
secret store or interactive prompt, never arguments persisted in the manifest.
deterministic peer. Native Windows `test-host` validates administrator state, OS
build, UAC/policy fixture, active sessions, service identity, VM/snapshot UUIDs,
and test-root ownership before running. It is a POSIX controller which uses SSH
to run `VBoxManage` on the Linux fixture host; it uses a test-specific
ProgramData root and an exclusive remote host lease. Production-name SCM/Run-key
installation tests run only in a resettable VM snapshot. Passwords and VM access
credentials come from the CI secret store or interactive prompt, never arguments
persisted in the manifest.
The E2E controller owns the canonical run manifest on Linux and passes the same
run ID plus a one-run configuration bundle to the preconfigured Windows runner.
@@ -761,7 +772,7 @@ supported Windows 10 or Server 2016 baseline; it need not be the everyday runner
A physical Windows machine is optional. It is useful for an additional real
display/audio/DDC command smoke, but RVBox only guarantees correct token/session/
process execution—not success of arbitrary vendor hardware APIs—so physical
hardware is not a release blocker. `test-host.ps1 Prepare` must inventory the
hardware is not a release blocker. `test-host prepare` must inventory the
host against this checklist and refuse destructive suites unless the machine is
explicitly marked disposable/resettable and the clean snapshot identity is
recorded.
@@ -787,7 +798,7 @@ mirror; update both documents when the fixture is reprovisioned.
| VM name / UUID | `rvbox-win10-test` / `6cdc114f-71e5-4167-a394-e922e14e6f5c` |
| VM group / config | `/RVBox/Tests`; `/home/cabbage/VirtualBox VMs/RVBox/Tests/rvbox-win10-test/rvbox-win10-test.vbox` |
| Guest OS | Windows 10 Pro 22H2, build `19045.2006`, en-US, BIOS boot |
| Guest Additions | `7.2.16r174877`; Guest Control readiness requires `GuestAdditionsRunLevel=3` |
| Guest Additions | `7.2.16r174877`; readiness requires published Guest Additions version and Windows OS-release properties (this build does not publish a RunLevel property) |
| Resources | 2 vCPU, 4096 MiB RAM, 64 MiB VRAM, `VBoxSVGA`, 3D acceleration disabled, 40 GiB dynamically allocated VDI |
| Disk / source media | `/home/cabbage/VMs/rvbox-win10-test.vdi`; source ISO `/media/Data2/Downloaded/Win10_22H2_English_x64.iso` (Windows image index 6) |
| Devices | Audio (`none`), playback/capture, USB (OHCI/EHCI/xHCI), clipboard/file transfer, drag-and-drop, and shared folders disabled; Intel 82540EM NIC, cable connected |
@@ -802,10 +813,23 @@ The guest password, SSH key, and any host account secret are test secrets. Keep
them in the operator/CI secret store or a mode-600 password file outside the
repository; never put them in this plan, a command-line argument, a run
manifest, or collected logs. `VBoxManage guestcontrol` supports
`--passwordfile`; prefer that option over an inline password. Every operator or
agent must set `RVBOX_TEST_GUEST_PASSWORD_FILE` to the absolute path of that
host-side file before a native run. The account name and VM metadata above are
not credentials.
`--passwordfile`; prefer that option over an inline password. The documented
fixture's host-local password-file path is a controller default and may be
overridden with `RVBOX_TEST_GUEST_PASSWORD_FILE`; the password value is never a
default or repository value. The account name and VM metadata above are not
credentials.
Guest Control uses this split-token administrator's medium-integrity token; its
Administrators SID is deny-only. Do not bypass UAC to create the service during
automation. A one-time interactive elevated fixture bootstrap must install the
test `RVBoxClient` service in the reset baseline and grant `rvboxtest` only
query/change-config/start/stop service access plus write access to its dedicated
test subtree. Each native run then changes that bootstrapped service's explicit
image/configuration and starts it through SCM. This is fixture administration,
not a second product worker/elevation broker or a Task Scheduler dependency.
Keep the exact service SDDL and test-subtree ACL with the fixture record before
taking its replacement baseline snapshot. The production installer/UAC flow is
tested separately through an interactive elevated lane.
For this provisioned lane, the approved host-only credential-file location is
`/home/cabbage/.local/share/rvbox-secrets/rvbox-win10-test.password`. It must
@@ -853,15 +877,18 @@ ssh "$RVBOX_TEST_VBOX_HOST" \
ssh "$RVBOX_TEST_VBOX_HOST" \
'VBoxManage startvm "rvbox-win10-test" --type headless'
# Poll these properties before a test; GuestAdditionsRunLevel=3 is required
# for Guest Control, and LoggedInUsers/NoLoggedInUsers selects the session case.
# Poll these properties before a test. This fixture requires Guest Additions
# version plus Windows OS-release properties; LoggedInUsers/NoLoggedInUsers
# selects the session case.
ssh "$RVBOX_TEST_VBOX_HOST" \
'VBoxManage guestproperty enumerate "rvbox-win10-test"'
```
The harness must wait for the VM to report `running`, then poll Guest
Properties until Guest Additions is ready and the requested login fixture is
observed. NAT address `10.0.2.15` was observed during provisioning but is DHCP
Properties until the Guest Additions version and Windows OS-release properties
are present and the requested login fixture is observed. Do not require a
`GuestAdditionsRunLevel` value: VirtualBox Guest Additions `7.2.16r174877` on
this fixture does not publish it. NAT address `10.0.2.15` was observed during provisioning but is DHCP
state, not an identity or a stable endpoint; use Guest Control for management
and discover any test networking separately. A failed readiness poll is a
stopped-resumable run, not permission to start a second VM with the same name.
@@ -964,7 +991,7 @@ scripts/
test-integration # resumable component-suite entry point
test-e2e # resumable production-shaped scenario entry point
test-env # doctor/recover/reuse/cleanup by exact run ID
windows/test-host.ps1 # native Windows host lifecycle adapter
windows/test-host # POSIX controller for the native Windows VM lifecycle
test/
coverage.toml # requirement-to-case inventory with stable IDs
harness/ # shared manifest, journal, orchestration, and reporting
@@ -2196,7 +2223,7 @@ The native `windows-supervisor` and `windows-service-tray` integration suites us
real Windows subprocesses and APIs for both shells, CWD/environment overlays,
concurrent output without newlines, stdin ordering/close, Job tree termination,
script materialization/cleanup, service shutdown interruption, and every token/
session context. They run through `scripts/windows/test-host.ps1` under the
session context. They run through `scripts/windows/test-host` under the
exclusive host lease and journal every machine-wide mutation for reset.
Add a table-driven crash suite for every acceptance, script-upload, launch,