Skip to content

Commit 3a221cc

Browse files
committed
Allow specification of outer attributes on generated tests
Previously additional outer attributes on the test_resource function are discarded. This allows passing any additional attributes. Addresses frehberg#8
1 parent d6d279b commit 3a221cc

1 file changed

Lines changed: 18 additions & 2 deletions

File tree

test-generator/src/lib.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ use self::glob::{glob, Paths};
126126
use quote::quote;
127127
use std::path::PathBuf;
128128
use syn::parse::{Parse, ParseStream, Result};
129-
use syn::{parse_macro_input, Expr, ExprLit, Ident, Lit, Token, ItemFn};
129+
use syn::{parse_macro_input, Attribute, Expr, ExprLit, Ident, ItemFn, Lit, Token};
130130

131131
// Form canonical name without any punctuation/delimiter or special character
132132
fn canonical_fn_name(s: &str) -> String {
@@ -165,6 +165,13 @@ impl Parse for MacroAttributes {
165165
}
166166
}
167167

168+
fn relevant_attribs_from_ast(func_ast: &ItemFn) -> Vec<Attribute> {
169+
func_ast.clone().attrs.into_iter().filter
170+
(|a| {
171+
a.path.segments.iter().all(|ps| ps.ident!="test_resources")
172+
}).collect()
173+
}
174+
168175
/// Macro generating test-functions, invoking the fn for each item matching the resource-pattern.
169176
///
170177
/// The resource-pattern must not expand to empty list, otherwise an error is raised.
@@ -223,7 +230,7 @@ impl Parse for MacroAttributes {
223230
/// ```
224231
#[proc_macro_attribute]
225232
pub fn test_resources(attrs: TokenStream, func: TokenStream) -> TokenStream {
226-
let MacroAttributes { glob_pattern } = parse_macro_input!(attrs as MacroAttributes);
233+
let MacroAttributes { glob_pattern, } = parse_macro_input!(attrs as MacroAttributes);
227234

228235
let pattern = match glob_pattern {
229236
Lit::Str(l) => l.value(),
@@ -241,6 +248,8 @@ pub fn test_resources(attrs: TokenStream, func: TokenStream) -> TokenStream {
241248
let func_ast: ItemFn = syn::parse(func)
242249
.expect("failed to parse tokens as a function");
243250

251+
let func_attrs = relevant_attribs_from_ast(&func_ast);
252+
244253
let func_ident = func_ast.ident;
245254

246255
let paths: Paths = glob(&pattern).expect(&format!("No such file or directory {}", &pattern));
@@ -261,9 +270,11 @@ pub fn test_resources(attrs: TokenStream, func: TokenStream) -> TokenStream {
261270
// quote! requires proc_macro2 elements
262271
let test_ident = proc_macro2::Ident::new(&test_name, proc_macro2::Span::call_site());
263272

273+
let func_attrs = func_attrs.clone();
264274
let item = quote! {
265275
#[test]
266276
#[allow(non_snake_case)]
277+
#(#func_attrs)*
267278
fn # test_ident () {
268279
# func_ident ( #path_as_str .into() );
269280
}
@@ -277,6 +288,7 @@ pub fn test_resources(attrs: TokenStream, func: TokenStream) -> TokenStream {
277288
if result.0 == 0 {
278289
panic!("no resource matching the pattern {}", &pattern);
279290
}
291+
280292
// transforming proc_macro2::TokenStream into proc_macro::TokenStream
281293
result.1.into()
282294
}
@@ -360,6 +372,8 @@ pub fn bench_resources(attrs: TokenStream, func: TokenStream) -> TokenStream {
360372
let func_ast: ItemFn = syn::parse(func)
361373
.expect("failed to parse tokens as a function");
362374

375+
let func_attrs = relevant_attribs_from_ast(&func_ast);
376+
363377
let func_ident = func_ast.ident;
364378

365379
let paths: Paths = glob(&pattern).expect(&format!("No such file or directory {}", &pattern));
@@ -380,9 +394,11 @@ pub fn bench_resources(attrs: TokenStream, func: TokenStream) -> TokenStream {
380394
// quote! requires proc_macro2 elements
381395
let test_ident = proc_macro2::Ident::new(&test_name, proc_macro2::Span::call_site());
382396

397+
let func_attrs = func_attrs.clone();
383398
let item = quote! {
384399
#[bench]
385400
#[allow(non_snake_case)]
401+
#(#func_attrs)*
386402
fn # test_ident (b: &mut test::Bencher) {
387403
# func_ident ( b, #path_as_str .into() );
388404
}

0 commit comments

Comments
 (0)