Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

90 changes: 46 additions & 44 deletions crates/libtest2-harness/src/harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,67 +19,69 @@ impl Harness {
Self { raw, cases: vec![] }
}

pub fn case(mut self, case: impl Case + 'static) -> Self {
pub fn case(&mut self, case: impl Case + 'static) {
self.cases.push(Box::new(case));
self
}

pub fn cases(mut self, cases: impl IntoIterator<Item = impl Case + 'static>) -> Self {
pub fn cases(&mut self, cases: impl IntoIterator<Item = impl Case + 'static>) {
for case in cases {
self.cases.push(Box::new(case));
}
self
}

pub fn main(mut self) -> ! {
let start = std::time::Instant::now();
pub fn main(self) -> ! {
main(self.raw, self.cases)
}
}

let raw = match self.raw {
Ok(raw) => raw,
Err(err) => {
eprintln!("{err}");
std::process::exit(1)
}
};
let mut parser = cli::Parser::new(&raw);
let opts = parse(&mut parser).unwrap_or_else(|err| {
eprintln!("{err}");
std::process::exit(1)
});
const ERROR_EXIT_CODE: i32 = 101;

#[cfg(feature = "color")]
match opts.color {
libtest_lexarg::ColorConfig::AutoColor => anstream::ColorChoice::Auto,
libtest_lexarg::ColorConfig::AlwaysColor => anstream::ColorChoice::Always,
libtest_lexarg::ColorConfig::NeverColor => anstream::ColorChoice::Never,
}
.write_global();
fn main(raw: std::io::Result<Vec<std::ffi::OsString>>, mut cases: Vec<Box<dyn Case>>) -> ! {
let start = std::time::Instant::now();

let mut notifier = notifier(&opts).unwrap_or_else(|err| {
eprintln!("{err}");
std::process::exit(1)
});
discover(&start, &opts, &mut self.cases, notifier.as_mut()).unwrap_or_else(|err| {
let raw = match raw {
Ok(raw) => raw,
Err(err) => {
eprintln!("{err}");
std::process::exit(1)
});

if !opts.list {
match run(&start, &opts, self.cases, notifier.as_mut()) {
Ok(true) => {}
Ok(false) => std::process::exit(ERROR_EXIT_CODE),
Err(e) => {
eprintln!("error: io error when listing tests: {e:?}");
std::process::exit(ERROR_EXIT_CODE)
}
}
}
};
let mut parser = cli::Parser::new(&raw);
let opts = parse(&mut parser).unwrap_or_else(|err| {
eprintln!("{err}");
std::process::exit(1)
});

std::process::exit(0)
#[cfg(feature = "color")]
match opts.color {
libtest_lexarg::ColorConfig::AutoColor => anstream::ColorChoice::Auto,
libtest_lexarg::ColorConfig::AlwaysColor => anstream::ColorChoice::Always,
libtest_lexarg::ColorConfig::NeverColor => anstream::ColorChoice::Never,
}
}
.write_global();

const ERROR_EXIT_CODE: i32 = 101;
let mut notifier = notifier(&opts).unwrap_or_else(|err| {
eprintln!("{err}");
std::process::exit(1)
});
discover(&start, &opts, &mut cases, notifier.as_mut()).unwrap_or_else(|err| {
eprintln!("{err}");
std::process::exit(1)
});

if !opts.list {
match run(&start, &opts, cases, notifier.as_mut()) {
Ok(true) => {}
Ok(false) => std::process::exit(ERROR_EXIT_CODE),
Err(e) => {
eprintln!("error: io error when listing tests: {e:?}");
std::process::exit(ERROR_EXIT_CODE)
}
}
}

std::process::exit(0)
}

fn parse<'p>(parser: &mut cli::Parser<'p>) -> Result<libtest_lexarg::TestOpts, cli::LexError<'p>> {
let mut test_opts = libtest_lexarg::TestOptsBuilder::new();
Expand Down
1 change: 1 addition & 0 deletions crates/libtest2-mimic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ json = ["libtest2-harness/json"]
threads = ["libtest2-harness/threads"]

[dependencies]
libtest-json = { version = "0.0.1", path = "../libtest-json" }
libtest2-harness = { version = "0.0.1", path = "../libtest2-harness" }

[dev-dependencies]
Expand Down
10 changes: 5 additions & 5 deletions crates/libtest2-mimic/examples/mimic-simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,21 @@ fn main() {

// Tests

fn check_toph(_context: &TestContext) -> RunResult {
fn check_toph(_context: TestContext<'_>) -> RunResult {
Ok(())
}
fn check_katara(_context: &TestContext) -> RunResult {
fn check_katara(_context: TestContext<'_>) -> RunResult {
Ok(())
}
fn check_sokka(_context: &TestContext) -> RunResult {
fn check_sokka(_context: TestContext<'_>) -> RunResult {
Err(RunError::fail("Sokka tripped and fell :("))
}
fn long_computation(context: &TestContext) -> RunResult {
fn long_computation(context: TestContext<'_>) -> RunResult {
context.ignore_for("slow")?;

std::thread::sleep(std::time::Duration::from_secs(1));
Ok(())
}
fn compile_fail_dummy(_context: &TestContext) -> RunResult {
fn compile_fail_dummy(_context: TestContext<'_>) -> RunResult {
Ok(())
}
107 changes: 91 additions & 16 deletions crates/libtest2-mimic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,51 @@
#![warn(clippy::print_stderr)]
#![warn(clippy::print_stdout)]

pub use libtest2_harness::Harness;
pub use libtest2_harness::RunError;
pub use libtest2_harness::RunResult;
pub use libtest2_harness::TestContext;
pub use libtest2_harness::TestKind;
pub use libtest_json::RunMode;

use libtest2_harness::Case;
use libtest2_harness::Source;
pub struct Harness {
harness: libtest2_harness::Harness,
}

impl Harness {
pub fn with_args(args: impl IntoIterator<Item = impl Into<std::ffi::OsString>>) -> Self {
Self {
harness: libtest2_harness::Harness::with_args(args),
}
}

pub fn with_env() -> Self {
Self {
harness: libtest2_harness::Harness::with_env(),
}
}

pub fn case(mut self, case: Trial) -> Self {
self.harness.case(TrialCase { inner: case });
self
}

pub fn cases(mut self, cases: impl IntoIterator<Item = Trial>) -> Self {
self.harness
.cases(cases.into_iter().map(|c| TrialCase { inner: c }));
self
}

pub fn main(self) -> ! {
self.harness.main()
}
}

pub struct Trial {
name: String,
#[allow(clippy::type_complexity)]
runner: Box<dyn Fn(&TestContext) -> Result<(), RunError> + Send + Sync>,
runner: Box<dyn Fn(TestContext<'_>) -> Result<(), RunError> + Send + Sync>,
}

impl Trial {
pub fn test(
name: impl Into<String>,
runner: impl Fn(&TestContext) -> Result<(), RunError> + Send + Sync + 'static,
runner: impl Fn(TestContext<'_>) -> Result<(), RunError> + Send + Sync + 'static,
) -> Self {
Self {
name: name.into(),
Expand All @@ -51,22 +77,71 @@ impl Trial {
}
}

impl Case for Trial {
struct TrialCase {
inner: Trial,
}

impl libtest2_harness::Case for TrialCase {
fn name(&self) -> &str {
&self.name
&self.inner.name
}
fn kind(&self) -> TestKind {
fn kind(&self) -> libtest2_harness::TestKind {
Default::default()
}
fn source(&self) -> Option<&Source> {
fn source(&self) -> Option<&libtest2_harness::Source> {
None
}
fn exclusive(&self, _: &TestContext) -> bool {
fn exclusive(&self, _: &libtest2_harness::TestContext) -> bool {
false
}

fn run(&self, context: &TestContext) -> Result<(), RunError> {
(self.runner)(context)
fn run(
&self,
context: &libtest2_harness::TestContext,
) -> Result<(), libtest2_harness::RunError> {
(self.inner.runner)(TestContext { inner: context }).map_err(|e| e.inner)
}
}

pub type RunResult = Result<(), RunError>;

#[derive(Debug)]
pub struct RunError {
inner: libtest2_harness::RunError,
}

impl RunError {
pub fn with_cause(cause: impl std::error::Error + Send + Sync + 'static) -> Self {
Self {
inner: libtest2_harness::RunError::with_cause(cause),
}
}

pub fn fail(cause: impl std::fmt::Display) -> Self {
Self {
inner: libtest2_harness::RunError::fail(cause),
}
}
}

#[derive(Debug)]
pub struct TestContext<'t> {
inner: &'t libtest2_harness::TestContext,
}

impl<'t> TestContext<'t> {
pub fn ignore(&self) -> Result<(), RunError> {
self.inner.ignore().map_err(|e| RunError { inner: e })
}

pub fn ignore_for(&self, reason: impl std::fmt::Display) -> Result<(), RunError> {
self.inner
.ignore_for(reason)
.map_err(|e| RunError { inner: e })
}

pub fn current_mode(&self) -> RunMode {
self.inner.current_mode()
}
}

Expand Down
4 changes: 3 additions & 1 deletion crates/libtest2/examples/tidy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use libtest2::Trial;

fn main() -> std::io::Result<()> {
let tests = collect_tests()?;
libtest2::Harness::with_env().cases(tests).main()
let mut harness = libtest2::Harness::with_env();
harness.cases(tests);
harness.main()
}

/// Creates one test for each `.rs` file in the current directory or
Expand Down
6 changes: 3 additions & 3 deletions crates/libtest2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ impl Case for Trial {
macro_rules! libtest2_main {
( $( $test:path ),* $(,)*) => {
fn main() {
::libtest2::Harness::with_env()
$(.case(::libtest2::Trial::test(::std::stringify!($test), $test)))*
.main();
let mut harness = ::libtest2::Harness::with_env();
$(harness.case(::libtest2::Trial::test(::std::stringify!($test), $test));)*
harness.main();
}
}
}
Expand Down
Loading