use std::{
process::{ExitCode, Termination},
time::Duration,
};
use crate::{formatter::FormatError, outcome::TestOutcome};
pub type TestOutcomes<'t> = Vec<(&'t str, TestOutcome)>;
#[derive(Debug)]
#[non_exhaustive]
#[must_use = "ignoring this report may hide test failures or formatting errors"]
pub struct TestReport<'t, FmtError: 't> {
pub outcomes: TestOutcomes<'t>,
pub duration: Duration,
pub fmt_errors: Vec<(FormatError, FmtError)>,
}
impl<'t, FmtError: 't> TestReport<'t, FmtError> {
pub fn exit_code(&self) -> ExitCode {
let any_failed = self.outcomes.iter().any(|(_, outcome)| outcome.failed());
if any_failed {
return ExitCode::FAILURE;
}
match self.fmt_errors.is_empty() {
true => ExitCode::SUCCESS,
false => ExitCode::FAILURE,
}
}
}
impl<'t, FmtError: 't> Termination for TestReport<'t, FmtError> {
fn report(self) -> ExitCode {
self.exit_code()
}
}
pub type GroupedTestOutcomes<'t, GroupKey, GroupCtx> =
Vec<(GroupKey, Vec<(&'t str, TestOutcome)>, Option<GroupCtx>)>;
#[derive(Debug)]
#[non_exhaustive]
#[must_use = "ignoring this report may hide test failures or formatting errors"]
pub struct GroupedTestReport<'t, GroupKey, GroupCtx, FmtError: 't> {
pub outcomes: GroupedTestOutcomes<'t, GroupKey, GroupCtx>,
pub duration: Duration,
pub fmt_errors: Vec<(FormatError, FmtError)>,
}
impl<'t, GroupKey, GroupCtx, FmtError: 't> GroupedTestReport<'t, GroupKey, GroupCtx, FmtError> {
pub fn exit_code(&self) -> ExitCode {
let any_failed = self
.outcomes
.iter()
.any(|(_, outcomes, _)| outcomes.iter().any(|(_, outcome)| outcome.failed()));
if any_failed {
return ExitCode::FAILURE;
}
match self.fmt_errors.is_empty() {
true => ExitCode::SUCCESS,
false => ExitCode::FAILURE,
}
}
}
impl<'t, GroupKey, GroupCtx, FmtError: 't> Termination
for GroupedTestReport<'t, GroupKey, GroupCtx, FmtError>
{
fn report(self) -> ExitCode {
self.exit_code()
}
}
#[derive(Debug)]
#[non_exhaustive]
#[must_use = "ignoring this report may hide formatter errors"]
pub struct TestListReport<E>(
pub Vec<(FormatError, E)>,
);
impl<E> TestListReport<E> {
pub fn exit_code(&self) -> ExitCode {
match self.0.is_empty() {
true => ExitCode::SUCCESS,
false => ExitCode::FAILURE,
}
}
}
impl<E> Termination for TestListReport<E> {
fn report(self) -> ExitCode {
self.exit_code()
}
}