use crate::antithesis::TestLocation;
use crate::test_case::TestCase;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum HealthCheck {
FilterTooMuch,
TooSlow,
TestCasesTooLarge,
LargeInitialTestCase,
}
impl HealthCheck {
pub const fn all() -> [HealthCheck; 4] {
[
HealthCheck::FilterTooMuch,
HealthCheck::TooSlow,
HealthCheck::TestCasesTooLarge,
HealthCheck::LargeInitialTestCase,
]
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Phase {
Explicit,
Reuse,
Generate,
Target,
Shrink,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Mode {
TestRun,
SingleTestCase,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Verbosity {
Quiet,
Normal,
Verbose,
Debug,
}
#[derive(Debug, Clone)]
pub struct Settings {
pub(crate) mode: Mode,
pub(crate) test_cases: u64,
pub(crate) verbosity: Verbosity,
pub(crate) seed: Option<u64>,
pub(crate) derandomize: bool,
pub(crate) database: Database,
pub(crate) suppress_health_check: Vec<HealthCheck>,
pub(crate) phases: Vec<Phase>,
pub(crate) report_multiple_failures: bool,
}
impl Settings {
pub fn new() -> Self {
let in_ci = is_in_ci();
Self {
mode: Mode::TestRun,
test_cases: 100,
verbosity: Verbosity::Normal,
seed: None,
derandomize: in_ci,
database: if in_ci {
Database::Disabled
} else {
Database::Unset },
suppress_health_check: Vec::new(),
phases: vec![
Phase::Explicit,
Phase::Reuse,
Phase::Generate,
Phase::Target,
Phase::Shrink,
],
report_multiple_failures: true,
}
}
pub fn mode(mut self, mode: Mode) -> Self {
self.mode = mode;
self
}
pub fn test_cases(mut self, n: u64) -> Self {
self.test_cases = n;
self
}
pub fn verbosity(mut self, verbosity: Verbosity) -> Self {
self.verbosity = verbosity;
self
}
pub fn seed(mut self, seed: Option<u64>) -> Self {
self.seed = seed;
self
}
pub fn derandomize(mut self, derandomize: bool) -> Self {
self.derandomize = derandomize;
self
}
pub fn database(mut self, database: Option<String>) -> Self {
self.database = match database {
None => Database::Disabled,
Some(path) => Database::Path(path),
};
self
}
pub fn suppress_health_check(mut self, checks: impl IntoIterator<Item = HealthCheck>) -> Self {
self.suppress_health_check.extend(checks);
self
}
pub fn phases(mut self, phases: impl IntoIterator<Item = Phase>) -> Self {
self.phases = phases.into_iter().collect();
self
}
pub fn has_phase(&self, phase: Phase) -> bool {
self.phases.contains(&phase)
}
pub fn report_multiple_failures(mut self, report_multiple_failures: bool) -> Self {
self.report_multiple_failures = report_multiple_failures;
self
}
}
impl Default for Settings {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum Database {
Unset,
Disabled,
Path(String),
}
#[doc(hidden)]
pub fn hegel<F>(test_fn: F)
where
F: FnMut(TestCase),
{
Hegel::new(test_fn).run();
}
fn is_in_ci() -> bool {
const CI_VARS: &[(&str, Option<&str>)] = &[
("CI", None),
("TF_BUILD", Some("true")),
("BUILDKITE", Some("true")),
("CIRCLECI", Some("true")),
("CIRRUS_CI", Some("true")),
("CODEBUILD_BUILD_ID", None),
("GITHUB_ACTIONS", Some("true")),
("GITLAB_CI", None),
("HEROKU_TEST_RUN_ID", None),
("TEAMCITY_VERSION", None),
("bamboo.buildKey", None),
];
CI_VARS.iter().any(|(key, value)| match value {
None => std::env::var_os(key).is_some(),
Some(expected) => std::env::var(key).ok().as_deref() == Some(expected),
})
}
#[doc(hidden)]
pub struct Hegel<F> {
test_fn: F,
database_key: Option<String>,
test_location: Option<TestLocation>,
settings: Settings,
}
impl<F> Hegel<F>
where
F: FnMut(TestCase),
{
pub fn new(test_fn: F) -> Self {
Self {
test_fn,
database_key: None,
settings: Settings::new(),
test_location: None,
}
}
pub fn settings(mut self, settings: Settings) -> Self {
self.settings = settings;
self
}
#[doc(hidden)]
pub fn __database_key(mut self, key: String) -> Self {
self.database_key = Some(key);
self
}
#[doc(hidden)]
pub fn test_location(mut self, location: TestLocation) -> Self {
self.test_location = Some(location);
self
}
pub fn run(self) {
crate::server::runner::server_run(
self.test_fn,
&self.settings,
self.database_key.as_deref(),
self.test_location.as_ref(),
);
}
}
#[cfg(test)]
#[path = "../tests/embedded/runner_tests.rs"]
mod tests;