From 1265ae09f385a991e0d35dd7836f9bada5bd2a3f Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Thu, 1 Oct 2026 17:17:18 -0700 Subject: [PATCH 1/2] quest: plan moq-mux live import clock and tracing capture audit Co-Authored-By: Claude Opus 5.5 --- quest/m1/test-flakes-2/README.md | 2 ++ .../m1/test-flakes-2/mux-live-import-clock.md | 28 +++++++++++++++++++ quest/m1/test-flakes-2/trace-capture-audit.md | 24 ++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 quest/m1/test-flakes-2/mux-live-import-clock.md create mode 100644 quest/m1/test-flakes-2/trace-capture-audit.md diff --git a/quest/m1/test-flakes-2/README.md b/quest/m1/test-flakes-2/README.md index 80843a5165..04e35825c2 100644 --- a/quest/m1/test-flakes-2/README.md +++ b/quest/m1/test-flakes-2/README.md @@ -37,6 +37,8 @@ Public API: none. Wire: none. - [moq-mux debounce clock](/quest/m1/test-flakes-2/mux-debounce-clock.md) - the TS export debounce test advances on the paused clock - [js/publish audio clock](/quest/m1/test-flakes-2/publish-audio-clock.md) - the audio encoder delay test runs on mock time - [WebSocket paused TLS dial](/quest/m1/test-flakes-2/websocket-paused-tls.md) - the fixed-address WebSocket tests stop pausing the clock over a real dial +- [moq-mux live import clock](/quest/m1/test-flakes-2/mux-live-import-clock.md) - the live import restart tests advance a paused clock instead of sleeping +- [Tracing capture audit](/quest/m1/test-flakes-2/trace-capture-audit.md) - no test misses tracing events because a parallel test silenced the call site ## Related diff --git a/quest/m1/test-flakes-2/mux-live-import-clock.md b/quest/m1/test-flakes-2/mux-live-import-clock.md new file mode 100644 index 0000000000..c468e4258a --- /dev/null +++ b/quest/m1/test-flakes-2/mux-live-import-clock.md @@ -0,0 +1,28 @@ +# [S] moq-mux live import tests on the paused clock + +## Goal + +The moq-mux live import restart tests (`live_import_restarts_forward_after_idle` +for ts, fmp4, and flv) advance a paused clock across their idle gap and sleep +no real time. + +## Plan + +Facts (`origin/main`, 2026-10-01): the helpers (`live_import` in +`container/{ts,fmp4}/import_test.rs`, `import` in `flv/import_test.rs`) call +`std::thread::sleep(idle)` with a 300 ms idle. The gap is measured through +`clock::Anchor`, which reads `crate::Clock::now()`, and that is +`std::time::Instant::elapsed()`, so a paused tokio clock can't move it. + +Decided (2026-10-01): `crate::Clock`'s monotonic epoch becomes a +`web_async::time::Instant`. That is tokio's clock on native, so the tests start +paused and call `tokio::time::advance`, and it takes `std::time::Instant` off the +wasm path, as #4687 did for the TS SI debounce. The wall mapping stays +`SystemTime`. Rejected: injecting a `now` into the importers through +`translate_at`, which is plumbing only tests want. + +Update `test_util::late_clock` to match, and check other `crate::Clock` users +(including `Clock::at` callers) still build on wasm. + +Public API: check whether `Clock::at` is exported; if its `Instant` type +changes, report it. Wire: none. diff --git a/quest/m1/test-flakes-2/trace-capture-audit.md b/quest/m1/test-flakes-2/trace-capture-audit.md new file mode 100644 index 0000000000..b6be476abd --- /dev/null +++ b/quest/m1/test-flakes-2/trace-capture-audit.md @@ -0,0 +1,24 @@ +# [XS] Tracing captures survive the call-site cache + +## Goal + +No test in the workspace counts or asserts tracing events through a +thread-scoped subscriber (`with_default`, `set_default`) that a parallel +test can silence under a shared-process `cargo test`. + +## Plan + +#4690 found that tracing caches, per call site and for the whole process, +whether any subscriber wants its events. With only scoped subscribers, the +first thread to hit a call site decides for everyone, so a parallel test on a +thread with no subscriber turns the event off and the capture misses it. +Nextest runs each test in its own process and can't hit it, but `cargo test` +does. + +Grep the Rust crates for tests that capture tracing output with scoped +subscribers. Move each one to the helper #4690 added in +`rs/moq-net/src/model/test_tracing.rs` (one process-wide subscriber, events +routed to a per-thread counter), or a shared copy of it if other crates need +it. If none turn up, delete this quest. + +Public API: none. Wire: none. From ac25d88ab58eb1aba8e064630148bb2d313d33b6 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Thu, 1 Oct 2026 17:30:38 -0700 Subject: [PATCH 2/2] quest: address review on live import clock and tracing capture audit Co-Authored-By: Claude Opus 5.5 --- .../m1/test-flakes-2/mux-live-import-clock.md | 24 ++++++++++++++----- quest/m1/test-flakes-2/trace-capture-audit.md | 11 ++++++--- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/quest/m1/test-flakes-2/mux-live-import-clock.md b/quest/m1/test-flakes-2/mux-live-import-clock.md index c468e4258a..5d5375a721 100644 --- a/quest/m1/test-flakes-2/mux-live-import-clock.md +++ b/quest/m1/test-flakes-2/mux-live-import-clock.md @@ -17,12 +17,24 @@ Facts (`origin/main`, 2026-10-01): the helpers (`live_import` in Decided (2026-10-01): `crate::Clock`'s monotonic epoch becomes a `web_async::time::Instant`. That is tokio's clock on native, so the tests start paused and call `tokio::time::advance`, and it takes `std::time::Instant` off the -wasm path, as #4687 did for the TS SI debounce. The wall mapping stays -`SystemTime`. Rejected: injecting a `now` into the importers through +wasm path. #4687 used the same `Instant` type, but only for the private SI +debounce after dropping its `crate::Clock`; `Clock` itself still reads +`std::time::Instant`. The wall mapping stays `SystemTime`. Rejected: injecting a `now` into the importers through `translate_at`, which is plumbing only tests want. -Update `test_util::late_clock` to match, and check other `crate::Clock` users -(including `Clock::at` callers) still build on wasm. +`std::time::Instant` is public at the boundary: `Clock::at(epoch, wall)` is +re-exported from `moq-mux`, and the json and binary timed writes +(`json.rs` `update`/`append`, and their `binary.rs` twins) take +`Timed<_, Instant>` through the crate-private `Clock::stamp`/`capture`. +`moq_net::Timed`'s docs say moq-mux uses `std::time::Instant`. Callers pass +`std::time::Instant` from `test_util::late_clock`, moq-cli publish, moq-hls +export, moq-audio and moq-video capture, and the catalog producer tests. -Public API: check whether `Clock::at` is exported; if its `Instant` type -changes, report it. Wire: none. +Open (maintainer, ask before starting): keep the public inputs on +`std::time::Instant` and convert at the boundary (native only; additive, stays +on `main`), or switch them to `web_async::time::Instant` as a typed break on +`dev` and update every caller and doc. Recommended: convert at the boundary, +so only the private epoch moves. + +Public API: none if converted at the boundary; otherwise `Clock::at` and the +timed writes change type. Wire: none. diff --git a/quest/m1/test-flakes-2/trace-capture-audit.md b/quest/m1/test-flakes-2/trace-capture-audit.md index b6be476abd..7dca6d7ea8 100644 --- a/quest/m1/test-flakes-2/trace-capture-audit.md +++ b/quest/m1/test-flakes-2/trace-capture-audit.md @@ -15,10 +15,15 @@ thread with no subscriber turns the event off and the capture misses it. Nextest runs each test in its own process and can't hit it, but `cargo test` does. +Start after #4690 lands, with its open review finding on the subscriber +installation window resolved, so the race isn't copied into other crates. + Grep the Rust crates for tests that capture tracing output with scoped -subscribers. Move each one to the helper #4690 added in +subscribers. Move each one onto #4690's pattern in `rs/moq-net/src/model/test_tracing.rs` (one process-wide subscriber, events -routed to a per-thread counter), or a shared copy of it if other crates need -it. If none turn up, delete this quest. +routed to a per-thread capture). Its helper only counts WARN events by +message, so a capture that asserts something else needs the helper +generalized, or a shared copy if other crates need it. If none turn up, delete +this quest. Public API: none. Wire: none.