use std::collections::BTreeMap;
use tensogram::*;
fn make_global_meta() -> GlobalMetadata {
GlobalMetadata {
..Default::default()
}
}
fn make_descriptor(shape: Vec<u64>, dtype: Dtype) -> DataObjectDescriptor {
let strides = if shape.is_empty() {
vec![]
} else {
let mut s = vec![1u64; shape.len()];
for i in (0..shape.len() - 1).rev() {
s[i] = s[i + 1] * shape[i + 1];
}
s
};
DataObjectDescriptor {
obj_type: "ntensor".to_string(),
ndim: shape.len() as u64,
shape,
strides,
dtype,
byte_order: ByteOrder::native(),
encoding: "none".to_string(),
filter: "none".to_string(),
compression: "none".to_string(),
masks: None,
params: BTreeMap::new(),
}
}
fn f64_bytes(values: &[f64]) -> Vec<u8> {
values.iter().flat_map(|v| v.to_ne_bytes()).collect()
}
#[test]
fn validate_full_passes_on_masked_nan_frame() {
let data = f64_bytes(&[1.0, f64::NAN, 3.0, f64::NAN, 5.0]);
let desc = make_descriptor(vec![5], Dtype::Float64);
let options = EncodeOptions {
allow_nan: true,
small_mask_threshold_bytes: 0,
..Default::default()
};
let msg = encode(&make_global_meta(), &[(&desc, &data)], &options).unwrap();
let report = validate_message(
&msg,
&ValidateOptions {
max_level: ValidationLevel::Fidelity,
..Default::default()
},
);
let nan_errors: Vec<_> = report
.issues
.iter()
.filter(|i| matches!(i.code, IssueCode::NanDetected | IssueCode::InfDetected))
.collect();
assert!(
nan_errors.is_empty(),
"mask-bearing frame must not raise NaN/Inf validation errors at Fidelity level; got: {nan_errors:?}"
);
}
#[test]
fn validate_full_passes_on_masked_inf_frame() {
let data = f64_bytes(&[f64::INFINITY, 1.0, f64::NEG_INFINITY, 2.0]);
let desc = make_descriptor(vec![4], Dtype::Float64);
let options = EncodeOptions {
allow_inf: true,
small_mask_threshold_bytes: 0,
..Default::default()
};
let msg = encode(&make_global_meta(), &[(&desc, &data)], &options).unwrap();
let report = validate_message(
&msg,
&ValidateOptions {
max_level: ValidationLevel::Fidelity,
..Default::default()
},
);
let nan_errors: Vec<_> = report
.issues
.iter()
.filter(|i| matches!(i.code, IssueCode::NanDetected | IssueCode::InfDetected))
.collect();
assert!(
nan_errors.is_empty(),
"+Inf/-Inf at masked positions must not raise validation errors; got: {nan_errors:?}"
);
}
#[test]
fn validate_full_rejects_non_finite_without_masks() {
let data = f64_bytes(&[1.0, f64::NAN, 3.0]);
let desc = make_descriptor(vec![3], Dtype::Float64);
let msg = encode_pre_encoded(
&make_global_meta(),
&[(&desc, &data)],
&EncodeOptions::default(),
)
.unwrap();
let report = validate_message(
&msg,
&ValidateOptions {
max_level: ValidationLevel::Fidelity,
..Default::default()
},
);
let has_nan_error = report
.issues
.iter()
.any(|i| matches!(i.code, IssueCode::NanDetected));
assert!(
has_nan_error,
"non-masked NaN must still raise NanDetected at Fidelity level; issues: {:?}",
report.issues
);
}
#[test]
fn validate_full_passes_on_masked_frame_with_all_finite_payload() {
let data = f64_bytes(&[1.0, 2.0, 3.0]);
let desc = make_descriptor(vec![3], Dtype::Float64);
let options = EncodeOptions {
allow_nan: true,
allow_inf: true,
..Default::default()
};
let msg = encode(&make_global_meta(), &[(&desc, &data)], &options).unwrap();
let report = validate_message(
&msg,
&ValidateOptions {
max_level: ValidationLevel::Fidelity,
..Default::default()
},
);
let errors: Vec<_> = report
.issues
.iter()
.filter(|i| i.severity == IssueSeverity::Error)
.collect();
assert!(
errors.is_empty(),
"finite-only frame must pass; errors: {errors:?}"
);
}
#[test]
fn validate_full_multi_object_only_flags_unexpected_positions() {
let desc = make_descriptor(vec![3], Dtype::Float64);
let d0 = f64_bytes(&[f64::NAN, 1.0, 2.0]);
let d1 = f64_bytes(&[3.0, 4.0, 5.0]);
let options = EncodeOptions {
allow_nan: true,
small_mask_threshold_bytes: 0,
..Default::default()
};
let msg = encode(&make_global_meta(), &[(&desc, &d0), (&desc, &d1)], &options).unwrap();
let report = validate_message(
&msg,
&ValidateOptions {
max_level: ValidationLevel::Fidelity,
..Default::default()
},
);
let nan_errors: Vec<_> = report
.issues
.iter()
.filter(|i| matches!(i.code, IssueCode::NanDetected | IssueCode::InfDetected))
.collect();
assert!(
nan_errors.is_empty(),
"all NaNs are masked; no errors expected; got: {nan_errors:?}"
);
}