Skip to content

test(agent): e2e + registry + routing test suite#1772

Open
irvingouj@Devolutions (irvingoujAtDevolution) wants to merge 4 commits into
masterfrom
feat/agent-tunnel-tests
Open

test(agent): e2e + registry + routing test suite#1772
irvingouj@Devolutions (irvingoujAtDevolution) wants to merge 4 commits into
masterfrom
feat/agent-tunnel-tests

Conversation

@irvingoujAtDevolution
Copy link
Copy Markdown
Contributor

@irvingoujAtDevolution irvingouj@Devolutions (irvingoujAtDevolution) commented Apr 29, 2026

Summary

Adds the agent-tunnel test suite under testsuite/tests/agent_tunnel/:

  • integration.rs — full QUIC end-to-end (CA → enroll → mTLS → control stream → ConnectRequest → echo) plus the domain-routing variant
  • registry.rsAgentRegistry unit tests (online/offline timeouts, route epoch handling, domain advertisement persistence, agent-info snapshot)
  • routing.rsRoutePlan::resolve / try_route decision matrix (explicit jet_agent_id, subnet/domain match, fallback, offline filtering, no-handle paths)

Why split out

The routing/upstream feature (#1741, since merged) kept its diff focused on production code. Tests live here so the test scaffolding diff doesn't muddle the feature review.

Test plan

  • cargo test -p testsuite --test integration_tests agent_tunnel:: — 25/25 pass locally

@irvingoujAtDevolution irvingouj@Devolutions (irvingoujAtDevolution) changed the title test(agent-tunnel): e2e + registry + routing test suite test(agent): e2e + registry + routing test suite Apr 29, 2026
@irvingoujAtDevolution irvingouj@Devolutions (irvingoujAtDevolution) force-pushed the feat/quic-tunnel-2-routing branch 2 times, most recently from b4ec360 to a2b2ff5 Compare May 12, 2026 17:40
irvingouj@Devolutions (irvingoujAtDevolution) added a commit that referenced this pull request May 12, 2026
Address CBenoit's review on #1741: in addition to the `#[doc(hidden)]`
marker and the `_for_test` naming, gate `AgentPeer::set_last_seen_for_test`
and `set_received_at_for_test` behind `#[cfg(any(test, feature = "test-utils"))]`
so production builds of `devolutions-gateway` and `devolutions-agent` don't
compile these methods at all. Cross-crate test consumers (the workspace
`testsuite` crate carrying the agent-tunnel integration tests, in #1772)
opt in via `features = ["test-utils"]` on their `agent-tunnel` dev-dep.
Base automatically changed from feat/quic-tunnel-2-routing to master May 13, 2026 15:19
@irvingoujAtDevolution irvingouj@Devolutions (irvingoujAtDevolution) force-pushed the feat/agent-tunnel-tests branch 3 times, most recently from 8887df1 to c2da5a9 Compare May 19, 2026 19:05
- testsuite/tests/agent_tunnel/integration.rs: full QUIC e2e (CA →
  enroll → mTLS → control stream → ConnectRequest → echo) and a
  domain-routing variant.
- testsuite/tests/agent_tunnel/registry.rs: AgentRegistry unit tests
  covering online/offline timeouts, route epoch handling (replace vs
  refresh vs ignore stale), domain advertisement persistence, and the
  agent-info snapshot.
- testsuite/tests/agent_tunnel/routing.rs: RoutePlan::resolve / try_route
  decision matrix — explicit jet_agent_id, subnet match, domain match,
  fallback to direct, offline filtering, and the no-handle paths.

Also includes the read_cert_chain rewrite from #1771 (needed for the
e2e tests to parse the rcgen-produced PEM); once #1771 lands this
collapses to just the test files.
…iants

Backfills coverage that the original test suite (#1741-era) predates:

- New `common.rs` consolidates the QUIC + mTLS test scaffolding so all
  E2E tests share one `bind_test_listener` helper instead of duplicating
  ~80 lines per test.

- New `cert.rs` pins three invariants of `agent-tunnel/src/cert.rs`:
  - `sign_agent_csr` must encode the caller-passed agent_id in the URN
    SAN, *ignoring* the CSR's Common Name (#1775 review feedback —
    prevents a compromised agent from impersonating via CSR subject).
  - `extract_agent_id_from_pem` round-trips a freshly signed cert.
  - `extract_agent_id_from_pem` rejects a cert with no urn:uuid SAN
    (e.g. the CA root cert).

- Extra `routing.rs` cases against a live `AgentTunnelHandle`:
  - `route_and_connect` errors on empty candidate slice.
  - `try_route` with handle present and no match returns `Ok(None)`.
  - `try_route` with handle present and missing explicit agent_id errors
    rather than silently falling back to direct.

- New `cert_renewal_preserves_mtls_identity_e2e` runs the full QUIC
  `CertRenewalRequest` → `CertRenewalResponse::Success` round-trip with
  a renewal CSR filed under `CN=evil-impersonator`. Asserts the renewed
  cert still encodes the mTLS-authenticated `agent_id` — guards the
  #1775 handler's "never trust the CSR subject" comment with a test.

32 tests now pass; 3 parallel runs verified stable (~0.3s each).
…dvertise

`ctrl.send(&RouteAdvertise)` only guarantees the message is on the wire,
not that the gateway has processed it and updated `peer.route_state()`.
A fixed 200ms `tokio::time::sleep` was racy on slow/loaded CI runners.

Replace the three call sites with `wait_for_route_advertised`, a 10ms
poll loop that exits as soon as the agent appears in the registry with
`route_state().epoch >= min_epoch`, or panics with a clear message
after 5s. Default `RouteAdvertisementState` has epoch 0, so any
successful RouteAdvertise bumps it to >= 1.

Side effect: the e2e tests finish in ~0.16s instead of ~0.32s because
they no longer eat the worst-case fixed delay.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant