Skip to content
Open
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
38 changes: 38 additions & 0 deletions crates/libtest2-harness/src/case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,44 @@ pub trait Case: Send + Sync + 'static {
fn run(&self, state: &TestContext) -> Result<(), RunError>;
}

impl Case for Box<dyn Case> {
fn name(&self) -> &str {
self.as_ref().name()
}
fn kind(&self) -> TestKind {
self.as_ref().kind()
}
fn source(&self) -> Option<&Source> {
self.as_ref().source()
}
fn exclusive(&self, state: &TestContext) -> bool {
self.as_ref().exclusive(state)
}

fn run(&self, state: &TestContext) -> Result<(), RunError> {
self.as_ref().run(state)
}
}

impl Case for std::sync::Arc<dyn Case> {
fn name(&self) -> &str {
self.as_ref().name()
}
fn kind(&self) -> TestKind {
self.as_ref().kind()
}
fn source(&self) -> Option<&Source> {
self.as_ref().source()
}
fn exclusive(&self, state: &TestContext) -> bool {
self.as_ref().exclusive(state)
}

fn run(&self, state: &TestContext) -> Result<(), RunError> {
self.as_ref().run(state)
}
}

/// Type of the test according to the [rust book](https://doc.rust-lang.org/cargo/guide/tests.html)
/// conventions.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
Expand Down
11 changes: 7 additions & 4 deletions crates/libtest2/examples/tidy.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use std::borrow::Cow;

use libtest2::Case;
use libtest2::FnCase;
use libtest2::RunError;
use libtest2::RunResult;
Expand All @@ -23,8 +26,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<Vec<FnCase>> {
fn visit_dir(path: &std::path::Path, tests: &mut Vec<FnCase>) -> std::io::Result<()> {
fn collect_tests() -> std::io::Result<Vec<Box<dyn Case>>> {
fn visit_dir(path: &std::path::Path, tests: &mut Vec<Box<dyn Case>>) -> std::io::Result<()> {
let current_dir = std::env::current_dir()?;
for entry in std::fs::read_dir(path)? {
let entry = entry?;
Expand All @@ -44,8 +47,8 @@ fn collect_tests() -> std::io::Result<Vec<FnCase>> {
.to_string_lossy()
.into_owned();

let test = FnCase::test(name, move |_| check_file(&path));
tests.push(test);
let test = FnCase::test(Cow::Owned(name), move |_| check_file(&path));
tests.push(Box::new(test));
}
} else if file_type.is_dir() {
// Handle directories
Expand Down
27 changes: 13 additions & 14 deletions crates/libtest2/src/case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,24 @@ impl Case for DynCase {
}
}

pub struct FnCase {
name: String,
#[allow(clippy::type_complexity)]
runner: Box<dyn Fn(&TestContext) -> RunResult + Send + Sync>,
pub struct FnCase<R> {
name: std::borrow::Cow<'static, str>,
runner: R,
}

impl FnCase {
pub fn test(
name: impl Into<String>,
runner: impl Fn(&TestContext) -> RunResult + Send + Sync + 'static,
) -> Self {
Self {
name: name.into(),
runner: Box::new(runner),
}
impl<R> FnCase<R>
where
R: Fn(&TestContext) -> RunResult + Send + Sync + 'static,
{
pub const fn test(name: std::borrow::Cow<'static, str>, runner: R) -> Self {
Self { name, runner }
}
}

impl Case for FnCase {
impl<R> Case for FnCase<R>
where
R: Fn(&TestContext) -> RunResult + Send + Sync + 'static,
{
fn name(&self) -> &str {
&self.name
}
Expand Down
2 changes: 1 addition & 1 deletion crates/libtest2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ mod macros;
pub mod _private {
pub use distributed_list::push;
pub use distributed_list::DistributedList;
pub use libtest2_harness::Case;
pub use libtest2_harness::Source;
pub use libtest2_harness::TestKind;

Expand All @@ -67,6 +66,7 @@ pub mod _private {

pub use case::main;
pub use case::FnCase;
pub use libtest2_harness::Case;
pub use libtest2_harness::IntoRunResult;
pub use libtest2_harness::RunError;
pub use libtest2_harness::RunResult;
Expand Down
52 changes: 20 additions & 32 deletions crates/libtest2/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,39 +30,27 @@ macro_rules! _parse_ignore {
#[allow(clippy::crate_in_macro_def)] // accessing item defined by `_main_parse`
macro_rules! _test_parse {
(#[test] $(#[$($attr:tt)*])* fn $name:ident $($item:tt)*) => {
#[allow(non_camel_case_types)]
struct $name;

impl $crate::_private::Case for $name {
fn name(&self) -> &str {
$crate::_private::push!(crate::TESTS, _: $crate::_private::DynCase = $crate::_private::DynCase(&$name));

stringify!($name)
}
fn kind(&self) -> $crate::_private::TestKind {
Default::default()
}
fn source(&self) -> Option<&$crate::_private::Source> {
None
}
fn exclusive(&self, _: &$crate::TestContext) -> bool {
false
}

fn run(&self, context: &$crate::TestContext) -> $crate::RunResult {
fn run $($item)*

$(
match $crate::_private::parse_ignore!($($attr)*) {
::std::option::Option::None => context.ignore()?,
::std::option::Option::Some(reason) => context.ignore_for(reason)?,
const _: () = {
$crate::_private::push!(
crate::TESTS,
_: $crate::_private::DynCase = $crate::_private::DynCase(&$crate::FnCase::test(
::std::borrow::Cow::Borrowed(stringify!($name)),
|context| {
$(
match $crate::_private::parse_ignore!($($attr)*) {
::std::option::Option::None => context.ignore()?,
::std::option::Option::Some(reason) => context.ignore_for(reason)?,
}
)*

use $crate::IntoRunResult;
let result = $name(context);
IntoRunResult::into_run_result(result)
}
)*
))
);
};

use $crate::IntoRunResult;
let result = run(context);
IntoRunResult::into_run_result(result)
}
}
fn $name $($item)*
};
}
Loading