use crate::core::ForgeGuardError;
pub struct FuzzingConfig {
pub runs: u32,
pub seed: Option<u64>,
pub test_filter: Option<String>,
pub contract_filter: Option<String>,
pub fail_on_revert: bool,
}
impl Default for FuzzingConfig {
fn default() -> Self {
Self {
runs: 10_000,
seed: None,
test_filter: None,
contract_filter: None,
fail_on_revert: false,
}
}
}
pub struct FuzzingAdapter;
impl FuzzingAdapter {
pub fn run_forge_fuzz(config: &FuzzingConfig) -> Result<FuzzingReport, ForgeGuardError> {
let mut cmd = std::process::Command::new("forge");
cmd.arg("test");
cmd.arg("--fuzz-runs").arg(config.runs.to_string());
if let Some(seed) = config.seed {
cmd.arg("--fuzz-seed").arg(seed.to_string());
}
if let Some(test) = &config.test_filter {
cmd.arg("--match-test").arg(test);
}
if let Some(contract) = &config.contract_filter {
cmd.arg("--match-contract").arg(contract);
}
if config.fail_on_revert {
cmd.arg("--fail-on-revert");
}
let start = std::time::Instant::now();
let output = cmd
.output()
.map_err(|e| ForgeGuardError::Command(format!("Failed to run fuzz: {}", e)))?;
let duration = start.elapsed();
Ok(FuzzingReport {
passed: output.status.success(),
runs: config.runs,
duration_secs: duration.as_secs_f64(),
output: String::from_utf8_lossy(&output.stdout).to_string(),
errors: if output.status.success() {
String::new()
} else {
String::from_utf8_lossy(&output.stderr).to_string()
},
})
}
}
#[derive(Debug, Clone)]
pub struct FuzzingReport {
pub passed: bool,
pub runs: u32,
pub duration_secs: f64,
pub output: String,
pub errors: String,
}