diff --git a/crates/test-case-core/src/test_case.rs b/crates/test-case-core/src/test_case.rs index 376b14e..b9c95ef 100644 --- a/crates/test-case-core/src/test_case.rs +++ b/crates/test-case-core/src/test_case.rs @@ -5,7 +5,38 @@ use proc_macro2::{Span as Span2, TokenStream as TokenStream2}; use quote::quote; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; -use syn::{parse_quote, Error, Expr, Ident, ItemFn, ReturnType, Token}; +use syn::{parse_quote, Attribute, Error, Expr, Ident, ItemFn, ReturnType, Token}; + +// Check whether given attribute is a test attribute of forms: +// * `#[test]` +// * `#[core::prelude::*::test]` or `#[::core::prelude::*::test]` +// * `#[std::prelude::*::test]` or `#[::std::prelude::*::test]` +fn is_test_attribute(attr: &Attribute) -> bool { + let path = match &attr.meta { + syn::Meta::Path(path) => path, + _ => return false, + }; + const CANDIDATES_LEN: usize = 4; + + let candidates: [[&str; CANDIDATES_LEN]; 2] = [ + ["core", "prelude", "*", "test"], + ["std", "prelude", "*", "test"], + ]; + if path.leading_colon.is_none() + && path.segments.len() == 1 + && path.segments[0].arguments.is_none() + && path.segments[0].ident == "test" + { + return true; + } else if path.segments.len() != candidates[0].len() { + return false; + } + candidates.into_iter().any(|segments| { + path.segments.iter().zip(segments).all(|(segment, path)| { + segment.arguments.is_none() && (path == "*" || segment.ident == path) + }) + }) +} #[derive(Debug)] pub struct TestCase { @@ -99,7 +130,12 @@ impl TestCase { quote! { let _result = super::#item_name(#(#arg_values),*).await; }, ) } else { - attrs.insert(0, parse_quote! { #[::core::prelude::v1::test] }); + let qualified_test_attr = parse_quote! { #[::core::prelude::v1::test] }; + if let Some(attr) = attrs.iter().find(|attr| is_test_attribute(attr)) { + let msg = "second test attribute is supplied, consider removing or changing the order of your test attributes"; + return Error::new_spanned(attr, msg).into_compile_error(); + } + attrs.push(qualified_test_attr); ( TokenStream2::new(), quote! { let _result = super::#item_name(#(#arg_values),*); }, diff --git a/crates/test-case-macros/src/lib.rs b/crates/test-case-macros/src/lib.rs index 90d4675..940725c 100644 --- a/crates/test-case-macros/src/lib.rs +++ b/crates/test-case-macros/src/lib.rs @@ -110,7 +110,7 @@ fn expand_additional_test_case_macros(item: &mut ItemFn) -> syn::Result { diff --git a/tests/snapshots/rust-nightly/acceptance__matrices_compilation_errors.snap b/tests/snapshots/rust-nightly/acceptance__matrices_compilation_errors.snap index 2617d4f..2a83f9c 100644 --- a/tests/snapshots/rust-nightly/acceptance__matrices_compilation_errors.snap +++ b/tests/snapshots/rust-nightly/acceptance__matrices_compilation_errors.snap @@ -5,6 +5,6 @@ expression: output error: All literal values must be of the same type error: Range bounds can only be an integer literal error: Unbounded ranges are not supported -error: could not compile `matrices_compilation_errors` (lib test) due to 5 previous errors +error: could not compile `matrices_compilation_errors` (lib test) due to 5 previous errors; 1 warning emitted error: number too large to fit in target type error[E0308]: mismatched types diff --git a/tests/snapshots/rust-stable/acceptance__features_produce_human_readable_errors.snap b/tests/snapshots/rust-stable/acceptance__features_produce_human_readable_errors.snap index 2646115..2b5a76f 100644 --- a/tests/snapshots/rust-stable/acceptance__features_produce_human_readable_errors.snap +++ b/tests/snapshots/rust-stable/acceptance__features_produce_human_readable_errors.snap @@ -3,4 +3,4 @@ source: tests/acceptance_tests.rs expression: output --- error: 'with-regex' feature is required to use 'matches-regex' keyword -error: could not compile `features_produce_human_readable_errors` (lib test) due to previous error +error: could not compile `features_produce_human_readable_errors` (lib test) due to 1 previous error diff --git a/tests/snapshots/rust-stable/acceptance__matrices_compilation_errors.snap b/tests/snapshots/rust-stable/acceptance__matrices_compilation_errors.snap index 2617d4f..2a83f9c 100644 --- a/tests/snapshots/rust-stable/acceptance__matrices_compilation_errors.snap +++ b/tests/snapshots/rust-stable/acceptance__matrices_compilation_errors.snap @@ -5,6 +5,6 @@ expression: output error: All literal values must be of the same type error: Range bounds can only be an integer literal error: Unbounded ranges are not supported -error: could not compile `matrices_compilation_errors` (lib test) due to 5 previous errors +error: could not compile `matrices_compilation_errors` (lib test) due to 5 previous errors; 1 warning emitted error: number too large to fit in target type error[E0308]: mismatched types