chore: initial clean commit

This commit is contained in:
2026-02-26 13:56:21 -05:00
commit 1755075657
53 changed files with 18068 additions and 0 deletions

View File

@@ -0,0 +1,188 @@
// Integration tests for LLM Proxy Gateway
use llm_proxy::config::Config;
use llm_proxy::database::Database;
use llm_proxy::state::AppState;
use llm_proxy::rate_limiting::RateLimitManager;
use tempfile::TempDir;
use std::fs;
#[tokio::test]
async fn test_config_loading() {
// Create a temporary config file
let temp_dir = TempDir::new().unwrap();
let config_path = temp_dir.path().join("config.toml");
let config_content = r#"
[server]
port = 8080
host = "0.0.0.0"
[database]
path = "./data/test.db"
max_connections = 5
[providers.openai]
enabled = true
base_url = "https://api.openai.com/v1"
[providers.gemini]
enabled = true
base_url = "https://generativelanguage.googleapis.com/v1"
[providers.deepseek]
enabled = true
base_url = "https://api.deepseek.com"
[providers.grok]
enabled = false
base_url = "https://api.x.ai/v1"
[model_mapping]
"gpt-*" = "openai"
"gemini-*" = "gemini"
"deepseek-*" = "deepseek"
"grok-*" = "grok"
[pricing]
openai = { input = 0.01, output = 0.03 }
gemini = { input = 0.0005, output = 0.0015 }
deepseek = { input = 0.00014, output = 0.00028 }
grok = { input = 0.001, output = 0.003 }
"#;
fs::write(&config_path, config_content).unwrap();
// Test loading config
let config = Config::load_from_path(&config_path);
assert!(config.is_ok());
let config = config.unwrap();
assert_eq!(config.server.port, 8080);
assert!(config.providers.openai.is_some());
assert!(config.providers.grok.is_none());
}
#[tokio::test]
async fn test_database_initialization() {
// Create a temporary database file
let temp_dir = TempDir::new().unwrap();
let db_path = temp_dir.path().join("test.db");
// Test database initialization
let database = Database::new(&db_path).await;
assert!(database.is_ok());
let database = database.unwrap();
// Test connection
let test_result = database.test_connection().await;
assert!(test_result.is_ok());
}
#[tokio::test]
async fn test_provider_manager() {
// Create a provider manager
use llm_proxy::providers::{ProviderManager, Provider};
use llm_proxy::config::OpenAIConfig;
let mut manager = ProviderManager::new();
assert_eq!(manager.providers.len(), 0);
// Test adding providers (we can't actually add real providers without API keys)
// This test just verifies the manager structure works
assert!(manager.get_provider_for_model("gpt-4").is_none());
assert!(manager.get_provider("openai").is_none());
}
#[tokio::test]
async fn test_rate_limit_manager() {
let manager = RateLimitManager::new(60, 10);
// Test client rate limiting
let allowed = manager.check_request("test-client").await;
assert!(allowed); // First request should be allowed
// Test provider circuit breaker
let allowed = manager.check_provider("openai").await;
assert!(allowed); // Circuit should be closed initially
// Record some failures
manager.record_provider_failure("openai").await;
manager.record_provider_failure("openai").await;
manager.record_provider_failure("openai").await;
manager.record_provider_failure("openai").await;
manager.record_provider_failure("openai").await;
// After 5 failures, circuit should be open
let allowed = manager.check_provider("openai").await;
assert!(!allowed); // Circuit should be open
// Record success to close circuit
manager.record_provider_success("openai").await;
manager.record_provider_success("openai").await;
manager.record_provider_success("openai").await;
// After 3 successes in half-open state, circuit should be closed
let allowed = manager.check_provider("openai").await;
assert!(allowed); // Circuit should be closed again
}
#[tokio::test]
async fn test_app_state_creation() {
// Create a temporary database
let temp_dir = TempDir::new().unwrap();
let db_path = temp_dir.path().join("test.db");
let database = Database::new(&db_path).await.unwrap();
// Test AppState creation using test utilities
use llm_proxy::test_utils::create_test_state;
let state = create_test_state().await;
// Verify state components are initialized
assert!(state.database.test_connection().await.is_ok());
}
#[tokio::test]
async fn test_multimodal_image_converter() {
use llm_proxy::multimodal::{ImageConverter, ImageInput};
// Test model detection
assert!(ImageConverter::model_supports_multimodal("gpt-4-vision-preview"));
assert!(ImageConverter::model_supports_multimodal("gemini-pro-vision"));
assert!(!ImageConverter::model_supports_multimodal("gpt-3.5-turbo"));
assert!(!ImageConverter::model_supports_multimodal("gemini-pro"));
// Test data URL parsing (utility function)
let test_url = "data:image/jpeg;base64,SGVsbG8gV29ybGQ=";
let parts: Vec<&str> = test_url[5..].split(";base64,").collect();
assert_eq!(parts.len(), 2);
assert_eq!(parts[0], "image/jpeg");
assert_eq!(parts[1], "SGVsbG8gV29ybGQ=");
}
#[tokio::test]
async fn test_error_conversions() {
use llm_proxy::errors::AppError;
use anyhow::anyhow;
// Test anyhow error conversion
let anyhow_error = anyhow!("Test error");
let app_error: AppError = anyhow_error.into();
match app_error {
AppError::InternalError(msg) => assert_eq!(msg, "Test error"),
_ => panic!("Expected InternalError"),
}
// Test sqlx error conversion
use sqlx::Error as SqlxError;
let sqlx_error = SqlxError::PoolClosed;
let app_error: AppError = sqlx_error.into();
match app_error {
AppError::DatabaseError(msg) => assert!(msg.contains("pool closed")),
_ => panic!("Expected DatabaseError"),
}
}