matrix_sdk_test_macros/
lib.rs1use proc_macro::TokenStream;
2use quote::{format_ident, quote, ToTokens};
3use syn::parse_macro_input;
4
5#[proc_macro_attribute]
8pub fn async_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
9 let fun = parse_macro_input!(item as syn::ItemFn);
10
11 if !fun.sig.ident.to_string().starts_with("test_") {
12 panic!("test function names must start with test_");
13 }
14
15 if fun.sig.output == syn::ReturnType::Default {
17 let attrs = r#"
18 #[cfg_attr(not(target_arch = "wasm32"), tokio::test)]
19 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
20 "#;
21
22 let mut out: TokenStream = attrs.parse().expect("Static works");
23 let inner: TokenStream = fun.into_token_stream().into();
24 out.extend(inner);
25 return out;
26 }
27
28 let attrs = r#"
36 #[cfg_attr(not(target_arch = "wasm32"), tokio::test)]
37 "#;
38
39 let mut out: TokenStream = attrs.parse().expect("Static works.");
40
41 let mut outer = fun.clone();
42 let fn_name = fun.sig.ident.clone();
43 let fn_call: TokenStream = if fun.sig.asyncness.is_some() {
44 quote! {
45 {
46 let res = #fn_name().await;
47 assert!(res.is_ok(), "{:?}", res);
48 }
49 }
50 } else {
51 quote! {
52 {
53 let res = #fn_name();
54 assert!(res.is_ok(), "{:?}", res);
55 }
56 }
57 }
58 .into();
59 outer.sig.output = syn::ReturnType::Default;
60 outer.sig.ident = format_ident!("{}_outer", fun.sig.ident);
61 outer.block = Box::new(parse_macro_input!(fn_call as syn::Block));
62
63 let inner: TokenStream = fun.into_token_stream().into();
64 out.extend(inner);
65
66 let attrs = r#"
67 #[cfg(target_arch = "wasm32")]
68 #[wasm_bindgen_test::wasm_bindgen_test]
69 "#;
70 let outer_attrs: TokenStream = attrs.parse().expect("Static works.");
71 let of: TokenStream = outer.into_token_stream().into();
72 out.extend(outer_attrs);
73 out.extend(of);
74
75 out
76}