use darling::FromMeta;
use proc_macro::TokenStream;
use syn::{parse_macro_input, spanned::Spanned, AttributeArgs, ItemFn};
#[derive(Debug, FromMeta)]
struct MacroArgs {
#[darling(default)]
root: Option<String>,
}
#[proc_macro_attribute]
pub fn trident_test(args: TokenStream, input: TokenStream) -> TokenStream {
let attr_args = parse_macro_input!(args as AttributeArgs);
let macro_args = match MacroArgs::from_list(&attr_args) {
Ok(macro_args) => macro_args,
Err(error) => {
return TokenStream::from(error.write_errors());
}
};
let root = macro_args.root.unwrap_or_else(|| "../../".to_owned());
let input_fn: ItemFn =
syn::parse(input).expect("'trident_test' attribute is applicable only to async fn");
let input_fn_span = input_fn.span();
let input_fn_body = input_fn.block;
let input_fn_name = input_fn.sig.ident;
let input_fn_attrs = input_fn.attrs;
let input_fn_inputs = input_fn.sig.inputs;
quote::quote_spanned!(input_fn_span=>
#(#input_fn_attrs)*
#[trident_client::test::rstest]
#[trident_client::test::tokio::test(flavor = "multi_thread")]
#[trident_client::test::serial_test::serial]
async fn #input_fn_name(#input_fn_inputs) -> trident_client::test::anyhow::Result<()> {
let mut tester = trident_client::test::Tester::with_root(#root);
let localnet_handle = tester.before().await?;
let test = async {
#input_fn_body
Ok::<(), trident_client::test::anyhow::Error>(())
};
let result = std::panic::AssertUnwindSafe(test).catch_unwind().await;
tester.after(localnet_handle).await?;
assert!(result.is_ok());
let final_result = result.unwrap();
if let Err(error) = final_result {
trident_client::test::report_error(&error);
return Err(error);
}
Ok(())
}
)
.into()
}