Squashed 'vendor/ruvector/' content from commit b64c2172

git-subtree-dir: vendor/ruvector
git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
This commit is contained in:
ruv
2026-02-28 14:39:40 -05:00
commit d803bfe2b1
7854 changed files with 3522914 additions and 0 deletions

View File

@@ -0,0 +1,166 @@
//! Integration tests for model loading
use ruvector_sparse_inference::model::*;
mod common;
use common::*;
#[test]
fn test_gguf_header_parsing() {
let mock_gguf = create_mock_gguf_header();
let header = GgufParser::parse_header(&mock_gguf).unwrap();
assert_eq!(header.magic, 0x46554747); // "GGUF"
assert_eq!(header.version, 3);
}
#[test]
fn test_gguf_invalid_magic() {
let mut invalid_gguf = vec![0u8; 8];
invalid_gguf[0..4].copy_from_slice(&0x12345678u32.to_le_bytes()); // Wrong magic
invalid_gguf[4..8].copy_from_slice(&3u32.to_le_bytes());
let result = GgufParser::parse_header(&invalid_gguf);
assert!(result.is_err(), "Should fail with invalid magic number");
}
#[test]
fn test_gguf_too_small() {
let tiny_data = vec![0u8; 4]; // Too small
let result = GgufParser::parse_header(&tiny_data);
assert!(result.is_err(), "Should fail with too small data");
}
#[test]
fn test_llama_model_structure() {
let model = load_test_llama_model();
assert!(model.metadata().hidden_size > 0);
assert!(model.layers.len() > 0);
assert!(model.embed_tokens.vocab_size() > 0);
}
#[test]
fn test_llama_model_dimensions() {
let model = load_test_llama_model();
assert_eq!(model.hidden_size(), 512);
assert_eq!(model.intermediate_size(), 2048);
assert_eq!(model.layers.len(), 4);
assert_eq!(model.embed_tokens.vocab_size(), 32000);
}
#[test]
fn test_model_forward_pass() {
let model = load_test_llama_model();
let input = ModelInput::TokenIds(vec![1, 2, 3, 4, 5]);
let config = InferenceConfig::default();
let output = model.forward(&input, &config).unwrap();
assert!(!output.logits.is_empty());
assert_eq!(output.logits.len(), model.embed_tokens.vocab_size());
}
#[test]
fn test_model_forward_with_embeddings() {
let model = load_test_llama_model();
let embeddings = vec![
random_vector(512),
random_vector(512),
random_vector(512),
];
let input = ModelInput::Embeddings(embeddings);
let config = InferenceConfig::default();
let output = model.forward(&input, &config).unwrap();
assert!(!output.logits.is_empty());
}
#[test]
fn test_inference_config_default() {
let config = InferenceConfig::default();
assert_eq!(config.temperature, 1.0);
assert_eq!(config.top_k, None);
assert_eq!(config.top_p, None);
}
#[test]
fn test_inference_config_custom() {
let config = InferenceConfig {
temperature: 0.8,
top_k: Some(50),
top_p: Some(0.95),
};
assert_eq!(config.temperature, 0.8);
assert_eq!(config.top_k, Some(50));
assert_eq!(config.top_p, Some(0.95));
}
#[test]
fn test_model_metadata_access() {
let model = load_test_llama_model();
let metadata = model.metadata();
assert_eq!(metadata.hidden_size(), 512);
assert_eq!(metadata.hidden_size, 512);
assert_eq!(metadata.intermediate_size, 2048);
assert_eq!(metadata.num_layers, 4);
assert_eq!(metadata.vocab_size, 32000);
}
#[test]
fn test_embed_tokens_vocab_size() {
let embed = EmbedTokens::new(50000, 768);
assert_eq!(embed.vocab_size(), 50000);
}
#[test]
fn test_transformer_layer_indices() {
let model = load_test_llama_model();
for (i, layer) in model.layers.iter().enumerate() {
assert_eq!(layer.layer_idx, i, "Layer index should match position");
}
}
#[test]
fn test_model_creation_various_sizes() {
// Test different model sizes
let small = LlamaModel::new(256, 1024, 2, 10000);
assert_eq!(small.hidden_size(), 256);
assert_eq!(small.layers.len(), 2);
let large = LlamaModel::new(2048, 8192, 32, 100000);
assert_eq!(large.hidden_size(), 2048);
assert_eq!(large.layers.len(), 32);
}
#[test]
fn test_gguf_header_version() {
let mut data = create_mock_gguf_header();
// Modify version
data[4..8].copy_from_slice(&2u32.to_le_bytes());
let header = GgufParser::parse_header(&data).unwrap();
assert_eq!(header.version, 2);
}
#[test]
fn test_model_forward_deterministic() {
let model = load_test_llama_model();
let input = ModelInput::TokenIds(vec![1, 2, 3]);
let config = InferenceConfig::default();
let output1 = model.forward(&input, &config).unwrap();
let output2 = model.forward(&input, &config).unwrap();
// Same input should produce same output
assert_eq!(output1.logits.len(), output2.logits.len());
for (a, b) in output1.logits.iter().zip(output2.logits.iter()) {
assert_eq!(a, b);
}
}

View File

@@ -0,0 +1,206 @@
//! Integration tests for sparse inference pipeline
use ruvector_sparse_inference::*;
mod common;
use common::*;
#[test]
fn test_full_sparse_pipeline() {
let model = load_test_llama_model();
let mut engine = SparseInferenceEngine::new_sparse(model, 0.3);
// Calibrate
let calibration_samples = generate_calibration_data(100);
engine.calibrate(&calibration_samples).unwrap();
// Run inference
let input = random_vector(512);
let output = engine.infer(&input).unwrap();
// Verify output
assert_eq!(output.len(), 512, "Output dimension should match input");
assert!(output.iter().all(|&x| x.is_finite()), "All outputs should be finite");
// Check sparsity was applied
let stats = engine.sparsity_statistics();
assert!(stats.average_active_ratio < 0.5, "Should have at least 50% sparsity");
}
#[test]
fn test_dense_vs_sparse_accuracy() {
let model = load_test_llama_model();
let dense_engine = SparseInferenceEngine::new_dense(model.clone());
let sparse_engine = SparseInferenceEngine::new_sparse(model, 0.1);
let inputs: Vec<_> = (0..100).map(|_| random_vector(512)).collect();
let mut total_error = 0.0;
for input in &inputs {
let dense_out = dense_engine.infer(input).unwrap();
let sparse_out = sparse_engine.infer(input).unwrap();
let error = mse(&dense_out, &sparse_out);
total_error += error;
}
let avg_error = total_error / inputs.len() as f64;
assert!(avg_error < 0.1, "Average error too high: {}", avg_error);
}
#[test]
fn test_sparse_inference_batch_processing() {
let model = load_test_llama_model();
let engine = SparseInferenceEngine::new_sparse(model, 0.2);
let batch_size = 10;
let inputs: Vec<_> = (0..batch_size).map(|_| random_vector(512)).collect();
let mut outputs = Vec::new();
for input in &inputs {
let output = engine.infer(input).unwrap();
outputs.push(output);
}
assert_eq!(outputs.len(), batch_size);
for output in &outputs {
assert_eq!(output.len(), 512);
assert!(output.iter().all(|&x| x.is_finite()));
}
}
#[test]
fn test_calibration_improves_accuracy() {
let model = load_test_llama_model();
// Create two engines: one calibrated, one not
let mut calibrated = SparseInferenceEngine::new_sparse(model.clone(), 0.3);
let uncalibrated = SparseInferenceEngine::new_sparse(model, 0.3);
// Calibrate one
let calibration_samples = generate_calibration_data(50);
calibrated.calibrate(&calibration_samples).unwrap();
// Test both
let test_inputs: Vec<_> = (0..20).map(|_| random_vector(512)).collect();
for input in &test_inputs {
let cal_output = calibrated.infer(input).unwrap();
let uncal_output = uncalibrated.infer(input).unwrap();
assert_eq!(cal_output.len(), uncal_output.len());
assert!(cal_output.iter().all(|&x| x.is_finite()));
assert!(uncal_output.iter().all(|&x| x.is_finite()));
}
}
#[test]
fn test_different_sparsity_levels() {
let model = load_test_llama_model();
let input = random_vector(512);
for sparsity in [0.1, 0.3, 0.5, 0.7, 0.9] {
let engine = SparseInferenceEngine::new_sparse(model.clone(), sparsity);
let output = engine.infer(&input).unwrap();
assert_eq!(output.len(), 512, "Output dimension mismatch for sparsity {}", sparsity);
assert!(output.iter().all(|&x| x.is_finite()), "Non-finite output for sparsity {}", sparsity);
}
}
#[test]
fn test_sparse_inference_consistency() {
let model = load_test_llama_model();
let engine = SparseInferenceEngine::new_sparse(model, 0.3);
let input = random_vector(512);
// Same input should produce same output
let output1 = engine.infer(&input).unwrap();
let output2 = engine.infer(&input).unwrap();
assert_vectors_close(&output1, &output2, 1e-10);
}
#[test]
fn test_sparsity_statistics() {
let model = load_test_llama_model();
let engine = SparseInferenceEngine::new_sparse(model, 0.4);
let stats = engine.sparsity_statistics();
assert!(stats.average_active_ratio >= 0.0);
assert!(stats.average_active_ratio <= 1.0);
assert!(stats.min_active <= stats.max_active);
}
#[test]
fn test_dense_engine_activates_all_neurons() {
let model = load_test_llama_model();
let dense_engine = SparseInferenceEngine::new_dense(model);
let stats = dense_engine.sparsity_statistics();
// Dense engine should have statistics indicating all neurons are active
// (exact values depend on implementation, but ratio should be high)
assert!(stats.average_active_ratio >= 0.0);
}
#[test]
fn test_multiple_inferences() {
let model = load_test_llama_model();
let engine = SparseInferenceEngine::new_sparse(model, 0.2);
// Run many inferences to ensure stability
for _ in 0..100 {
let input = random_vector(512);
let output = engine.infer(&input).unwrap();
assert_eq!(output.len(), 512);
assert!(output.iter().all(|&x| x.is_finite()));
}
}
#[test]
fn test_extreme_input_values() {
let model = load_test_llama_model();
let engine = SparseInferenceEngine::new_sparse(model, 0.3);
// Test with very large values
let large_input = vec![1000.0f32; 512];
let output_large = engine.infer(&large_input).unwrap();
assert!(output_large.iter().all(|&x| x.is_finite()));
// Test with very small values
let small_input = vec![-1000.0f32; 512];
let output_small = engine.infer(&small_input).unwrap();
assert!(output_small.iter().all(|&x| x.is_finite()));
// Test with zero
let zero_input = vec![0.0f32; 512];
let output_zero = engine.infer(&zero_input).unwrap();
assert!(output_zero.iter().all(|&x| x.is_finite()));
}
#[test]
fn test_calibration_with_empty_samples() {
let model = load_test_llama_model();
let mut engine = SparseInferenceEngine::new_sparse(model, 0.3);
let empty_samples: Vec<Vec<f32>> = vec![];
let result = engine.calibrate(&empty_samples);
// Should handle empty calibration gracefully
assert!(result.is_ok());
}
#[test]
fn test_calibration_with_many_samples() {
let model = load_test_llama_model();
let mut engine = SparseInferenceEngine::new_sparse(model, 0.3);
// Large calibration set
let samples = generate_calibration_data(1000);
let result = engine.calibrate(&samples);
assert!(result.is_ok());
}