use std::collections::HashSet;
use cribler_core::{ParanoidConfig, ParanoidError, ParanoidResult, run_paranoid};
struct Case<'a> {
name: String,
trial: Box<dyn FnMut(usize) -> f64 + 'a>,
}
#[derive(Default)]
pub struct ParanoidSuite<'a> {
config: ParanoidConfig,
cases: Vec<Case<'a>>,
}
impl<'a> ParanoidSuite<'a> {
pub fn new() -> Self {
Self::default()
}
pub fn with_config(config: ParanoidConfig) -> Result<Self, ParanoidError> {
config.validate()?;
Ok(Self {
config,
cases: Vec::new(),
})
}
pub fn config(&self) -> ParanoidConfig {
self.config
}
pub fn set_config(&mut self, config: ParanoidConfig) -> Result<(), ParanoidError> {
config.validate()?;
self.config = config;
Ok(())
}
pub fn len(&self) -> usize {
self.cases.len()
}
pub fn is_empty(&self) -> bool {
self.cases.is_empty()
}
pub fn clear(&mut self) {
self.cases.clear();
}
pub fn add_trial<F>(
&mut self,
name: impl Into<String>,
trial: F,
) -> Result<&mut Self, ParanoidError>
where
F: FnMut(usize) -> f64 + 'a,
{
let name = name.into();
if name.trim().is_empty() {
return Err(ParanoidError::EmptyCaseName);
}
self.cases.push(Case {
name,
trial: Box::new(trial),
});
Ok(self)
}
pub fn run(&mut self) -> Result<Vec<ParanoidResult>, ParanoidError> {
let mut seen = HashSet::with_capacity(self.cases.len());
let mut out = Vec::with_capacity(self.cases.len());
for case in &mut self.cases {
if !seen.insert(case.name.clone()) {
return Err(ParanoidError::DuplicateCaseName {
name: case.name.clone(),
});
}
let result = run_paranoid(case.name.clone(), self.config, case.trial.as_mut())?;
out.push(result);
}
Ok(out)
}
}