From 5d5133d23587f54d5c952e338169272236f4ed6c Mon Sep 17 00:00:00 2001 From: la10736 Date: Sun, 14 Apr 2024 12:12:51 +0200 Subject: [PATCH 1/4] First implementation --- rstest/tests/resources/rstest/lifetimes.rs | 21 +++++++++++++++++++++ rstest/tests/rstest/mod.rs | 12 ++++++++++++ rstest_macros/src/render/mod.rs | 14 +++++++++++--- 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 rstest/tests/resources/rstest/lifetimes.rs diff --git a/rstest/tests/resources/rstest/lifetimes.rs b/rstest/tests/resources/rstest/lifetimes.rs new file mode 100644 index 00000000..440751b1 --- /dev/null +++ b/rstest/tests/resources/rstest/lifetimes.rs @@ -0,0 +1,21 @@ +use rstest::*; + +enum E<'a> { + A(bool), + B(&'a std::cell::Cell>), +} + +#[rstest] +#[case(E::A(true))] +fn case<'a>(#[case] e: E<'a>) {} + +#[rstest] +fn values<'a>(#[values(E::A(true))] e: E<'a>) {} + +#[fixture] +fn e<'a>() -> E<'a> { + E::A(true) +} + +#[rstest] +fn fixture<'a>(e: E<'a>) {} diff --git a/rstest/tests/rstest/mod.rs b/rstest/tests/rstest/mod.rs index a4fe1a5e..98dce287 100644 --- a/rstest/tests/rstest/mod.rs +++ b/rstest/tests/rstest/mod.rs @@ -168,6 +168,18 @@ fn use_mutable_fixture_in_parametric_argumnts() { .assert(output); } +#[test] +fn should_not_remove_lifetimes() { + let (output, _) = run_test("lifetimes.rs"); + + TestResults::new() + .with_contains(true) + .ok("case") + .ok("values") + .ok("fixture") + .assert(output); +} + #[test] fn should_reject_no_item_function() { let (output, name) = run_test("reject_no_item_function.rs"); diff --git a/rstest_macros/src/render/mod.rs b/rstest_macros/src/render/mod.rs index c293e407..93261735 100644 --- a/rstest_macros/src/render/mod.rs +++ b/rstest_macros/src/render/mod.rs @@ -7,7 +7,9 @@ use std::collections::HashMap; use syn::token::Async; use proc_macro2::{Span, TokenStream}; -use syn::{parse_quote, Attribute, Expr, FnArg, Ident, ItemFn, Path, ReturnType, Stmt}; +use syn::{ + parse_quote, Attribute, Expr, FnArg, Ident, ItemFn, LifetimeParam, Path, ReturnType, Stmt, +}; use quote::{format_ident, quote}; @@ -45,6 +47,7 @@ pub(crate) fn single(mut test: ItemFn, info: RsTestInfo) -> TokenStream { .map(|tp| &tp.ident) .cloned() .collect::>(); + let lifetimes = test.sig.generics.lifetimes().cloned().collect::>(); single_test_case( &test.sig.ident, @@ -57,6 +60,7 @@ pub(crate) fn single(mut test: ItemFn, info: RsTestInfo) -> TokenStream { resolver, &info.attributes, &generic_types, + &lifetimes, ) } @@ -207,7 +211,8 @@ fn render_test_call( ) -> TokenStream { let timeout = timeout.map(|x| quote! {#x}).or_else(|| { std::env::var("RSTEST_TIMEOUT") - .ok().map(|to| quote! { std::time::Duration::from_secs( (#to).parse().unwrap()) }) + .ok() + .map(|to| quote! { std::time::Duration::from_secs( (#to).parse().unwrap()) }) }); match (timeout, is_async) { (Some(to_expr), true) => quote! { @@ -248,6 +253,7 @@ fn single_test_case( resolver: impl Resolver, attributes: &RsTestAttributes, generic_types: &[Ident], + lifetimes: &[LifetimeParam], ) -> TokenStream { let (attrs, trace_me): (Vec<_>, Vec<_>) = attrs.iter().cloned().partition(|a| !attr_is(a, "trace")); @@ -286,7 +292,7 @@ fn single_test_case( quote! { #test_attr #(#attrs)* - #asyncness fn #name() #output { + #asyncness fn #name<#(#lifetimes,)*>() #output { #test_impl #inject #trace_args @@ -346,6 +352,7 @@ impl<'a> TestCaseRender<'a> { .map(|tp| &tp.ident) .cloned() .collect::>(); + let lifetimes = testfn.sig.generics.lifetimes().cloned().collect::>(); single_test_case( &self.name, @@ -358,6 +365,7 @@ impl<'a> TestCaseRender<'a> { self.resolver, attributes, &generic_types, + &lifetimes, ) } } From db726a0a75b6ee1299974a8043b3b99db73d9666 Mon Sep 17 00:00:00 2001 From: la10736 Date: Sun, 14 Apr 2024 12:33:34 +0200 Subject: [PATCH 2/4] Little refactoring --- rstest_macros/src/render/mod.rs | 37 ++++++++++----------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/rstest_macros/src/render/mod.rs b/rstest_macros/src/render/mod.rs index 93261735..9e07a9ba 100644 --- a/rstest_macros/src/render/mod.rs +++ b/rstest_macros/src/render/mod.rs @@ -7,9 +7,7 @@ use std::collections::HashMap; use syn::token::Async; use proc_macro2::{Span, TokenStream}; -use syn::{ - parse_quote, Attribute, Expr, FnArg, Ident, ItemFn, LifetimeParam, Path, ReturnType, Stmt, -}; +use syn::{parse_quote, Attribute, Expr, FnArg, Ident, ItemFn, Path, ReturnType, Stmt}; use quote::{format_ident, quote}; @@ -40,14 +38,6 @@ pub(crate) fn single(mut test: ItemFn, info: RsTestInfo) -> TokenStream { let args = test.sig.inputs.iter().cloned().collect::>(); let attrs = std::mem::take(&mut test.attrs); let asyncness = test.sig.asyncness; - let generic_types = test - .sig - .generics - .type_params() - .map(|tp| &tp.ident) - .cloned() - .collect::>(); - let lifetimes = test.sig.generics.lifetimes().cloned().collect::>(); single_test_case( &test.sig.ident, @@ -59,8 +49,7 @@ pub(crate) fn single(mut test: ItemFn, info: RsTestInfo) -> TokenStream { Some(&test), resolver, &info.attributes, - &generic_types, - &lifetimes, + &test.sig.generics, ) } @@ -227,6 +216,10 @@ fn render_test_call( } } +fn generics_types_ident<'a>(generics: &'a syn::Generics) -> impl Iterator { + generics.type_params().map(|tp| &tp.ident) +} + /// Render a single test case: /// /// * `name` - Test case name @@ -252,8 +245,7 @@ fn single_test_case( test_impl: Option<&ItemFn>, resolver: impl Resolver, attributes: &RsTestAttributes, - generic_types: &[Ident], - lifetimes: &[LifetimeParam], + generics: &syn::Generics, ) -> TokenStream { let (attrs, trace_me): (Vec<_>, Vec<_>) = attrs.iter().cloned().partition(|a| !attr_is(a, "trace")); @@ -261,7 +253,8 @@ fn single_test_case( if !trace_me.is_empty() { attributes.add_trace(format_ident!("trace")); } - let inject = inject::resolve_aruments(args.iter(), &resolver, generic_types); + let generics_types = generics_types_ident(generics).cloned().collect::>(); + let inject = inject::resolve_aruments(args.iter(), &resolver, &generics_types); let args = args .iter() .filter_map(MaybeIdent::maybe_ident) @@ -288,6 +281,7 @@ fn single_test_case( Some(resolve_default_test_attr(is_async)) }; let execute = render_test_call(testfn_name.clone().into(), &args, timeout, is_async); + let lifetimes = generics.lifetimes(); quote! { #test_attr @@ -345,14 +339,6 @@ impl<'a> TestCaseRender<'a> { let mut attrs = testfn.attrs.clone(); attrs.extend(self.attrs.iter().cloned()); let asyncness = testfn.sig.asyncness; - let generic_types = testfn - .sig - .generics - .type_params() - .map(|tp| &tp.ident) - .cloned() - .collect::>(); - let lifetimes = testfn.sig.generics.lifetimes().cloned().collect::>(); single_test_case( &self.name, @@ -364,8 +350,7 @@ impl<'a> TestCaseRender<'a> { None, self.resolver, attributes, - &generic_types, - &lifetimes, + &testfn.sig.generics, ) } } From 5bc3840d99fea6e13293610fa68bec33353492db Mon Sep 17 00:00:00 2001 From: la10736 Date: Sun, 14 Apr 2024 12:43:26 +0200 Subject: [PATCH 3/4] Add unit test --- rstest_macros/src/render/test.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/rstest_macros/src/render/test.rs b/rstest_macros/src/render/test.rs index ac3911e8..870ebcac 100644 --- a/rstest_macros/src/render/test.rs +++ b/rstest_macros/src/render/test.rs @@ -80,6 +80,20 @@ mod single_test_should { assert_eq!(inner_fn_impl.display_code(), input_fn.block.display_code()); } + #[test] + fn not_remove_lifetimes() { + let input_fn: ItemFn = r#" + pub fn test<'a, 'b, 'c: 'a + 'b>(a: A<'a>, b: A<'b>, c: A<'c>) -> A<'c> + { + } + "# + .ast(); + + let result: ItemFn = single(input_fn.clone(), Default::default()).ast(); + + assert_eq!(3, result.sig.generics.lifetimes().count()); + } + #[rstest] fn not_copy_any_attributes( #[values( From e1e6b4db765c97ba49145a21018c446a58936aa8 Mon Sep 17 00:00:00 2001 From: la10736 Date: Sun, 14 Apr 2024 12:46:33 +0200 Subject: [PATCH 4/4] Add changelog line --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0be3fa3..61b17dcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,14 @@ ### Fixed +- Don't remove Lifetimes from test function if any. See [#230](https://github.com/la10736/rstest/issues/230) +[#241](https://github.com/la10736/rstest/issues/241) for more details. + ## [0.19.0] 2024/4/9 ### Changed -- Defined `rust-version` for each crate (see [#227](https://github.com/la10736/rstest/issues/235)) +- Defined `rust-version` for each crate (see [#227](https://github.com/la10736/rstest/issues/227)) ### Fixed