#[allow(unused_imports)]
use super::super::*;
#[cfg(test)]
mod tests_bug1_gguf_export_falsification {
use crate::format::converter::export::{apr_export, ExportFormat, ExportOptions};
use crate::format::gguf::GgufReader;
use std::collections::BTreeMap;
#[test]
fn test_f_gguf_export_001_valid_magic() {
let mut tensors: BTreeMap<String, (Vec<f32>, Vec<usize>)> = BTreeMap::new();
let hidden_size = 64;
let vocab_size = 100;
let intermediate_size = 128;
tensors.insert(
"model.embed_tokens.weight".to_string(),
(
vec![0.01; vocab_size * hidden_size],
vec![vocab_size, hidden_size],
),
);
tensors.insert(
"model.layers.0.self_attn.q_proj.weight".to_string(),
(
vec![0.01; hidden_size * hidden_size],
vec![hidden_size, hidden_size],
),
);
tensors.insert(
"model.layers.0.self_attn.k_proj.weight".to_string(),
(
vec![0.01; hidden_size * hidden_size],
vec![hidden_size, hidden_size],
),
);
tensors.insert(
"model.layers.0.self_attn.v_proj.weight".to_string(),
(
vec![0.01; hidden_size * hidden_size],
vec![hidden_size, hidden_size],
),
);
tensors.insert(
"model.layers.0.self_attn.o_proj.weight".to_string(),
(
vec![0.01; hidden_size * hidden_size],
vec![hidden_size, hidden_size],
),
);
tensors.insert(
"model.layers.0.mlp.gate_proj.weight".to_string(),
(
vec![0.01; intermediate_size * hidden_size],
vec![intermediate_size, hidden_size],
),
);
tensors.insert(
"model.layers.0.mlp.up_proj.weight".to_string(),
(
vec![0.01; intermediate_size * hidden_size],
vec![intermediate_size, hidden_size],
),
);
tensors.insert(
"model.layers.0.mlp.down_proj.weight".to_string(),
(
vec![0.01; hidden_size * intermediate_size],
vec![hidden_size, intermediate_size],
),
);
tensors.insert(
"model.layers.0.input_layernorm.weight".to_string(),
(vec![1.0; hidden_size], vec![hidden_size]),
);
tensors.insert(
"model.layers.0.post_attention_layernorm.weight".to_string(),
(vec![1.0; hidden_size], vec![hidden_size]),
);
tensors.insert(
"model.norm.weight".to_string(),
(vec![1.0; hidden_size], vec![hidden_size]),
);
tensors.insert(
"lm_head.weight".to_string(),
(
vec![0.01; vocab_size * hidden_size],
vec![vocab_size, hidden_size],
),
);
let temp_dir = tempfile::tempdir().expect("create temp dir");
let input_path = temp_dir.path().join("model.safetensors");
crate::serialization::safetensors::save_safetensors(&input_path, &tensors)
.expect("write safetensors");
let output_path = temp_dir.path().join("model.gguf");
let options = ExportOptions {
format: ExportFormat::Gguf,
quantize: None,
include_tokenizer: false,
include_config: false,
..Default::default()
};
apr_export(&input_path, &output_path, options).expect("GGUF export should succeed");
let gguf_data = std::fs::read(&output_path).expect("read exported GGUF");
assert!(gguf_data.len() >= 4, "GGUF file too small");
let magic = &gguf_data[0..4];
assert_eq!(
magic, b"GGUF",
"F-GGUF-EXPORT-001: GGUF magic bytes must be 'GGUF'"
);
}
#[test]
fn test_f_gguf_export_002_has_metadata() {
let mut tensors: BTreeMap<String, (Vec<f32>, Vec<usize>)> = BTreeMap::new();
let hidden_size = 64;
let vocab_size = 100;
tensors.insert(
"model.embed_tokens.weight".to_string(),
(
vec![0.01; vocab_size * hidden_size],
vec![vocab_size, hidden_size],
),
);
tensors.insert(
"model.layers.0.self_attn.q_proj.weight".to_string(),
(
vec![0.01; hidden_size * hidden_size],
vec![hidden_size, hidden_size],
),
);
tensors.insert(
"lm_head.weight".to_string(),
(
vec![0.01; vocab_size * hidden_size],
vec![vocab_size, hidden_size],
),
);
let temp_dir = tempfile::tempdir().expect("create temp dir");
let input_path = temp_dir.path().join("model.safetensors");
crate::serialization::safetensors::save_safetensors(&input_path, &tensors)
.expect("write safetensors");
let output_path = temp_dir.path().join("model.gguf");
let options = ExportOptions {
format: ExportFormat::Gguf,
quantize: None,
include_tokenizer: false,
include_config: false,
..Default::default()
};
apr_export(&input_path, &output_path, options).expect("GGUF export should succeed");
let reader = GgufReader::from_file(&output_path)
.expect("F-GGUF-EXPORT-002: GGUF file must be readable");
let arch = reader.architecture();
assert!(
arch.is_some(),
"F-GGUF-EXPORT-002: GGUF must have general.architecture metadata"
);
}
#[test]
fn test_f_gguf_export_003_tensor_names_ggml() {
let mut tensors: BTreeMap<String, (Vec<f32>, Vec<usize>)> = BTreeMap::new();
let hidden_size = 64;
let vocab_size = 100;
tensors.insert(
"model.embed_tokens.weight".to_string(),
(
vec![0.01; vocab_size * hidden_size],
vec![vocab_size, hidden_size],
),
);
tensors.insert(
"model.layers.0.self_attn.q_proj.weight".to_string(),
(
vec![0.01; hidden_size * hidden_size],
vec![hidden_size, hidden_size],
),
);
let temp_dir = tempfile::tempdir().expect("create temp dir");
let input_path = temp_dir.path().join("model.safetensors");
crate::serialization::safetensors::save_safetensors(&input_path, &tensors)
.expect("write safetensors");
let output_path = temp_dir.path().join("model.gguf");
let options = ExportOptions {
format: ExportFormat::Gguf,
quantize: None,
include_tokenizer: false,
include_config: false,
..Default::default()
};
apr_export(&input_path, &output_path, options).expect("GGUF export should succeed");
let reader = GgufReader::from_file(&output_path).expect("read GGUF");
let tensor_names: Vec<String> = reader.tensors.iter().map(|t| t.name.clone()).collect();
let has_ggml_embed = tensor_names
.iter()
.any(|n: &String| n == "token_embd.weight");
let has_ggml_attn = tensor_names
.iter()
.any(|n: &String| n.starts_with("blk.0.attn_"));
assert!(
has_ggml_embed,
"F-GGUF-EXPORT-003: embed_tokens must be renamed to token_embd.weight, got: {:?}",
tensor_names
);
assert!(
has_ggml_attn,
"F-GGUF-EXPORT-003: layers.0.self_attn must be renamed to blk.0.attn_*, got: {:?}",
tensor_names
);
}
}
#[cfg(test)]
mod tests_pmat201_fingerprint_falsification {
#[test]
fn test_f_fingerprint_001_basic_stats() {
let data: Vec<f32> = (0..100).map(|i| i as f32).collect();
let mean: f32 = data.iter().sum::<f32>() / data.len() as f32;
assert!(
(mean - 49.5).abs() < 0.01,
"F-FINGERPRINT-001: Mean should be ~49.5"
);
let min = data.iter().cloned().fold(f32::INFINITY, f32::min);
let max = data.iter().cloned().fold(f32::NEG_INFINITY, f32::max);
assert_eq!(min, 0.0, "F-FINGERPRINT-001: Min should be 0");
assert_eq!(max, 99.0, "F-FINGERPRINT-001: Max should be 99");
let variance: f32 =
data.iter().map(|x| (x - mean).powi(2)).sum::<f32>() / data.len() as f32;
let std = variance.sqrt();
assert!(
(std - 28.87).abs() < 0.1,
"F-FINGERPRINT-001: Std should be ~28.87"
);
}
#[test]
fn test_f_fingerprint_002_nan_detection() {
let data = vec![1.0_f32, 2.0, f32::NAN, 4.0, f32::NAN, 6.0];
let nan_count = data.iter().filter(|x| x.is_nan()).count();
assert_eq!(
nan_count, 2,
"F-FINGERPRINT-002: Should detect 2 NaN values"
);
}
#[test]
fn test_f_fingerprint_003_inf_detection() {
let data = vec![1.0_f32, f32::INFINITY, 3.0, f32::NEG_INFINITY, 5.0];
let inf_count = data.iter().filter(|x| x.is_infinite()).count();
assert_eq!(
inf_count, 2,
"F-FINGERPRINT-003: Should detect 2 Inf values"
);
}
#[test]
fn test_f_fingerprint_004_zero_fraction() {
let data = vec![0.0_f32, 1.0, 0.0, 2.0, 0.0, 3.0, 0.0, 4.0];
let zero_count = data.iter().filter(|&&x| x == 0.0).count();
let zero_fraction = zero_count as f32 / data.len() as f32;
assert_eq!(
zero_fraction, 0.5,
"F-FINGERPRINT-004: Zero fraction should be 0.5"
);
}
#[test]
fn test_f_fingerprint_005_checksum() {
let data = vec![1.0_f32, 2.0, 3.0, 4.0];
let bytes: Vec<u8> = data.iter().flat_map(|f| f.to_le_bytes()).collect();
let checksum: u32 = bytes
.iter()
.fold(0u32, |acc, &b| acc.wrapping_add(b as u32));
let bytes2: Vec<u8> = data.iter().flat_map(|f| f.to_le_bytes()).collect();
let checksum2: u32 = bytes2
.iter()
.fold(0u32, |acc, &b| acc.wrapping_add(b as u32));
assert_eq!(
checksum, checksum2,
"F-FINGERPRINT-005: Same data should produce same checksum"
);
}
#[test]
fn test_f_fingerprint_006_anomaly_detection() {
let normal_mean = 0.001_f32;
let normal_std = 0.02_f32;
let corrupted_mean = 11.3_f32;
let threshold = normal_mean.abs() + 3.0 * normal_std;
let is_anomaly = corrupted_mean.abs() > threshold;
assert!(
is_anomaly,
"F-FINGERPRINT-006: Mean 11.3 should be detected as anomaly (3 sigma = {})",
threshold
);
}
}
include!("coverage_golden_output.rs");
include!("coverage_distribution_tags.rs");