Skip to content

Commit

Permalink
introduce #[fbinit::nested_test] that nests well with other #[test] a…
Browse files Browse the repository at this point in the history
…ttribute wrapper

Summary:
`#[fbinit::test]` does not nest well with other test attributes e.g. `rstest`. This change introduces a new attribute `#[fbinit::nested_test]` to solve this problem. Example usage

```
#[rstest]
#[fbinit::nested_test]
fn some_test(fb: FacebookInit, some_fixture: u32) {
    // ...
}
```

Reviewed By: edward-shen

Differential Revision: D54487672

fbshipit-source-id: dbee66d38ac8719ded84944fa4f6218f1d39fbb3
  • Loading branch information
Lu Pan authored and facebook-github-bot committed Mar 5, 2024
1 parent e9e30a2 commit c613759
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 5 deletions.
19 changes: 14 additions & 5 deletions shed/fbinit/fbinit_macros/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use syn::Token;
pub enum Mode {
Main,
Test,
NestedTest,
}

mod kw {
Expand Down Expand Up @@ -108,10 +109,10 @@ pub fn expand(
}
}

if function.sig.inputs.len() > 1 {
if mode != Mode::NestedTest && function.sig.inputs.len() > 1 {
return Err(Error::new_spanned(
function.sig,
"expected one argument of type fbinit::FacebookInit",
"expected one argument of type fbinit::FacebookInit unless #[fbinit::nested_test] is used",
));
}

Expand All @@ -128,16 +129,24 @@ pub fn expand(
panic!("fbinit must be performed in the crate root on the main function");
}
}),
Mode::Test => None,
_ => None,
};

let assignment = function.sig.inputs.first().map(|arg| quote!(let #arg =));
function.sig.inputs = Punctuated::new();
match mode {
Mode::NestedTest => {
// remove the first input (fb: FacebookInit) from function signature
function.sig.inputs = function.sig.inputs.into_iter().skip(1).collect();
}
_ => {
function.sig.inputs = Punctuated::new();
}
}

let block = function.block;

let body = match (function.sig.asyncness.is_some(), mode) {
(true, Mode::Test) => quote! {
(true, Mode::Test | Mode::NestedTest) => quote! {
fbinit_tokio::tokio_test(async #block )
},
(true, Mode::Main) => quote! {
Expand Down
26 changes: 26 additions & 0 deletions shed/fbinit/fbinit_macros/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,29 @@ pub fn test(args: TokenStream, input: TokenStream) -> TokenStream {
.unwrap_or_else(|err| err.to_compile_error())
.into()
}

// Similar to #[fbinit::test], but allows for nesting with other test attributes (e.g. #[rstest]) that wraps #[test].
//
// #[rstest]
// #[fbinit::nested_test]
// fn name_of_test(fb: FacebookInit, some_fixture: u32) {
// ...
// }
//
// to:
//
// #[rstest]
// fn name_of_test(some_fixture: u32) {
// let fb: FacebookInit = fbinit::perform_init();
// ...
// }
#[proc_macro_attribute]
pub fn nested_test(args: TokenStream, input: TokenStream) -> TokenStream {
expand(
Mode::NestedTest,
parse_macro_input!(args with Punctuated::parse_terminated),
parse_macro_input!(input),
)
.unwrap_or_else(|err| err.to_compile_error())
.into()
}
1 change: 1 addition & 0 deletions shed/fbinit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
mod oss;

pub use fbinit_macros::main;
pub use fbinit_macros::nested_test;
pub use fbinit_macros::test;
#[cfg(not(fbcode_build))]
pub use oss::*;
Expand Down

0 comments on commit c613759

Please sign in to comment.