Skip to content

Commit 6f5764f

Browse files
h4x0rclaude
andcommitted
test(ese-carver,srum-analysis): real-fixture integration for carver and before/after delta
ese-carver: detect_fragments_db(32) returns 0 on chainsaw, rathbunvm_win10, aptvm_clean — confirms no false positives at synthetic record size against real ESE page layouts. srum-analysis: aptvm_server2022_clean vs _1daylater delta shows new processes appear after 1 day of activity (compare_databases surfaces them in new_processes). 1day timeline has more entries than clean. chainsaw and aptvm_clean build_timeline smoke tests confirm no panics. 410 tests pass workspace-wide. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent eb753be commit 6f5764f

2 files changed

Lines changed: 136 additions & 0 deletions

File tree

crates/ese-carver/tests/fragment_tests.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,53 @@ fn detect_fragments_db_finds_split_via_ese_database() {
7171
assert_eq!(pairs[0].suffix_len, 8);
7272
}
7373

74+
// ── detect_fragments_db: real fixture smoke tests ────────────────────────────
75+
76+
fn real_fixture(path: &str) -> Option<ese_core::EseDatabase> {
77+
let p = std::path::Path::new(path);
78+
if !p.exists() { return None; }
79+
Some(ese_core::EseDatabase::open(p).expect("open real SRUDB"))
80+
}
81+
82+
const CHAINSAW: &str = concat!(
83+
env!("CARGO_MANIFEST_DIR"),
84+
"/../../tests/data/srudb/chainsaw_SRUDB.dat"
85+
);
86+
const RATHBUNVM_WIN10: &str = concat!(
87+
env!("CARGO_MANIFEST_DIR"),
88+
"/../../tests/data/srudb/museum_rathbunvm_win10_SRUDB.dat"
89+
);
90+
const APTVM_CLEAN: &str = concat!(
91+
env!("CARGO_MANIFEST_DIR"),
92+
"/../../tests/data/srudb/museum_aptvm_server2022_clean_SRUDB.dat"
93+
);
94+
95+
/// Real ESE records are larger than 32 bytes; detect_fragments_db(32) must
96+
/// return 0 — confirming no false positives at the synthetic fixture size.
97+
#[test]
98+
fn chainsaw_has_no_fragments_at_size_32() {
99+
let Some(db) = real_fixture(CHAINSAW) else { return };
100+
let pairs = ese_carver::detect_fragments_db(&db, 32);
101+
assert_eq!(pairs.len(), 0,
102+
"chainsaw: real ESE records do not split at exactly 32 bytes");
103+
}
104+
105+
#[test]
106+
fn rathbunvm_win10_has_no_fragments_at_size_32() {
107+
let Some(db) = real_fixture(RATHBUNVM_WIN10) else { return };
108+
let pairs = ese_carver::detect_fragments_db(&db, 32);
109+
assert_eq!(pairs.len(), 0,
110+
"rathbunvm_win10: real ESE records do not split at exactly 32 bytes");
111+
}
112+
113+
#[test]
114+
fn aptvm_clean_has_no_fragments_at_size_32() {
115+
let Some(db) = real_fixture(APTVM_CLEAN) else { return };
116+
let pairs = ese_carver::detect_fragments_db(&db, 32);
117+
assert_eq!(pairs.len(), 0,
118+
"aptvm_clean: fresh Server 2022 must not produce carver false positives");
119+
}
120+
74121
// ── reconstruct_fragment ─────────────────────────────────────────────────────
75122

76123
#[test]
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//! Integration tests for srum-analysis against real SRUDB.dat fixtures.
2+
3+
use std::path::Path;
4+
use srum_analysis::{
5+
analysis::{build_stats, compare_databases},
6+
pipeline::build_timeline,
7+
};
8+
9+
const APTVM_CLEAN: &str = concat!(
10+
env!("CARGO_MANIFEST_DIR"),
11+
"/../../tests/data/srudb/museum_aptvm_server2022_clean_SRUDB.dat"
12+
);
13+
const APTVM_1DAY: &str = concat!(
14+
env!("CARGO_MANIFEST_DIR"),
15+
"/../../tests/data/srudb/museum_aptvm_server2022_1daylater_SRUDB.dat"
16+
);
17+
const CHAINSAW: &str = concat!(
18+
env!("CARGO_MANIFEST_DIR"),
19+
"/../../tests/data/srudb/chainsaw_SRUDB.dat"
20+
);
21+
22+
fn fixture_exists(path: &str) -> bool {
23+
Path::new(path).exists()
24+
}
25+
26+
// ── before/after delta: aptvm_clean vs aptvm_1daylater ───────────────────────
27+
28+
/// After one day of Server 2022 activity, new processes appear in SRUM.
29+
/// compare_databases must surface them in `new_processes`.
30+
#[test]
31+
fn aptvm_1day_introduces_new_processes_relative_to_clean() {
32+
if !fixture_exists(APTVM_CLEAN) || !fixture_exists(APTVM_1DAY) { return; }
33+
34+
let clean_timeline = build_timeline(Path::new(APTVM_CLEAN), None);
35+
let oneday_timeline = build_timeline(Path::new(APTVM_1DAY), None);
36+
37+
let clean_stats = build_stats(clean_timeline);
38+
let oneday_stats = build_stats(oneday_timeline);
39+
40+
let diff = compare_databases(clean_stats, oneday_stats);
41+
42+
let new_procs = diff["new_processes"]
43+
.as_array()
44+
.expect("diff must have new_processes array");
45+
46+
assert!(
47+
!new_procs.is_empty(),
48+
"aptvm_1day must have new processes relative to clean install (got 0)"
49+
);
50+
}
51+
52+
/// The clean install has fewer total SRUM records than the 1-day-later snapshot.
53+
#[test]
54+
fn aptvm_1day_has_more_timeline_entries_than_clean() {
55+
if !fixture_exists(APTVM_CLEAN) || !fixture_exists(APTVM_1DAY) { return; }
56+
57+
let clean_count = build_timeline(Path::new(APTVM_CLEAN), None).len();
58+
let oneday_count = build_timeline(Path::new(APTVM_1DAY), None).len();
59+
60+
assert!(
61+
oneday_count > clean_count,
62+
"aptvm_1day must have more SRUM timeline entries than clean install \
63+
(clean={clean_count}, 1day={oneday_count})"
64+
);
65+
}
66+
67+
// ── pipeline smoke tests: build_timeline does not panic on any fixture ────────
68+
69+
#[test]
70+
fn chainsaw_build_timeline_returns_non_empty_results() {
71+
if !fixture_exists(CHAINSAW) { return; }
72+
let timeline = build_timeline(Path::new(CHAINSAW), None);
73+
assert!(
74+
!timeline.is_empty(),
75+
"chainsaw build_timeline must return records"
76+
);
77+
}
78+
79+
#[test]
80+
fn aptvm_clean_build_timeline_runs_without_panic() {
81+
if !fixture_exists(APTVM_CLEAN) { return; }
82+
// Fresh Server 2022: no app activity, no push/network/energy records.
83+
// build_timeline must complete without panicking and may return 0 entries.
84+
let timeline = build_timeline(Path::new(APTVM_CLEAN), None);
85+
// IdMap is a lookup table, not included in the activity timeline.
86+
// Verify the count is 0 (all tables absent for a truly fresh install).
87+
assert_eq!(timeline.len(), 0,
88+
"aptvm_clean fresh install must have no activity timeline entries");
89+
}

0 commit comments

Comments
 (0)