use super::*;
#[test]
fn p107_empty_tensor_list() {
let report = InspectionReport {
format: FormatType::Apr,
file_size: 0,
metadata: BTreeMap::new(),
tensors: vec![],
total_params: 0,
quantization: None,
architecture: None,
};
assert!(report.tensors.is_empty());
assert_eq!(report.total_params, 0);
}
#[test]
fn p108_large_tensor_count() {
let tensors: Vec<TensorInfo> = (0..100)
.map(|i| TensorInfo {
name: format!("layer.{}", i),
dtype: "F16".to_string(),
shape: vec![256, 256],
size_bytes: 256 * 256 * 2,
stats: None,
})
.collect();
let report = InspectionReport {
format: FormatType::Gguf,
file_size: tensors.len() * 256 * 256 * 2,
metadata: BTreeMap::new(),
tensors,
total_params: 100 * 256 * 256,
quantization: None,
architecture: None,
};
assert_eq!(report.tensors.len(), 100);
}
#[test]
fn p109_metadata_long_value() {
let mut metadata = BTreeMap::new();
let long_value = "x".repeat(1000);
metadata.insert("long_key".to_string(), long_value.clone());
let report = InspectionReport {
format: FormatType::SafeTensors,
file_size: 1000,
metadata,
tensors: vec![],
total_params: 0,
quantization: None,
architecture: None,
};
let display = format!("{}", report);
assert!(display.len() < long_value.len() * 2);
}
#[test]
fn p110_conversion_duration() {
let report = ConversionReport {
path: ConversionPath::direct(FormatType::Gguf, FormatType::Apr),
source_inspection: InspectionReport {
format: FormatType::Gguf,
file_size: 1000,
metadata: BTreeMap::new(),
tensors: vec![],
total_params: 100,
quantization: None,
architecture: None,
},
target_inspection: InspectionReport {
format: FormatType::Apr,
file_size: 1000,
metadata: BTreeMap::new(),
tensors: vec![],
total_params: 100,
quantization: None,
architecture: None,
},
warnings: vec![],
duration_ms: 1500,
modified_tensors: vec![],
dropped_tensors: vec![],
};
assert_eq!(report.duration_ms, 1500);
}
pub(crate) fn unique_temp_path(prefix: &str, ext: &str) -> std::path::PathBuf {
use std::sync::atomic::{AtomicU64, Ordering};
static COUNTER: AtomicU64 = AtomicU64::new(0);
let id = COUNTER.fetch_add(1, Ordering::Relaxed);
let pid = std::process::id();
std::env::temp_dir().join(format!("{prefix}_{pid}_{id}.{ext}"))
}
pub(crate) fn create_safetensors_fixture() -> std::path::PathBuf {
use std::io::Write;
let path = unique_temp_path("test_tiny", "safetensors");
let mut file = std::fs::File::create(&path).expect("Create temp file");
let header = r#"{"test.bias":{"dtype":"F32","shape":[4],"data_offsets":[0,16]},"__metadata__":{"format":"test"}}"#;
file.write_all(&(header.len() as u64).to_le_bytes())
.expect("Write header len");
file.write_all(header.as_bytes()).expect("Write header");
let data: [f32; 4] = [0.01, -0.02, 0.03, -0.01];
for val in &data {
file.write_all(&val.to_le_bytes()).expect("Write tensor");
}
path
}
pub(crate) fn create_apr_fixture() -> std::path::PathBuf {
use crate::format::v2::{AprV2Metadata, AprV2Writer};
let path = unique_temp_path("test_tiny", "apr");
let metadata = AprV2Metadata::new("test");
let mut writer = AprV2Writer::new(metadata);
writer.add_f32_tensor("test.bias", vec![4], &[0.01, -0.02, 0.03, -0.01]);
let mut file = std::fs::File::create(&path).expect("Create temp APR file");
writer.write_to(&mut file).expect("Write APR");
path
}
#[test]
fn p111_integration_inspect_safetensors() {
let path = create_safetensors_fixture();
let rosetta = RosettaStone::new();
let report = rosetta.inspect(&path).expect("Inspect SafeTensors");
assert_eq!(report.format, FormatType::SafeTensors);
assert!(
!report.tensors.is_empty(),
"Should have at least one tensor"
);
let _ = std::fs::remove_file(path);
}
#[test]
fn p112_integration_inspect_apr() {
let path = create_apr_fixture();
let rosetta = RosettaStone::new();
let report = rosetta.inspect(&path).expect("Inspect APR");
assert_eq!(report.format, FormatType::Apr);
assert!(
!report.tensors.is_empty(),
"Should have at least one tensor"
);
let _ = std::fs::remove_file(path);
}
#[test]
fn p113_integration_convert_safetensors_to_apr() {
let source = create_safetensors_fixture();
let target = unique_temp_path("test_converted", "apr");
let rosetta = RosettaStone::new();
let report = rosetta
.convert(&source, &target, None)
.expect("Convert SafeTensors to APR");
assert_eq!(report.path.source, FormatType::SafeTensors);
assert_eq!(report.path.target, FormatType::Apr);
assert!(target.exists(), "Output file should exist");
let verify_report = rosetta.inspect(&target).expect("Inspect converted APR");
assert_eq!(verify_report.format, FormatType::Apr);
let _ = std::fs::remove_file(source);
let _ = std::fs::remove_file(target);
}
#[test]
fn p114_integration_conversion_inspection() {
let source = create_safetensors_fixture();
let target = unique_temp_path("test_converted", "apr");
let rosetta = RosettaStone::new();
rosetta
.convert(&source, &target, None)
.expect("Convert to APR");
let source_report = rosetta.inspect(&source).expect("Inspect source");
let target_report = rosetta.inspect(&target).expect("Inspect target APR");
assert_eq!(
source_report.tensors.len(),
target_report.tensors.len(),
"Conversion should preserve tensor count"
);
assert_eq!(target_report.format, FormatType::Apr);
let _ = std::fs::remove_file(source);
let _ = std::fs::remove_file(target);
}
#[test]
fn p115_bitflip_safetensors_corruption_detected() {
let path = create_safetensors_fixture();
let mut data = std::fs::read(&path).expect("Read fixture");
data[0] = data[0].wrapping_add(50);
let corrupted_path = unique_temp_path("test_corrupted_len", "safetensors");
std::fs::write(&corrupted_path, &data).expect("Write corrupted file");
let rosetta = RosettaStone::new();
let result = rosetta.inspect(&corrupted_path);
assert!(
result.is_err(),
"SafeTensors with corrupted header length should fail to parse"
);
let _ = std::fs::remove_file(path);
let _ = std::fs::remove_file(corrupted_path);
}
#[test]
fn p116_bitflip_apr_corruption_detected() {
let path = create_apr_fixture();
let mut data = std::fs::read(&path).expect("Read APR fixture");
if data.len() > 100 {
data[100] ^= 0xFF; }
let corrupted_path = unique_temp_path("test_corrupted", "apr");
std::fs::write(&corrupted_path, &data).expect("Write corrupted APR file");
let rosetta = RosettaStone::new();
let result = rosetta.inspect(&corrupted_path);
assert!(
result.is_err(),
"Corrupted APR file should fail checksum verification"
);
let _ = std::fs::remove_file(path);
let _ = std::fs::remove_file(corrupted_path);
}
#[test]
#[ignore = "requires local GGUF model file"]
fn p117_gguf_format_detection_real_file() {
let gguf_path = Path::new("models/qwen2.5-coder-0.5b-instruct-q4_k_m.gguf");
let format = FormatType::from_magic(gguf_path).expect("Detect GGUF format");
assert_eq!(format, FormatType::Gguf, "Should detect GGUF format");
}
#[test]
#[ignore = "requires local GGUF model file"]
fn p118_gguf_inspection_real_file() {
let gguf_path = Path::new("models/qwen2.5-coder-0.5b-instruct-q4_k_m.gguf");
let rosetta = RosettaStone::new();
let report = rosetta.inspect(gguf_path).expect("Inspect GGUF");
assert_eq!(report.format, FormatType::Gguf);
assert!(!report.tensors.is_empty(), "GGUF should have tensors");
assert!(report.total_params > 0, "Should have non-zero params");
}
#[test]
fn p119_apr_embedded_tokenizer_metadata() {
use crate::format::v2::{AprV2Metadata, AprV2Writer};
use std::collections::HashMap;
let path = unique_temp_path("test_tokenizer", "apr");
let mut metadata = AprV2Metadata::new("test");
let vocab = vec!["<pad>", "<bos>", "<eos>", "hello", "world"];
let vocab_json: Vec<serde_json::Value> = vocab
.iter()
.map(|s| serde_json::Value::String(s.to_string()))
.collect();
let mut custom: HashMap<String, serde_json::Value> = HashMap::new();
custom.insert(
"tokenizer.vocabulary".to_string(),
serde_json::Value::Array(vocab_json),
);
custom.insert(
"tokenizer.vocab_size".to_string(),
serde_json::Value::Number(5.into()),
);
custom.insert(
"tokenizer.bos_token_id".to_string(),
serde_json::Value::Number(1.into()),
);
custom.insert(
"tokenizer.eos_token_id".to_string(),
serde_json::Value::Number(2.into()),
);
metadata.custom = custom;
let mut writer = AprV2Writer::new(metadata);
writer.add_f32_tensor("embed.weight", vec![5, 4], &[0.0; 20]);
let mut file = std::fs::File::create(&path).expect("Create APR file");
writer.write_to(&mut file).expect("Write APR");
drop(file);
let rosetta = RosettaStone::new();
let report = rosetta.inspect(&path).expect("Inspect APR with tokenizer");
assert_eq!(report.format, FormatType::Apr);
assert!(!report.tensors.is_empty(), "Should have tensors");
let _ = std::fs::remove_file(path);
}