113 lines
5.5 KiB
Markdown
113 lines
5.5 KiB
Markdown
# Graphics and recovery verification
|
||
|
||
Run from the checkout. Tools are temporary Nix development dependencies; no
|
||
persistent host installation is required. The two-guest smoke test needs access
|
||
to `/dev/kvm` and creates its own headless Wayland display, VM disks and sockets
|
||
under a fresh `/tmp/hydra-smoke-*` directory. It never uses the inherited display,
|
||
active TTY, existing guests or existing disks. Evidence remains in that directory;
|
||
the script stops only its own verified QEMU instances on exit.
|
||
|
||
```sh
|
||
python3 -m unittest discover -s tests -v
|
||
nix-build dev/tools.nix -A viewer --no-out-link
|
||
nix-build dev/tools.nix -A qemu --no-out-link
|
||
nix-shell dev/tools.nix --run 'python3 dev/smoke.py'
|
||
```
|
||
|
||
The smoke test builds a private input helper with an ordinary evdev/pc105 US
|
||
keyboard map. It boots two tiny counter workloads from separate scratch qcow2
|
||
disks, connects two fullscreen viewers, and checks reserved switching/recovery,
|
||
manual USB selection, explicit reconnect and independent QMP lifecycles.
|
||
Guest memory counters must advance and QEMU PIDs must remain unchanged through
|
||
switching. Viewer protocol logs must show no reconnection during switching.
|
||
A test-only `ToggleKeybinds` action and F12 marker establish native labwc
|
||
keybinding inhibition before checking the production reserved bindings. Those
|
||
extra controls are absent from the production session configuration. See the
|
||
[labwc configuration manual](https://labwc.github.io/labwc-config.5.html) for
|
||
`overrideInhibition` and the [actions manual](https://labwc.github.io/labwc-actions.5.html)
|
||
for native `ToggleKeybinds` behavior.
|
||
|
||
USB acceptance checks the actual selector window title, holds the modifiers
|
||
through opening, releases them inside the modal dialog, then switches again.
|
||
QEMU's USB device list must stay unchanged without a selection. Both viewer
|
||
USB filters deny automatic hotplug and connection redirection. This check does
|
||
not attach a physical USB device or prove guest driver behavior.
|
||
|
||
The viewer adaptation handles only the configured manual USB accelerator before
|
||
forwarding an event to the guest. Upstream keyboard grabs remove the GTK
|
||
application accelerator group; without this adaptation, the configured USB
|
||
shortcut reaches the viewer but does not open its selector.
|
||
|
||
## Installed guest workflow
|
||
|
||
`--iso` is optional. Attach or detach media only while the VM is stopped:
|
||
|
||
```sh
|
||
bin/hydra add guest --iso /absolute/path/installer.iso
|
||
bin/hydra start guest
|
||
bin/hydra view guest
|
||
# Shut down from inside the guest, then check it is stopped.
|
||
bin/hydra status guest
|
||
bin/hydra media guest --detach
|
||
bin/hydra start guest
|
||
```
|
||
|
||
For an existing stopped guest, `bin/hydra media guest --iso PATH` attaches
|
||
installation/rescue media. A missing configured ISO prevents a new start with
|
||
an actionable error; it does not prevent listing profiles, status, stopping a
|
||
running guest, reconnecting a viewer or detaching the missing media. Media
|
||
updates share the VM lifecycle lock and preserve its qcow2 disk. Abrupt stopping
|
||
still requires `bin/hydra stop guest --force` and verified QMP identity.
|
||
|
||
## Display preferences and EDID
|
||
|
||
New developer profiles use user networking, 1280×800 and `refresh_millihz=0`.
|
||
Zero omits the patched QEMU refresh property and remains compatible with stock
|
||
QEMU. Hydra's installed defaults can use this flat `/etc/hydra/defaults.toml`:
|
||
|
||
```toml
|
||
network = "bridge"
|
||
bridge = "hydrabr0"
|
||
width = 1920
|
||
height = 1080
|
||
refresh_millihz = 144000
|
||
```
|
||
|
||
Only `add` reads distribution defaults. Explicit `--network`, `--bridge`,
|
||
`--width`, `--height` and `--refresh-millihz` options win; existing profiles do
|
||
not change. `--defaults PATH` selects another preferences file for development.
|
||
Missing defaults use developer preferences; unknown or invalid fields fail
|
||
before creating a profile. Dimensions are integers from 1 to 16384, refresh is
|
||
an integer from 0 to 1000000 mHz. Nonzero refresh requires the tracked patched
|
||
QEMU provided by `dev/tools.nix` and distribution packaging.
|
||
|
||
The patch keeps the requested refresh through frontend resizing and extends
|
||
EDID monitor ranges to include the generated preferred mode. To verify the
|
||
actual patched QEMU generator with the pinned source archive:
|
||
|
||
```sh
|
||
qemu_source=$(nix-build dev/tools.nix -A qemu.src --no-out-link)
|
||
nix-shell dev/tools.nix --run "python3 dev/check-edid.py '$qemu_source'"
|
||
```
|
||
|
||
The probe applies the tracked patch to four relevant source files in a temporary
|
||
directory, compiles the actual EDID and virtio GPU generator functions with a
|
||
small dependency harness, and decodes the result. It checks 60/75 Hz fallback,
|
||
144 Hz configuration, a conflicting 60 Hz frontend request, resized dimensions,
|
||
checksums and monitor ranges. At 1920×1080/144000 mHz the preferred timing is
|
||
143.997231 Hz after EDID clock rounding. This is an advertised guest mode,
|
||
not measured frame delivery or proof of a 144 Hz physical output.
|
||
|
||
## Still requiring a dedicated physical session
|
||
|
||
- Physical reserved chords, brightness/backlight permissions and touchpad input.
|
||
- Physical held keys/modifiers across guest switching, grabs and modal dialogs;
|
||
guest key-up delivery, pointer grab release and absence of stuck modifiers.
|
||
- Physical USB selection/redirection and guest drivers; no automatic redirection.
|
||
- Toolbar behavior at physical screen edges and actual recovery shell usability.
|
||
- ASUS output selection at 1920×1080/144 Hz, guest-reported display mode, delivered
|
||
frame rate, hidden guest graphics continuity, tearing and switching latency.
|
||
|
||
Headless checks establish CPU workload continuity, protocol focus transitions
|
||
and the exercised compositor actions. They cannot prove physical input or scanout.
|