use anyhow::Result;
use assay_evidence::bundle::writer::{ErrorClass, ErrorCode};
use serde::Serialize;
#[derive(Debug, Serialize, Clone)]
pub struct SimReport {
pub suite: String,
pub seed: u64,
pub summary: SimSummary,
pub results: Vec<AttackResult>,
}
#[derive(Debug, Serialize, Clone, Default)]
pub struct SimSummary {
pub total: usize,
pub passed: usize, pub blocked: usize, pub bypassed: usize, pub failed: usize, pub errors: usize,
}
#[derive(Debug, Serialize, Clone)]
pub struct AttackResult {
pub name: String,
pub status: AttackStatus,
pub error_class: Option<String>,
pub error_code: Option<String>,
pub message: Option<String>,
pub duration_ms: u64, }
#[derive(Debug, Serialize, Clone, PartialEq, Eq)]
pub enum AttackStatus {
Passed, Failed, Blocked, Bypassed, Error, }
impl SimReport {
pub fn new(suite: &str, seed: u64) -> Self {
Self {
suite: suite.to_string(),
seed,
summary: SimSummary::default(),
results: Vec::new(),
}
}
pub fn add_attack(
&mut self,
name: &str,
result: Result<(ErrorClass, ErrorCode), anyhow::Error>,
duration_ms: u64,
) {
self.summary.total += 1;
let res = match result {
Ok((class, code)) => {
self.summary.blocked += 1;
AttackResult {
name: name.to_string(),
status: AttackStatus::Blocked,
error_class: Some(format!("{:?}", class)),
error_code: Some(format!("{:?}", code)),
message: None,
duration_ms,
}
}
Err(e) => {
self.summary.bypassed += 1;
AttackResult {
name: name.to_string(),
status: AttackStatus::Bypassed,
error_class: None,
error_code: None,
message: Some(e.to_string()),
duration_ms,
}
}
};
self.results.push(res);
}
pub fn add_result(&mut self, result: AttackResult) {
self.summary.total += 1;
match result.status {
AttackStatus::Passed => self.summary.passed += 1,
AttackStatus::Failed => self.summary.failed += 1,
AttackStatus::Blocked => self.summary.blocked += 1,
AttackStatus::Bypassed => self.summary.bypassed += 1,
AttackStatus::Error => self.summary.errors += 1,
}
self.results.push(result);
}
pub fn add_check(&mut self, name: &str, result: Result<()>, duration_ms: u64) {
self.summary.total += 1;
let res = match result {
Ok(_) => {
self.summary.passed += 1;
AttackResult {
name: name.to_string(),
status: AttackStatus::Passed,
error_class: None,
error_code: None,
message: None,
duration_ms,
}
}
Err(e) => {
self.summary.failed += 1;
AttackResult {
name: name.to_string(),
status: AttackStatus::Failed,
error_class: None,
error_code: None,
message: Some(e.to_string()),
duration_ms,
}
}
};
self.results.push(res);
}
}