use std::path::Path;
use ort::value::TensorElementType;
use crate::{
error::Result,
runtime::contracts::{
ModelIoProbe, require_fixed_dim, require_single_input, require_single_output,
require_tensor,
},
};
pub const FORMULA_INPUT_RANK: usize = 4;
pub const FORMULA_INPUT_SPATIAL: i64 = 384;
pub const FORMULA_INPUT_CHANNELS: i64 = 1;
pub const FORMULA_OUTPUT_RANK: usize = 2;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FormulaContract {
pub input_name: String,
pub output_name: String,
}
pub fn validate_formula_contract(
probe: &ModelIoProbe,
model_path: &Path,
) -> Result<FormulaContract> {
let input = require_single_input(probe, model_path, "formula")?;
require_tensor(
input,
"input",
FORMULA_INPUT_RANK,
TensorElementType::Float32,
model_path,
)?;
require_fixed_dim(input, "input", 1, FORMULA_INPUT_CHANNELS, model_path)?;
require_fixed_dim(input, "input", 2, FORMULA_INPUT_SPATIAL, model_path)?;
require_fixed_dim(input, "input", 3, FORMULA_INPUT_SPATIAL, model_path)?;
let output = require_single_output(probe, model_path, "formula")?;
require_tensor(
output,
"output",
FORMULA_OUTPUT_RANK,
TensorElementType::Int64,
model_path,
)?;
Ok(FormulaContract {
input_name: input.name.clone(),
output_name: output.name.clone(),
})
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use super::*;
use crate::model_verify::VerifiedModel;
use crate::runtime::session::OrtSession;
use crate::{config::RuntimeConfig, formula::session::FormulaSession};
fn fixture(name: &str) -> PathBuf {
crate::test_support::fixture_dir("formula-onnx").join(name)
}
#[test]
fn probe_and_session_agree_on_every_fixture() {
for name in [
"formula_ok.onnx",
"formula_no_metadata.onnx",
"formula_bad_metadata.onnx",
"formula_multi_input.onnx",
"formula_multi_output.onnx",
"formula_input_int64.onnx",
"formula_input_rank3.onnx",
"formula_input_512.onnx",
"formula_output_f32.onnx",
"formula_output_rank1.onnx",
] {
let path = fixture(name);
let runtime = RuntimeConfig::default();
let session =
OrtSession::open_unchecked(&path, &runtime, &[]).expect("fixture must load");
let probe = session.probe_io().expect("fixture must probe");
let contract = validate_formula_contract(&probe, &path);
let session_result =
FormulaSession::new(&VerifiedModel::verify(&path, None).unwrap(), &runtime);
if let Err(error) = &contract {
let session_error =
session_result.expect_err("contract failure must also fail the typed session");
assert_eq!(
session_error.to_string(),
error.to_string(),
"probe/session contract messages must match for {name}"
);
}
}
}
#[test]
fn spatial_dims_must_be_fixed_at_384() {
let path = fixture("formula_input_512.onnx");
let runtime = RuntimeConfig::default();
let session = OrtSession::open_unchecked(&path, &runtime, &[]).expect("fixture must load");
let probe = session.probe_io().expect("fixture must probe");
let error = validate_formula_contract(&probe, &path).expect_err("512 must be rejected");
assert!(error.to_string().contains("384"), "error: {error}");
}
#[test]
fn dynamic_spatial_dims_are_rejected_consistently() {
use crate::runtime::contracts::TensorSpec;
let probe = ModelIoProbe {
inputs: vec![TensorSpec::new(
"x",
vec![-1, 1, -1, -1],
TensorElementType::Float32,
)],
outputs: vec![TensorSpec::new(
"fetch_name_0",
vec![-1, -1],
TensorElementType::Int64,
)],
};
let error = validate_formula_contract(&probe, Path::new("dynamic.onnx"))
.expect_err("dynamic spatial dims must be rejected");
assert!(error.to_string().contains("384"), "error: {error}");
}
}