diff --git a/crates/sylpheed-formats/tests/slb_leading_segment_disc.rs b/crates/sylpheed-formats/tests/slb_leading_segment_disc.rs index 213a38ef..27d0dd4f 100644 --- a/crates/sylpheed-formats/tests/slb_leading_segment_disc.rs +++ b/crates/sylpheed-formats/tests/slb_leading_segment_disc.rs @@ -6,14 +6,34 @@ //! silence. One rule, two outcomes. use std::path::Path; +use std::sync::OnceLock; use sylpheed_formats::{slb, PakArchive}; mod common; use common::skip_without_disc; +/// One archive for the whole binary. +/// +/// `PakArchive` holds the entire concatenated payload in memory, and +/// `sound.pak` is **1.01 GB** (`sound.p00`-`.p04`). Opening it per call — which +/// the helpers below did, inside loops — put one copy per test thread in flight, +/// so at the default thread count the suite needed ~6 GB and was SIGKILLed by +/// the CI container's 7 GB cap (`--memory-swap` equals `--memory`, so there is +/// no swap to absorb it). A killed suite prints no `test result:` line at all, +/// so it vanishes from the tally rather than failing visibly. +/// +/// The archive is immutable once open and every accessor takes `&self`, so one +/// shared instance is equivalent to N private ones — at 1/N the memory. +fn sound(root: &Path) -> &'static PakArchive { + static SOUND: OnceLock = OnceLock::new(); + // Every caller passes the same `disc_root()`, so first-writer-wins is the + // same archive whichever test initialises it. + SOUND.get_or_init(|| PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak")) +} + fn bank(root: &Path, n: u32) -> Vec { - let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak"); + let snd = sound(root); let path = format!("eng\\etc\\VOICE_D_{n}.slb"); let entry = snd.find_by_name(&path).expect("bank present"); snd.read(entry).expect("read") @@ -71,7 +91,7 @@ fn all_zero_leading_region_is_skipped() { } fn bank_named(root: &Path, path: &str) -> Vec { - let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak"); + let snd = sound(root); let entry = snd .find_by_name(path) .unwrap_or_else(|| panic!("{path} present")); @@ -154,7 +174,7 @@ fn derived_offset_recovers_voice_banks_without_regressing_etc() { #[test] fn scan_data_offset_agrees_with_the_riff_derived_answer() { skip_without_disc!(root); - let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak"); + let snd = sound(&root); let mut checked = 0usize; let mut agreed = 0usize; for lang in ["eng", "jpn"] { @@ -198,7 +218,7 @@ fn scan_data_offset_agrees_with_the_riff_derived_answer() { #[test] fn scan_only_returns_known_offsets() { skip_without_disc!(root); - let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak"); + let snd = sound(&root); let mut seen = 0usize; for n in 1u32..200 { for path in [ @@ -232,7 +252,7 @@ fn scan_only_returns_known_offsets() { #[test] fn a_waves_declared_size_is_confirmed_by_the_next_seek() { skip_without_disc!(root); - let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak"); + let snd = sound(&root); let mut checked = 0usize; for n in 1u32..400 { for path in [ @@ -289,7 +309,7 @@ fn a_waves_declared_size_is_confirmed_by_the_next_seek() { #[test] fn a_bank_that_states_its_own_header_has_no_leading_segment() { skip_without_disc!(root); - let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak"); + let snd = sound(&root); let mut with_header = 0usize; let mut mid_bank = 0usize; // Peek at the 56-byte header through the archive's flat data rather than @@ -327,7 +347,7 @@ fn a_bank_that_states_its_own_header_has_no_leading_segment() { #[test] fn the_menu_music_bank_is_exactly_two_sub_waves() { skip_without_disc!(root); - let snd = PakArchive::open(root.join("dat/sound.pak")).expect("sound.pak"); + let snd = sound(&root); for (name, sizes) in [ ("BGM_103.slb", [3_876_864usize, 3_930_112]), ("BGM_001.slb", [4_466_688, 4_673_536]),