From ee4996ddb7f8cb1bcdc02f06f3420ea91fa86356 Mon Sep 17 00:00:00 2001 From: Kezhu Wang Date: Mon, 20 Jan 2025 11:14:56 +0800 Subject: [PATCH] Append generated test macro so next test macros are aware of it `#[gtest]` will benefit from la10736/rstest#291, we could also benefit other test macros. This is an attempt to improve capabilities among test macros to avoid duplicated test runs which is rare to be aware of. The rationale is simple: procedure of attribute macro see only attributes following it. Macros next to processing macro will not see generated macro if it is generated in-place. So, instead of generating test macro in-place, appending generated test macro will let macros next to processing macro have chance to react, for example, not generate test macro if there is already one. We could deprecate `#[googletest::test]` oneday after la10736/rstest#291 released. See: tokio-rs/tokio#6497, d-e-s-o/test-log#46, frondeus/test-case#143, la10736/rstest#291, kezhuw/stuck#53. Refs: rust-lang/rust#67839, rust-lang/rust#82419. --- googletest_macro/src/lib.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/googletest_macro/src/lib.rs b/googletest_macro/src/lib.rs index 7569a737..52ae75b5 100644 --- a/googletest_macro/src/lib.rs +++ b/googletest_macro/src/lib.rs @@ -14,8 +14,9 @@ use quote::quote; use syn::{ - parse_macro_input, punctuated::Punctuated, spanned::Spanned, Attribute, DeriveInput, Expr, - ExprLit, FnArg, ItemFn, Lit, MetaNameValue, PatType, ReturnType, Signature, Type, + parse_macro_input, parse_quote, punctuated::Punctuated, spanned::Spanned, Attribute, + DeriveInput, Expr, ExprLit, FnArg, ItemFn, Lit, MetaNameValue, PatType, ReturnType, Signature, + Type, }; /// Marks a test to be run by the Google Rust test runner. @@ -75,7 +76,7 @@ pub fn gtest( _args: proc_macro::TokenStream, input: proc_macro::TokenStream, ) -> proc_macro::TokenStream { - let ItemFn { attrs, sig, block, .. } = parse_macro_input!(input as ItemFn); + let ItemFn { mut attrs, sig, block, .. } = parse_macro_input!(input as ItemFn); let test_case_hash: u64 = { use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; @@ -185,6 +186,13 @@ pub fn gtest( ) } }; + + if !attrs.iter().any(is_test_attribute) && !is_rstest_enabled { + let test_attr: Attribute = parse_quote! { + #[::core::prelude::v1::test] + }; + attrs.push(test_attr); + }; let function = quote! { #(#attrs)* #outer_sig -> #outer_return_type { @@ -200,17 +208,7 @@ pub fn gtest( #trailer } }; - - let output = if attrs.iter().any(is_test_attribute) || is_rstest_enabled { - function - } else { - quote! { - #[::core::prelude::v1::test] - #function - } - }; - - output.into() + function.into() } /// Extract the optional "expected" string literal from a `should_panic`