//! Loudness (extensions/packaging.md §12): the committed corpus `pack-conformance/loudness/` //! regenerates byte for byte, holds no other file, every case in it gets the outcome it states, //! and §12.7 lists exactly the reasons the reference reports. #![cfg(feature = "loudness")] use std::collections::BTreeMap; use std::path::PathBuf; use wai::loudness::{corpus, CODES}; fn wai_dir() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..") } fn committed() -> BTreeMap { let dir = wai_dir().join("pack-conformance/loudness"); std::fs::read_dir(&dir) .expect("the committed corpus") .flatten() .map(|e| (e.file_name().to_string_lossy().into_owned(), e.path())) .filter(|(n, _)| n != "README.md") .map(|(n, p)| (n, std::fs::read_to_string(p).expect("a text file"))) .collect() } #[test] fn the_committed_corpus_regenerates_from_its_seeds() { let files = committed(); let generated: BTreeMap = corpus::generate().into_iter().collect(); let extra: Vec<&String> = files.keys().filter(|k| !generated.contains_key(*k)).collect(); let missing: Vec<&String> = generated.keys().filter(|k| !files.contains_key(*k)).collect(); let differ: Vec<&String> = generated.iter().filter(|(k, v)| files.get(*k).is_some_and(|f| f != *v)).map(|(k, _)| k).collect(); assert!(extra.is_empty() && missing.is_empty() && differ.is_empty(), "extra {extra:?}, missing {missing:?}, differ {differ:?}: run `wai_loudness_vectors gen`"); } #[test] fn every_case_gets_its_stated_outcome() { let fails = corpus::verify_corpus(&committed()); assert!(fails.is_empty(), "{}", fails.join("\n")); } /// §12.7 lists exactly the codes `CODES` has, each once, in order. #[test] fn the_extension_lists_the_reasons() { let text = std::fs::read_to_string(wai_dir().join("extensions/packaging.md")).expect("the extension"); let at = text.find("\n**12.7**").expect("§12.7"); let end = text[at + 1..].find("\n## ").map_or(text.len(), |e| at + 1 + e); let listed: Vec = text[at..end].lines().filter(|l| l.starts_with("| `")).filter_map(|l| l.split('`').nth(1).map(String::from)).collect(); let want: Vec = CODES.iter().map(|c| c.to_string()).collect(); assert_eq!(listed, want, "§12.7's table and CODES differ"); } /// §12.8 states the tone's period the corpus is written from, value for value. #[test] fn the_text_states_the_tone() { let text = std::fs::read_to_string(wai_dir().join("extensions/packaging.md")).expect("the extension"); let at = text.find("sine_1k = [").expect("§12.8's table") + "sine_1k = [".len(); let end = at + text[at..].find(']').expect("the table's end"); let listed: Vec = text[at..end].split(',').map(|v| v.trim().parse().expect("an integer")).collect(); assert_eq!(listed, corpus::SINE_1K.to_vec()); } /// §12.2 states the filter's coefficients the reference uses, value for value. #[test] fn the_text_states_the_filter() { let text = std::fs::read_to_string(wai_dir().join("extensions/packaging.md")).expect("the extension"); let read = |after: &str| -> Vec { let at = text.find(after).unwrap_or_else(|| panic!("{after}")) + after.len(); let end = at + text[at..].find(')').expect("the list's end"); text[at..end].replace(['\u{2212}'], "-").split(',').map(|v| v.split_whitespace().collect::().parse().expect("an integer")).collect() }; assert_eq!(read("the first section (b0, b1, b2, a1, a2) = ("), wai::loudness::STAGE1.to_vec()); assert_eq!(read("the second ("), wai::loudness::STAGE2.to_vec()); }