#[path = "../../support/models_lock_manifest.rs"]
#[allow(dead_code)]
pub mod models_lock_manifest;
#[path = "../../support/workspace_root.rs"]
#[allow(dead_code)]
mod workspace_root;
#[allow(unused_imports)]
pub use workspace_root::{checkout_parent, models_root, workspace_root};
use std::path::{Path, PathBuf};
#[path = "../../support/coremlit_dir.rs"]
#[allow(dead_code)]
mod coremlit_dir;
use coremlit_dir::coremlit_path;
#[allow(dead_code)]
pub fn models_dir() -> PathBuf {
std::env::var_os("CLAPKIT_TEST_MODELS").map_or_else(
|| workspace_root::models_root().join("clapkit"),
PathBuf::from,
)
}
#[allow(dead_code)]
pub const VENDOR_DIR: &str = "clapkit";
#[allow(dead_code)]
pub const ARTIFACT_LOCK_REVISION: &str = "02a99c6a8be21da1e9a947499ea503a10c80c4f1";
#[allow(dead_code)]
pub fn artifact_sha256(bundle: &str) -> Vec<(String, String)> {
models_lock_manifest::bundle_manifest(
&workspace_root::workspace_root(),
VENDOR_DIR,
ARTIFACT_LOCK_REVISION,
bundle,
)
}
#[allow(dead_code)]
pub fn audio_model_path() -> PathBuf {
models_dir().join("clap_audio.mlmodelc")
}
#[allow(dead_code)]
pub fn text_model_path() -> PathBuf {
models_dir().join("clap_text.mlmodelc")
}
#[allow(dead_code)]
pub fn audio_model_int8_path() -> PathBuf {
models_dir().join("clap_audio_int8.mlmodelc")
}
#[allow(dead_code)]
pub fn text_model_int8_path() -> PathBuf {
models_dir().join("clap_text_int8.mlmodelc")
}
#[allow(dead_code)]
pub fn textclap_onnx_dir() -> PathBuf {
std::env::var_os("CLAPKIT_TEXTCLAP_ONNX").map_or_else(
|| {
workspace_root::models_root()
.join("textclap-onnx")
.join("onnx")
},
PathBuf::from,
)
}
#[allow(dead_code)]
pub fn fixture_path(relative: &str) -> PathBuf {
coremlit_path("tests/clap/fixtures").join(relative)
}
#[allow(dead_code)]
pub fn read_wav_48k_mono(path: &Path) -> Vec<f32> {
let mut reader =
hound::WavReader::open(path).unwrap_or_else(|e| panic!("open wav {path:?}: {e}"));
let spec = reader.spec();
assert_eq!(spec.sample_rate, 48_000, "fixture {path:?} must be 48 kHz");
assert_eq!(spec.channels, 1, "fixture {path:?} must be mono");
match spec.sample_format {
hound::SampleFormat::Int => {
let scale = 1.0 / (1_i64 << (spec.bits_per_sample - 1)) as f32;
reader
.samples::<i32>()
.map(|s| s.expect("decode i32 sample") as f32 * scale)
.collect()
}
hound::SampleFormat::Float => reader
.samples::<f32>()
.map(|s| s.expect("decode f32 sample"))
.collect(),
}
}
#[allow(dead_code)]
pub fn sha256_hex(path: &Path) -> String {
use sha2::{Digest, Sha256};
let bytes = std::fs::read(path).unwrap_or_else(|e| panic!("read {path:?}: {e}"));
Sha256::digest(&bytes)
.iter()
.map(|b| format!("{b:02x}"))
.collect()
}
#[allow(dead_code)]
pub fn collect_files_rel(dir: &Path, prefix: &str, out: &mut Vec<String>) {
let entries = std::fs::read_dir(dir).unwrap_or_else(|e| panic!("read_dir {dir:?}: {e}"));
for entry in entries {
let entry = entry.unwrap_or_else(|e| panic!("dir entry under {dir:?}: {e}"));
let name = entry.file_name().to_string_lossy().into_owned();
if name.starts_with("._") || name == ".DS_Store" {
continue;
}
let rel = if prefix.is_empty() {
name
} else {
format!("{prefix}/{name}")
};
let file_type = entry
.file_type()
.unwrap_or_else(|e| panic!("file_type {:?}: {e}", entry.path()));
if file_type.is_dir() {
collect_files_rel(&entry.path(), &rel, out);
} else {
out.push(rel);
}
}
}
#[allow(dead_code)]
pub fn assert_exact_sha_manifest(dir: &Path, cases: &[(String, String)]) {
use std::collections::BTreeSet;
let mut found = Vec::new();
collect_files_rel(dir, "", &mut found);
let on_disk: BTreeSet<String> = found.into_iter().collect();
let pinned: BTreeSet<String> = cases.iter().map(|(rel, _)| rel.clone()).collect();
if on_disk != pinned {
let missing: Vec<&String> = pinned.difference(&on_disk).collect();
let extra: Vec<&String> = on_disk.difference(&pinned).collect();
panic!(
"artifact manifest mismatch under {dir:?}:\n \
missing (pinned but not on disk): {missing:?}\n \
extra (on disk but not pinned): {extra:?}\n \
if the bundle changed intentionally, update the pinned `cases` list AND \
the doc SHA table"
);
}
for (relative, expected) in cases {
let actual = sha256_hex(&dir.join(relative));
assert_eq!(
&actual, expected,
"sha256 drift on artifact {relative} under {dir:?}"
);
}
}
#[allow(dead_code)]
pub fn deterministic_window(len: usize) -> Vec<f32> {
const SR: f32 = 48_000.0;
(0..len)
.map(|i| {
let t = i as f32 / SR;
let two_pi = std::f32::consts::TAU;
0.5 * (two_pi * 220.0 * t).sin()
+ 0.3 * (two_pi * 440.0 * t).sin()
+ 0.2 * (two_pi * 1760.0 * t).sin()
})
.collect()
}
#[path = "../../support/model_gate_report.rs"]
mod model_gate_report;
#[test]
fn model_gate_report() {
model_gate_report::report(&[("CLAPKIT_TEST_MODELS", models_dir())]);
}