Line data Source code
1 : //! Test attribute to run async integration tests on the shared runtime.
2 : //!
3 : //! Apply `#[shared_runtime_test]` to an async test function. It will expand to
4 : //! a synchronous `#[test]` that executes the body on `crate::common::test_db::run_test`.
5 : use proc_macro::TokenStream;
6 : use quote::quote;
7 : use syn::{parse_macro_input, spanned::Spanned, ItemFn, Meta};
8 :
9 : #[proc_macro_attribute]
10 38 : pub fn shared_runtime_test(attr: TokenStream, item: TokenStream) -> TokenStream {
11 38 : parse_macro_input!(attr as syn::parse::Nothing);
12 :
13 38 : let input_fn = parse_macro_input!(item as ItemFn);
14 :
15 38 : if input_fn.sig.asyncness.is_none() {
16 0 : return syn::Error::new(
17 0 : input_fn.sig.span(),
18 0 : "shared_runtime_test can only be applied to async functions",
19 0 : )
20 0 : .to_compile_error()
21 0 : .into();
22 38 : }
23 :
24 38 : if !input_fn.sig.inputs.is_empty() {
25 0 : return syn::Error::new(
26 0 : input_fn.sig.inputs.span(),
27 0 : "shared_runtime_test functions cannot accept arguments",
28 0 : )
29 0 : .to_compile_error()
30 0 : .into();
31 38 : }
32 :
33 38 : if !input_fn.sig.generics.params.is_empty() {
34 0 : return syn::Error::new(
35 0 : input_fn.sig.generics.span(),
36 0 : "shared_runtime_test does not support generic parameters",
37 0 : )
38 0 : .to_compile_error()
39 0 : .into();
40 38 : }
41 :
42 : let ItemFn {
43 38 : attrs,
44 38 : vis,
45 38 : sig,
46 38 : block,
47 38 : } = input_fn;
48 :
49 38 : let name = sig.ident;
50 38 : let output = sig.output;
51 :
52 38 : let filtered_attrs = attrs.into_iter().filter(
53 1 : |attr| !matches!(attr.meta, Meta::Path(ref path) if path.is_ident("shared_runtime_test")),
54 : );
55 :
56 38 : TokenStream::from(quote! {
57 : #(#filtered_attrs)*
58 : #[test]
59 : #vis fn #name() #output {
60 : crate::common::test_db::run_test(async #block)
61 : }
62 : })
63 38 : }
|