Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 16 additions & 22 deletions rs/moq-relay/tests/auth_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,25 +703,28 @@ async fn http_routes_hold_a_lease() {

/// An outage keeps the session until `expires`, then closes it as expired.
///
/// Paused: the relay times the lease and its re-checks on tokio's clock, so the
/// minutes below pass virtually. `expires` is wall-clock, so the relay's deadline
/// comes early by the setup's real time, which the slack absorbs.
#[tokio::test(start_paused = true)]
/// On the real clock: a paused one jumps to the next timer whenever the runtime
/// waits on a socket, and macOS delivers loopback asynchronously, so a virtual
/// timeout can fire before the relay answers. Load only delays the close, so
/// asserting it never lands before `expires` holds on a busy machine.
#[tokio::test]
async fn an_outage_keeps_the_session_until_expires() {
const EXPIRES: Duration = Duration::from_secs(120);
const SLACK: Duration = Duration::from_secs(30);
// Whole seconds, as the grant crosses the wire, so the relay sees this exact instant.
let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
let expires = SystemTime::UNIX_EPOCH + Duration::from_secs(now.as_secs() + 3);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Start the short expiry after connection setup

This deadline is only 2–3 seconds away, but it starts before binding the auth server and relay and before completing two sequential client handshakes plus the media round-trip, even though those setup operations individually allow up to 10 seconds. On a sufficiently loaded runner the grant can therefore expire during setup, causing connection failure or exercising the clock-skew path instead of the intended live-session outage behavior; load does not merely delay the observed close as the comment claims.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Not changing this. The grant's expires is fixed by the connect answer, and re-checks answer 503, so it can't start after setup. Setup is a few ms of loopback round-trips against a 2-3s budget, and if it ever overran expires the connect would be refused and the test fails loudly at "publisher/subscriber connect failed", never a false pass. Widening the margin would add real seconds to every run for a load level that would already time out other tests.

(Written by Claude Opus 5.5)


let mut grant = grant(EXPIRES);
grant.revalidate = Some(Duration::from_secs(10));
let mut grant = grant(Duration::ZERO);
grant.expires = Some(expires);
let script = Script::new(grant);
// Down from the start: a re-check that succeeded would restart the deadline
// at whatever the virtual clock had reached.
script.on_revalidate(Answer::Status(503));
let (port, relay) = spawn_relay(build_auth(script.spawn().await)).await;
let (pub_session, sub_session) = connect_and_round_trip(&room_url("tcp", port)).await;

// Through every failed re-check up to just short of expires, the session is up...
tokio::time::sleep(EXPIRES - SLACK).await;
assert_closed(pub_session, TIMEOUT, "publisher").await;
assert!(
SystemTime::now() >= expires,
"an outage must not close the publisher before expires"
);
let outages = script
.seen
.lock()
Expand All @@ -730,16 +733,7 @@ async fn an_outage_keeps_the_session_until_expires() {
.filter(|r| r.event == Event::Revalidate)
.count();
assert!(outages > 0, "no re-check reached the server during the outage");
assert!(
tokio::time::timeout(Duration::from_millis(100), pub_session.closed())
.await
.is_err(),
"an outage must not close the publisher before expires"
);

// ...and it closes once the grant expires, not later.
assert_closed(pub_session, SLACK, "publisher").await;
assert_closed(sub_session, SLACK, "subscriber").await;
assert_closed(sub_session, TIMEOUT, "subscriber").await;

let ends = tokio::time::timeout(TIMEOUT, async {
loop {
Expand Down
Loading