ohttp-gateway/tests/integration_tests.rs

204 lines
6.7 KiB
Rust
Raw Permalink Normal View History

use std::time::Duration;
use ohttp_gateway::{key_manager::KeyManager, key_manager::KeyManagerConfig};
mod common;
use common::*;
#[tokio::test]
async fn test_end_to_end_encryption_decryption() {
let config = KeyManagerConfig::default();
let manager = KeyManager::new(config).await.unwrap();
// Get the server for decryption
let _ = manager.get_current_server().await.unwrap();
// Get the key config for client encryption
let encoded_config = manager.get_encoded_config().await.unwrap();
// Parse the config (this would normally be done by a real OHTTP client)
// For now, create a client with the current key config
let stats = manager.get_stats().await;
let _ = manager.get_server_by_id(stats.active_key_id).await.unwrap();
// Test message
let test_message = create_test_binary_http_message();
// This test verifies that encryption/decryption round trip works
// In a real implementation, you'd use the ohttp client/server APIs
// For now, just verify we can get the components we need
assert!(!encoded_config.is_empty());
assert!(!test_message.is_empty());
}
#[tokio::test]
async fn test_key_rotation_during_requests() {
let config = KeyManagerConfig {
rotation_interval: Duration::from_millis(100),
key_retention_period: Duration::from_millis(200),
auto_rotation_enabled: false, // Manual control
..Default::default()
};
let manager = KeyManager::new(config).await.unwrap();
let initial_stats = manager.get_stats().await;
// Get server for old key
let old_server = manager.get_server_by_id(initial_stats.active_key_id).await;
assert!(old_server.is_some());
// Rotate keys
manager.rotate_keys().await.unwrap();
let new_stats = manager.get_stats().await;
// Old key should still be available for decryption
let old_server_after_rotation = manager.get_server_by_id(initial_stats.active_key_id).await;
assert!(old_server_after_rotation.is_some());
// New key should also be available
let new_server = manager.get_server_by_id(new_stats.active_key_id).await;
assert!(new_server.is_some());
// Active key should have changed
assert_ne!(initial_stats.active_key_id, new_stats.active_key_id);
assert_eq!(new_stats.total_keys, 2);
}
#[tokio::test]
async fn test_invalid_key_id_handling() {
let config = KeyManagerConfig::default();
let manager = KeyManager::new(config).await.unwrap();
let stats = manager.get_stats().await;
let invalid_key_id = stats.active_key_id.wrapping_add(100);
// Should return None for invalid key ID
let server = manager.get_server_by_id(invalid_key_id).await;
assert!(server.is_none());
}
#[tokio::test]
async fn test_concurrent_key_operations() {
let config = KeyManagerConfig::default();
let manager = std::sync::Arc::new(KeyManager::new(config).await.unwrap());
let mut handles = vec![];
// Spawn multiple tasks that access keys concurrently
for i in 0..10 {
let manager_clone = manager.clone();
let handle = tokio::spawn(async move {
if i % 2 == 0 {
// Half the tasks get the current server
let _server = manager_clone.get_current_server().await.unwrap();
} else {
// Half get stats
let _stats = manager_clone.get_stats().await;
}
});
handles.push(handle);
}
// Wait for all tasks to complete
for handle in handles {
handle.await.unwrap();
}
// Manager should still be functional
let final_stats = manager.get_stats().await;
assert_eq!(final_stats.total_keys, 1);
}
#[tokio::test]
async fn test_automatic_rotation_scheduler() {
let config = KeyManagerConfig {
rotation_interval: Duration::from_millis(100),
key_retention_period: Duration::from_millis(200),
auto_rotation_enabled: true,
..Default::default()
};
let manager = std::sync::Arc::new(KeyManager::new(config).await.unwrap());
let initial_stats = manager.get_stats().await;
// Start the rotation scheduler
let manager_clone = manager.clone();
manager_clone.start_rotation_scheduler().await;
// Wait for automatic rotation to occur
tokio::time::sleep(Duration::from_millis(300)).await;
let final_stats = manager.get_stats().await;
// Key should have rotated automatically
// Note: This test might be flaky depending on timing
assert!(final_stats.active_key_id != initial_stats.active_key_id || final_stats.total_keys > 1);
}
#[tokio::test]
async fn test_metrics_tracking() {
let factory = MockMetricsFactory::new();
// Simulate various operations and metric collection
let metrics = factory.create("test_event".to_string()).await;
metrics.fire("operation_success").await;
metrics.response_status("test", 200).await;
assert!(metrics.contains_result("operation_success").await);
assert!(metrics.contains_result("test_response_status_200").await);
// Test the helper function
assert_metrics_contains_result(&factory, "test_event", "operation_success")
.await
.unwrap();
}
#[tokio::test]
async fn test_config_serialization_format() {
let config = KeyManagerConfig::default();
let manager = KeyManager::new(config).await.unwrap();
let encoded_config = manager.get_encoded_config().await.unwrap();
2025-11-23 20:27:24 +00:00
// Verify we have config data with 2-byte length prefix per RFC 9458
2025-07-24 11:21:37 +00:00
assert!(!encoded_config.is_empty());
2025-11-23 20:27:24 +00:00
assert!(encoded_config.len() > 12); // At least 2 bytes for length + some config data
// Verify the length prefix is correct
let length_prefix = u16::from_be_bytes([encoded_config[0], encoded_config[1]]);
assert_eq!(length_prefix as usize, encoded_config.len() - 2);
2025-07-24 11:21:37 +00:00
// Verify it contains reasonable OHTTP key configuration data
assert!(encoded_config.len() < 1000); // Reasonable upper bound
2025-11-23 20:27:24 +00:00
// The config should be the length-prefixed encoded configuration
let config_data = &encoded_config[2..]; // Skip the length prefix
assert!(!config_data.is_empty());
}
#[tokio::test]
async fn test_error_conditions() {
// Test various error conditions
// Invalid seed length
let config = KeyManagerConfig::default();
let short_seed = vec![0u8; 16];
let result = KeyManager::new_with_seed(config.clone(), short_seed).await;
assert!(result.is_err());
// Test with empty cipher suites (if your implementation supports this validation)
let invalid_config = KeyManagerConfig {
cipher_suites: vec![], // Empty cipher suites
..Default::default()
};
// Should return an error for empty cipher suites
let result = KeyManager::new(invalid_config).await;
assert!(
result.is_err(),
"KeyManager should reject empty cipher suites"
);
}