use cache_kit::serialization::serialize_for_cache;
use cache_kit::CacheEntity;
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::PathBuf;
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
struct User {
id: u64,
name: String,
email: String,
}
impl CacheEntity for User {
type Key = u64;
fn cache_key(&self) -> Self::Key {
self.id
}
fn cache_prefix() -> &'static str {
"user"
}
}
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
struct Product {
id: String,
name: String,
price: f64,
in_stock: bool,
}
impl CacheEntity for Product {
type Key = String;
fn cache_key(&self) -> Self::Key {
self.id.clone()
}
fn cache_prefix() -> &'static str {
"product"
}
}
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
struct ComplexEntity {
id: u64,
name: String,
tags: Vec<String>,
score: f64,
}
impl CacheEntity for ComplexEntity {
type Key = u64;
fn cache_key(&self) -> Self::Key {
self.id
}
fn cache_prefix() -> &'static str {
"complex"
}
}
fn golden_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/golden")
}
fn generate_user_v1() -> std::io::Result<()> {
let user = User {
id: 42,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
};
let bytes = serialize_for_cache(&user).expect("Serialization should succeed");
let path = golden_dir().join("user_v1.bin");
fs::write(&path, &bytes)?;
println!("✅ Generated: {}", path.display());
println!(" Size: {} bytes", bytes.len());
println!(" Checksum: {}", md5_hash(&bytes));
println!();
Ok(())
}
fn generate_product_v1() -> std::io::Result<()> {
let product = Product {
id: "prod_123".to_string(),
name: "Widget".to_string(),
price: 99.99,
in_stock: true,
};
let bytes = serialize_for_cache(&product).expect("Serialization should succeed");
let path = golden_dir().join("product_v1.bin");
fs::write(&path, &bytes)?;
println!("✅ Generated: {}", path.display());
println!(" Size: {} bytes", bytes.len());
println!(" Checksum: {}", md5_hash(&bytes));
println!();
Ok(())
}
fn generate_complex_v1() -> std::io::Result<()> {
let entity = ComplexEntity {
id: 100,
name: "Complex Test Entity".to_string(),
tags: vec!["tag1".to_string(), "tag2".to_string(), "tag3".to_string()],
score: 95.5,
};
let bytes = serialize_for_cache(&entity).expect("Serialization should succeed");
let path = golden_dir().join("complex_v1.bin");
fs::write(&path, &bytes)?;
println!("✅ Generated: {}", path.display());
println!(" Size: {} bytes", bytes.len());
println!(" Checksum: {}", md5_hash(&bytes));
println!();
Ok(())
}
fn md5_hash(data: &[u8]) -> String {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut hasher = DefaultHasher::new();
data.hash(&mut hasher);
format!("{:016x}", hasher.finish())
}
#[test]
fn generate_all_golden_blobs() {
println!("\n🔧 Generating golden blob files...\n");
fs::create_dir_all(golden_dir()).expect("Failed to create golden directory");
generate_user_v1().expect("Failed to generate user_v1.bin");
generate_product_v1().expect("Failed to generate product_v1.bin");
generate_complex_v1().expect("Failed to generate complex_v1.bin");
println!("✅ All golden blobs generated successfully!");
println!("\nNext steps:");
println!("1. Verify tests pass: cargo test --test golden_blobs");
println!("2. Commit the .bin files to version control");
println!("3. Update CHANGELOG with schema version bump");
}
#[test]
fn verify_golden_blobs_exist() {
let golden_files = vec!["user_v1.bin", "product_v1.bin", "complex_v1.bin"];
for file in golden_files {
let path = golden_dir().join(file);
if !path.exists() {
panic!(
"Golden blob missing: {}\nRun: cargo test --test golden_blob_generator -- --nocapture",
path.display()
);
}
}
}