use anyhow::Result; use bytes::Bytes; use http_body_util::{BodyExt, Full}; use hyper::{Response, StatusCode}; use serde_json::Value; use std::sync::Arc; use quantum::{ config::Config, services::ServiceRegistry, admin::AdminServer, }; /// Integration tests for the Quantum web server /// Tests the complete functionality including TLS, metrics, admin API, and proxy features #[tokio::test] async fn test_service_registry_initialization() -> Result<()> { // Test that service registry initializes correctly let config = Config::default_with_ports(8080, 8443); let services = ServiceRegistry::new(&config).await?; // Verify metrics are working assert_eq!(services.metrics.get_request_count(), 0); assert_eq!(services.metrics.get_active_connections(), 0); // Test metrics increment services.metrics.record_request(); assert_eq!(services.metrics.get_request_count(), 1); // Verify TLS manager is initialized let tls_manager = services.tls_manager.lock().await; assert_eq!(tls_manager.get_certificate_count().await, 0); Ok(()) } #[tokio::test] async fn test_admin_api_endpoints() -> Result<()> { // Initialize services let config = Config::default_with_ports(8080, 8443); let services = Arc::new(ServiceRegistry::new(&config).await?); let config_arc = Arc::new(tokio::sync::RwLock::new(config)); // Create admin server (but don't start it) let _admin = AdminServer::new(config_arc, services.clone(), "127.0.0.1:9999".to_string()); // Test status endpoint let status_response = admin_request(&services, "/status").await?; assert_eq!(status_response.status(), StatusCode::OK); let status_body = status_response.into_body().collect().await?.to_bytes(); let status_json: Value = serde_json::from_slice(&status_body)?; assert_eq!(status_json["status"], "running"); assert_eq!(status_json["version"], "0.2.0"); assert!(status_json["features"].as_array().unwrap().len() > 0); // Test metrics endpoint let metrics_response = admin_request(&services, "/metrics").await?; assert_eq!(metrics_response.status(), StatusCode::OK); let metrics_body = metrics_response.into_body().collect().await?.to_bytes(); let metrics_json: Value = serde_json::from_slice(&metrics_body)?; // Note: may be > 0 due to previous requests in test assert!(metrics_json["requests_total"].as_u64().unwrap() >= 0); assert_eq!(metrics_json["active_connections"], 0); assert_eq!(metrics_json["certificates_count"], 0); // Test health endpoint let health_response = admin_request(&services, "/health").await?; assert_eq!(health_response.status(), StatusCode::OK); let health_body = health_response.into_body().collect().await?.to_bytes(); let health_json: Value = serde_json::from_slice(&health_body)?; assert!(health_json["status"].as_str().unwrap() == "healthy" || health_json["status"].as_str().unwrap() == "degraded"); assert_eq!(health_json["checks"]["metrics"], "ok"); // Test certificates endpoint let certs_response = admin_request(&services, "/certificates").await?; assert_eq!(certs_response.status(), StatusCode::OK); let certs_body = certs_response.into_body().collect().await?.to_bytes(); let certs_json: Value = serde_json::from_slice(&certs_body)?; assert_eq!(certs_json["certificate_count"], 0); assert_eq!(certs_json["certificates"].as_array().unwrap().len(), 0); Ok(()) } #[tokio::test] async fn test_metrics_collection() -> Result<()> { let config = Config::default_with_ports(8080, 8443); let services = ServiceRegistry::new(&config).await?; // Test request counting assert_eq!(services.metrics.get_request_count(), 0); services.metrics.record_request(); services.metrics.record_request(); assert_eq!(services.metrics.get_request_count(), 2); // Test connection counting services.metrics.increment_active_connections(); assert_eq!(services.metrics.get_active_connections(), 1); services.metrics.decrement_active_connections(); assert_eq!(services.metrics.get_active_connections(), 0); // Test uptime tracking assert!(services.metrics.get_uptime_seconds() >= 0); Ok(()) } #[tokio::test] async fn test_tls_manager() -> Result<()> { // Test TLS manager without ACME let config = Config::default_with_ports(8080, 8443); let services = ServiceRegistry::new(&config).await?; let tls_manager = services.tls_manager.lock().await; // Should have no certificates initially assert_eq!(tls_manager.get_certificate_count().await, 0); assert_eq!(tls_manager.get_certificate_domains().await.len(), 0); // Should have no ACME manager without configuration assert!(tls_manager.acme_manager.is_none()); Ok(()) } #[tokio::test] async fn test_config_validation() -> Result<()> { // Test default configuration let config = Config::default_with_ports(8080, 8443); assert!(config.apps.http.servers.len() > 0); // Verify server configuration exists assert!(config.apps.http.servers.len() > 0); // Get the first server (since naming may vary) let first_server = config.apps.http.servers.values().next().unwrap(); assert!(first_server.listen.len() > 0); // Verify we have at least one server listening on expected ports let has_http = config.apps.http.servers.values() .any(|s| s.listen.iter().any(|l| l.contains("8080"))); let has_https = config.apps.http.servers.values() .any(|s| s.listen.iter().any(|l| l.contains("8443"))); assert!(has_http || has_https, "Should have at least one server on port 8080 or 8443"); Ok(()) } #[tokio::test] async fn test_certificate_operations() -> Result<()> { let config = Config::default_with_ports(8080, 8443); let services = Arc::new(ServiceRegistry::new(&config).await?); // Test certificate reload endpoint without ACME let reload_response = admin_request(&services, "/certificates/reload").await?; assert_eq!(reload_response.status(), StatusCode::OK); let reload_body = reload_response.into_body().collect().await?.to_bytes(); let reload_json: Value = serde_json::from_slice(&reload_body)?; assert_eq!(reload_json["status"], "ok"); assert!(reload_json["message"].as_str().unwrap().contains("No ACME manager")); Ok(()) } #[tokio::test] async fn test_admin_api_error_handling() -> Result<()> { let config = Config::default_with_ports(8080, 8443); let services = Arc::new(ServiceRegistry::new(&config).await?); // Test 404 for non-existent endpoint let not_found_response = admin_request(&services, "/nonexistent").await?; assert_eq!(not_found_response.status(), StatusCode::NOT_FOUND); let not_found_body = not_found_response.into_body().collect().await?.to_bytes(); let not_found_json: Value = serde_json::from_slice(¬_found_body)?; assert_eq!(not_found_json["error"], "Not Found"); Ok(()) } #[tokio::test] async fn test_configuration_management() -> Result<()> { let config = Config::default_with_ports(8080, 8443); let services = Arc::new(ServiceRegistry::new(&config).await?); let config_arc = Arc::new(tokio::sync::RwLock::new(config)); // Create admin server let _admin = AdminServer::new(config_arc.clone(), services.clone(), "127.0.0.1:9998".to_string()); // Test getting configuration let config_response = admin_request(&services, "/config").await?; assert_eq!(config_response.status(), StatusCode::OK); let config_body = config_response.into_body().collect().await?.to_bytes(); let config_json: Value = serde_json::from_slice(&config_body)?; assert_eq!(config_json["version"], "0.2.0"); assert!(config_json["config"].is_object()); Ok(()) } #[tokio::test] async fn test_api_documentation() -> Result<()> { let config = Config::default_with_ports(8080, 8443); let services = Arc::new(ServiceRegistry::new(&config).await?); // Test API documentation endpoint let docs_response = admin_request(&services, "/").await?; assert_eq!(docs_response.status(), StatusCode::OK); let docs_body = docs_response.into_body().collect().await?.to_bytes(); let docs_json: Value = serde_json::from_slice(&docs_body)?; assert_eq!(docs_json["name"], "Quantum Admin API"); assert_eq!(docs_json["version"], "0.2.0"); assert!(docs_json["endpoints"].is_object()); assert!(docs_json["features"].as_array().unwrap().len() > 0); Ok(()) } /// Helper function to simulate admin API requests /// This is a simplified mock that directly calls the admin handlers async fn admin_request( services: &Arc, path: &str ) -> Result>> { use tokio::sync::RwLock; // Create a mock config for endpoints that need it let config = Config::default_with_ports(8080, 8443); let config_arc = Arc::new(RwLock::new(config)); // For testing purposes, we'll call the individual handler methods directly // since creating a proper Incoming body is complex for unit tests match path { "/status" => AdminServer::get_status(services.clone()).await, "/metrics" => AdminServer::get_metrics(services.clone()).await, "/health" => AdminServer::get_health(services.clone()).await, "/certificates" => AdminServer::get_certificates(services.clone()).await, "/certificates/reload" => AdminServer::reload_certificates(services.clone()).await, "/config" => AdminServer::get_config(config_arc).await, "/" => AdminServer::get_api_docs().await, _ => Ok(Response::builder() .status(StatusCode::NOT_FOUND) .header("content-type", "application/json") .body(Full::new(Bytes::from(r#"{"error":"Not Found","message":"Admin endpoint not found"}"#))) .unwrap()), }.map_err(|e| anyhow::anyhow!("Admin request failed: {}", e)) } #[tokio::test] async fn test_service_integration() -> Result<()> { // Test that all services work together let config = Config::default_with_ports(8080, 8443); let services = ServiceRegistry::new(&config).await?; // Simulate some activity services.metrics.record_request(); services.metrics.record_response_time(150.0); services.metrics.record_upstream_request("backend1"); // Check that metrics were recorded assert_eq!(services.metrics.get_request_count(), 1); // Verify all services are accessible let _tls_manager = services.tls_manager.lock().await; // No need to access tls_manager further since we're testing integration Ok(()) } /// Test that demonstrates the complete server startup sequence #[tokio::test] async fn test_server_initialization_sequence() -> Result<()> { // This test verifies the initialization order is correct let config = Config::default_with_ports(8080, 8443); // Step 1: Initialize services let services = ServiceRegistry::new(&config).await?; assert!(services.metrics.get_uptime_seconds() >= 0); // Step 2: Verify TLS is ready (even without certificates) { let tls_manager = services.tls_manager.lock().await; // TLS acceptor might be None without certificates, but that's expected let _ = tls_manager.get_certificate_count(); } // Step 3: Verify metrics are working services.metrics.record_request(); assert_eq!(services.metrics.get_request_count(), 1); // Step 4: Test that admin API configuration would work let config_arc = Arc::new(tokio::sync::RwLock::new(config.clone())); let _admin = AdminServer::new( config_arc, Arc::new(services), "127.0.0.1:9997".to_string(), ); Ok(()) }