mirror of
https://github.com/xzcrpw/blackwall.git
synced 2026-05-04 13:22:37 +02:00
v2.0.0: adaptive eBPF firewall with AI honeypot and P2P threat mesh
This commit is contained in:
commit
37c6bbf5a1
133 changed files with 28073 additions and 0 deletions
125
hivemind/tests/ioc_format.rs
Executable file
125
hivemind/tests/ioc_format.rs
Executable file
|
|
@ -0,0 +1,125 @@
|
|||
//! Integration tests for the enriched IoC file IPC format.
|
||||
//!
|
||||
//! Tests that the JSON Lines format produced by hivemind is correctly parsed
|
||||
//! and that legacy raw u32 format is still supported.
|
||||
//!
|
||||
//! Run: `cargo test -p hivemind --test ioc_format -- --nocapture`
|
||||
|
||||
#[test]
|
||||
fn enriched_ioc_json_format() {
|
||||
// Verify the JSON format produced by append_accepted_ioc
|
||||
let test_entries = [
|
||||
// severity 2 → 1800s
|
||||
(0x0A000001u32, 2u8, 3u8, 1800u32),
|
||||
// severity 5 → 3600s
|
||||
(0x0A000002, 5, 4, 3600),
|
||||
// severity 7 → 7200s
|
||||
(0x0A000003, 7, 5, 7200),
|
||||
// severity 9 → 14400s
|
||||
(0x0A000004, 9, 3, 14400),
|
||||
];
|
||||
|
||||
for (ip, severity, confirmations, expected_duration) in &test_entries {
|
||||
// Compute duration the same way as append_accepted_ioc
|
||||
let duration_secs: u32 = match severity {
|
||||
0..=2 => 1800,
|
||||
3..=5 => 3600,
|
||||
6..=8 => 7200,
|
||||
_ => 14400,
|
||||
};
|
||||
assert_eq!(
|
||||
duration_secs, *expected_duration,
|
||||
"severity {} should map to {} seconds",
|
||||
severity, expected_duration
|
||||
);
|
||||
|
||||
// Verify JSON serialization format
|
||||
let json = format!(
|
||||
r#"{{"ip":{},"severity":{},"confirmations":{},"duration_secs":{}}}"#,
|
||||
ip, severity, confirmations, duration_secs,
|
||||
);
|
||||
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(parsed["ip"], *ip);
|
||||
assert_eq!(parsed["severity"], *severity);
|
||||
assert_eq!(parsed["confirmations"], *confirmations);
|
||||
assert_eq!(parsed["duration_secs"], duration_secs);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn legacy_u32_format_still_parseable() {
|
||||
// Old format: one u32 per line
|
||||
let legacy_content = "167772161\n167772162\n167772163\n";
|
||||
let mut ips = Vec::new();
|
||||
for line in legacy_content.lines() {
|
||||
let trimmed = line.trim();
|
||||
if !trimmed.is_empty() {
|
||||
if let Ok(ip) = trimmed.parse::<u32>() {
|
||||
ips.push(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(ips.len(), 3);
|
||||
assert_eq!(ips[0], 167772161); // 10.0.0.1
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mixed_format_lines() {
|
||||
// Content with both legacy and enriched lines (during upgrade transition)
|
||||
let content = r#"167772161
|
||||
{"ip":167772162,"severity":5,"confirmations":3,"duration_secs":3600}
|
||||
167772163
|
||||
{"ip":167772164,"severity":9,"confirmations":5,"duration_secs":14400}
|
||||
"#;
|
||||
|
||||
let mut entries = Vec::new();
|
||||
for line in content.lines() {
|
||||
let trimmed = line.trim();
|
||||
if trimmed.is_empty() {
|
||||
continue;
|
||||
}
|
||||
if trimmed.starts_with('{') {
|
||||
let parsed: serde_json::Value = serde_json::from_str(trimmed).unwrap();
|
||||
entries.push((
|
||||
parsed["ip"].as_u64().unwrap() as u32,
|
||||
parsed["duration_secs"].as_u64().unwrap() as u32,
|
||||
));
|
||||
} else if let Ok(ip) = trimmed.parse::<u32>() {
|
||||
entries.push((ip, 3600)); // default duration
|
||||
}
|
||||
}
|
||||
assert_eq!(entries.len(), 4);
|
||||
assert_eq!(entries[0], (167772161, 3600)); // legacy → default
|
||||
assert_eq!(entries[1], (167772162, 3600)); // enriched
|
||||
assert_eq!(entries[3], (167772164, 14400)); // enriched high severity
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn malformed_json_line_skipped() {
|
||||
let content = r#"{"ip":123,"severity":5
|
||||
{"ip":167772162,"severity":5,"confirmations":3,"duration_secs":3600}
|
||||
not_a_number
|
||||
"#;
|
||||
|
||||
let mut valid = 0u32;
|
||||
let mut invalid = 0u32;
|
||||
for line in content.lines() {
|
||||
let trimmed = line.trim();
|
||||
if trimmed.is_empty() {
|
||||
continue;
|
||||
}
|
||||
if trimmed.starts_with('{') {
|
||||
if serde_json::from_str::<serde_json::Value>(trimmed).is_ok() {
|
||||
valid += 1;
|
||||
} else {
|
||||
invalid += 1;
|
||||
}
|
||||
} else if trimmed.parse::<u32>().is_ok() {
|
||||
valid += 1;
|
||||
} else {
|
||||
invalid += 1;
|
||||
}
|
||||
}
|
||||
assert_eq!(valid, 1);
|
||||
assert_eq!(invalid, 2);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue