diff --git a/crates/libtest2/examples/simple.rs b/crates/libtest2/examples/simple.rs index 040bfce..1ec2b2b 100644 --- a/crates/libtest2/examples/simple.rs +++ b/crates/libtest2/examples/simple.rs @@ -2,7 +2,7 @@ use libtest2::RunError; use libtest2::RunResult; use libtest2::TestContext; -libtest2::libtest2_main!( +libtest2::main!( check_toph, check_katara, check_sokka, diff --git a/crates/libtest2/examples/tidy.rs b/crates/libtest2/examples/tidy.rs index 7c9b588..752c85d 100644 --- a/crates/libtest2/examples/tidy.rs +++ b/crates/libtest2/examples/tidy.rs @@ -1,6 +1,6 @@ +use libtest2::FnCase; use libtest2::RunError; use libtest2::RunResult; -use libtest2::Trial; fn main() -> std::io::Result<()> { let harness = ::libtest2_harness::Harness::new(); @@ -23,8 +23,8 @@ fn main() -> std::io::Result<()> { /// Creates one test for each `.rs` file in the current directory or /// sub-directories of the current directory. -fn collect_tests() -> std::io::Result> { - fn visit_dir(path: &std::path::Path, tests: &mut Vec) -> std::io::Result<()> { +fn collect_tests() -> std::io::Result> { + fn visit_dir(path: &std::path::Path, tests: &mut Vec) -> std::io::Result<()> { let current_dir = std::env::current_dir()?; for entry in std::fs::read_dir(path)? { let entry = entry?; @@ -44,7 +44,7 @@ fn collect_tests() -> std::io::Result> { .to_string_lossy() .into_owned(); - let test = Trial::test(name, move |_| check_file(&path)); + let test = FnCase::test(name, move |_| check_file(&path)); tests.push(test); } } else if file_type.is_dir() { diff --git a/crates/libtest2/src/case.rs b/crates/libtest2/src/case.rs new file mode 100644 index 0000000..914cc4e --- /dev/null +++ b/crates/libtest2/src/case.rs @@ -0,0 +1,76 @@ +use libtest2_harness::Case; +use libtest2_harness::Source; +use libtest2_harness::TestKind; + +use crate::RunResult; +use crate::TestContext; + +pub struct FnCase { + name: String, + #[allow(clippy::type_complexity)] + runner: Box RunResult + Send + Sync>, +} + +impl FnCase { + pub fn test( + name: impl Into, + runner: impl Fn(&TestContext) -> RunResult + Send + Sync + 'static, + ) -> Self { + Self { + name: name.into(), + runner: Box::new(runner), + } + } +} + +impl Case for FnCase { + fn name(&self) -> &str { + &self.name + } + fn kind(&self) -> TestKind { + Default::default() + } + fn source(&self) -> Option<&Source> { + None + } + fn exclusive(&self, _: &TestContext) -> bool { + false + } + + fn run(&self, context: &TestContext) -> RunResult { + (self.runner)(context) + } +} + +pub fn main(cases: impl IntoIterator) { + let harness = libtest2_harness::Harness::new(); + let harness = match harness.with_env() { + Ok(harness) => harness, + Err(err) => { + eprintln!("{err}"); + ::std::process::exit(1); + } + }; + let harness = match harness.parse() { + Ok(harness) => harness, + Err(err) => { + eprintln!("{err}"); + ::std::process::exit(1); + } + }; + let harness = match harness.discover(cases) { + Ok(harness) => harness, + Err(err) => { + eprintln!("{err}"); + ::std::process::exit(libtest2_harness::ERROR_EXIT_CODE) + } + }; + match harness.run() { + Ok(true) => ::std::process::exit(0), + Ok(false) => ::std::process::exit(libtest2_harness::ERROR_EXIT_CODE), + Err(err) => { + eprintln!("{err}"); + ::std::process::exit(libtest2_harness::ERROR_EXIT_CODE) + } + } +} diff --git a/crates/libtest2/src/lib.rs b/crates/libtest2/src/lib.rs index a3f834f..06254d3 100644 --- a/crates/libtest2/src/lib.rs +++ b/crates/libtest2/src/lib.rs @@ -12,18 +12,17 @@ //! harness = false //! ``` //! -//! And in `tests/mytest.rs` you would call [`libtest2_main`], passing it each of your tests: +//! And in `tests/mytest.rs` you would call [`main!`], passing it each of your tests: //! //! ```no_run //! # use libtest2::RunError; //! # use libtest2::RunResult; //! # use libtest2::TestContext; -//! # use libtest2::libtest2_main; //! fn check_toph(_context: &TestContext) -> RunResult { //! Ok(()) //! } //! -//! libtest2_main!(check_toph); +//! libtest2::main!(check_toph); //! ``` //! @@ -31,93 +30,20 @@ //#![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 libtest2_harness::ERROR_EXIT_CODE; - -use libtest2_harness::Case; -use libtest2_harness::Source; +mod case; +mod macros; -pub struct Trial { - name: String, - #[allow(clippy::type_complexity)] - runner: Box Result<(), RunError> + Send + Sync>, +#[doc(hidden)] +pub mod _private { + pub use crate::_main as main; } -impl Trial { - pub fn test( - name: impl Into, - runner: impl Fn(&TestContext) -> Result<(), RunError> + Send + Sync + 'static, - ) -> Self { - Self { - name: name.into(), - runner: Box::new(runner), - } - } -} - -impl Case for Trial { - fn name(&self) -> &str { - &self.name - } - fn kind(&self) -> TestKind { - Default::default() - } - fn source(&self) -> Option<&Source> { - None - } - fn exclusive(&self, _: &TestContext) -> bool { - false - } - - fn run(&self, context: &TestContext) -> Result<(), RunError> { - (self.runner)(context) - } -} - -/// Expands to the test harness -#[macro_export] -macro_rules! libtest2_main { - ( $( $test:path ),* $(,)*) => { - fn main() { - let harness = $crate::Harness::new(); - let harness = match harness.with_env() { - Ok(harness) => harness, - Err(err) => { - eprintln!("{err}"); - ::std::process::exit(1); - } - }; - let harness = match harness.parse() { - Ok(harness) => harness, - Err(err) => { - eprintln!("{err}"); - ::std::process::exit(1); - } - }; - let harness = match harness.discover([ - $($crate::Trial::test(::std::stringify!($test), $test)),* - ]) { - Ok(harness) => harness, - Err(err) => { - eprintln!("{err}"); - ::std::process::exit($crate::ERROR_EXIT_CODE) - } - }; - match harness.run() { - Ok(true) => ::std::process::exit(0), - Ok(false) => ::std::process::exit($crate::ERROR_EXIT_CODE), - Err(err) => { - eprintln!("{err}"); - ::std::process::exit($crate::ERROR_EXIT_CODE) - } - } - } - } -} +pub use _private::main; +pub use case::main; +pub use case::FnCase; +pub use libtest2_harness::RunError; +pub use libtest2_harness::RunResult; +pub use libtest2_harness::TestContext; #[doc = include_str!("../README.md")] #[cfg(doctest)] diff --git a/crates/libtest2/src/macros.rs b/crates/libtest2/src/macros.rs new file mode 100644 index 0000000..82e44ef --- /dev/null +++ b/crates/libtest2/src/macros.rs @@ -0,0 +1,11 @@ +/// Expands to the test harness +#[macro_export] +macro_rules! _main { + ( $( $test:path ),* $(,)*) => { + fn main() { + $crate::main([ + $($crate::FnCase::test(::std::stringify!($test), $test)),* + ]); + } + } +} diff --git a/crates/libtest2/tests/testsuite/all_passing.rs b/crates/libtest2/tests/testsuite/all_passing.rs index fab4541..7937300 100644 --- a/crates/libtest2/tests/testsuite/all_passing.rs +++ b/crates/libtest2/tests/testsuite/all_passing.rs @@ -7,7 +7,7 @@ fn test_cmd() -> snapbox::cmd::Command { let (bin, current_dir) = BIN.get_or_init(|| { let package_root = crate::util::new_test( r#" -libtest2::libtest2_main!(foo, bar, barro); +libtest2::main!(foo, bar, barro); fn foo(_context: &libtest2::TestContext) -> libtest2::RunResult { Ok(()) diff --git a/crates/libtest2/tests/testsuite/argfile.rs b/crates/libtest2/tests/testsuite/argfile.rs index ad2556b..da6b241 100644 --- a/crates/libtest2/tests/testsuite/argfile.rs +++ b/crates/libtest2/tests/testsuite/argfile.rs @@ -7,7 +7,7 @@ fn test_cmd() -> snapbox::cmd::Command { let (bin, current_dir) = BIN.get_or_init(|| { let package_root = crate::util::new_test( r#" -libtest2::libtest2_main!(one, two, three, one_two); +libtest2::main!(one, two, three, one_two); fn one(_context: &libtest2::TestContext) -> libtest2::RunResult { Ok(()) diff --git a/crates/libtest2/tests/testsuite/mixed_bag.rs b/crates/libtest2/tests/testsuite/mixed_bag.rs index a30cd53..876f920 100644 --- a/crates/libtest2/tests/testsuite/mixed_bag.rs +++ b/crates/libtest2/tests/testsuite/mixed_bag.rs @@ -7,7 +7,7 @@ fn test_cmd() -> snapbox::cmd::Command { let (bin, current_dir) = BIN.get_or_init(|| { let package_root = crate::util::new_test( r#" -libtest2::libtest2_main!(cat, dog, fox, bunny, frog, owl, fly, bear); +libtest2::main!(cat, dog, fox, bunny, frog, owl, fly, bear); fn cat(_context: &libtest2::TestContext) -> libtest2::RunResult { Ok(()) diff --git a/crates/libtest2/tests/testsuite/panic.rs b/crates/libtest2/tests/testsuite/panic.rs index b99d661..6f6fbe1 100644 --- a/crates/libtest2/tests/testsuite/panic.rs +++ b/crates/libtest2/tests/testsuite/panic.rs @@ -7,7 +7,7 @@ fn test_cmd() -> snapbox::cmd::Command { let (bin, current_dir) = BIN.get_or_init(|| { let package_root = crate::util::new_test( r#" -libtest2::libtest2_main!(passes, panics); +libtest2::main!(passes, panics); fn passes(_context: &libtest2::TestContext) -> libtest2::RunResult { Ok(())