use super::*;
fn offsets(plan: &WindowPlan, total: usize) -> Vec<(usize, usize)> {
plan
.spans(total)
.unwrap()
.iter()
.map(|s| (s.start(), s.len()))
.collect()
}
#[test]
fn window_samples_is_the_model_geometry() {
assert_eq!(WINDOW_SAMPLES, 480_000);
assert_eq!(
WINDOW_SAMPLES,
crate::embeddings::clap::audio::TARGET_SAMPLES
);
assert_eq!(DEFAULT_HOP_SAMPLES, 480_000);
assert_eq!(DEFAULT_TAIL_MIN_SAMPLES, 120_000);
}
#[test]
fn default_plan_is_no_overlap_pad() {
let plan = WindowPlan::new();
assert_eq!(plan, WindowPlan::default());
assert_eq!(plan.hop_samples(), 480_000);
assert_eq!(plan.tail_policy(), TailPolicy::Pad);
assert_eq!(TailPolicy::default(), TailPolicy::Pad);
}
#[test]
fn empty_clip_plans_no_windows() {
assert!(WindowPlan::new().spans(0).unwrap().is_empty());
}
#[test]
fn short_clip_is_one_window_regardless_of_hop() {
for hop in [1u32, 120_000, 240_000, 480_000] {
let plan = WindowPlan::new().with_hop_samples(hop);
assert_eq!(offsets(&plan, 100), vec![(0, 100)], "hop {hop}");
assert_eq!(offsets(&plan, 480_000), vec![(0, 480_000)], "hop {hop}");
}
}
#[test]
fn short_clip_survives_drop_below_min() {
let plan =
WindowPlan::new().with_tail_policy(TailPolicy::DropBelowMin(DropBelowMin::new(200_000)));
assert_eq!(
plan
.spans(100_000)
.unwrap()
.iter()
.map(|s| (s.start(), s.len()))
.collect::<Vec<_>>(),
vec![(0, 100_000)]
);
}
#[test]
fn short_clip_coverage_is_padding_aware() {
let spans = WindowPlan::new().spans(240_000).unwrap();
assert_eq!(spans.len(), 1);
assert_eq!(spans[0].coverage(), 0.5); assert_eq!(WindowPlan::new().spans(480_000).unwrap()[0].coverage(), 1.0);
}
#[test]
fn no_overlap_tiling_with_padded_tail() {
let plan = WindowPlan::new();
assert_eq!(
offsets(&plan, 1_000_000),
vec![(0, 480_000), (480_000, 480_000), (960_000, 40_000)]
);
assert_eq!(
offsets(&plan, 960_000),
vec![(0, 480_000), (480_000, 480_000)]
);
}
#[test]
fn drop_below_min_drops_the_short_tail() {
let plan =
WindowPlan::new().with_tail_policy(TailPolicy::DropBelowMin(DropBelowMin::new(120_000)));
assert_eq!(
offsets(&plan, 1_000_000),
vec![(0, 480_000), (480_000, 480_000)]
);
let plan2 =
WindowPlan::new().with_tail_policy(TailPolicy::DropBelowMin(DropBelowMin::new(40_000)));
assert_eq!(
offsets(&plan2, 1_000_000),
vec![(0, 480_000), (480_000, 480_000), (960_000, 40_000)]
);
}
#[test]
fn overlapping_hop_produces_full_windows_then_tails() {
let plan = WindowPlan::new().with_hop_samples(240_000);
assert_eq!(
offsets(&plan, 1_000_000),
vec![
(0, 480_000),
(240_000, 480_000),
(480_000, 480_000),
(720_000, 280_000),
(960_000, 40_000),
]
);
let dropped = plan.with_tail_policy(TailPolicy::DropBelowMin(DropBelowMin::new(120_000)));
assert_eq!(
offsets(&dropped, 1_000_000),
vec![
(0, 480_000),
(240_000, 480_000),
(480_000, 480_000),
(720_000, 280_000),
]
);
}
#[test]
fn window_just_over_boundary_keeps_a_one_sample_tail_under_pad() {
assert_eq!(
offsets(&WindowPlan::new(), 480_001),
vec![(0, 480_000), (480_000, 1)]
);
let dropped = WindowPlan::new().with_tail_policy(TailPolicy::DropBelowMin(DropBelowMin::new(2)));
assert_eq!(offsets(&dropped, 480_001), vec![(0, 480_000)]);
}
#[test]
fn span_geometry_accessors() {
let s = Span::new(720_000, 280_000, WINDOW_SAMPLES);
assert_eq!(s.start(), 720_000);
assert_eq!(s.len(), 280_000);
assert_eq!(s.end(), 1_000_000);
assert_eq!(s.window(), WINDOW_SAMPLES);
assert_eq!(s.coverage(), 280_000.0 / 480_000.0);
}
#[test]
fn window_embedding_pairs_embedding_with_span() {
let mut raw = [0.0f32; crate::embeddings::clap::embedding::EMBEDDING_DIM];
raw[0] = 1.0;
let emb = Embedding::from_slice_normalizing(&raw).unwrap();
let span = Span::new(0, 240_000, WINDOW_SAMPLES);
let we = WindowEmbedding::new(emb, span);
assert_eq!(we.span(), span);
assert_eq!(we.span().coverage(), 0.5);
assert_eq!(we.value().as_slice()[0], 1.0);
}
#[test]
#[should_panic(expected = "hop_samples")]
fn zero_hop_setter_panics() {
let _ = WindowPlan::new().with_hop_samples(0);
}
#[test]
#[should_panic(expected = "hop_samples")]
fn hop_past_window_setter_panics() {
let _ = WindowPlan::new().with_hop_samples(480_001);
}
#[test]
#[should_panic(expected = "min_samples")]
fn zero_drop_min_setter_panics() {
let _ = WindowPlan::new().with_tail_policy(TailPolicy::DropBelowMin(DropBelowMin::new(0)));
}
#[test]
fn huge_total_is_rejected_typed_not_panic() {
let plan = WindowPlan::new().with_hop_samples(1);
let err = plan.spans(usize::MAX).unwrap_err();
assert!(
matches!(
err,
Error::Windowing(WinditError::TooManyWindows { got: usize::MAX, max })
if max == DEFAULT_MAX_WINDOWS as usize
),
"expected TooManyWindows {{ got: usize::MAX, max: {} }}, got {err:?}",
DEFAULT_MAX_WINDOWS
);
}
#[test]
fn hop_one_over_long_clip_is_rejected_typed() {
let plan = WindowPlan::new().with_hop_samples(1);
let total = 2 * WINDOW_SAMPLES; let err = plan.spans(total).unwrap_err();
assert!(
matches!(
err,
Error::Windowing(WinditError::TooManyWindows { got: 960_000, max })
if max == DEFAULT_MAX_WINDOWS as usize
),
"expected TooManyWindows {{ got: 960_000, max: {} }}, got {err:?}",
DEFAULT_MAX_WINDOWS
);
}
#[test]
fn cap_boundary_exact_count_passes_and_plus_one_fails() {
let expected = vec![
(0, 480_000),
(240_000, 480_000),
(480_000, 480_000),
(720_000, 280_000),
(960_000, 40_000),
];
let at_cap = WindowPlan::new()
.with_hop_samples(240_000)
.with_max_windows(5);
assert_eq!(offsets(&at_cap, 1_000_000), expected);
let under_cap = WindowPlan::new()
.with_hop_samples(240_000)
.with_max_windows(4);
let err = under_cap.spans(1_000_000).unwrap_err();
assert!(
matches!(
err,
Error::Windowing(WinditError::TooManyWindows { got: 5, max: 4 })
),
"got {err:?}"
);
}
#[test]
fn planned_windows_matches_materialized_len() {
let pad = |hop: u32| {
WindowPlan::new()
.with_hop_samples(hop)
.with_max_windows(u32::MAX)
};
let drop_min = |hop: u32, min: u32| {
WindowPlan::new()
.with_hop_samples(hop)
.with_tail_policy(TailPolicy::DropBelowMin(DropBelowMin::new(min)))
.with_max_windows(u32::MAX)
};
let cases: [(WindowPlan, usize); 18] = [
(pad(480_000), 1_000_000),
(pad(240_000), 1_000_000),
(pad(120_000), 1_000_000),
(pad(100_000), 1_000_000),
(pad(480_000), 960_000),
(pad(480_000), 480_001),
(pad(480_000), 0),
(pad(480_000), 100),
(pad(480_000), WINDOW_SAMPLES - 1),
(pad(480_000), WINDOW_SAMPLES),
(pad(1), WINDOW_SAMPLES), (drop_min(480_000, 120_000), 1_000_000),
(drop_min(480_000, 40_000), 1_000_000),
(drop_min(240_000, 120_000), 1_000_000),
(drop_min(240_000, 40_000), 1_000_000),
(drop_min(480_000, 2), 480_001),
(drop_min(480_000, 120_000), 100),
(drop_min(480_000, 120_000), 0),
];
for (plan, total) in cases {
assert_eq!(
plan.planned_windows(total),
plan.spans(total).unwrap().len(),
"planned_windows != materialized len for hop={} tail={:?} total={total}",
plan.hop_samples(),
plan.tail_policy(),
);
}
}
#[test]
fn short_clip_never_trips_cap() {
let plan = WindowPlan::new().with_max_windows(1).with_hop_samples(1);
let spans = plan.spans(WINDOW_SAMPLES).unwrap();
assert_eq!(spans.len(), 1);
assert_eq!((spans[0].start(), spans[0].len()), (0, WINDOW_SAMPLES));
}
#[test]
#[should_panic(expected = "max_windows")]
fn zero_max_windows_setter_panics() {
let _ = WindowPlan::new().with_max_windows(0);
}
#[cfg(feature = "serde")]
mod serde_tests {
use super::*;
#[test]
fn round_trips_through_json() {
for plan in [
WindowPlan::new(),
WindowPlan::new().with_hop_samples(240_000),
WindowPlan::new().with_tail_policy(TailPolicy::DropBelowMin(DropBelowMin::new(120_000))),
WindowPlan::new()
.with_hop_samples(240_000)
.with_tail_policy(TailPolicy::DropBelowMin(DropBelowMin::new(120_000)))
.with_max_windows(50_000),
] {
let json = serde_json::to_string(&plan).unwrap();
let back: WindowPlan = serde_json::from_str(&json).unwrap();
assert_eq!(back, plan, "round-trip drift via {json}");
}
}
#[test]
fn defaults_fill_for_a_partial_config() {
let plan: WindowPlan = serde_json::from_str("{}").unwrap();
assert_eq!(plan, WindowPlan::new());
assert_eq!(plan.max_windows(), DEFAULT_MAX_WINDOWS);
let hop_only: WindowPlan = serde_json::from_str(r#"{"hop_samples": 240000}"#).unwrap();
assert_eq!(hop_only.hop_samples(), 240_000);
assert_eq!(hop_only.tail_policy(), TailPolicy::Pad);
assert_eq!(hop_only.max_windows(), DEFAULT_MAX_WINDOWS);
}
#[test]
fn tail_policy_wire_spellings_are_pinned() {
for (policy, doc) in [
(TailPolicy::Pad, r#"{"kind":"pad"}"#),
(
TailPolicy::DropBelowMin(DropBelowMin::new(120_000)),
r#"{"kind":"drop_below_min","value":{"min_samples":120000}}"#,
),
] {
assert_eq!(serde_json::to_string(&policy).unwrap(), doc);
assert_eq!(serde_json::from_str::<TailPolicy>(doc).unwrap(), policy);
}
assert_eq!(
serde_json::to_string(&WindowPlan::new()).unwrap(),
r#"{"hop_samples":480000,"tail":{"kind":"pad"},"max_windows":100000}"#
);
let doc = r#"{"hop_samples":240000,"tail":{"kind":"drop_below_min","value":{"min_samples":120000}},"max_windows":50000}"#;
let plan = WindowPlan::new()
.with_hop_samples(240_000)
.with_tail_policy(TailPolicy::DropBelowMin(DropBelowMin::new(120_000)))
.with_max_windows(50_000);
assert_eq!(serde_json::to_string(&plan).unwrap(), doc);
assert_eq!(serde_json::from_str::<WindowPlan>(doc).unwrap(), plan);
assert!(serde_json::from_str::<TailPolicy>(r#""pad""#).is_err());
assert!(
serde_json::from_str::<TailPolicy>(r#"{"drop_below_min":{"min_samples":120000}}"#).is_err()
);
}
#[test]
fn every_variant_round_trips_through_a_non_self_describing_format() {
for policy in [
TailPolicy::Pad,
TailPolicy::DropBelowMin(DropBelowMin::new(120_000)),
] {
let bytes = postcard::to_allocvec(&policy).unwrap();
assert_eq!(
postcard::from_bytes::<TailPolicy>(&bytes).unwrap(),
policy,
"postcard round-trip lost {policy:?} (bytes {bytes:?})"
);
}
for plan in [
WindowPlan::new(),
WindowPlan::new()
.with_hop_samples(240_000)
.with_tail_policy(TailPolicy::DropBelowMin(DropBelowMin::new(120_000)))
.with_max_windows(50_000),
] {
let bytes = postcard::to_allocvec(&plan).unwrap();
assert_eq!(
postcard::from_bytes::<WindowPlan>(&bytes).unwrap(),
plan,
"postcard round-trip lost {plan:?} (bytes {bytes:?})"
);
}
}
#[test]
fn invalid_hop_fails_to_deserialize() {
assert!(serde_json::from_str::<WindowPlan>(r#"{"hop_samples": 0}"#).is_err());
assert!(serde_json::from_str::<WindowPlan>(r#"{"hop_samples": 480001}"#).is_err());
}
#[test]
fn invalid_tail_min_fails_to_deserialize() {
assert!(
serde_json::from_str::<WindowPlan>(
r#"{"tail": {"kind": "drop_below_min", "value": {"min_samples": 0}}}"#
)
.is_err()
);
assert!(
serde_json::from_str::<WindowPlan>(
r#"{"tail": {"kind": "drop_below_min", "value": {"min_samples": 480001}}}"#
)
.is_err()
);
}
#[test]
fn zero_max_windows_fails_to_deserialize() {
assert!(serde_json::from_str::<WindowPlan>(r#"{"max_windows": 0}"#).is_err());
}
#[test]
fn a_misspelled_key_is_refused_rather_than_silently_defaulted() {
for (doc, key) in [
(r#"{"max_window":1}"#, "max_window"),
(r#"{"hop":240000}"#, "hop"),
(r#"{"tail_policy":{"kind":"pad"}}"#, "tail_policy"),
(r#"{"hop_samples":240000,"max_window":1}"#, "max_window"),
] {
let err = match serde_json::from_str::<WindowPlan>(doc) {
Ok(plan) => panic!(
"{doc} must be refused; it deserialized to {plan:?} (max_windows {})",
plan.max_windows()
),
Err(e) => e.to_string(),
};
assert!(
err.contains(key),
"the refusal must name {key}, got {err:?}"
);
}
let ok: WindowPlan = serde_json::from_str(r#"{"hop_samples":240000,"max_windows":1}"#).unwrap();
assert_eq!(ok.hop_samples(), 240_000);
assert_eq!(ok.max_windows(), 1);
}
#[test]
fn invalid_tail_min_rejection_message_names_the_payload_once() {
let err = WindowPlan::try_from(WindowPlanRepr {
hop_samples: DEFAULT_HOP_SAMPLES,
tail: TailPolicy::DropBelowMin(DropBelowMin::new(0)),
max_windows: DEFAULT_MAX_WINDOWS,
})
.unwrap_err();
assert_eq!(
err,
"tail DropBelowMin.min_samples must be > 0 and <= WINDOW_SAMPLES \
(480000), got DropBelowMin { min_samples: 0 }"
);
}
}