Files
rvbox/docs/testing.md
T

195 lines
9.7 KiB
Markdown

# RVBox implementation test workflow
All Go, protobuf, and harness work runs in the pinned toolchain container. No
host Go installation is used.
Run the normal pre-commit gate with:
```sh
make verify
```
Run focused unit tests with:
```sh
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
```
`scripts/build doctor` reports the exact owned builder image, Go cache volumes,
and ignored `bin/` artifact directory. To reclaim space, cleanup is dry-run by
default and never performs a global Docker prune:
```sh
scripts/build clean --all
scripts/build clean --all --execute --yes
scripts/build recover
```
The second command removes only `bin/`, `rvbox-dev-toolchain:latest`, and the
two named RVBox Go-cache volumes. `recover` rebuilds the pinned toolchain and
all binaries from source. It intentionally does not remove `.test-runs/`, which
may contain resumable environments; use the exact-run `scripts/test-env purge`
workflow for those.
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
scripts/windows/test-host install --run-id windows-smoke
```
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`
scenarios. Each run writes its manifest and run ID before starting work.
The storage suite uses a real temporary SQLite database in WAL mode and a real
segment/audit filesystem. The session suite uses a real HTTP/WebSocket listener,
binary protobuf frames, SQLite fencing, and the race detector; neither mocks its
respective durability or wire boundary:
```sh
scripts/test-env doctor
scripts/test-integration --suite sample --run-id my-sample
scripts/test-env status --run-id my-sample
scripts/test-env collect --run-id my-sample
scripts/test-env reset --run-id my-sample
scripts/test-env reuse --run-id my-sample
scripts/test-integration --suite sample --run-id my-sample --resume
scripts/test-env reset --run-id my-sample
scripts/test-env purge --run-id my-sample
scripts/test-integration --suite store --run-id store-smoke
scripts/test-env logs --run-id store-smoke
scripts/test-env collect --run-id store-smoke
scripts/test-env reset --run-id store-smoke
scripts/test-env purge --run-id store-smoke
scripts/test-integration --suite server-session --run-id session-smoke
scripts/test-env logs --run-id session-smoke
scripts/test-env collect --run-id session-smoke
scripts/test-env reset --run-id session-smoke
scripts/test-env purge --run-id session-smoke
scripts/test-e2e --scenario smoke --run-id e2e-smoke
scripts/test-env status --run-id e2e-smoke
scripts/test-env recover --run-id e2e-smoke
scripts/test-e2e --scenario smoke --run-id e2e-smoke --resume
scripts/test-env reset --run-id e2e-smoke
scripts/test-env purge --run-id e2e-smoke
```
The client runtime unit lane also exercises a real child process through the
portable supervisor adapter. `internal/client/agent/executor_test.go` verifies
that command text is accepted once, output is journaled, lifecycle/terminal
events are durable, and a script cannot launch before its contiguous upload is
committed. The Windows build uses the same executor contract with the
platform-native adapter: a verified token is selected, the child is created
suspended, assigned to a kill-on-close Job, and held behind an authenticated
per-command launcher pipe. The daemon records `launch_prepared`, then the
durable `launch_authorized` transition sends the launcher's release frame; the
launcher resumes the shell only after that acknowledgement. The durable
`launch_phase` barrier is recovered as `interrupted` after a daemon restart, so
an uncertain release is never redispatched.
The Windows artifact is linked with the GUI subsystem (`-H=windowsgui`) so
service, launcher, and tray startup do not flash a console. Human-facing modes
still attach to a parent console explicitly when one exists.
Suite output is capped at 1 MiB and stored as `artifacts/suite.log`. A failed
run remains inspectable and can be moved back to `ready` with `recover`, then
resumed with the same run ID and deterministic shuffle seed. Test-run cleanup
never removes the shared Go module or build-cache volumes.
Each run owns only `.test-runs/<run-id>` and resources explicitly recorded in
that run's versioned manifest. The journal is append-only and fsynced. `purge`
validates the run ID and manifest identity, refuses symlink targets or manifests
that still list runtime resources, and then removes only that exact run. Purged
artifacts are not recoverable. Dependency cache volumes are never part of run
cleanup.
`test/coverage.toml` is the incremental requirement-to-test inventory. The
`make verify` lint stage checks unique stable IDs and verifies every implemented
test reference against source. A resettable Windows smoke VM is now available.
The authoritative fixture record is
[testing-vm.md](testing-vm.md): it lists the VM/host UUIDs, Windows build,
hardware and device profile, NAT and VRDE endpoints, snapshot UUIDs,
credential-file contract, and the required reset sequence. At the last check
the VM was powered off with `baseline-clean-administrator` selected. The guest address
`10.0.2.15` is DHCP state only; use SSH plus VirtualBox Guest Control rather
than treating it as a stable endpoint. VRDE is enabled only on Helium loopback
at `127.0.0.1:3389` for diagnostics, while native Windows RDP is disabled in
the baseline.
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 VM identity, fixed test-only account names, and
password-file path are safe defaults in that script and may be overridden for
another documented fixture. The fixed disposable-VM password remains only in
that mode-600 file; the controller never puts it on a command line, manifest,
log, or artifact.
The native lifecycle is `status`, `prepare`, `stage`, `install`, `run`,
`collect`, `stop`, and `reset`. `prepare` verifies the VM and snapshot UUIDs,
restores the clean baseline, starts headless, waits for Guest Additions, and
proves that `RVBoxClient` is absent. `stage` copies a versioned non-secret test
bundle through a run-specific host directory to a run-specific guest directory.
`install` uses the fixture-only high-integrity automation principal to invoke
the real `rvbox.exe --install-service` path and proves completion through SCM.
`run` is for reconfiguration/restart scenarios after that first installation.
Neither action invokes the GUI-subsystem executable directly with the normal
Guest Control account. `collect` obtains only bounded/redacted artifacts, and
`reset` restores the exact clean 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 clean baseline intentionally contains no RVBox service, tray registration,
or RVBox state. Guest Control supplies `rvboxtest` with a filtered medium UAC
token, so it cannot safely perform the first machine-wide install. The fixture
therefore uses its separately enabled built-in `Administrator` account as a
test-only full-token automation principal. Its `FilterAdministratorToken` must
remain `0`, preserving UAC for `rvboxtest` rather than disabling it machine-wide.
Its username and mode-600 host-side password-file are provided only as
`RVBOX_TEST_PROVISIONER_USER` and `RVBOX_TEST_PROVISIONER_PASSWORD_FILE` for
the `install`/machine-mutation actions. It is not an RVBox process, service,
broker, or Task Scheduler dependency, and it is never used to choose a command
execution context. The normal `rvboxtest` console session remains the subject
of active-user and elevation tests. See [testing-vm.md](testing-vm.md) for the
exact fixture contract.
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.