proc-macro: Timeout for tests

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
This commit is contained in:
Alexandru Vasile
2024-03-01 20:20:14 +02:00
parent 88ccc54339
commit b6c98c7fa0
6 changed files with 124 additions and 0 deletions
@@ -0,0 +1,21 @@
[package]
name = "integration-tests-proc-macro"
version.workspace = true
authors.workspace = true
edition.workspace = true
rust-version.workspace = true
publish = false
license.workspace = true
repository.workspace = true
documentation.workspace = true
homepage.workspace = true
description = "Subxt integration tests proc-macros"
[lib]
proc-macro = true
[dependencies]
syn = { workspace = true }
proc-macro2 = { workspace = true }
quote = { workspace = true }
@@ -0,0 +1,80 @@
// Copyright 2019-2023 Parity Technologies (UK) Ltd.
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::{
parse::{Parse, ParseStream},
Error,
};
#[proc_macro_attribute]
pub fn subxt_test(attr: TokenStream, item: TokenStream) -> TokenStream {
let subxt_attr = match syn::parse::<SubxtTestAttr>(attr) {
Ok(subxt_attr) => subxt_attr,
Err(err) => return err.into_compile_error().into(),
};
let timeout_duration = subxt_attr.timeout.unwrap_or(60 * 5);
let func: syn::ItemFn = match syn::parse(item) {
Ok(func) => func,
Err(err) => return err.into_compile_error().into(),
};
let func_attrs = &func.attrs;
let func_vis = &func.vis;
let func_sig = &func.sig;
let func_block = &func.block;
let func_output = &func.sig.output;
let func_name = &func.sig.ident;
let inner_func_name = format_ident!("{}_inner", func_name);
let result = quote! {
#[tokio::test]
#( #func_attrs )*
#func_vis #func_sig #func_output {
async fn #inner_func_name() #func_output
#func_block
tokio::time::timeout(std::time::Duration::from_secs(#timeout_duration), #inner_func_name())
.await
.expect("Test timedout");
}
};
result.into()
}
mod keywords {
syn::custom_keyword!(timeout);
}
struct SubxtTestAttr {
timeout: Option<u64>,
}
impl Parse for SubxtTestAttr {
fn parse(input: ParseStream) -> Result<Self, Error> {
if input.is_empty() {
return Ok(Self { timeout: None });
}
let _keyword = input.parse::<keywords::timeout>()?;
input.parse::<syn::token::Eq>()?;
let timeout = input.parse::<syn::LitInt>()?.base10_parse::<u64>()?;
if !input.is_empty() {
return Err(Error::new(
input.span(),
"Expected tokens: `timeout = value`",
));
}
Ok(Self {
timeout: Some(timeout),
})
}
}