Skip to content
2 changes: 1 addition & 1 deletion quest/m1/mock-clock-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ before starting, since tests land and move.

- [js/net tests run on a mocked clock](/quest/m1/mock-clock-tests/js-net.md) - about 120 js/net tests stop waiting on real time, through their shared helpers
- [Other JS tests run on a mocked clock](/quest/m1/mock-clock-tests/js-rest.md) - hang's `settle(20)`, publish's fanout helpers, and the rest of JS
- [moq-relay tests run on a mocked clock](/quest/m1/mock-clock-tests/rs-relay.md) - the relay's `timeout(..).is_err()` session proofs and settle sleeps
- [moq-relay's mesh tests run on a mocked clock](/quest/m1/mock-clock-tests/rs-relay.md) - the relay's multi-relay quiet windows and settle sleeps
- [Transport crate tests run on a mocked clock](/quest/m1/mock-clock-tests/rs-transport.md) - moq-tokio, moq-quic, moq-sock, and moq-uring
- [Media crate tests run on a mocked clock](/quest/m1/mock-clock-tests/rs-media.md) - moq-audio, moq-video, moq-hls, moq-mux, and the bridges
- [Binding and CLI tests run on a mocked clock](/quest/m1/mock-clock-tests/rs-bindings.md) - moq-ffi, moq-c, moq-cli, and kio
Expand Down
62 changes: 48 additions & 14 deletions quest/m1/mock-clock-tests/rs-relay.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,55 @@
# [M] moq-relay tests run on a mocked clock
# [M] moq-relay's mesh tests run on a mocked clock

## Goal

moq-relay's tests stop proving a session stayed open with
`timeout(200ms, session.closed()).is_err()` on the real clock, and stop
sleeping to settle. See the [epic](/quest/m1/mock-clock-tests/README.md)
for the rules.
moq-relay's multi-relay and process-signal tests stop proving that nothing
happened by waiting out a quiet window, and stop sleeping to settle. See the
[epic](/quest/m1/mock-clock-tests/README.md) for the rules.

## Plan

As of 2026-11-06, 28 tests: `tests/integration/auth_lifetime.rs` 9,
`session_revalidate.rs` 4, `public_rules.rs` 3, `goaway_cluster.rs` 2,
`runtime_uring.rs` 2, `tenant_matrix.rs` 2, `web.rs` 2, and one each in
`cluster_unknown.rs`, `socket_auth.rs`, `src/auth.rs`, and `src/session.rs`.
Many run over real sockets: assert on the event the relay emits (a
revalidation, a close reason), or drive the deadline with the
[simulator or a `Manual` clock](/quest/m0/test-flakes-2/README.md), rather
than waiting out a window.
The single-relay tests are done: a session that stays open is proven by the
`end` its lease reports for the client's own close, an absent broadcast by a
listing read to `Synced`, and the GOAWAY handover by a manual clock. What is
left, as of 2026-11-06:

Public API: none. Wire: none.
- `cluster_unknown.rs`: `assert_unknown_publisher_stays_announced` watches for
a flap for `SETTLE` (1s) after the frame reaches D.
- `goaway_cluster.rs`: `cluster_migrates_on_upstream_goaway` and
`cluster_continues_a_group_split_by_goaway` end on a 500ms window with no
retraction, and the second also on a 500ms window with no downstream GOAWAY.
- `cluster_drain.rs`: `pass` moves a manual clock in steps and sleeps `SETTLE`
on tokio's clock after each, so real sockets catch up.
- `shutdown_signal.rs`: `an_embedder_owns_the_signals` waits `DRAIN_TIMEOUT / 2`
for a GOAWAY that must not come.

Each crosses a mesh of relays over loopback, where no event marks convergence:
`Synced` is per hop, origin cursors coalesce across prefixes, and retractions
are held for `update_hold`. A quiet window is the only proof that fits today.
Only the simulator's `idle` proves a mesh has settled, and the cluster dials
peers only through `moq_tokio` sockets.

Tests that only wait for progress, or bound real-socket timing from below, stay
on the real clock: the `runtime_uring.rs` and listing poll loops, `web.rs`'s
`start.elapsed() >= timeout`, `bitrate_caps.rs`'s `LEAST`, and
`shutdown_signal.rs`'s drain-window lower bounds.

Decided 2026-11-06 (maintainer, on
[moq-dev/moq#8087](https://github.com/moq-dev/moq/pull/8087)):

- ✅ **A dial hook on `cluster::Options` that an in-memory link can fill**, so
the four tests above run on `kio::clock::sim` and prove convergence with

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

four tests does not match the bullets above: goaway_cluster.rs names two, so five tests across four files are listed. Say the tests above (or the four files above) so whoever converts them is not short by one.

Suggested change
the four tests above run on `kio::clock::sim` and prove convergence with
the tests above run on `kio::clock::sim` and prove convergence with

`sim::idle` instead of a quiet window. Not chosen: keeping them as documented
real-clock exceptions opted out of the [Rust guard](/quest/m0/clock-guard/rust.md).

Guidance:

- The hook is public API whose only consumer today is these tests; name it by
role (how a peer is reached), not by the test transport.
- The mesh tests build whole relays with `Relay::load` over loopback, so the
simulator needs a relay that accepts in-memory links too, as
`tests/integration/memory.rs` already does for one relay.
- `shutdown_signal`'s window waits on a process signal, not a mesh: its relay
must also take that signal from a source the simulator can drive.

Public API: a new `cluster::Options` dial hook. Wire: none.
8 changes: 3 additions & 5 deletions rs/moq-relay/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1856,14 +1856,12 @@ mod tests {

#[tokio::test]
async fn dropping_the_last_auth_ends_admissions() {
use futures::FutureExt;

let (auth, mut admissions) = Auth::embedded("relay-1");
let clone = auth.clone();
drop(auth);
assert!(
kio::clock::timeout(std::time::Duration::ZERO, admissions.next())
.await
.is_err()
);
assert!(admissions.next().now_or_never().is_none(), "a clone still admits");
drop(clone);
assert!(admissions.next().await.is_none());
}
Expand Down
9 changes: 3 additions & 6 deletions rs/moq-relay/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,8 @@ mod tests {

#[tokio::test]
async fn a_push_wakes_the_registration_once() {
use futures::FutureExt;

let registry = Registry::new();
let request = request("abc", "/room", "127.0.0.1:1");
let reg = registry.register(request);
Expand All @@ -598,11 +600,6 @@ mod tests {
kio::clock::timeout(Duration::from_secs(1), reg.nudged())
.await
.expect("the registration woke");
assert!(
kio::clock::timeout(std::time::Duration::from_millis(20), reg.nudged())
.await
.is_err(),
"a single push wakes once"
);
assert!(reg.nudged().now_or_never().is_none(), "a single push wakes once");
}
}
Loading
Loading