Some checks failed
wai-quantum WebGPU member / member · DX12 and Vulkan (cbio-windows) (pull_request) Successful in 12m9s
wai-web wasm32 / does this change touch it (pull_request) Has been cancelled
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Has been cancelled
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Has been cancelled
WAI mbt2018_mean integer decode (regenerated vectors) / does this change touch it (pull_request) Has been cancelled
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Has been cancelled
wai-quantum WebGPU member / does this change touch it (pull_request) Has been cancelled
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness · MSRV (pull_request) Has been cancelled
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · discrete GPU, Vulkan (jetson-hub) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Has been cancelled
wai-quantum CPU vector units / does this change touch it (pull_request) Has been cancelled
wai-quantum CPU vector units / member · vector unit, rvv 1024-bit (riscv64, emulated) (pull_request) Has been cancelled
wai-quantum CPU vector units / member · vector unit, sve 128-bit (aarch64, emulated) (pull_request) Has been cancelled
wai-quantum CPU vector units / member · vector unit, rvv 128-bit (riscv64, emulated) (pull_request) Has been cancelled
wai-quantum CPU vector units / member · vector unit, sve 2048-bit (aarch64, emulated) (pull_request) Has been cancelled
wai-quantum CPU vector units / member · vector unit, avx2 (x86_64 silicon) (pull_request) Has been cancelled
wai-quantum CPU vector units / member · vector unit, sve 512-bit (aarch64, emulated) (pull_request) Has been cancelled
wai-quantum CPU vector units / member · vector units, avx2 and avx512 (framework-128gb silicon) (pull_request) Has been cancelled
wai-quantum CPU vector units / member · vector unit absent (macos) (pull_request) Has been cancelled
wai-quantum portable tensor program / does this change touch it (pull_request) Has been cancelled
wai-quantum portable tensor program / tensor program · CPU, mutants, GPU builds (pull_request) Has been cancelled
wai-quantum portable tensor program / tensor program · GPUs (jetson-hub) (pull_request) Has been cancelled
wai-quantum portable tensor program / tensor program · integrated GPU (framework-128gb) (pull_request) Has been cancelled
wai-quantum portable tensor program / tensor program · Metal and the arm64 CPU (macos) (pull_request) Has been cancelled
wai-quantum tensor-engine member / does this change touch it (pull_request) Has been cancelled
wai-quantum tensor-engine member / member · tensor engine, the kernel toolchain's simulator (linux) (pull_request) Has been cancelled
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Has been cancelled
wai-quantum matrix-extension member / does this change touch it (pull_request) Has been cancelled
wai-quantum matrix-extension member / member · matrix extension, emulated (aarch64 Linux) (pull_request) Has been cancelled
wai-quantum matrix-extension member / member · matrix extension absent (macos) (pull_request) Has been cancelled
wai-quantum-qpu / does this change touch it (pull_request) Has been cancelled
wai-quantum-qpu / clients against their contracts (linux) (pull_request) Has been cancelled
wai-quantum on every processor / emulated · aarch64-unknown-linux-gnu (pull_request) Has been cancelled
wai-quantum on every processor / emulated · armv7-unknown-linux-gnueabihf (pull_request) Has been cancelled
wai-quantum on every processor / emulated · loongarch64-unknown-linux-gnu (pull_request) Has been cancelled
wai-quantum on every processor / emulated · powerpc64-unknown-linux-gnu (pull_request) Has been cancelled
wai-quantum on every processor / emulated · powerpc64le-unknown-linux-gnu (pull_request) Has been cancelled
wai-quantum on every processor / emulated · riscv64gc-unknown-linux-gnu (pull_request) Has been cancelled
wai-quantum on every processor / emulated · s390x-unknown-linux-gnu (pull_request) Has been cancelled
wai-quantum on every processor / emulated · sparc64-unknown-linux-gnu (pull_request) Has been cancelled
wai-quantum on every processor / emulated · i686-unknown-linux-gnu (pull_request) Has been cancelled
wai-quantum OpenCL member / does this change touch it (pull_request) Has been cancelled
wai-quantum OpenCL member / member · OpenCL GPU and CPU (jetson-hub) (pull_request) Has been cancelled
wai-quantum OpenCL member / member · OpenCL GPU (framework-128gb) (pull_request) Has been cancelled
wai-quantum OpenCL member / member · OpenCL GPU (macos) (pull_request) Has been cancelled
wai-quantum OpenCL member / member · OpenCL absent (linux) (pull_request) Has been cancelled
wai-quantum neural-processor member / does this change touch it (pull_request) Has been cancelled
wai-quantum neural-processor member / member · neural processor (macos) (pull_request) Has been cancelled
wai-quantum neural-processor member / member · neural processor absent (linux) (pull_request) Has been cancelled
wai-quantum npu-cores member / does this change touch it (pull_request) Has been cancelled
wai-quantum npu-cores member / member · npu-cores, neural processor (framework-128gb silicon) (pull_request) Has been cancelled
wai-quantum npu-cores member / member · npu-cores absent (linux-arm64) (pull_request) Has been cancelled
wai-quantum Metal member / does this change touch it (pull_request) Has been cancelled
wai-quantum Metal member / member · Metal (macos) (pull_request) Has been cancelled
wai-quantum Metal member / member · Metal absent (linux) (pull_request) Has been cancelled
wai-quantum HIP member / does this change touch it (pull_request) Has been cancelled
wai-quantum HIP member / member · HIP (framework-128gb) (pull_request) Has been cancelled
wai-quantum HIP member / member · HIP absent (linux-arm64) (pull_request) Has been cancelled
wai-quantum FPGA member / does this change touch it (pull_request) Has been cancelled
wai-quantum FPGA member / member · FPGA datapath, simulated (macos) (pull_request) Has been cancelled
wai-quantum FPGA member / member · FPGA simulation absent (linux) (pull_request) Has been cancelled
wai-quantum signal processor / does this change touch it (pull_request) Has been cancelled
wai-quantum signal processor / processor and member · signal processor, emulated (pull_request) Has been cancelled
wai-quantum dataflow member / does this change touch it (pull_request) Has been cancelled
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:b140) (pull_request) Has been cancelled
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:401e) (pull_request) Has been cancelled
wai-quantum dataflow member / member · dataflow device absent (macos) (pull_request) Has been cancelled
wai-quantum CUDA member / does this change touch it (pull_request) Has been cancelled
wai-quantum CUDA member / member · CUDA (jetson-hub) (pull_request) Has been cancelled
wai-quantum CUDA member / member · CUDA absent (linux) (pull_request) Has been cancelled
wai-pack / wai-pack · does this change touch it (pull_request) Has been cancelled
wai-pack / wai-pack · linux (pull_request) Has been cancelled
wai-pack / wai-pack · linux-arm64 (pull_request) Has been cancelled
wai-pack / wai-pack · macos (pull_request) Has been cancelled
wai-pack / wai-pack · independent verifier (Python) (pull_request) Has been cancelled
wai-pack / wai-pack · the floor through a media prober (pull_request) Has been cancelled
wai-pack / wai-pack · dependency licences (pull_request) Has been cancelled
wai-ops integer operators / does this change touch it (pull_request) Has been cancelled
wai-ops integer operators / linux-aarch64 (pull_request) Has been cancelled
wai-ops integer operators / linux-x86_64 (pull_request) Has been cancelled
wai-ops integer operators / macos-arm64 (pull_request) Has been cancelled
wai-ops integer operators / wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
wai-ops integer operators / wasm32 under Node (pull_request) Has been cancelled
wai-ops integer operators / independent checker (Python) (pull_request) Has been cancelled
wai-ops differential (nightly) / differential · debug (pull_request) Has been cancelled
wai-ops differential (nightly) / differential · release (pull_request) Has been cancelled
WAI neural sink gates / does this change touch it (pull_request) Has been cancelled
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Has been cancelled
WAI neural decoders end-to-end / does this change touch it (pull_request) Has been cancelled
WAI neural decoders end-to-end / synthetic fixtures → Rust decode → reference (±4) (pull_request) Has been cancelled
WAI JPEG-AI whole decode (pinned inputs, required) / does this change touch it (pull_request) Has been cancelled
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Has been cancelled
WAI HTTP delivery / WAI HTTP · does this change touch it (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · every patch and mutation in exactly one shard (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Has been cancelled
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Has been cancelled
wai formal verification (integer core) / does this change touch it (pull_request) Has been cancelled
wai formal verification (integer core) / every harness in one shard (pull_request) Has been cancelled
wai formal verification (integer core) / kani (arith) (pull_request) Has been cancelled
wai formal verification (integer core) / kani (isqrt512) (pull_request) Has been cancelled
wai formal verification (integer core) / kani (plan) (pull_request) Has been cancelled
wai formal verification (integer core) / kani (sound) (pull_request) Has been cancelled
wai formal verification (integer core) / kani (stage) (pull_request) Has been cancelled
wai formal verification (integer core) / kani (rans64-t2) (pull_request) Has been cancelled
wai formal verification (integer core) / kani (stage-long) (pull_request) Has been cancelled
wai formal verification (integer core) / kani (integer-core) (pull_request) Has been cancelled
WAI energy receipts / does this change touch it (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
WAI conformance / does this change touch it (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
wai cross-architecture byte-equality / does this change touch it (pull_request) Has been cancelled
wai cross-architecture byte-equality / linux-aarch64 (pull_request) Has been cancelled
wai cross-architecture byte-equality / linux-x86_64 (pull_request) Has been cancelled
wai cross-architecture byte-equality / macos-arm64 (reference) (pull_request) Has been cancelled
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 2m3s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 17s
joule-code conformance gate / joule-moq-relay, every target (pull_request) Successful in 1m31s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 2m29s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 8m20s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 2m50s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
190 lines
11 KiB
Rust
190 lines
11 KiB
Rust
//! A slow subscriber: its low-priority objects time out at the relay, while every receipt
|
|
//! still reaches it and its high-priority track is unaffected (`draft-ietf-moq-transport-22`
|
|
//! §5.1, §5.2; WAI jwp-receipts §4.1, §4.4).
|
|
//!
|
|
//! One publisher sends a staged pair over native QUIC: a base track at publisher priority
|
|
//! 0 with no delivery timeout, and a layer track at priority 200 whose
|
|
//! OBJECT_DELIVERY_TIMEOUT is 100 ms, each with its receipts track. A fast subscriber reads
|
|
//! as it goes. A slow one gives the relay small receive windows and reads nothing until the
|
|
//! publisher has sent everything and a second and a half more has passed; the relay is
|
|
//! given a small send window, so what cannot be sent waits in its scheduler, where the
|
|
//! layer's objects pass their deadline. Then it reads all its streams concurrently.
|
|
|
|
mod common;
|
|
|
|
use common::*;
|
|
use joule_moq::draft22::{Parameter, Parameters, StreamResetCode};
|
|
use joule_moq::receipt::ReceiptVerifier;
|
|
use joule_moq_relay::client::ClientOptions;
|
|
use std::time::Duration;
|
|
|
|
const GROUPS: u64 = 40;
|
|
const STALL: Duration = Duration::from_millis(1500);
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
|
|
async fn a_slow_subscriber_loses_late_layers_and_keeps_every_receipt() {
|
|
tokio::time::timeout(Duration::from_secs(120), run()).await.expect("the test finishes in time");
|
|
}
|
|
|
|
async fn run() {
|
|
let server = relay(|c| {
|
|
c.limits.quic_send_window_bytes = 64 * 1024;
|
|
})
|
|
.await;
|
|
let key = ed25519_dalek::SigningKey::from_bytes(&[0x51; 32]);
|
|
let space = ns(&["stage", "cam"]);
|
|
let base = Tracks::new(space.clone(), "base", 10, 1, 0);
|
|
let layer = Tracks::new(space.clone(), "layer", 20, 2, 200);
|
|
|
|
let (publisher, _ep) = connect(&server, Via::Quic, ClientOptions::default()).await;
|
|
let _b = publish_tracks(&publisher, &base, None).await;
|
|
let _l = publish_tracks(&publisher, &layer, Some(100)).await;
|
|
|
|
let (fast, _ef) = connect(&server, Via::Quic, ClientOptions::default()).await;
|
|
let mut small = quinn::TransportConfig::default();
|
|
small.stream_receive_window(quinn::VarInt::from_u32(32 * 1024));
|
|
small.receive_window(quinn::VarInt::from_u32(96 * 1024));
|
|
let (slow, _es) = connect_with(&server, Via::Quic, ClientOptions { lazy_data: true, ..ClientOptions::default() }, Some(small)).await;
|
|
|
|
let next = || Parameters::new().with(Parameter::LocationFilter(joule_moq::draft22::LocationFilter::NextObject));
|
|
let fast_base = subscribe_both(&fast, &base, next()).await;
|
|
let fast_layer = subscribe_both(&fast, &layer, next()).await;
|
|
// The slow subscriber also asks for a 50 ms delivery timeout on its receipts
|
|
// subscriptions, which it should not (moq-streaming-format §4.1): a receipts track has
|
|
// none, and the relay applies none to it.
|
|
let receipts_timeout = || Parameters::new().with(Parameter::ObjectDeliveryTimeout(50));
|
|
let slow_base = subscribe_both_with(&slow, &base, next(), receipts_timeout()).await;
|
|
let slow_layer = subscribe_both_with(&slow, &layer, next(), receipts_timeout()).await;
|
|
|
|
let (published_tx, published_rx) = tokio::sync::oneshot::channel::<()>();
|
|
let publish = async {
|
|
for g in 0..GROUPS {
|
|
publish_group(&publisher, &key, &base, g, &payload("base", g, 1024)).await;
|
|
publish_group(&publisher, &key, &layer, g, &payload("layer", g, 24 * 1024)).await;
|
|
tokio::time::sleep(Duration::from_millis(15)).await;
|
|
}
|
|
let _ = published_tx.send(());
|
|
};
|
|
// Both subscribers read their streams concurrently, as a subscriber does: one that read
|
|
// them one at a time could wait on a stream whose bytes wait for connection credit
|
|
// held by the unread streams behind it (see the README, "A subscriber that does not
|
|
// read"). Each reads until the base track and every receipt are whole, then until a
|
|
// second passes with nothing new, so every layer stream is read or seen reset.
|
|
let whole = |media: u64, receipts: u64, layer_receipts: u64| {
|
|
move |got: &[Got]| {
|
|
let n = |a: u64| got.iter().filter(|x| x.header.track_alias == a && x.reset.is_none()).count() as u64;
|
|
n(media) == GROUPS && n(receipts) == GROUPS && n(layer_receipts) == GROUPS
|
|
}
|
|
};
|
|
let fast_reads = collect_concurrent(&fast, STEP * 2, Duration::from_secs(1), whole(fast_base.media_alias, fast_base.receipts_alias, fast_layer.receipts_alias));
|
|
let slow_reads = async {
|
|
// Nothing is read while the load arrives, however long a loaded host takes to send
|
|
// it, nor for the stall after: every layer object waiting then is past its deadline.
|
|
let _ = tokio::time::timeout(STEP * 2, published_rx).await;
|
|
tokio::time::sleep(STALL).await;
|
|
collect_concurrent(&slow, STEP * 2, Duration::from_secs(1), whole(slow_base.media_alias, slow_base.receipts_alias, slow_layer.receipts_alias)).await
|
|
};
|
|
let ((), fast_got, slow_got) = tokio::join!(publish, fast_reads, slow_reads);
|
|
|
|
// The fast subscriber: every base object and every receipt.
|
|
let (fo, fb, _, _) = verify(&fast_got, &fast_base, &key);
|
|
assert_eq!((fo, fb), (GROUPS as usize, GROUPS as usize));
|
|
let (_, flb, _, _) = verify(&fast_got, &fast_layer, &key);
|
|
assert_eq!(flb, GROUPS as usize, "every layer receipt reached the fast subscriber");
|
|
|
|
// The slow subscriber's base track is whole: each group once, none reset. (Objects on
|
|
// different streams may arrive in any order; the order the relay hands them to the
|
|
// transport is checked in priority_fan_out.rs.)
|
|
let (bo, bb, _, _) = verify(&slow_got, &slow_base, &key);
|
|
if (bo, bb) != (GROUPS as usize, GROUPS as usize) {
|
|
// Where the missing base objects were: what the subscriber saw, what its transport
|
|
// counted, and what the relay says it handed to the transport.
|
|
let seen: Vec<(u64, Option<u64>)> = slow_got.iter().filter(|x| x.header.track_alias == slow_base.media_alias).map(|x| (x.header.group_id, x.reset)).collect();
|
|
let missing: Vec<u64> = (0..GROUPS).filter(|g| !seen.iter().any(|(b, r)| b == g && r.is_none())).collect();
|
|
let waited = slow.waited_out.lock().unwrap().clone();
|
|
let client_quic = slow.conn.diagnostics();
|
|
let relay_sessions = server.relay().session_diagnostics();
|
|
// Then read every stream still queued, all at once, as a subscriber reading its
|
|
// streams concurrently would: base objects held only by flow control now arrive.
|
|
let mut reads = Vec::new();
|
|
for _ in 0..8 * GROUPS {
|
|
let Some(mut r) = slow.next_stream(Duration::from_millis(500)).await else { break };
|
|
reads.push(tokio::spawn(async move {
|
|
tokio::time::timeout(Duration::from_secs(10), r.start()).await.ok()?.ok()?;
|
|
read_stream(r).await
|
|
}));
|
|
}
|
|
let mut late_base = Vec::new();
|
|
for t in reads {
|
|
if let Ok(Some(g)) = t.await
|
|
&& g.header.track_alias == slow_base.media_alias
|
|
&& g.reset.is_none()
|
|
{
|
|
late_base.push(g.header.group_id);
|
|
}
|
|
}
|
|
late_base.sort();
|
|
slow.close(0, "diagnosis");
|
|
let relay = server.relay().clone();
|
|
until(STEP, || relay.summaries().iter().any(|s| s.summary.tally.subscriber.tracks.len() >= 4)).await;
|
|
let base_name = joule_moq::draft22::names::render(&space, Some(&base.media));
|
|
let tallies: Vec<String> = relay
|
|
.summaries()
|
|
.iter()
|
|
.filter_map(|s| s.summary.tally.subscriber.tracks.get(&base_name).map(|t| format!("session {}: {:?}, undelivered at close {}", s.summary.session, t, s.summary.tally.subscriber.undelivered_at_close)))
|
|
.collect();
|
|
panic!(
|
|
"the high-priority track is unaffected: {bo} base objects and {bb} base receipts of {GROUPS}\n\
|
|
missing base groups {missing:?}; base streams seen (group, reset) {seen:?}\n\
|
|
next_data gave up waiting on a header {} time(s), streams queued behind each: {waited:?}\n\
|
|
base groups that arrived once the queued streams were read concurrently: {late_base:?}\n\
|
|
subscriber QUIC: {client_quic:?}\nrelay sessions: {relay_sessions:?}\nrelay's base tallies: {tallies:?}",
|
|
waited.len()
|
|
);
|
|
}
|
|
let mut base_groups: Vec<u64> = slow_got.iter().filter(|x| x.header.track_alias == slow_base.media_alias).map(|x| x.header.group_id).collect();
|
|
base_groups.sort();
|
|
assert_eq!(base_groups, (0..GROUPS).collect::<Vec<_>>());
|
|
|
|
// Its layer track lost objects to the delivery timeout; every layer receipt arrived
|
|
// anyway, and each dropped object is accounted for by inclusion (jwp-receipts §4.4).
|
|
let (lo, lb, groups, receipts) = verify(&slow_got, &slow_layer, &key);
|
|
assert_eq!(lb, GROUPS as usize, "every layer receipt reached the slow subscriber");
|
|
assert!(lo < GROUPS as usize, "some layer objects passed their deadline ({lo} of {GROUPS} delivered)");
|
|
let delivered: std::collections::HashSet<u64> =
|
|
slow_got.iter().filter(|x| x.header.track_alias == slow_layer.media_alias && x.reset.is_none()).map(|x| x.header.group_id).collect();
|
|
let verifier = ReceiptVerifier::with_anchors(vec![key.verifying_key()]);
|
|
let mut inclusion = 0;
|
|
for g in 0..GROUPS {
|
|
if !delivered.contains(&g) {
|
|
verifier.verify_object(&receipts[&g], &groups[&g]).expect("a dropped object's receipt verifies by inclusion");
|
|
inclusion += 1;
|
|
}
|
|
}
|
|
assert_eq!(inclusion as usize, GROUPS as usize - lo);
|
|
for x in slow_got.iter().filter(|x| x.header.track_alias == slow_layer.media_alias) {
|
|
if let Some(code) = x.reset {
|
|
assert_eq!(code, StreamResetCode::DELIVERY_TIMEOUT.0, "a layer stream reset for its deadline");
|
|
}
|
|
}
|
|
|
|
// The relay's summary of the slow session says the same.
|
|
slow.close(0, "done");
|
|
let relay = server.relay().clone();
|
|
assert!(until(STEP, || relay.summaries().iter().any(|s| s.summary.tally.subscriber.dropped_delivery_timeout > 0)).await);
|
|
let s = relay.summaries().into_iter().find(|s| s.summary.tally.subscriber.dropped_delivery_timeout > 0).unwrap();
|
|
s.verify().unwrap();
|
|
let t = &s.summary.tally.subscriber.tracks;
|
|
let layer_name = joule_moq::draft22::names::render(&space, Some(&layer.media));
|
|
let base_name = joule_moq::draft22::names::render(&space, Some(&base.media));
|
|
let lt = &t[&layer_name];
|
|
assert_eq!(lt.objects_forwarded as usize, lo, "the relay forwarded exactly what arrived whole");
|
|
assert_eq!(lt.objects_forwarded + lt.dropped_delivery_timeout, GROUPS, "each layer object forwarded or dropped");
|
|
assert_eq!(lt.dropped_receipts_track_subscribed, lt.dropped_delivery_timeout, "every drop on a track whose receipts track the session holds");
|
|
assert_eq!(t[&base_name].dropped_delivery_timeout, 0);
|
|
assert_eq!(t[&base_name].objects_forwarded, GROUPS);
|
|
|
|
fast.close(0, "done");
|
|
publisher.close(0, "done");
|
|
server.shutdown().await;
|
|
}
|