add comprehensive unit tests for detection engine
This commit is contained in:
103
ghost-core/tests/detection_tests.rs
Normal file
103
ghost-core/tests/detection_tests.rs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use ghost_core::{DetectionEngine, MemoryProtection, MemoryRegion, ProcessInfo, ThreatLevel};
|
||||||
|
|
||||||
|
fn create_test_process() -> ProcessInfo {
|
||||||
|
ProcessInfo {
|
||||||
|
pid: 1234,
|
||||||
|
ppid: 4,
|
||||||
|
name: "test.exe".to_string(),
|
||||||
|
path: Some("C:\\Windows\\System32\\test.exe".to_string()),
|
||||||
|
thread_count: 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_rwx_region() -> MemoryRegion {
|
||||||
|
MemoryRegion {
|
||||||
|
base_address: 0x10000000,
|
||||||
|
size: 0x1000,
|
||||||
|
protection: MemoryProtection::ReadWriteExecute,
|
||||||
|
region_type: "PRIVATE".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_clean_process_detection() {
|
||||||
|
let mut engine = DetectionEngine::new();
|
||||||
|
let process = create_test_process();
|
||||||
|
let regions = vec![MemoryRegion {
|
||||||
|
base_address: 0x400000,
|
||||||
|
size: 0x10000,
|
||||||
|
protection: MemoryProtection::ReadExecute,
|
||||||
|
region_type: "IMAGE".to_string(),
|
||||||
|
}];
|
||||||
|
|
||||||
|
let result = engine.analyze_process(&process, ®ions, None);
|
||||||
|
assert_eq!(result.threat_level, ThreatLevel::Clean);
|
||||||
|
assert!(result.indicators.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rwx_region_detection() {
|
||||||
|
let mut engine = DetectionEngine::new();
|
||||||
|
let process = create_test_process();
|
||||||
|
let regions = vec![create_rwx_region()];
|
||||||
|
|
||||||
|
let result = engine.analyze_process(&process, ®ions, None);
|
||||||
|
assert_ne!(result.threat_level, ThreatLevel::Clean);
|
||||||
|
assert!(!result.indicators.is_empty());
|
||||||
|
assert!(result.indicators[0].contains("RWX"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multiple_small_executable_regions() {
|
||||||
|
let mut engine = DetectionEngine::new();
|
||||||
|
let process = create_test_process();
|
||||||
|
let regions = vec![
|
||||||
|
MemoryRegion {
|
||||||
|
base_address: 0x10000000,
|
||||||
|
size: 0x800, // Small size
|
||||||
|
protection: MemoryProtection::ReadExecute,
|
||||||
|
region_type: "PRIVATE".to_string(),
|
||||||
|
},
|
||||||
|
MemoryRegion {
|
||||||
|
base_address: 0x20000000,
|
||||||
|
size: 0x600, // Small size
|
||||||
|
protection: MemoryProtection::ReadExecute,
|
||||||
|
region_type: "PRIVATE".to_string(),
|
||||||
|
},
|
||||||
|
MemoryRegion {
|
||||||
|
base_address: 0x30000000,
|
||||||
|
size: 0x400, // Small size
|
||||||
|
protection: MemoryProtection::ReadExecute,
|
||||||
|
region_type: "PRIVATE".to_string(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let result = engine.analyze_process(&process, ®ions, None);
|
||||||
|
assert!(result.confidence > 0.0);
|
||||||
|
assert!(result
|
||||||
|
.indicators
|
||||||
|
.iter()
|
||||||
|
.any(|i| i.contains("small executable")));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_baseline_tracking() {
|
||||||
|
let mut engine = DetectionEngine::new();
|
||||||
|
let mut process = create_test_process();
|
||||||
|
let regions = vec![];
|
||||||
|
|
||||||
|
// First scan establishes baseline
|
||||||
|
let result1 = engine.analyze_process(&process, ®ions, None);
|
||||||
|
assert_eq!(result1.threat_level, ThreatLevel::Clean);
|
||||||
|
|
||||||
|
// Second scan with increased thread count
|
||||||
|
process.thread_count = 5;
|
||||||
|
let result2 = engine.analyze_process(&process, ®ions, None);
|
||||||
|
assert!(result2
|
||||||
|
.indicators
|
||||||
|
.iter()
|
||||||
|
.any(|i| i.contains("new threads")));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user