use kindly_guard_server::{
component_selector::ComponentManager, Config, ScannerConfig, SecurityScanner, ThreatType,
};
use std::sync::Arc;
#[tokio::test]
async fn test_storage_integration() {
let mut config = Config::default();
config.storage.enabled = true;
let component_manager = Arc::new(ComponentManager::new(&config).unwrap());
let storage = component_manager.storage_provider();
let event = kindly_guard_server::traits::SecurityEvent {
event_type: "test_threat".to_string(),
client_id: "test_client".to_string(),
timestamp: 1234567890,
metadata: serde_json::json!({
"severity": "high",
"description": "Test threat"
}),
};
let event_id = storage.store_event(&event).await.unwrap();
assert!(!event_id.0.is_empty());
use kindly_guard_server::storage::EventFilter;
let filter = EventFilter {
client_id: Some("test_client".to_string()),
..Default::default()
};
let events = storage.query_events(filter).await.unwrap();
assert_eq!(events.len(), 1);
assert_eq!(events[0].client_id, "test_client");
}
#[test]
fn test_scanner_without_plugins() {
let config = ScannerConfig {
unicode_detection: true,
injection_detection: true,
path_traversal_detection: true,
custom_patterns: None,
max_scan_depth: 10,
enable_event_buffer: false,
xss_detection: Some(true),
enhanced_mode: Some(false),
crypto_detection: true,
max_content_size: 5 * 1024 * 1024, max_input_size: None,
};
let scanner = SecurityScanner::new(config).unwrap();
let threats = scanner
.scan_text("SELECT * FROM users WHERE id = '1' OR '1'='1'")
.unwrap();
assert!(!threats.is_empty());
let sql_threats: Vec<_> = threats
.iter()
.filter(|t| matches!(t.threat_type, ThreatType::SqlInjection))
.collect();
assert!(!sql_threats.is_empty());
}
#[test]
fn test_scanner_threat_detection() {
let config = ScannerConfig {
unicode_detection: true,
injection_detection: true,
path_traversal_detection: true,
custom_patterns: None,
max_scan_depth: 10,
enable_event_buffer: false,
xss_detection: Some(true),
enhanced_mode: Some(false),
crypto_detection: true,
max_content_size: 5 * 1024 * 1024, max_input_size: None,
};
let scanner = SecurityScanner::new(config).unwrap();
let test_cases = vec![
("Hello\u{202E}World", ThreatType::UnicodeBiDi),
("rm -rf /; echo done", ThreatType::CommandInjection),
("../../etc/passwd", ThreatType::PathTraversal),
];
for (input, expected_type) in test_cases {
let threats = scanner.scan_text(input).unwrap();
assert!(!threats.is_empty(), "Expected threats for input: {input}");
let has_expected = threats.iter().any(|t| t.threat_type == expected_type);
assert!(
has_expected,
"Expected {expected_type:?} threat for input: {input}"
);
}
}
#[tokio::test]
async fn test_component_manager_creation() {
let config = Config::default();
let component_manager = ComponentManager::new(&config).unwrap();
assert!(!component_manager.event_processor().is_monitored("test"));
assert_eq!(component_manager.scanner().get_metrics().scans_performed, 0);
assert_eq!(
component_manager
.rate_limiter()
.get_stats()
.requests_allowed,
0
);
let storage_stats = component_manager
.storage_provider()
.get_stats()
.await
.unwrap();
assert_eq!(storage_stats.event_count, 0);
let plugins = component_manager
.plugin_manager()
.list_plugins()
.await
.unwrap();
assert!(plugins.is_empty());
}
#[test]
fn test_json_scanning() {
let config = ScannerConfig {
unicode_detection: true,
injection_detection: true,
path_traversal_detection: true,
custom_patterns: None,
max_scan_depth: 10,
enable_event_buffer: false,
xss_detection: Some(true),
enhanced_mode: Some(false),
crypto_detection: true,
max_content_size: 5 * 1024 * 1024, max_input_size: None,
};
let scanner = SecurityScanner::new(config).unwrap();
let json = serde_json::json!({
"user": "admin' OR '1'='1",
"command": "ls; cat /etc/passwd",
"path": "../../../etc/shadow",
"script": "<img src=x onerror=alert('xss')>"
});
let threats = scanner.scan_json(&json).unwrap();
assert!(
threats.len() >= 3,
"Expected at least 3 threats, got {}",
threats.len()
);
for threat in &threats {
match &threat.location {
kindly_guard_server::scanner::Location::Json { path } => {
assert!(path.starts_with('$'), "JSON path should start with $");
},
_ => panic!("Expected JSON location for JSON scanning"),
}
}
}
#[tokio::test]
async fn test_audit_logger_integration() {
use kindly_guard_server::audit::{AuditEvent, AuditEventType, AuditFilter, AuditSeverity};
let mut config = Config::default();
config.audit.enabled = true;
config.audit.backend = kindly_guard_server::audit::AuditBackend::Memory;
let component_manager = Arc::new(ComponentManager::new(&config).unwrap());
let audit_logger = component_manager.audit_logger();
let event1 = AuditEvent::new(
AuditEventType::AuthSuccess {
user_id: "test_user".to_string(),
},
AuditSeverity::Info,
)
.with_client_id("client123".to_string());
let event2 = AuditEvent::new(
AuditEventType::ThreatDetected {
client_id: "client123".to_string(),
threat_count: 3,
},
AuditSeverity::Warning,
)
.with_client_id("client123".to_string());
let event3 = AuditEvent::new(
AuditEventType::RateLimitTriggered {
client_id: "client456".to_string(),
limit_type: "request".to_string(),
},
AuditSeverity::Warning,
)
.with_client_id("client456".to_string());
let id1 = audit_logger.log(event1).await.unwrap();
let id2 = audit_logger.log(event2).await.unwrap();
let id3 = audit_logger.log(event3).await.unwrap();
let all_events = audit_logger.query(AuditFilter::default()).await.unwrap();
assert_eq!(all_events.len(), 3);
let filter = AuditFilter {
client_id: Some("client123".to_string()),
..Default::default()
};
let client_events = audit_logger.query(filter).await.unwrap();
assert_eq!(client_events.len(), 2);
let filter = AuditFilter {
min_severity: Some(AuditSeverity::Warning),
..Default::default()
};
let warning_events = audit_logger.query(filter).await.unwrap();
assert_eq!(warning_events.len(), 2);
let event = audit_logger.get_event(&id1).await.unwrap();
assert!(event.is_some());
let stats = audit_logger.get_stats().await.unwrap();
assert_eq!(stats.total_events, 3);
assert_eq!(stats.events_by_severity.get("Warning"), Some(&2));
assert_eq!(stats.events_by_severity.get("Info"), Some(&1));
}