festive_macros/
lib.rs

1use quote::quote;
2use syn::{
3    parse_macro_input, parse_quote, AttributeArgs, ItemFn, Lit, Meta, MetaNameValue, NestedMeta,
4    Path,
5};
6
7#[proc_macro_attribute]
8pub fn festive(
9    args: proc_macro::TokenStream,
10    input: proc_macro::TokenStream,
11) -> proc_macro::TokenStream {
12    let args = parse_macro_input!(args as AttributeArgs);
13    let timeout: syn::Expr = syn::parse_str(&format!("{:?}", parse_args(&args))).unwrap();
14
15    let ItemFn {
16        attrs,
17        vis,
18        sig,
19        block,
20    } = parse_macro_input!(input as ItemFn);
21    let fun_name = sig.ident.to_string();
22
23    (quote! {
24        #(
25            #attrs
26        )*
27        #[test]
28        #vis #sig {
29            fn inner() #block
30
31            struct _Anon;
32            let fork_id = ::festive::ForkId::of(::std::any::TypeId::of::<_Anon>());
33
34            let path = format!("{}::{}", ::std::module_path!(), #fun_name);
35
36            let res = ::festive::fork(
37                &path,
38                fork_id,
39                #timeout,
40                inner,
41            ).expect("forking test failed");
42
43            let stringout = format!(
44                "Child stdout:: {}\nChild stderr: {}",
45                String::from_utf8_lossy(&res.stdout),
46                String::from_utf8_lossy(&res.stderr)
47            );
48
49            assert!(res.status.success(), stringout);
50        }
51    })
52    .into()
53}
54
55fn parse_args(args: &[NestedMeta]) -> Option<u64> {
56    let timeout_path: Path = parse_quote!(timeout_ms);
57    for a in args {
58        match a {
59            NestedMeta::Meta(Meta::NameValue(MetaNameValue { path, lit, .. }))
60                if path == &timeout_path =>
61            {
62                if let Lit::Int(li) = lit {
63                    return li.base10_parse().ok();
64                } else {
65                    panic!("timeout_ms should have an int value")
66                }
67            }
68            _ => {}
69        }
70    }
71    None
72}