use std::path::PathBuf;
use edgefirst_decoder::{schema::SchemaV2, DecoderBuilder};
fn workspace_root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("..")
.join("..")
}
fn fixture_path(stem: &str) -> PathBuf {
workspace_root()
.join("testdata/decoder")
.join(format!("{stem}.json"))
}
fn build_from_fixture(stem: &str) -> (SchemaV2, edgefirst_decoder::Decoder) {
let path = fixture_path(stem);
let schema =
SchemaV2::parse_file(&path).unwrap_or_else(|e| panic!("parse {}: {e}", path.display()));
let decoder = DecoderBuilder::new()
.with_schema(schema.clone())
.build()
.unwrap_or_else(|e| panic!("build {}: {e}", path.display()));
(schema, decoder)
}
fn assert_modelpack_invariants(
stem: &str,
schema: &SchemaV2,
decoder: &edgefirst_decoder::Decoder,
) {
assert_eq!(
schema.decoder_version, None,
"{stem}: ModelPack must not set decoder_version (Ultralytics-only field)",
);
assert_eq!(
decoder.input_dims(),
Some((320, 320)),
"{stem}: expected 320x320 input",
);
}
#[test]
fn build_decoder_from_modelpack_det_logical() {
let stem = "modelpack_det_logical";
let (schema, decoder) = build_from_fixture(stem);
assert_modelpack_invariants(stem, &schema, &decoder);
assert_eq!(
schema.outputs.len(),
2,
"{stem}: detection-only should expose 2 per-scale logical outputs",
);
for out in &schema.outputs {
assert!(
out.outputs.is_empty(),
"{stem}: logical layout must not carry per-scale children, found on {:?}",
out.name,
);
}
}
#[test]
fn build_decoder_from_modelpack_seg_logical() {
let stem = "modelpack_seg_logical";
let (schema, decoder) = build_from_fixture(stem);
assert_modelpack_invariants(stem, &schema, &decoder);
assert_eq!(
schema.outputs.len(),
1,
"{stem}: segmentation-only should expose 1 logical output",
);
assert!(
schema.outputs[0].outputs.is_empty(),
"{stem}: segmentation logical layout must not carry per-scale children",
);
}
#[test]
fn build_decoder_from_modelpack_multitask_logical() {
let stem = "modelpack_multitask_logical";
let (schema, decoder) = build_from_fixture(stem);
assert_modelpack_invariants(stem, &schema, &decoder);
assert_eq!(
schema.outputs.len(),
4,
"{stem}: multitask should expose 3 detection + 1 segmentation = 4 logical outputs",
);
for out in &schema.outputs {
assert!(
out.outputs.is_empty(),
"{stem}: logical layout must not carry per-scale children, found on {:?}",
out.name,
);
}
}
#[test]
fn build_decoder_from_modelpack_det_smart() {
let stem = "modelpack_det_smart";
let (schema, decoder) = build_from_fixture(stem);
assert_modelpack_invariants(stem, &schema, &decoder);
assert_eq!(
schema.outputs.len(),
2,
"{stem}: post-conversion layout should expose 2 per-scale outputs",
);
for out in &schema.outputs {
assert!(
out.outputs.is_empty(),
"{stem}: ModelPack post-conversion layout must not carry per-scale children, found on {:?}",
out.name,
);
assert!(
out.quantization.is_some(),
"{stem}: post-conversion ModelPack output {:?} must declare quantization",
out.name,
);
}
}