pub mod attacks;
pub mod corpus;
pub mod differential;
pub mod mutators;
pub mod report;
pub mod subprocess;
pub mod suite;
pub use report::{AttackResult, AttackStatus, SimReport};
pub use suite::{run_suite, tier_default_limits, SuiteConfig, SuiteTier, TimeBudget};
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
const QUICK_REFUSALS: &[QuickRefusal] = &[
QuickRefusal::class("integrity.bitflip", "Integrity"),
QuickRefusal::code_and_message(
"integrity.bitflip_crc",
"Integrity",
"IntegrityGzip",
"Gzip trailer",
),
QuickRefusal::code("integrity.truncate", "Integrity", "IntegrityIo"),
QuickRefusal::code(
"integrity.inject_file",
"Contract",
"ContractUnexpectedFile",
),
QuickRefusal::code("security.zip_bomb", "Limits", "LimitDecodeBytes"),
QuickRefusal::code(
"integrity.tar_duplicate",
"Contract",
"ContractDuplicateFile",
),
QuickRefusal::code_and_message(
"integrity.ndjson_bom",
"Contract",
"ContractInvalidJson",
"BOM not allowed",
),
QuickRefusal::passed("integrity.ndjson_crlf"),
QuickRefusal::code("integrity.limit_bundle_bytes", "Limits", "LimitBundleBytes"),
QuickRefusal::passed("differential.invariants"),
];
struct QuickRefusal {
name: &'static str,
status: AttackStatus,
class: Option<&'static str>,
code: Option<&'static str>,
message_contains: Option<&'static str>,
}
impl QuickRefusal {
const fn class(name: &'static str, class: &'static str) -> Self {
Self {
name,
status: AttackStatus::Blocked,
class: Some(class),
code: None,
message_contains: None,
}
}
const fn code(name: &'static str, class: &'static str, code: &'static str) -> Self {
Self {
name,
status: AttackStatus::Blocked,
class: Some(class),
code: Some(code),
message_contains: None,
}
}
const fn code_and_message(
name: &'static str,
class: &'static str,
code: &'static str,
message_contains: &'static str,
) -> Self {
Self {
name,
status: AttackStatus::Blocked,
class: Some(class),
code: Some(code),
message_contains: Some(message_contains),
}
}
const fn passed(name: &'static str) -> Self {
Self {
name,
status: AttackStatus::Passed,
class: None,
code: None,
message_contains: None,
}
}
}
#[test]
fn test_quick_suite() {
let cfg = SuiteConfig {
tier: SuiteTier::Quick,
target_bundle: PathBuf::from("placeholder"),
seed: 42,
verify_limits: None,
time_budget_secs: 60,
};
let report = run_suite(cfg).expect("Suite failed to run");
if report.summary.bypassed > 0 {
println!("{}", serde_json::to_string_pretty(&report).unwrap());
}
assert_eq!(
report.summary.bypassed, 0,
"SECURITY: {} attacks bypassed verification",
report.summary.bypassed
);
assert!(
report.summary.blocked >= 1,
"SANITY: no attacks were blocked — suite may not have run"
);
let differential_ran = report
.results
.iter()
.any(|r| r.name == "differential.invariants");
assert!(
report.summary.passed >= 1 || differential_ran,
"SANITY: no checks passed and differential did not run — suite may not have run"
);
for r in &report.results {
let is_chaos_io = r.name.starts_with("chaos.io_fault.");
match r.status {
AttackStatus::Blocked | AttackStatus::Passed => {} AttackStatus::Error if is_chaos_io => {} _ => panic!(
"Unexpected status {:?} for '{}': {:?}",
r.status, r.name, r.message
),
}
}
assert_named_quick_refusals(&report);
}
fn assert_named_quick_refusals(report: &SimReport) {
for expected in QUICK_REFUSALS {
let r = report
.results
.iter()
.find(|r| r.name == expected.name)
.unwrap_or_else(|| panic!("Quick suite is missing '{}'", expected.name));
assert_eq!(
r.status, expected.status,
"{}: status {:?} (message {:?})",
expected.name, r.status, r.message
);
if let Some(class) = expected.class {
assert_eq!(
r.error_class.as_deref(),
Some(class),
"{}: refusing class",
expected.name
);
}
if let Some(code) = expected.code {
assert_eq!(
r.error_code.as_deref(),
Some(code),
"{}: refusing code (message {:?})",
expected.name,
r.message
);
}
if let Some(part) = expected.message_contains {
let message = r.message.as_deref().unwrap_or("");
assert!(
message.contains(part),
"{}: message {message:?} should name {part:?}",
expected.name
);
}
}
for r in &report.results {
assert!(
QUICK_REFUSALS
.iter()
.any(|expected| expected.name == r.name),
"Quick suite result '{}' has no pinned refusal",
r.name
);
}
}
}