test: add reproducible Windows VM bundle harness
This commit is contained in:
+70
-17
@@ -15,6 +15,30 @@ Run focused unit tests with:
|
||||
scripts/test-unit --package ./internal/domain --run UUIDv7 --race
|
||||
```
|
||||
|
||||
Build all supported binaries without installing `make` or Go on the host:
|
||||
|
||||
```sh
|
||||
scripts/build build
|
||||
```
|
||||
|
||||
For a native Windows run, create the immutable per-run test bundle with the
|
||||
pinned toolchain. Supply a test-specific config whose endpoint and CA path are
|
||||
valid for that run; the command refuses to replace an existing bundle.
|
||||
|
||||
```sh
|
||||
scripts/windows/build-test-bundle \
|
||||
--run-id windows-smoke \
|
||||
--config .test-runs/windows-smoke/client.toml \
|
||||
--ca .test-runs/windows-smoke/ca.pem
|
||||
scripts/windows/test-host prepare --run-id windows-smoke
|
||||
scripts/windows/test-host stage --run-id windows-smoke \
|
||||
--bundle .test-runs/windows-smoke/windows-bundle
|
||||
```
|
||||
|
||||
The bundle manifest records the source commit and SHA-256 of every bundled
|
||||
file. It is a test artifact, not a signed release package; release signing,
|
||||
version resources, and publication are Phase 8 gates.
|
||||
|
||||
The integration harness provides the Phase 0 `sample` suite, the incremental
|
||||
Phase 2 `store` suite, and the incremental Phase 3 `server-session` suite.
|
||||
The resumable E2E harness adds `smoke`, `script`, `recovery`, and `all`
|
||||
@@ -97,20 +121,49 @@ than treating it as a stable endpoint. VRDE is enabled at
|
||||
`192.168.50.162:3389` for diagnostics, while native Windows RDP is disabled in
|
||||
the baseline.
|
||||
|
||||
The exact headless VirtualBox/Guest Control adapter is
|
||||
`scripts/windows/test-host.ps1`; it takes the VM name, baseline snapshot, and
|
||||
guest identity/password-file only from host environment variables, acquires an
|
||||
exclusive lease, and never writes secrets to the repository. Set
|
||||
`RVBOX_WINDOWS_GUEST_PASSWORD_FILE` to a mode-600 file outside the repository;
|
||||
the adapter passes it with VirtualBox `--passwordfile` and never accepts an
|
||||
inline password. Use `Prepare`, `Run`,
|
||||
`Collect`, `Stop`, and `Reset` in that order for a native run. The VM is the
|
||||
minimum smoke lane, so deferred native multi-session/ambiguous-session, Server
|
||||
Core, and older-build entries remain explicitly blocked until their own
|
||||
fixtures exist. A previous Windows 10 fixture probe found that VirtualBox Guest
|
||||
Control 7.2.16 rejects the GUI-subsystem `rvbox.exe` as a directly runnable
|
||||
guest executable; wrapping it through `cmd.exe` exited the RVBox process but
|
||||
left the Guest Control wrapper waiting. This remains an adapter completion-path
|
||||
limitation: native runtime coverage needs a service-driven or
|
||||
console-compatible guest runner. Wine or a protocol stub is not treated as
|
||||
equivalent coverage.
|
||||
The canonical headless VirtualBox/Guest Control adapter is
|
||||
`scripts/windows/test-host`. It is a POSIX controller script because the
|
||||
fixture's VirtualBox host is Arch Linux and has no PowerShell runtime. The
|
||||
controller connects to Helium over SSH; `VBoxManage` and the host-only password
|
||||
file never need to exist on the Linux development controller. It takes the VM
|
||||
identity, baseline snapshot, guest identity, and password-file only from host
|
||||
environment variables, acquires an exclusive remote lease, and never writes
|
||||
secrets to the repository, run manifest, or command line. Set
|
||||
`RVBOX_TEST_GUEST_PASSWORD_FILE` to the mode-600 host-side file; the adapter
|
||||
passes it only as VirtualBox `--passwordfile`.
|
||||
The provisioned fixture's non-secret identity values, including the host-local
|
||||
password-file path, are safe defaults in that script and may be overridden for
|
||||
another documented fixture; the password itself is never embedded.
|
||||
|
||||
The native lifecycle is `status`, `prepare`, `stage`, `run`, `collect`,
|
||||
`stop`, and `reset`. `prepare` verifies the VM and snapshot UUIDs, restores the
|
||||
baseline, starts headless, waits for Guest Additions, and records the selected
|
||||
login fixture. `stage` copies a versioned non-secret test bundle through a
|
||||
run-specific host directory to a run-specific guest directory. `run` starts
|
||||
the real RVBox SCM service and observes it through SCM, the local health/tray
|
||||
pipe, durable artifacts, and the test agent endpoint; it must not invoke the
|
||||
GUI-subsystem `rvbox.exe` directly through Guest Control. `collect` obtains
|
||||
only bounded/redacted artifacts, and `reset` restores the exact baseline and
|
||||
leaves the VM powered off.
|
||||
|
||||
This service-driven protocol is required because VirtualBox Guest Control
|
||||
7.2.16 does not reliably complete a direct GUI-subsystem `rvbox.exe` run;
|
||||
wrapping it in `cmd.exe` can leave the Guest Control wrapper waiting. Guest
|
||||
Control is therefore limited to console-safe setup tools (`sc.exe`, `whoami`,
|
||||
`query`, bounded file operations) and artifact collection. A native E2E run
|
||||
also performs a bounded guest-to-nginx HTTPS/TCP readiness probe before it
|
||||
starts the service. Wine and protocol stubs are not equivalent Windows
|
||||
coverage.
|
||||
|
||||
The fixture needs a one-time operator-approved service bootstrap before the
|
||||
SCM smoke lane can run: Guest Control supplies the split-token administrator's
|
||||
medium UAC token, so it cannot safely install services. The bootstrap installs
|
||||
the test service in the reset baseline and grants the test account only the SCM
|
||||
query/change-config/start/stop rights plus access to its dedicated test subtree.
|
||||
Each run then reconfigures and starts that one service. This does not add a
|
||||
product broker or use Task Scheduler; it is fixture setup. See
|
||||
[testing-vm.md](testing-vm.md) for the exact boundary.
|
||||
|
||||
The VM is the minimum smoke lane, so native multi-session/ambiguous-session,
|
||||
Server Core, and older-build entries remain explicitly blocked until their own
|
||||
fixtures exist. Their pure selector tests remain mandatory.
|
||||
|
||||
Reference in New Issue
Block a user