From c813f4c03ba900d340bc915bb5c88f3e9c6680d9 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Fri, 16 Oct 2026 15:52:24 -0700 Subject: [PATCH] test: link the remaining multi-file test suites into one binary moq-cli, moq-audio, moq-json, and moq-pattern still built one binary per `tests/*.rs` file. Each now builds one `tests/integration` binary, as moq-net, moq-relay, moq-tokio, and moq-uring do since #5689. moq-json's two suites shared an identical counting allocator, now declared once. Co-Authored-By: Claude Opus 5.5 --- .../tests/{ => integration}/import.rs | 2 +- rs/moq-audio/tests/integration/main.rs | 8 +++ .../tests/{ => integration}/playback.rs | 0 .../tests/{ => integration}/roundtrip.rs | 0 .../tests/{ => integration}/auth_serve.rs | 0 rs/moq-cli/tests/{ => integration}/export.rs | 6 +-- rs/moq-cli/tests/{ => integration}/import.rs | 4 +- rs/moq-cli/tests/{ => integration}/listen.rs | 0 rs/moq-cli/tests/integration/main.rs | 9 ++++ .../{ => integration}/decode_allocations.rs | 46 +--------------- rs/moq-json/tests/integration/main.rs | 54 +++++++++++++++++++ .../{ => integration}/window_allocations.rs | 47 +--------------- rs/moq-pattern/tests/integration/main.rs | 7 +++ .../tests/{ => integration}/pattern.rs | 2 +- .../{ => integration}/pattern_exhaustive.rs | 0 rs/moq-pattern/tests/pattern.json | 2 +- 16 files changed, 88 insertions(+), 99 deletions(-) rename rs/moq-audio/tests/{ => integration}/import.rs (96%) create mode 100644 rs/moq-audio/tests/integration/main.rs rename rs/moq-audio/tests/{ => integration}/playback.rs (100%) rename rs/moq-audio/tests/{ => integration}/roundtrip.rs (100%) rename rs/moq-cli/tests/{ => integration}/auth_serve.rs (100%) rename rs/moq-cli/tests/{ => integration}/export.rs (98%) rename rs/moq-cli/tests/{ => integration}/import.rs (97%) rename rs/moq-cli/tests/{ => integration}/listen.rs (100%) create mode 100644 rs/moq-cli/tests/integration/main.rs rename rs/moq-json/tests/{ => integration}/decode_allocations.rs (52%) create mode 100644 rs/moq-json/tests/integration/main.rs rename rs/moq-json/tests/{ => integration}/window_allocations.rs (68%) create mode 100644 rs/moq-pattern/tests/integration/main.rs rename rs/moq-pattern/tests/{ => integration}/pattern.rs (98%) rename rs/moq-pattern/tests/{ => integration}/pattern_exhaustive.rs (100%) diff --git a/rs/moq-audio/tests/import.rs b/rs/moq-audio/tests/integration/import.rs similarity index 96% rename from rs/moq-audio/tests/import.rs rename to rs/moq-audio/tests/integration/import.rs index a1a5a147e43..be750fb327e 100644 --- a/rs/moq-audio/tests/import.rs +++ b/rs/moq-audio/tests/integration/import.rs @@ -10,7 +10,7 @@ use moq_audio::{Format, Layout, decode}; #[tokio::test] async fn ts_surround_opus_decodes() { // A 440 Hz center channel in 5.1; see `import_opus_surround_catalog` in moq-mux. - let data = include_bytes!("../../moq-mux/src/container/ts/test_data/opus_5_1.ts"); + let data = include_bytes!("../../../moq-mux/src/container/ts/test_data/opus_5_1.ts"); let mut broadcast = moq_net::broadcast::Info::new().produce(); let broadcast_consumer = broadcast.consume(); diff --git a/rs/moq-audio/tests/integration/main.rs b/rs/moq-audio/tests/integration/main.rs new file mode 100644 index 00000000000..98cdd493f98 --- /dev/null +++ b/rs/moq-audio/tests/integration/main.rs @@ -0,0 +1,8 @@ +//! Every integration test, linked into one binary. +//! +//! Each `tests/*.rs` file is its own crate that links this package and its +//! dependencies again, so add new integration tests here as a module. + +mod import; +mod playback; +mod roundtrip; diff --git a/rs/moq-audio/tests/playback.rs b/rs/moq-audio/tests/integration/playback.rs similarity index 100% rename from rs/moq-audio/tests/playback.rs rename to rs/moq-audio/tests/integration/playback.rs diff --git a/rs/moq-audio/tests/roundtrip.rs b/rs/moq-audio/tests/integration/roundtrip.rs similarity index 100% rename from rs/moq-audio/tests/roundtrip.rs rename to rs/moq-audio/tests/integration/roundtrip.rs diff --git a/rs/moq-cli/tests/auth_serve.rs b/rs/moq-cli/tests/integration/auth_serve.rs similarity index 100% rename from rs/moq-cli/tests/auth_serve.rs rename to rs/moq-cli/tests/integration/auth_serve.rs diff --git a/rs/moq-cli/tests/export.rs b/rs/moq-cli/tests/integration/export.rs similarity index 98% rename from rs/moq-cli/tests/export.rs rename to rs/moq-cli/tests/integration/export.rs index de89cf1369e..ba3f1f05d0d 100644 --- a/rs/moq-cli/tests/export.rs +++ b/rs/moq-cli/tests/integration/export.rs @@ -18,13 +18,13 @@ use tokio::task::JoinHandle; const TIMEOUT: Duration = Duration::from_secs(30); /// About three seconds of HEVC and Opus. -const CLIP: &[u8] = include_bytes!("../../moq-mux/src/container/ts/test_data/bbb_cbr.ts"); +const CLIP: &[u8] = include_bytes!("../../../moq-mux/src/container/ts/test_data/bbb_cbr.ts"); /// Five seconds of the same capture at the same rate, which leaves media to come once an export /// has waited out the PCR-rate window and its delay (`ffmpeg -i scte35/bbb5s.ts -c copy /// -muxrate 400000 -f mpegts bbb5s_cbr.ts`). -const LONG: &[u8] = include_bytes!("../../moq-mux/src/container/ts/test_data/bbb5s_cbr.ts"); +const LONG: &[u8] = include_bytes!("../../../moq-mux/src/container/ts/test_data/bbb5s_cbr.ts"); /// Fragmented AV1, which the TS export does not carry. -const AV1: &[u8] = include_bytes!("../../moq-mux/src/container/fmp4/test_data/av1.mp4"); +const AV1: &[u8] = include_bytes!("../../../moq-mux/src/container/fmp4/test_data/av1.mp4"); type Output = Arc>>; diff --git a/rs/moq-cli/tests/import.rs b/rs/moq-cli/tests/integration/import.rs similarity index 97% rename from rs/moq-cli/tests/import.rs rename to rs/moq-cli/tests/integration/import.rs index bf0947aa824..f466f2ba140 100644 --- a/rs/moq-cli/tests/import.rs +++ b/rs/moq-cli/tests/integration/import.rs @@ -11,7 +11,7 @@ const TIMEOUT: Duration = Duration::from_secs(10); /// How long a finished import stays up: long enough for a subscriber to request its media /// after reading the final catalog, short enough that the process exits within `TIMEOUT`. const MAX_AGE: &str = "5s"; -const BBB: &[u8] = include_bytes!("../../moq-mux/src/container/ts/test_data/scte35/bbb5s.ts"); +const BBB: &[u8] = include_bytes!("../../../moq-mux/src/container/ts/test_data/scte35/bbb5s.ts"); /// Await `step` while `moq` still holds stdin open, failing as soon as the process exits. /// @@ -124,7 +124,7 @@ async fn import_delivers_the_catalog_finish_at_eof() { /// About one second of CBR HEVC and Opus: shorter than the two-second mux-rate window, so /// the catalog is only released at EOF. -const SHORT: &[u8] = include_bytes!("../../moq-mux/src/container/ts/test_data/bbb_cbr.ts") +const SHORT: &[u8] = include_bytes!("../../../moq-mux/src/container/ts/test_data/bbb_cbr.ts") .split_at(256 * 188) .0; diff --git a/rs/moq-cli/tests/listen.rs b/rs/moq-cli/tests/integration/listen.rs similarity index 100% rename from rs/moq-cli/tests/listen.rs rename to rs/moq-cli/tests/integration/listen.rs diff --git a/rs/moq-cli/tests/integration/main.rs b/rs/moq-cli/tests/integration/main.rs new file mode 100644 index 00000000000..831dea1e5e5 --- /dev/null +++ b/rs/moq-cli/tests/integration/main.rs @@ -0,0 +1,9 @@ +//! Every integration test, linked into one binary. +//! +//! Each `tests/*.rs` file is its own crate that links this package and its +//! dependencies again, so add new integration tests here as a module. + +mod auth_serve; +mod export; +mod import; +mod listen; diff --git a/rs/moq-json/tests/decode_allocations.rs b/rs/moq-json/tests/integration/decode_allocations.rs similarity index 52% rename from rs/moq-json/tests/decode_allocations.rs rename to rs/moq-json/tests/integration/decode_allocations.rs index d87f7ccb938..dcbd809f764 100644 --- a/rs/moq-json/tests/decode_allocations.rs +++ b/rs/moq-json/tests/integration/decode_allocations.rs @@ -1,54 +1,10 @@ //! Materializing a snapshot allocates only what the returned value owns. -use std::alloc::{GlobalAlloc, Layout, System}; -use std::cell::Cell; use std::collections::BTreeMap; +use crate::count; use moq_json::snapshot::{Decoder, consumer}; -struct Counter; - -thread_local! { - // Per thread, so tests running alongside don't leak into the count. - static ALLOCATIONS: Cell> = const { Cell::new(None) }; -} - -#[global_allocator] -static ALLOCATOR: Counter = Counter; - -fn bump() { - // `try_with` because the allocator can run while the thread-local is being torn down. - let _ = ALLOCATIONS.try_with(|count| count.set(count.get().map(|n| n + 1))); -} - -unsafe impl GlobalAlloc for Counter { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - bump(); - unsafe { System.alloc(layout) } - } - - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - bump(); - unsafe { System.alloc_zeroed(layout) } - } - - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - bump(); - unsafe { System.realloc(ptr, layout, new_size) } - } - - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - unsafe { System.dealloc(ptr, layout) } - } -} - -fn count(f: impl FnOnce() -> R) -> (R, usize) { - ALLOCATIONS.with(|count| count.set(Some(0))); - let out = f(); - let allocations = ALLOCATIONS.with(|count| count.take()).unwrap(); - (out, allocations) -} - #[derive(serde::Deserialize, Debug, PartialEq)] struct Entry { bytes: u64, diff --git a/rs/moq-json/tests/integration/main.rs b/rs/moq-json/tests/integration/main.rs new file mode 100644 index 00000000000..4f279360c73 --- /dev/null +++ b/rs/moq-json/tests/integration/main.rs @@ -0,0 +1,54 @@ +//! Every integration test, linked into one binary. +//! +//! Each `tests/*.rs` file is its own crate that links this package and its +//! dependencies again, so add new integration tests here as a module. Every +//! test here counts allocations, so the counting allocator is shared. + +use std::alloc::{GlobalAlloc, Layout, System}; +use std::cell::Cell; + +mod decode_allocations; +mod window_allocations; + +struct Counter; + +thread_local! { + // Per thread, so tests running alongside don't leak into the count. + static ALLOCATIONS: Cell> = const { Cell::new(None) }; +} + +#[global_allocator] +static ALLOCATOR: Counter = Counter; + +fn bump() { + // `try_with` because the allocator can run while the thread-local is being torn down. + let _ = ALLOCATIONS.try_with(|count| count.set(count.get().map(|n| n + 1))); +} + +unsafe impl GlobalAlloc for Counter { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + bump(); + unsafe { System.alloc(layout) } + } + + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + bump(); + unsafe { System.alloc_zeroed(layout) } + } + + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + bump(); + unsafe { System.realloc(ptr, layout, new_size) } + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + unsafe { System.dealloc(ptr, layout) } + } +} + +fn count(f: impl FnOnce() -> R) -> (R, usize) { + ALLOCATIONS.with(|count| count.set(Some(0))); + let out = f(); + let allocations = ALLOCATIONS.with(|count| count.take()).unwrap(); + (out, allocations) +} diff --git a/rs/moq-json/tests/window_allocations.rs b/rs/moq-json/tests/integration/window_allocations.rs similarity index 68% rename from rs/moq-json/tests/window_allocations.rs rename to rs/moq-json/tests/integration/window_allocations.rs index 590e1afd5a2..06d412a4d94 100644 --- a/rs/moq-json/tests/window_allocations.rs +++ b/rs/moq-json/tests/integration/window_allocations.rs @@ -1,53 +1,8 @@ //! Decoding a window frame allocates only what the decoded records own. -use std::alloc::{GlobalAlloc, Layout, System}; -use std::cell::Cell; - +use crate::count; use moq_json::window::{ConsumerConfig, Decoder, Event}; -struct Counter; - -thread_local! { - // Per thread, so tests running alongside don't leak into the count. - static ALLOCATIONS: Cell> = const { Cell::new(None) }; -} - -#[global_allocator] -static ALLOCATOR: Counter = Counter; - -fn bump() { - // `try_with` because the allocator can run while the thread-local is being torn down. - let _ = ALLOCATIONS.try_with(|count| count.set(count.get().map(|n| n + 1))); -} - -unsafe impl GlobalAlloc for Counter { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - bump(); - unsafe { System.alloc(layout) } - } - - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - bump(); - unsafe { System.alloc_zeroed(layout) } - } - - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - bump(); - unsafe { System.realloc(ptr, layout, new_size) } - } - - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - unsafe { System.dealloc(ptr, layout) } - } -} - -fn count(f: impl FnOnce() -> R) -> (R, usize) { - ALLOCATIONS.with(|count| count.set(Some(0))); - let out = f(); - let allocations = ALLOCATIONS.with(|count| count.take()).unwrap(); - (out, allocations) -} - #[derive(serde::Deserialize, Debug, PartialEq)] struct Record { bytes: u64, diff --git a/rs/moq-pattern/tests/integration/main.rs b/rs/moq-pattern/tests/integration/main.rs new file mode 100644 index 00000000000..73c5d36d88e --- /dev/null +++ b/rs/moq-pattern/tests/integration/main.rs @@ -0,0 +1,7 @@ +//! Every integration test, linked into one binary. +//! +//! Each `tests/*.rs` file is its own crate that links this package and its +//! dependencies again, so add new integration tests here as a module. + +mod pattern; +mod pattern_exhaustive; diff --git a/rs/moq-pattern/tests/pattern.rs b/rs/moq-pattern/tests/integration/pattern.rs similarity index 98% rename from rs/moq-pattern/tests/pattern.rs rename to rs/moq-pattern/tests/integration/pattern.rs index 2d64bb39119..0c27fd599e9 100644 --- a/rs/moq-pattern/tests/pattern.rs +++ b/rs/moq-pattern/tests/integration/pattern.rs @@ -4,7 +4,7 @@ use moq_pattern::{InvalidPattern, Pattern, Patterns, Segment}; use serde_json::Value; fn vectors() -> Value { - serde_json::from_str(include_str!("pattern.json")).expect("pattern.json parses") + serde_json::from_str(include_str!("../pattern.json")).expect("pattern.json parses") } fn pattern(text: &str) -> Pattern { diff --git a/rs/moq-pattern/tests/pattern_exhaustive.rs b/rs/moq-pattern/tests/integration/pattern_exhaustive.rs similarity index 100% rename from rs/moq-pattern/tests/pattern_exhaustive.rs rename to rs/moq-pattern/tests/integration/pattern_exhaustive.rs diff --git a/rs/moq-pattern/tests/pattern.json b/rs/moq-pattern/tests/pattern.json index 8b5905c3914..3603c992e29 100644 --- a/rs/moq-pattern/tests/pattern.json +++ b/rs/moq-pattern/tests/pattern.json @@ -1,5 +1,5 @@ { - "$comment": "Golden vectors shared by rs/moq-pattern (tests/pattern.rs) and js/pattern (src/index.test.ts). Both test suites read this file, so the two implementations cannot drift apart silently.", + "$comment": "Golden vectors shared by rs/moq-pattern (tests/integration/pattern.rs) and js/pattern (src/index.test.ts). Both test suites read this file, so the two implementations cannot drift apart silently.", "parse": [ { "text": "",