Files
alktunnels/tasks/tunnels/end-to-end-suite.md
T
glm-5.3-flash 2efac9b609 feat: end-to-end suite — 18-test consolidation over the shared harness
- tests/end_to_end.rs: 1 MiB backpressure, deadline→timeout (ADR-049 §2),
  CF-006 witness (transport + token), odd-ID asserts + distinctness
  (ADR-047 §5), full CF-005 precedence chain (ServingConfig override,
  distinct-id token probe, fail-closed), R-01 concurrency ×3, listen
  FIFO + typed-error table, datagram batching + 7-byte chunk-split
  codec probe + reverse codec session + TCP/UDP concurrent, teardown
  matrix arms (close-with-pump / join copy counts / Drop-with-pump /
  failed-adopt), no-phantom-channel + R-02 data-plane-tracking asserts
- tests/harness.rs: RegistrationMode::Timeout (hanging establisher,
  per-registration bound), wire_serving_identity (CF-005 (a) shape)
- task doc: status completed, notes + summary

Verified: cargo test (68), cargo test --features local (75), 3×
repeat-run clean both configs, clippy -D warnings (all-targets, local,
wasm32), fmt --check, wasm32 check
2026-09-08 10:03:42 +00:00

154 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: tunnels/end-to-end-suite
name: End-to-end suite — forward, reverse, listen, datagram, teardown matrix
status: completed
depends_on: [tunnels/consumer-session, tunnels/producer-listen, tunnels/local-socket-halves]
scope: broad
risk: medium
impact: phase
level: implementation
tags: [tests, integration, phase-gate]
---
## Description
Consolidate the integration coverage into `tests/` as the crate's
end-to-end suite: every validated POC behavior, re-expressed against the
crate's public API (not the POCs' internals). This is the quality gate
before the implementation review — the suite is the spec's executable
form.
### Suites
1. **Forward (`-L`)**: consumer `open` → producer establisher dials →
`pump_bidi` → round-trip; 1 MiB backpressure; typed errors
(unknown_resource / dial_failed / FORBIDDEN / timeout-adjacent);
per-call opener identity witness (CF-006).
2. **Reverse (`-R`)**: hub initiator — `open_reverse_channel` +
`adopt` + `pump_against`; odd-ID allocation asserted (ADR-047 §5);
identity precedence chain (transport alone / `ServingConfig.
identity` override / token override / identity-less fail-closed);
half-close (W4); out-of-band `channel/close` + self-reaping (W3);
concurrent same-resource opens (R-01, no handoff race).
3. **Listen producer**: the accept-queue flow end-to-end + its typed
errors (from `tunnels/producer-listen`).
4. **Datagram (`udp`)**: forward + reverse datagram sessions via the
codec — round-trip, empty datagram (the F-2 layering), chunk-split
survival, TCP+UDP concurrent channels on one connection.
5. **Teardown matrix** (ADR-005): close / join (with + without pump) /
Drop — `channel_ids()` asserts no leaks on either side after each.
6. **`local` feature suite**: real sockets end-to-end (from
`tunnels/local-socket-halves` — runs after that task lands; the
duplex-transport suites above do not need it).
Transport stand-in: `tokio::io::duplex` (both POCs' harness; the
alkcall layer owns real transports — unchanged scope). The suite may
share one harness module (`tests/common/`); the POC harnesses
(`/workspace/alktunnels-udp-poc/src/harness.rs`,
`/workspace/alktunnels-reverse-poc/src/harness.rs`) are the two
topologies to unify.
### The spec-conformance assertions to keep visible
- A failed open never returns a `channel_id` (no phantom channel —
both sides' `channel_ids()` hold only 0 afterward).
- A failed adopt never leaks the session (Drop reaps).
- The pump handler's `JoinHandle` tracks the data plane (a test that
simulates early-return would hang/EOF-instantly — the R-02 shape;
assert the correct shape survives).
## Acceptance Criteria
- [ ] All 6 suites present; ≥20 integration tests total
- [ ] `cargo test` green; `cargo test --features local` green
- [ ] Repeat-run stable (3× clean — the POCs' flakiness bar)
- [ ] Clippy/fmt clean; wasm32 check passes
## References
- docs/architecture/wire.md + consumer.md + producer.md (the normative
behaviors under test)
- POC test suites: `/workspace/alktunnels-udp-poc/tests/tunnel_poc.rs`
(10), `/workspace/alktunnels-reverse-poc/tests/tunnel_poc.rs` (16)
## Notes
> Agent fills during implementation.
### Implementation notes (2026-09-08)
The pre-existing per-task suites (36 integration tests across
`producer_open_op`, `consumer_session`, `producer_listen`,
`local_halves`) already carried much of the per-suite coverage; this
task consolidated the remaining POC-validated behaviors they didn't
cover into `tests/end_to_end.rs` (18 tests, the suites as enumerated)
and extended `tests/harness.rs`:
- `RegistrationMode::Timeout(Duration)` — a hanging establisher with
an explicit per-registration establishment timeout (the ADR-049 §2
deadline-expiry probe; the wrapper maps expiry to reason `timeout`
with no channel surviving).
- `wire_serving_identity` — the `ServingConfig.identity` override
probe shape (CF-005 (a)).
Gaps the suite filled (behaviors the per-task suites did not cover):
1 MiB backpressure round-trip (both POCs' sizing probe); the
deadline→`timeout` wire mapping; odd-ID allocation asserts (ADR-047 §5)
plus distinctness; the FULL identity precedence chain — the
`ServingConfig.identity` override and the token-over-transport
precedence with a DISTINCT resolved id (the existing token test
resolved to the same id as the transport identity, so it proved
authorization but not precedence — the new `DistinctTokenProvider`
probe proves precedence); reverse datagram sessions via the codec
(pump-less `(0, 0, reaped)` join shape); 40-datagram bursts with
batching (the pending-queue cover, both directions); the 7-byte
chunk-split codec probe (100 datagrams); TCP+UDP interleaved on one
connection; teardown matrix arms: close-with-pump (abort + reap both
sides), join copy counts, Drop-with-pump (abort AND reap), and the
failed-adopt no-leak arm; R-02's JoinHandle-tracks-the-data-plane
assertion (alive-and-pumpable long after the open, completion only at
both-direction EOF).
### Test-side findings (not product bugs — recorded for the record)
- **Parked ≠ adopted.** `teardown_channel` on a reverse-open'd but
never-adopted channel id is `UnknownChannel` — the manager parks
early arrivals for unseen ids (the adoption-race cover, ADR-047 §5)
but does not install a channel entry until adopt. Cleanup for such
ids is adopt-then-close (what the tests do). Worth knowing when an
assembly layer errors between `open_reverse_channel` and `adopt`.
- **`read(&mut Vec)` vs `read(buf)`** — an unpopulated `Vec` passed to
`AsyncReadExt::read` has len 0 and reads nothing (instant EOF); the
1 MiB loop needed a size-`expected` buffer with `&mut received[got..]`.
- The empty-queue-vs-error posture from `tunnels/producer-listen`
carries over verbatim: the queue's pop waits; mapping empty-pop to
`resource_shortage` is the assembly closure's posture (producer.md's
table), asserted here with a fail-fast closure.
## Summary
> Agent fills this on completion.
### Summary
`tests/end_to_end.rs` (18 tests) consolidates the POC-validated
behaviors into the crate's end-to-end suite over the shared duplex
harness: forward (1 MiB backpressure, deadline→`timeout`, CF-006
witness on transport + token paths), reverse (odd-ID asserts +
distinctness, the full CF-005 precedence chain incl. the
ServingConfig override and a distinct-id token probe, R-01 same-
resource concurrency ×3), listen (FIFO always-before-take, the typed
error table), datagram (batching survival, 7-byte chunk-split codec
probe, reverse codec session, TCP+UDP concurrent), teardown matrix
(close-with-pump / join copy counts / Drop-with-pump / failed-adopt),
and the spec-conformance assertions (no phantom channel, no leaked
session, R-02's data-plane-tracking pump handle).
Harness grew `RegistrationMode::Timeout` + `wire_serving_identity`.
Existing suites untouched. Verification: `cargo test` green (68 tests
incl. unit + doc), `cargo test --features local` green (75), 3×
repeat-run clean (both feature configs), clippy `-D warnings` clean
(all-targets, `--features local`, wasm32), `cargo fmt --check` clean,
wasm32 check passes. No product-code changes were needed — the
failures during development were all test-harness bugs (zero-len read
buffer, teardown-on-parked-id), recorded above.