mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-11-13 12:23:38 +01:00
docs(e2e): how the macOS guest works and how to run it
A README for e2e/platforms/tart_macos: what a run does, why the grants live in the golden image and are inherited through Terminal, why the agent is a Rust program (the stock image has no developer tools), and the limits (one display, no input, two guests per host, Apple hardware only, so not in CI). docs/dev/ci.md and e2e-to-unit.md said macOS had no integration coverage; they now say where it runs and what it cannot reach.
This commit is contained in:
1 parent
98b3b4bc0c
commit
18d7f9a506
3 files changed
+83
-5
No files matched your search
+5
-3
@@ -70,15 +70,17 @@ installs nextest on the Windows runners, which have no nix, and `windows.yaml` (
|
||||
| format | `fmt`, `checkSets.fmt` | the same | the same |
|
||||
| clippy | `lint` (cross build) | `lint` | `macos-hosted` only (`macos-lint`); `mac-typecheck` type-checks on Linux |
|
||||
| unit tests | `windows-native-test` on Windows, and `windows.yaml` on every event | `test` (`linux-test`) | `macos-hosted` only |
|
||||
| integration | none (the guest is experimental: `windows-guest.yaml`) | `vm-fast`, `vm-slow` | none |
|
||||
| integration | none (the guest is experimental: `windows-guest.yaml`) | `vm-fast`, `vm-slow` | none in CI; by hand on a Mac: `nix run .#e2e-macos` (a Tart guest, `e2e/platforms/tart_macos`) |
|
||||
| options and schemas | `linux-options`, `macos-options` on Linux; the Windows schemas are checked by the Windows e2e Python | `linux-options` | `macos-options` on Linux; the schemas by `macos-hosted` |
|
||||
|
||||
The gaps:
|
||||
|
||||
- No Windows e2e: the guest needs the evaluation ISO and about 20 minutes of Windows Setup, and nothing says a hosted runner can do it.
|
||||
- macOS runs on every change to its paths, on `macos-latest` (Apple silicon, the latest macOS, the only one supported): standard hosted runners are free and
|
||||
unlimited on a public repository. Nothing starts the daemon there, so tiling on macOS is not exercised; whether a hosted runner has a GUI session with the
|
||||
Accessibility and Screen Recording permissions is not known.
|
||||
unlimited on a public repository. Nothing starts the daemon there, so tiling on macOS is not exercised in CI; whether a hosted runner has a GUI session with the
|
||||
Accessibility and Screen Recording permissions is not known. The shared e2e scenarios do run on macOS, by hand, on a Mac (`nix run .#e2e-macos`,
|
||||
`e2e/platforms/tart_macos/README.md`): a hosted runner is itself a virtual machine and cannot start a macOS guest, and a guest runs on Apple
|
||||
hardware only, two at a time, so CI would need a Mac of its own.
|
||||
- The nightly rustfmt of `fmt` is the nightly of the day; `checkSets.fmt` in stage 1 uses the one the flake pins. When only `fmt` fails, the nightly moved.
|
||||
- `mac-typecheck` takes the std of `aarch64-apple-darwin` from the toolchain of the runner (`rustup target add`), because the dev shell of the
|
||||
flake only has the Windows target. clippy could run the same way (`cargo clippy --target aarch64-apple-darwin`); `tools/mac-check.sh` does not.
|
||||
|
||||
@@ -59,9 +59,11 @@ times (Windows `komorebi/src/window.rs:1178`, KDE `window.rs:661`, macOS `window
|
||||
| lifecycle (7), lifecycle_hidden (13), locking (7), handover (6), fullscreen (6), display_change (4), focus_follows_mouse (7) | stop/start restores windows, screen lock, minimize/unmanage/manage, fullscreen, mode change, pointer focus | A for hide/restore: `container_behaviour.rs` `restoring_*`, `workspace_layers.rs` `hiding_a_workspace_*`; the process, session, OS events and pointer are C | - | - | - |
|
||||
| Windows extras: bar (21), windows_padding, cloaking, config_file, tracking, second_display, display_change | bar process and window, 7 px border, cloaking, file watch, system focus setting, QXL display | bar schema: A (`crates/komorebi-bar-core/tests/schema_oracle.rs`); rest C | - | - | - |
|
||||
|
||||
## macOS-origin behaviour (never e2e-tested): what the shared tests now give
|
||||
## macOS-origin behaviour: what the shared tests give besides the e2e
|
||||
|
||||
macOS has no e2e. The shared-crate tests that exist protect its code path as far as the hooks do:
|
||||
The shared e2e scenarios run on macOS in a Tart guest, by hand on a Mac (`nix run .#e2e-macos`,
|
||||
`e2e/platforms/tart_macos/README.md`; not in CI). What a macOS guest cannot do (a second display, a
|
||||
pointer, a lock screen) is still never e2e-tested. The shared-crate tests that exist protect its code path as far as the hooks do:
|
||||
`state_roundtrip.rs` `a_macos_shaped_state_is_written_as_it_was_read_with_the_corner_last`,
|
||||
`a_macos_state_cannot_be_read_without_its_corner`, the `StubWindow` that is `Clone` but not `Copy`,
|
||||
and now `e2e_layouts.rs` (the tiles every macOS tiling goes through). Proposed B tests, platform
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
# The macOS guest
|
||||
|
||||
The scenarios of the shared core (`e2e/lib/komorebi_vm/core/scenarios`) run against the real
|
||||
`komorebi` daemon of macOS in a virtual machine, the way they run on KDE (a NixOS test) and on Windows
|
||||
(`../qemu_windows`). A scenario sees a [`Platform`](../../lib/komorebi_vm/core/platform.py); this
|
||||
directory is the one for macOS.
|
||||
|
||||
```text
|
||||
host (Apple silicon) guest (a clone of the golden image)
|
||||
python -m platforms.tart_macos.run macOS, logged in, one 1280x800 display
|
||||
Guest ── tart clone / run --no-graphics ──► Terminal (holds the grants)
|
||||
MacosPlatform ── agent protocol, TCP 7878 ──► komorebi-e2e-agent answers the host
|
||||
komorebi the daemon under test
|
||||
komorebi-testwin the windows to tile
|
||||
```
|
||||
|
||||
## What a run does
|
||||
|
||||
For each scenario, `Guest` clones the golden image (copy on write, so it costs nothing), boots it
|
||||
without a window, and waits for the agent, which answers about 20 s after the clone starts. The programs
|
||||
under test are uploaded through the agent, the daemon is started by it, the shared scenario runs, and
|
||||
the clone is deleted. `OUT/<scenario>/result.json` names the scenario, the commit and every check, as
|
||||
the Windows runner's does; a failed run also keeps the daemon's output, the processes and a screenshot.
|
||||
|
||||
## Why it is built this way
|
||||
|
||||
- **Permissions are the hard part.** The daemon needs Screen Recording and Accessibility, which macOS
|
||||
only grants to a person's click. They are granted once to `Terminal` in the golden image and are
|
||||
inherited by every clone. The agent is started at login by a launch agent that opens Terminal on it
|
||||
(`provision.sh`), so the agent, the daemon it spawns and the test windows are all attributed to
|
||||
Terminal, and no clone asks anything. A signed binary of our own would need a grant per build.
|
||||
- **The agent is a Rust program** (`crates/komorebi-e2e-agent`, the same crate and protocol as the
|
||||
Windows agent, with `macos.rs` for the verbs) because the stock image has no developer tools: `swift`,
|
||||
`clang` and `python3` there are stubs. It reads windows and displays through the accessibility API, as
|
||||
the daemon does, so a window's frame is what the application says.
|
||||
- **No SSH at run time.** The vanilla image has `admin`/`admin` and SSH on, which only
|
||||
`build-golden.sh` uses.
|
||||
- **The windows that are not the test's are left alone** by an ignore rule the platform adds to every
|
||||
configuration: the Terminal, and the desktop widgets of the image (Notification Center draws them as
|
||||
windows, and they are tiled otherwise).
|
||||
|
||||
## Limits
|
||||
|
||||
- **One display.** A macOS guest has one virtual display, so what needs a second one (`hotplug`,
|
||||
`monitors`, `display_change`, `unknown_monitor`) is skipped with the reason.
|
||||
- **No input is injected**, so there is no pointer (`focus_follows_mouse`, drags) and no lock screen.
|
||||
- **At most two guests at once on a host.** Apple's licence and Virtualization.framework both stop a
|
||||
third, so a host runs two scenarios in parallel at the most.
|
||||
- **Apple hardware only.** A hosted GitHub runner is itself a virtual machine and cannot start one, so
|
||||
this does not run in CI: it runs on a Mac you have (see `docs/dev/ci.md`).
|
||||
- **The wallpaper and the zoom button** are not driven yet.
|
||||
|
||||
## Running it
|
||||
|
||||
```sh
|
||||
# once: the golden image (30 GB of disk; one manual step, the grants, which the script stops for)
|
||||
e2e/platforms/tart_macos/build-bins.sh target/e2e-macos
|
||||
e2e/platforms/tart_macos/build-golden.sh target/e2e-macos
|
||||
|
||||
# every time: this checkout's daemon against the image
|
||||
nix run .#e2e-macos -- target/e2e-out tiling focus
|
||||
```
|
||||
|
||||
`nix run .#e2e-macos` builds the programs under test and brings `tart` (nixpkgs has it as an unfree
|
||||
package, so it is allowed for that one only). `KOMOREBI_E2E_BINS=dir` runs the programs of `dir`
|
||||
(`build-bins.sh` makes one), `KOMOREBI_E2E_GOLDEN=name` another image, `KOMOREBI_E2E_SCALE=1.5` makes
|
||||
every wait longer for a busy host. The image has to be built again when the agent changes, and for a
|
||||
new macOS.
|
||||
|
||||
The unit tests of the port need no guest and run with those of the Windows one
|
||||
(`python -m pytest lib/tests platforms/qemu_windows/tests platforms/tart_macos/tests`, in `e2e`, with
|
||||
`PYTHONPATH=lib:.`; the `windows-e2e-tests` check does it).
|
||||
|
||||
Do not run it alongside a heavy build, which makes the daemon slow to answer and the waits fail.
|
||||
Reference in new issue
Block a user