diff options
author | HampusM <hampus@hampusmat.com> | 2022-11-11 13:42:32 +0100 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2022-11-11 13:42:32 +0100 |
commit | 9ed051d56ef14290e532be2716b6f4fe6924b935 (patch) | |
tree | 1f0976fde21e06b7de9ee269b0d0ed35cbe20585 /macros/src/factory/declare_default_args.rs | |
parent | 3a0432e690f2ad7af4fb7ccf98ccfba6b3d49705 (diff) |
test: add unit tests for parsing declare_default_factory macro args
Diffstat (limited to 'macros/src/factory/declare_default_args.rs')
-rw-r--r-- | macros/src/factory/declare_default_args.rs | 178 |
1 files changed, 175 insertions, 3 deletions
diff --git a/macros/src/factory/declare_default_args.rs b/macros/src/factory/declare_default_args.rs index d19eba8..0828f9e 100644 --- a/macros/src/factory/declare_default_args.rs +++ b/macros/src/factory/declare_default_args.rs @@ -17,7 +17,7 @@ impl Parse for DeclareDefaultFactoryMacroArgs { fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> { - let interface = input.parse().unwrap(); + let interface = input.parse()?; if !input.peek(Token![,]) { return Ok(Self { @@ -26,7 +26,7 @@ impl Parse for DeclareDefaultFactoryMacroArgs }); } - input.parse::<Token![,]>().unwrap(); + input.parse::<Token![,]>()?; let flags = Punctuated::<MacroFlag, Token![,]>::parse_terminated(input)?; @@ -48,9 +48,181 @@ impl Parse for DeclareDefaultFactoryMacroArgs .collect::<Vec<_>>(); if let Some(dupe_flag_name) = flag_names.iter().find_duplicate() { - return Err(input.error(format!("Duplicate flag '{}'", dupe_flag_name))); + return Err(input.error(format!("Duplicate flag '{dupe_flag_name}'"))); } Ok(Self { interface, flags }) } } + +#[cfg(test)] +mod tests +{ + use std::error::Error; + + use proc_macro2::Span; + use quote::{format_ident, quote}; + use syn::token::Dyn; + use syn::{ + parse2, + Path, + PathArguments, + PathSegment, + TraitBound, + TraitBoundModifier, + Type, + TypeParamBound, + TypeTraitObject, + }; + + use super::*; + use crate::macro_flag::MacroFlag; + + #[test] + fn can_parse_with_interface_only() -> Result<(), Box<dyn Error>> + { + let input_args = quote! { + dyn IFoo + }; + + let dec_def_fac_args = parse2::<DeclareDefaultFactoryMacroArgs>(input_args)?; + + assert_eq!( + dec_def_fac_args.interface, + Type::TraitObject(TypeTraitObject { + dyn_token: Some(Dyn::default()), + bounds: Punctuated::from_iter(vec![TypeParamBound::Trait(TraitBound { + paren_token: None, + modifier: TraitBoundModifier::None, + lifetimes: None, + path: Path { + leading_colon: None, + segments: Punctuated::from_iter(vec![PathSegment { + ident: format_ident!("IFoo"), + arguments: PathArguments::None + }]) + } + })]) + }) + ); + + assert!(dec_def_fac_args.flags.is_empty()); + + Ok(()) + } + + #[test] + fn can_parse_with_interface_and_single_flag() -> Result<(), Box<dyn Error>> + { + let input_args = quote! { + dyn IBar, threadsafe = true + }; + + let dec_def_fac_args = parse2::<DeclareDefaultFactoryMacroArgs>(input_args)?; + + assert_eq!( + dec_def_fac_args.interface, + Type::TraitObject(TypeTraitObject { + dyn_token: Some(Dyn::default()), + bounds: Punctuated::from_iter(vec![TypeParamBound::Trait(TraitBound { + paren_token: None, + modifier: TraitBoundModifier::None, + lifetimes: None, + path: Path { + leading_colon: None, + segments: Punctuated::from_iter(vec![PathSegment { + ident: format_ident!("IBar"), + arguments: PathArguments::None + }]) + } + })]) + }) + ); + + assert_eq!( + dec_def_fac_args.flags, + Punctuated::from_iter(vec![MacroFlag { + flag: format_ident!("threadsafe"), + is_on: syn::LitBool::new(true, Span::call_site()) + }]) + ); + + Ok(()) + } + + #[test] + fn can_parse_with_interface_and_multiple_flags() -> Result<(), Box<dyn Error>> + { + let input_args = quote! { + dyn IBar, threadsafe = true, async = false + }; + + let dec_def_fac_args = parse2::<DeclareDefaultFactoryMacroArgs>(input_args)?; + + assert_eq!( + dec_def_fac_args.interface, + Type::TraitObject(TypeTraitObject { + dyn_token: Some(Dyn::default()), + bounds: Punctuated::from_iter(vec![TypeParamBound::Trait(TraitBound { + paren_token: None, + modifier: TraitBoundModifier::None, + lifetimes: None, + path: Path { + leading_colon: None, + segments: Punctuated::from_iter(vec![PathSegment { + ident: format_ident!("IBar"), + arguments: PathArguments::None + }]) + } + })]) + }) + ); + + assert_eq!( + dec_def_fac_args.flags, + Punctuated::from_iter(vec![ + MacroFlag { + flag: format_ident!("threadsafe"), + is_on: syn::LitBool::new(true, Span::call_site()) + }, + MacroFlag { + flag: format_ident!("async"), + is_on: syn::LitBool::new(false, Span::call_site()) + } + ]) + ); + + Ok(()) + } + + #[test] + fn cannot_parse_with_interface_and_invalid_flag() + { + let input_args = quote! { + dyn IBar, async = true, foo = false + }; + + assert!(matches!( + parse2::<DeclareDefaultFactoryMacroArgs>(input_args), + Err(_) + )); + } + + #[test] + fn cannot_parse_with_interface_and_duplicate_flag() + { + assert!(matches!( + parse2::<DeclareDefaultFactoryMacroArgs>(quote! { + dyn IBar, async = true, threadsafe = false, async = true + }), + Err(_) + )); + + assert!(matches!( + parse2::<DeclareDefaultFactoryMacroArgs>(quote! { + dyn IBar, async = true, threadsafe = false, async = false + }), + Err(_) + )); + } +} |