shadow_integration_tests/
lib.rs1pub mod crypto_messaging;
12pub mod stego_pipeline;
13pub mod dht_storage;
14pub mod e2e_flow;
15pub mod dpi_evasion;
16
17pub fn run_all_integration_tests() -> IntegrationReport {
19 let mut report = IntegrationReport::new();
20
21 report.run("crypto_messaging_e2e", || crypto_messaging::test_full_messaging_pipeline());
22 report.run("stego_transport_roundtrip", || stego_pipeline::test_stego_transport_roundtrip());
23 report.run("stego_multi_packet", || stego_pipeline::test_multi_packet_pipeline());
24 report.run("dht_storage_integration", || dht_storage::test_dht_with_content_store());
25 report.run("dht_replication_recovery", || dht_storage::test_replication_peer_loss());
26 report.run("e2e_message_flow", || e2e_flow::test_full_e2e_flow());
27 report.run("e2e_group_messaging", || e2e_flow::test_group_messaging_e2e());
28 report.run("e2e_offline_delivery", || e2e_flow::test_offline_queue_delivery());
29 report.run("dpi_entropy_analysis", || dpi_evasion::test_stego_entropy());
30 report.run("dpi_cover_traffic_analysis", || dpi_evasion::test_cover_traffic_indistinguishability());
31 report.run("dpi_packet_size_distribution", || dpi_evasion::test_packet_size_distribution());
32
33 report
34}
35
36#[derive(Debug)]
38pub struct IntegrationReport {
39 pub results: Vec<IntegrationTestResult>,
40}
41
42#[derive(Debug, Clone)]
44pub struct IntegrationTestResult {
45 pub name: String,
46 pub passed: bool,
47 pub error: Option<String>,
48}
49
50impl IntegrationReport {
51 pub fn new() -> Self {
52 Self {
53 results: Vec::new(),
54 }
55 }
56
57 pub fn run<F: FnOnce() -> Result<(), String>>(&mut self, name: &str, test: F) {
58 match test() {
59 Ok(()) => {
60 self.results.push(IntegrationTestResult {
61 name: name.to_string(),
62 passed: true,
63 error: None,
64 });
65 }
66 Err(e) => {
67 self.results.push(IntegrationTestResult {
68 name: name.to_string(),
69 passed: false,
70 error: Some(e),
71 });
72 }
73 }
74 }
75
76 pub fn all_passed(&self) -> bool {
77 self.results.iter().all(|r| r.passed)
78 }
79
80 pub fn passed_count(&self) -> usize {
81 self.results.iter().filter(|r| r.passed).count()
82 }
83
84 pub fn total_count(&self) -> usize {
85 self.results.len()
86 }
87
88 pub fn summary(&self) -> String {
89 let mut lines = vec![format!(
90 "Integration Tests: {}/{} passed",
91 self.passed_count(),
92 self.total_count()
93 )];
94 for r in &self.results {
95 let status = if r.passed { "pass" } else { "FAIL" };
96 let detail = r.error.as_deref().unwrap_or("OK");
97 lines.push(format!(" {} {} — {}", status, r.name, detail));
98 }
99 lines.join("\n")
100 }
101}
102
103impl Default for IntegrationReport {
104 fn default() -> Self {
105 Self::new()
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn test_all_integrations() {
115 let report = run_all_integration_tests();
116 println!("{}", report.summary());
117 assert!(
118 report.all_passed(),
119 "Some integration tests failed:\n{}",
120 report.summary()
121 );
122 }
123}