use std::panic::{catch_unwind, UnwindSafe};
use crate::hints::Hints;
use crate::runner;
use crate::runner::Error;
use crate::stats::Stats;
use crate::{Fate, Limit, Prng};
#[derive(Debug, Clone)]
pub struct Config {
pub limit: Limit,
pub hints_enabled: bool,
pub stats_enabled: bool,
}
#[derive(Debug)]
pub struct Report {
pub hints: Option<Hints>,
pub stats: Option<Stats>,
pub error: Option<Error>,
}
pub fn run<T>(mut prng: Prng, config: &Config, test: T) -> Report
where
T: FnOnce(Fate) + UnwindSafe,
{
let ((test_result, hints), stats) = {
let limit = config.limit;
runner::util::collect_stats(config.stats_enabled, || {
runner::util::collect_hints(config.hints_enabled, || {
catch_unwind(move || {
let fate = Fate::new(&mut prng, limit);
test(fate)
})
})
})
};
let error = test_result.err().map(Error);
Report {
hints,
stats,
error,
}
}
#[cfg(test)]
mod tests {
use crate::runner::once::{run, Config};
use crate::{Prng, Seed};
fn default_prng() -> Prng {
Prng::from_seed(Seed::from(42))
}
fn default_config() -> Config {
Config {
limit: 100.into(),
hints_enabled: true,
stats_enabled: false,
}
}
#[test]
fn has_error_if_test_fails() {
let config = default_config();
let report = run(default_prng(), &config, |_| panic!());
assert!(report.error.is_some());
}
#[test]
fn no_error_if_test_succeeds() {
let config = default_config();
let report = run(default_prng(), &config, |_| ());
assert!(report.error.is_none());
}
#[test]
fn no_hints_if_disabled_and_test_succeeds() {
let config = Config {
hints_enabled: false,
..default_config()
};
let report = run(default_prng(), &config, |_| ());
assert!(report.hints.is_none());
}
#[test]
fn no_hints_if_disabled_and_test_fails() {
let config = Config {
hints_enabled: false,
..default_config()
};
let report = run(default_prng(), &config, |_| panic!());
assert!(report.hints.is_none());
}
#[test]
fn has_hints_if_enabled_and_test_succeeds() {
let config = Config {
hints_enabled: true,
..default_config()
};
let report = run(default_prng(), &config, |_| ());
assert!(report.hints.is_some());
}
#[test]
fn has_hints_if_enabled_and_test_fails() {
let config = Config {
hints_enabled: true,
..default_config()
};
let report = run(default_prng(), &config, |_| panic!());
assert!(report.hints.is_some());
}
#[test]
fn no_stats_if_disabled_and_test_succeeds() {
let config = Config {
stats_enabled: false,
..default_config()
};
let report = run(default_prng(), &config, |_| ());
let stats = report.stats;
assert!(stats.is_none());
}
#[test]
fn no_stats_if_disabled_and_test_fails() {
let config = Config {
stats_enabled: false,
..default_config()
};
let report = run(default_prng(), &config, |_| panic!());
let stats = report.stats;
assert!(stats.is_none());
}
#[test]
fn has_stats_if_enabled_and_test_succeeds() {
let config = Config {
stats_enabled: true,
..default_config()
};
let report = run(default_prng(), &config, |_| ());
let stats = report.stats;
assert!(stats.is_some());
}
#[test]
fn has_stats_if_enabled_and_test_fails() {
let config = Config {
stats_enabled: true,
..default_config()
};
let report = run(default_prng(), &config, |_| panic!());
let stats = report.stats;
assert!(stats.is_some());
}
}