test(e2e): transfers through a gateway keep their promises
Los mantenedores suelen responder en 1 día
Evaluación
Este issue todavía no se ha evaluado.
Descripción
Part of #552.
Scope
After this PR, #552's measured promises are proven against a real gateway
and worker over the real WebSocket: bytes on the uplink, the 1 s bound
for small calls with uploads and downloads running, a slow reader slowing
only itself, memory per transfer in both directions, 2 GiB both ways with
the download inside agent-device's 90 s, and, on the slow lane, the 1.5×
upload time.
A promise that fails is fixed in this PR, in the module that breaks it.
A fix that would change a value ADR 0028 or #552's Shared values table
sets (credit, unsent mark, message size, channel limit, waits) is not
made: the implementer stops and reports, since those values are the
maintainer's.
The values are in #552's Shared values table.
In short
flowchart LR
T["test"] -->|relay| G["gateway"]
G --- P["counting TCP proxy (test)"] --- W["worker"]
W --> F["fake relay target / real agent-device"]
The tests put a TCP proxy between the worker and the gateway to count
the bytes on the uplink. The timing tests run in their own test project,
alone, so other test files do not compete for the CPU. If this goes
wrong, a promise #552 makes to users is false and nothing shows it.
Technical spec
Facts
| # | Fact | Source |
|---|---|---|
| F1 | startFleet starts a real gateway and worker over the real WebSocket on 127.0.0.1 with a fake relay target; it is local to the file's describe and points the worker's gateway.url straight at the gateway's port |
src/daemon/relay-gateway.e2e.test.ts:124-145, :178, :210 |
| F2 | patternStream and patternDigest make and check large bodies; the pattern is generated byte by byte |
src/daemon/test-relay-support.ts:88-93, :102-110 |
| F3 | The model for timing a small call while a relay runs, with a check that the relay had not finished first | src/daemon/relay-gateway.e2e.test.ts:294-328 |
| F4 | The worker dials gateway.url; the uplink endpoint is derived from it |
src/ports/uplink.ts:52 (resolveUplinkUrl) |
| F5 | The test projects: unit takes src/**/*.test.ts, e2e takes e2e/**/*.test.ts; CI runs pnpm run test:unit |
vitest.config.ts:14-27; package.json:47; .github/workflows/ci.yml:69 |
| F6 | The slow-lane gateway suite starts a gateway and one real-driver worker with one device; its lease tests each open their own lease through the gateway | e2e/slow-agent-device-gateway.test.ts:124-153, :181-200 |
| F7 | A worker answers agent-device calls made with its own agent tokens on its own front | docs/HTTP-API.md:1497-1499 |
| F8 | simlock's upload routes: preflight, direct upload, finalize, each naming the lease in x-agent-device-lease-id |
src/agent-device/shared/routes.ts:20-35; docs/HTTP-API.md:1507-1511 |
| F10 | CI's jobs: unit has a 10-minute limit; quality gates merges and needs static, unit and e2e; pnpm check runs pnpm test, and CI runs what it runs |
.github/workflows/ci.yml:49-54, :105-107; package.json:46, :62; docs/internal/agent-rules/toolchain.md:35 |
| F11 | The command guard lists the scripts agents never run, and toolchain.md's "Checks agents never run" table must match it |
.agents/scripts/tool-guard.mjs:17-28; docs/internal/agent-rules/toolchain.md:18-21 |
| F12 | The mutation config includes every src/**/*.test.ts, and Stryker reruns tests per mutant |
vitest.mutate.config.ts:8; stryker.config.mjs:4-6 |
| F13 | A test pins the lane filters in package.json |
src/test-lanes.test.ts |
| F9 | agent-device's preflight body: sha256, uploadAttemptId, fileName, sizeBytes, artifactType, optional platform and contentType; finalize takes { uploadId } and checks size and hash |
agent-device src/daemon/upload-http.ts:246-256, :197-205; src/daemon/resumable-upload.ts:104-117, at the commit vendor/README.md names |
Modules touched
src/daemon/test-relay-support.ts:startFleetmoves here from
src/daemon/relay-gateway.e2e.test.tswith agatewayUrloption (F1);
a counting TCP proxy helper that pipes each direction with backpressure
and holds no buffer of its own; the pattern helpers derive each byte
from its own offset (a hash in counter mode), so no stretch of the
pattern equals any other, and build it fast enough for 2 GiB (F2).src/daemon/relay-gateway.e2e.test.ts: uses the movedstartFleet.src/daemon/relay-promises.timing.test.ts(new): the tests below.vitest.config.ts,vitest.mutate.config.ts,package.json,
.github/workflows/ci.yml,docs/internal/agent-rules/toolchain.md,
.agents/scripts/tool-guard.mjs,src/test-lanes.test.ts: atiming
project that takessrc/**/*.timing.test.ts, which theunitproject
and the mutation config leave out (F12), runs its files one at a time
with nothing else in parallel, and gives each test 300 s; atest:timingscript that
pnpm test(and sopnpm check) runs (F10); atimingCI job with a
30-minute limit thatqualityneeds; the script intoolchain.md's
"Checks agents never run" table and in the command guard's list (F11),
and a "Tests agents run" row for one timing file:
pnpm vitest run --project timing <file>.e2e/slow-agent-device-gateway.test.ts: the slow-lane test.- A failing promise adds the module that fixes it (Scope).
Contract and event changes
None.
Other code on the same state
None: tests and test tooling. A fix this PR makes names the code it
changes in the PR body.
Rules in play
testing.md: rule 2, every test can fail for the right reason: a
timing test checks its load was still running when it measured.toolchain.md: the new script goes in "Checks agents never run" and
the command guard's list; the slow lane runs through
scripts/slow-e2e.sh.
Tests
Seam: startFleet (F1) with gatewayUrl pointed at the counting TCP
proxy in front of the gateway's port (F4). The proxy counts the bytes it
carries in both directions from a transfer's start to its end. The two
ratio tests (the 1 s bound and the 1.5× slow reader) take the median of 5
runs against a baseline measured the same way in the same test; every
other test is one run. Tests moving 1 GiB or more set a 180 s timeout
and compare by digest while streaming. Model: F3.
- a 100 MiB upload through the gateway puts at most 105 MiB on the uplink
- a 1 GiB upload through the gateway puts at most 1.05 GiB on the uplink, and so does a 1 GiB download, each measured on its own
- while 10 relays each upload 64 MiB and 10 each download 64 MiB to one worker, a forwarded
lease.renewand a relayed request whose target answers at once each answer at most 1 s later than with nothing running, and each of the 20 relays carried at least 1 MiB in the second before and the second after each answer came back - while one relay's caller reads none of its 1 GiB response, another relay's 256 MiB upload to the same worker takes at most 1.5 times as long as with nothing else running
- while the gateway's caller reads none of a 2 GiB response, the target has handed over at most 8 MiB after 5 s; reading it then gets every byte, in order
- while the target reads none of a 2 GiB upload, the gateway has read at most 8 MiB of the caller's body after 5 s; once the target reads, every byte arrives, in order
- a 2 GiB upload through the gateway arrives byte for byte
- a 2 GiB download through the gateway arrives byte for byte and finishes within 90 s
- swapping two chunks of different random sizes (1 byte to 64 KiB) at random offsets of a 2 GiB pattern changes its digest, in each of 100 trials
- the
unitproject and the mutation config leave out*.timing.test.ts, thetimingproject takes them and runs files one at a time,pnpm testrunstest:timing, and CI'squalityjob needs thetimingjob (insrc/test-lanes.test.ts)
Slow lane (F6–F9): in the iOS suite, a test opens a device through the
worker's own front with an agent token minted on the worker, and times a
1 GiB upload with that lease from the preflight to the finalize answer
(F9), three times, then closes it. It then opens a device through the
gateway and times the same upload the same way. The ratio compares the
medians. Both legs run on the same machine, one after the other.
Done when
- Every Tests line passes, and CI runs the
timingproject. - On a Mac with an iOS runtime and the agent-device checks of
toolchain.md: "a 1 GiB upload takes at most 1.5 times as long through the gateway as straight to the worker" passes ine2e/slow-agent-device-gateway.test.ts.
Out of scope
- Any behaviour #558 or #557 owns, except a fix a failing promise needs.
Depends on
- #558
Written by an agent.
- Lenguaje dominante
- TypeScript
- Estrellas
- 20
- Forks
- 2
- Merge medio
- 7 h 26 min
- PR fusionados (30 d)
- 253
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de callstackincubator/simlock
-
Console lane deletes a failed daemon's home, so a start failure names no causePosiblemente ocupada @V3RON la tomó hoy. Abiertobug:triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
callstackincubator/simlock#673 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
bug:needs-info
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
callstackincubator/simlock#657 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
callstackincubator/simlock#639 ·
Los mantenedores suelen responder en 1 día
-
bug:new
Dificultad 4/5 3-5 días Aptitud para principiantes 45/100
callstackincubator/simlock#684 ·
Los mantenedores suelen responder en 1 día
-
A preview system image installed makes the newest runtime its codename, not the highest API levelPosiblemente ocupada @V3RON la tomó hace 1 día. Abiertobug:ready
callstackincubator/simlock#678 · 1 asignado ·
Los mantenedores suelen responder en 1 día
Todos los issues de callstackincubator/simlock
Issues similares
-
"Contains" page watch never matches when its text has a trailing spacePosiblemente ocupada @RaphaelFakhri la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 77/100
CopilotKit/openmuse#184 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 67/100
bootstrap-vue-next/bootstrap-vue-next#3357 ·
Los mantenedores suelen responder en 1 día
-
[quality] tide.ts: six mutation survivors in the merge-queue gate, draft refusal, fork-403 workflow-file diagnosis and getPull's fork flag are unpinned by any testPosiblemente ocupada @hivecommons-hive la tomó hoy. Abiertoagent/quality needs-kind stage/040-covered-by-pr testing
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
cncf/prow-github-actions#517 · 1 comentario ·
Los mantenedores suelen responder en 2 días
-
Unsampled pageload span is profiled when profileLifecycle is 'trace' (browser UI profiling)Posiblemente ocupada @Jxxunnn la tomó hoy. AbiertoBrowser Waiting for: Product Owner
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
getsentry/sentry-javascript#25497 · 1 comentario ·
Los mantenedores suelen responder en 1 día