72 lines
2.5 KiB
Rust
72 lines
2.5 KiB
Rust
extern crate proc_macro;
|
|
|
|
use proc_macro::TokenStream;
|
|
use proc_macro2::Span;
|
|
use quote::quote;
|
|
|
|
/// Wraps function using `procspawn` to allocate a new temporary directory,
|
|
/// make it the process' working directory, and run the function.
|
|
#[proc_macro_attribute]
|
|
pub fn itest(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
|
let attrs = syn::parse_macro_input!(attrs as syn::AttributeArgs);
|
|
if attrs.len() > 1 {
|
|
return syn::Error::new_spanned(&attrs[1], "itest takes 0 or 1 attributes")
|
|
.to_compile_error()
|
|
.into();
|
|
}
|
|
let destructive = match attrs.get(0) {
|
|
Some(syn::NestedMeta::Meta(syn::Meta::NameValue(namevalue))) => {
|
|
if let Some(name) = namevalue.path.get_ident().map(|i| i.to_string()) {
|
|
if name == "destructive" {
|
|
match &namevalue.lit {
|
|
syn::Lit::Bool(v) => v.value,
|
|
_ => {
|
|
return syn::Error::new_spanned(
|
|
&attrs[1],
|
|
format!("destructive must be bool {}", name),
|
|
)
|
|
.to_compile_error()
|
|
.into();
|
|
}
|
|
}
|
|
} else {
|
|
return syn::Error::new_spanned(
|
|
&attrs[1],
|
|
format!("Unknown argument {}", name),
|
|
)
|
|
.to_compile_error()
|
|
.into();
|
|
}
|
|
} else {
|
|
false
|
|
}
|
|
}
|
|
Some(v) => {
|
|
return syn::Error::new_spanned(&v, "Unexpected argument")
|
|
.to_compile_error()
|
|
.into()
|
|
}
|
|
None => false,
|
|
};
|
|
let func = syn::parse_macro_input!(input as syn::ItemFn);
|
|
let fident = func.sig.ident.clone();
|
|
let varident = quote::format_ident!("ITEST_{}", fident);
|
|
let fidentstrbuf = format!(r#"{}"#, fident);
|
|
let fidentstr = syn::LitStr::new(&fidentstrbuf, Span::call_site());
|
|
let testident = if destructive {
|
|
quote::format_ident!("{}", "DESTRUCTIVE_TESTS")
|
|
} else {
|
|
quote::format_ident!("{}", "NONDESTRUCTIVE_TESTS")
|
|
};
|
|
let output = quote! {
|
|
#[linkme::distributed_slice(#testident)]
|
|
#[allow(non_upper_case_globals)]
|
|
static #varident : Test = Test {
|
|
name: #fidentstr,
|
|
f: #fident,
|
|
};
|
|
#func
|
|
};
|
|
output.into()
|
|
}
|