use super::*;
use crate::format::v2::{AprV2Metadata, AprV2Writer};
fn known_good_apr_bytes() -> Vec<u8> {
let mut writer = AprV2Writer::new(AprV2Metadata::new("truncation-fixture"));
writer.add_f32_tensor("layer.0.weight", vec![16, 16], &[0.125_f32; 256]);
writer.add_f32_tensor("layer.0.bias", vec![16], &[0.5_f32; 16]);
writer.write().expect("fixture must serialize")
}
fn check_5(data: &[u8]) -> ValidationCheck {
let mut validator = AprValidator::new();
validator.validate_bytes(data);
validator
.report()
.checks
.iter()
.find(|c| c.id == 5)
.cloned()
.expect("check 5 must be present in the report")
}
#[test]
fn intact_apr_passes_check_5() {
let bytes = known_good_apr_bytes();
let check = check_5(&bytes);
assert!(
check.status.is_pass(),
"a complete .apr must pass the data-extent check, got {:?}",
check.status
);
}
#[test]
fn truncated_apr_fails_check_5() {
let bytes = known_good_apr_bytes();
let full_len = bytes.len();
let truncated = &bytes[..full_len / 2];
let check = check_5(truncated);
assert!(
check.status.is_fail(),
"a .apr truncated from {full_len} to {} bytes must FAIL the data-extent check, got {:?}",
truncated.len(),
check.status
);
match &check.status {
CheckStatus::Fail(reason) => {
assert!(
reason.contains("Truncated APR"),
"the reason must name the defect, got: {reason}"
);
assert!(
reason.contains(&truncated.len().to_string()),
"the reason must cite the actual file length, got: {reason}"
);
}
other => panic!("expected Fail, got {other:?}"),
}
}
#[test]
fn truncated_apr_report_is_not_valid() {
let bytes = known_good_apr_bytes();
let truncated = &bytes[..bytes.len() / 2];
let mut validator = AprValidator::new();
let report = validator.validate_bytes(truncated);
assert!(
!report.is_valid(),
"a truncated .apr must not report VALID (failed checks: {})",
report.failed_checks().len()
);
let mut ok_validator = AprValidator::new();
let ok_report = ok_validator.validate_bytes(&bytes);
assert!(
ok_report.is_valid(),
"no false positive: the intact fixture must still report VALID"
);
}
#[test]
fn one_byte_short_still_fails() {
let bytes = known_good_apr_bytes();
let required = crate::format::v2::required_file_len(&bytes).expect("extent");
let cut = usize::try_from(required).expect("fixture fits usize") - 1;
let check = check_5(&bytes[..cut]);
assert!(
check.status.is_fail(),
"file one byte shorter than its declared extent must fail, got {:?}",
check.status
);
}
#[test]
fn gguf_buffer_skips_check_5() {
let mut gguf = vec![0u8; 128];
gguf[0..4].copy_from_slice(b"GGUF");
gguf[4..8].copy_from_slice(&3u32.to_le_bytes());
let check = check_5(&gguf);
assert!(
matches!(check.status, CheckStatus::Skip(_)),
"GGUF must skip the APR-only extent check, got {:?}",
check.status
);
}
#[test]
fn scope_of_2612_is_check_5_only() {
let bytes = known_good_apr_bytes();
let mut validator = AprValidator::new();
let report = validator.validate_bytes(&bytes);
let stubbed: Vec<u8> = report
.checks
.iter()
.filter(|c| (6..=25).contains(&c.id) && matches!(c.status, CheckStatus::Skip(_)))
.map(|c| c.id)
.collect();
assert_eq!(
stubbed.len(),
20,
"#2612 implemented check 5 only; checks 6-25 remain stubs (found {stubbed:?})"
);
}