use std::time::Duration;
use turboprop::embeddings::{EmbeddingConfig, OptimizedEmbeddingGenerator, PerformanceReport};
use turboprop::models::ModelInfo;
use turboprop::types::{ModelBackend, ModelName, ModelType};
#[cfg(any(test, feature = "test-utils"))]
use turboprop::embeddings::MockEmbeddingGenerator;
fn create_mock_model_info() -> ModelInfo {
ModelInfo {
name: ModelName::from("sentence-transformers/all-MiniLM-L6-v2"),
backend: ModelBackend::FastEmbed,
model_type: ModelType::SentenceTransformer,
dimensions: 384,
size_bytes: 90_000_000,
description: "Test model".to_string(),
download_url: Some("https://example.com".to_string()),
local_path: None,
}
}
#[tokio::test]
async fn test_optimized_generator_initialization() {
let model_info = create_mock_model_info();
let config = EmbeddingConfig::default();
if let Ok(generator) = OptimizedEmbeddingGenerator::new_with_model(&model_info, config).await {
let report = generator.get_performance_report();
assert_eq!(report.model_name, model_info.name.as_str());
assert_eq!(report.total_texts_processed, 0);
}
}
#[test]
fn test_performance_report_initialization() {
let report = PerformanceReport {
model_name: "test-model".to_string(),
total_texts_processed: 0,
total_processing_time: Duration::ZERO,
average_time_per_text: Duration::ZERO,
model_load_time: None,
peak_memory_usage: 0,
cache_efficiency: 0.0,
};
assert_eq!(report.model_name, "test-model");
assert_eq!(report.total_texts_processed, 0);
assert_eq!(report.cache_efficiency, 0.0);
}
#[test]
fn test_performance_report_with_data() {
let report = PerformanceReport {
model_name: "test-model".to_string(),
total_texts_processed: 100,
total_processing_time: Duration::from_secs(2),
average_time_per_text: Duration::from_millis(20),
model_load_time: Some(Duration::from_secs(5)),
peak_memory_usage: 50_000_000, cache_efficiency: 0.75,
};
assert_eq!(report.total_texts_processed, 100);
assert_eq!(report.total_processing_time, Duration::from_secs(2));
assert_eq!(report.average_time_per_text, Duration::from_millis(20));
assert_eq!(report.model_load_time, Some(Duration::from_secs(5)));
assert_eq!(report.peak_memory_usage, 50_000_000);
assert_eq!(report.cache_efficiency, 0.75);
}
#[test]
fn test_performance_report_print_summary() {
let report = PerformanceReport {
model_name: "test-model".to_string(),
total_texts_processed: 10,
total_processing_time: Duration::from_millis(100),
average_time_per_text: Duration::from_millis(10),
model_load_time: Some(Duration::from_secs(1)),
peak_memory_usage: 1_048_576, cache_efficiency: 0.5,
};
report.print_summary();
}
#[test]
fn test_format_bytes_function() {
let report = PerformanceReport {
model_name: "test-model".to_string(),
total_texts_processed: 0,
total_processing_time: Duration::ZERO,
average_time_per_text: Duration::ZERO,
model_load_time: None,
peak_memory_usage: 1024, cache_efficiency: 0.0,
};
report.print_summary();
}
#[test]
fn test_optimal_batch_size_calculation() {
let texts = [
"short text".to_string(),
"this is a longer text that should affect batch size calculations".to_string(),
"medium length text for testing".to_string(),
];
assert_eq!(texts.len(), 3);
let avg_length = texts.iter().map(|t| t.len()).sum::<usize>() / texts.len();
assert!(avg_length > 0);
}
#[test]
fn test_memory_scaling_factors() {
#[allow(dead_code)]
const HIGH_MEMORY_SCALING_FACTOR: f64 = 2.0;
#[allow(dead_code)]
const MEDIUM_MEMORY_SCALING_FACTOR: f64 = 1.5;
#[allow(dead_code)]
const LOW_MEMORY_SCALING_FACTOR: f64 = 0.75;
}
#[test]
fn test_batch_size_constraints() {
const MIN_SIZE: usize = 1;
const MAX_SIZE: usize = 128;
const CONSERVATIVE_MAX_SIZE: usize = 64;
let batch_size = 150;
let constrained = batch_size.clamp(MIN_SIZE, MAX_SIZE);
assert_eq!(constrained, MAX_SIZE);
let batch_size = 100;
let constrained = batch_size.clamp(MIN_SIZE, CONSERVATIVE_MAX_SIZE);
assert_eq!(constrained, CONSERVATIVE_MAX_SIZE);
let batch_size = 0;
let constrained = batch_size.clamp(MIN_SIZE, MAX_SIZE);
assert_eq!(constrained, MIN_SIZE);
}
#[test]
fn test_cache_efficiency_calculation() {
let total_capacity = 1000_f32;
let current_size = 750_f32;
let efficiency = current_size / total_capacity;
assert_eq!(efficiency, 0.75);
assert!((0.0..=1.0).contains(&efficiency));
}
#[cfg(any(test, feature = "test-utils"))]
#[test]
fn test_optimized_generator_with_cache() {
let config = EmbeddingConfig::default();
let mut generator = MockEmbeddingGenerator::new(config);
let text = "test text for caching";
let embedding1 = generator.embed_single(text).unwrap();
let embedding2 = generator.embed_single(text).unwrap();
assert_eq!(embedding1, embedding2);
}
#[test]
fn test_embedding_options_for_optimization() {
use turboprop::embeddings::EmbeddingOptions;
let mut options = EmbeddingOptions::with_instruction("test instruction");
options.max_length = Some(500);
assert_eq!(options.instruction.as_deref(), Some("test instruction"));
assert_eq!(options.max_length, Some(500));
assert!(options.normalize);
}
#[test]
fn test_text_preprocessing_logic() {
let original_texts = [
" text with extra spaces ".to_string(),
"normal text".to_string(),
"\t\ntext\nwith\tnewlines\t\n".to_string(),
];
let processed: Vec<String> = original_texts
.iter()
.map(|text| {
let mut result = String::new();
let mut first = true;
for word in text.split_whitespace() {
if !first {
result.push(' ');
}
result.push_str(word);
first = false;
}
result
})
.collect();
assert_eq!(processed[0], "text with extra spaces");
assert_eq!(processed[1], "normal text");
assert_eq!(processed[2], "text with newlines");
}
#[test]
fn test_performance_metrics_integration() {
use turboprop::metrics::MetricsCollector;
let collector = MetricsCollector::new("test-model".to_string());
collector.record_embedding(5, Duration::from_millis(100));
collector.record_model_load_time(Duration::from_secs(2));
let metrics = collector.get_metrics();
assert_eq!(metrics.texts_embedded, 5);
assert_eq!(metrics.model_load_time, Some(Duration::from_secs(2)));
assert_eq!(metrics.avg_time_per_text, Duration::from_millis(20));
}