atagen

matrix-rust-sdk

public
Star0
Watch0
ssh://brewery@pls.lobotomise.me:33/atagen/matrix-rust-sdk.git
testing/matrix-sdk-test-macros/src/lib.rsRust76 lines2.6 KB
1
use proc_macro::TokenStream;
2
use quote::{ToTokens, format_ident, quote};
3
use syn::parse_macro_input;
4
5
/// Attribute to use `wasm_bindgen_test` for wasm32 targets and `tokio::test`
6
/// for everything else with async-support and custom result-types
7
#[proc_macro_attribute]
8
pub 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
    // on the regular return-case, we can just use cfg_attr and quit early
16
    if fun.sig.output == syn::ReturnType::Default {
17
        let attrs = r#"
18
            #[cfg_attr(not(target_family = "wasm"), tokio::test)]
19
            #[cfg_attr(target_family = "wasm", 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
    // on the more complicated case, where we have some `->`-Result-Arrow
29
    // `wasm_bindgen_test` doesn't yet support
30
    // - see https://github.com/rustwasm/wasm-bindgen/issues/2565 -
31
    // we split the attribution into to functions: one with the original
32
    // to be attributed for non-wasm, and then a second outer-wrapper function
33
    // that calls the first in wasm32 cases.
34
35
    let attrs = r#"
36
        #[cfg_attr(not(target_family = "wasm"), 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_family = "wasm")]
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
}