Commit 5035fcb
test(e2e): prove the gateway happy path over the CLI and HTTP (ADR 0005) (#132)
Stacked on #131. Four smoke tests for the seam nothing covered: a real
gateway process, real worker processes on a real uplink, and a client
reaching the fleet the way a user does.
## Why
`src/daemon/gateway-fleet.e2e.test.ts` already proves lease routing and
a real `device.exec` across two worker processes — but through the
daemon's own `dispatch()`, in-process. Everything between that
dispatcher and a user was unproven for gateway mode: the CLI's
gateway/worker branch, the HTTP lease and exec routes against a gateway,
SSE streaming of proxied output, and exit-code propagation.
The one out-of-process lease that existed (`e2e/gateway-fleet.test.ts`)
deliberately went straight to a worker's own socket, with a comment
saying fleet routing belonged to a later PR than the one that wrote it.
That PR has since landed and nothing came back to close the gap.
## The tests
1. **CLI through a gateway** — `simlock lease` gives a grant carrying
its `worker` block and a worker-named id; the worker's own `status`
shows §27a's namespaced requester (`gw:<instance>:<agent>`); `simlock
adb` takes the gateway branch (`device.exec` rather than a local spawn),
streams both streams, and exits with the tool's own code; `release`.
2. **HTTP through a gateway** — lease request to granted, exec streaming
SSE with a real exit code, a silent long-running command answered while
it still runs, and a pre-process refusal keeping its own `422
PASSTHROUGH_REFUSED` instead of a committed `200`.
3. **Fleet-wide FIFO** — `REQUESTER_ALREADY_LEASED` (13), `--no-wait` →
`NO_CAPACITY` (11), a waiter reporting `queued` at position 1 and served
on release.
4. **Renew/release** — an over-cap `--ttl` refused gateway-side (§15),
and the gateway-issued id round-tripping through `status` and `lease
renew`.
These are smoke tests: they prove the layers are wired to each other,
not that the routing policy, queue ordering or refusal lists are
correct. `src/gateway`'s own suites own that.
## Two new fake-driver flags, for one assertion
`--fake-exec-silent` and `--fake-exec-sleep=<ms>` exist together to pin
ADR §19a's `started` push end to end.
What `started` buys a transport is **timing**, not status: `http/app.ts`
races the command settling against `started`, so a command that merely
succeeds reaches the same committed `200` either way — just not until it
exits. Only a command that is both silent and slow separates them. Every
existing fixture writes its argv and would let a first-chunk fallback
pass identically.
That assertion took three attempts, and the first two are why the third
is worth having. Billing the `422` refusal as "the only end-to-end test
of `started`" was false — it passes with the gateway's relay ripped out,
as does a short silent command. Neutering `FleetLeaseCoordinator#exec`'s
`onStarted` now fails exactly one assertion: `expected 4049 to be less
than 2000`, the response head arriving only after the command exited.
## One harness subtlety worth knowing
The CLI test passes `input: ""`, modelling `simlock adb ... <
/dev/null`. That is load-bearing rather than tidiness: against a worker
the CLI spawns the tool with inherited stdio and never reads stdin, but
against a gateway it must read stdin to EOF before it can send the one
`stdin` string `device.exec` carries. The e2e harness spawns with a pipe
it never closes, so without this the CLI waits for an EOF that never
comes — exactly what a real caller handing simlock an open pipe would
see.
## Verification
- typecheck, e2e typecheck, lint, format — clean
- 1810 unit tests pass
- 4/4 smoke tests pass against the pushed code (136s)
- `device-exec` and `lease-environment-passthrough` re-run and
unaffected by the fake-driver change
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01MA98m7ua7qvDFZjxFaww6Z
---
_Generated by [Claude
Code](https://claude.ai/code/session_01MA98m7ua7qvDFZjxFaww6Z)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent b9e0215 commit 5035fcb
3 files changed
Lines changed: 483 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
118 | 118 | | |
119 | 119 | | |
120 | 120 | | |
121 | | - | |
122 | | - | |
| 121 | + | |
| 122 | + | |
123 | 123 | | |
124 | | - | |
| 124 | + | |
125 | 125 | | |
126 | | - | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
127 | 136 | | |
128 | 137 | | |
129 | 138 | | |
| |||
137 | 146 | | |
138 | 147 | | |
139 | 148 | | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
140 | 154 | | |
141 | 155 | | |
142 | 156 | | |
| |||
151 | 165 | | |
152 | 166 | | |
153 | 167 | | |
154 | | - | |
| 168 | + | |
155 | 169 | | |
156 | 170 | | |
157 | 171 | | |
| |||
0 commit comments