diff --git a/src/parse/macros.rs b/src/parse/macros.rs index 6a1ea04..beb47cf 100644 --- a/src/parse/macros.rs +++ b/src/parse/macros.rs @@ -17,8 +17,8 @@ macro_rules! wrap_attributes { } } - #[cfg(test)] impl $ident { + #[allow(dead_code)] pub(crate) fn append(&mut self, attr: Attribute) { self.inner.attributes.push(attr) } diff --git a/src/render/fixture.rs b/src/render/fixture.rs index 52c9d36..30cae35 100644 --- a/src/render/fixture.rs +++ b/src/render/fixture.rs @@ -17,10 +17,18 @@ fn wrap_return_type_as_static_ref(rt: ReturnType) -> ReturnType { } } -fn output_type(rt: &ReturnType) -> syn::Type { +fn wrap_call_impl_with_call_once_impl(call_impl: TokenStream, rt: &ReturnType) -> TokenStream { match rt { - syn::ReturnType::Type(_, t) => *t.clone(), - _o => parse_quote! { () }, + syn::ReturnType::Type(_, t) => parse_quote! { + static mut S: Option<#t> = None; + static CELL: std::sync::Once = std::sync::Once::new(); + CELL.call_once(|| unsafe { S = Some(#call_impl) }); + unsafe { S.as_ref().unwrap() } + }, + _ => parse_quote! { + static CELL: std::sync::Once = std::sync::Once::new(); + CELL.call_once(|| #call_impl ); + }, } } @@ -59,13 +67,7 @@ pub(crate) fn render(fixture: ItemFn, info: FixtureInfo) -> TokenStream { let mut call_impl = render_exec_call(parse_quote! { #name }, args, asyncness.is_some()); if info.attributes.is_once() { - let return_type = output_type(&output); - call_impl = parse_quote! { - static mut S: Option<#return_type> = None; - static CELL: std::sync::Once = std::sync::Once::new(); - CELL.call_once(|| unsafe { S = Some(#call_impl) }); - unsafe { S.as_ref().unwrap() } - }; + call_impl = wrap_call_impl_with_call_once_impl(call_impl, &output); output = wrap_return_type_as_static_ref(output); default_output = wrap_return_type_as_static_ref(default_output); } @@ -147,7 +149,6 @@ mod should { use super::*; use crate::test::{assert_eq, *}; - use mytest::*; use rstest_reuse::*; #[derive(Clone)] diff --git a/tests/fixture/mod.rs b/tests/fixture/mod.rs index e14078e..1cb0517 100644 --- a/tests/fixture/mod.rs +++ b/tests/fixture/mod.rs @@ -198,9 +198,11 @@ mod should { .assert(output); } - #[test] - fn accept_once_attribute_and_call_fixture_just_once() { - let project = prj("once.rs").with_nocapture(); + #[rstest] + #[case("once.rs")] + #[case::no_return("once_no_return.rs")] + fn accept_once_attribute_and_call_fixture_just_once(#[case] fname: &str) { + let project = prj(fname).with_nocapture(); let output = project.run_tests().unwrap(); diff --git a/tests/resources/fixture/once_no_return.rs b/tests/resources/fixture/once_no_return.rs new file mode 100644 index 0000000..26674c9 --- /dev/null +++ b/tests/resources/fixture/once_no_return.rs @@ -0,0 +1,20 @@ +use rstest::*; + +#[fixture] +#[once] +fn once_fixture() { + eprintln!("Exec fixture() just once"); +} + +#[rstest] +fn base(_once_fixture: ()) { + assert!(true); +} + +#[rstest] +#[case()] +#[case()] +#[case()] +fn cases(_once_fixture: ()) { + assert!(true); +}