From 22838a6cbaab55f19bf226289c450179670e2fa4 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 3 Jan 2024 02:52:18 +0100 Subject: [PATCH] Write some tests and fix some issues --- _workspace.iml | 1 + micronfig/src/cache.rs | 11 +++-- micronfig/src/envdot.rs | 9 ++-- micronfig_macros/Cargo.toml | 1 + micronfig_macros/src/lib.rs | 25 +++++++---- micronfig_macros/tests/config.rs | 41 ------------------- micronfig_macros/tests/sources/empty.rs | 7 ++++ .../tests/sources/string_single_explicit.rs | 7 ++++ micronfig_macros/tests/tests.rs | 20 +++++++++ 9 files changed, 63 insertions(+), 59 deletions(-) delete mode 100644 micronfig_macros/tests/config.rs create mode 100644 micronfig_macros/tests/sources/empty.rs create mode 100644 micronfig_macros/tests/sources/string_single_explicit.rs create mode 100644 micronfig_macros/tests/tests.rs diff --git a/_workspace.iml b/_workspace.iml index c6b9173..9c3374c 100644 --- a/_workspace.iml +++ b/_workspace.iml @@ -3,6 +3,7 @@ + diff --git a/micronfig/src/cache.rs b/micronfig/src/cache.rs index 9eba93e..b308746 100644 --- a/micronfig/src/cache.rs +++ b/micronfig/src/cache.rs @@ -51,15 +51,14 @@ impl Cache { value } - /// Register a new `.env` file in the cache. - /// - /// Equivalent to adding an item to [`Cache::envdot`]. + /// Register a new `.env` file in the cache, if it exists. #[cfg(feature = "envdot")] pub fn register_dotenv(&mut self, path: Path) where Path: AsRef + Debug { - self.envdot.push( - crate::envdot::parse_dotenv(path) - ); + let dotenv = crate::envdot::parse_dotenv(path); + if let Some(dotenv) = dotenv { + self.envdot.push(dotenv); + } } } diff --git a/micronfig/src/envdot.rs b/micronfig/src/envdot.rs index f88b22c..2f9c8ed 100644 --- a/micronfig/src/envdot.rs +++ b/micronfig/src/envdot.rs @@ -12,11 +12,12 @@ use regex::Regex; pub type DotEnv = HashMap; /// Parse a `.env` file. -pub fn parse_dotenv

(value: P) -> DotEnv +/// +/// Returns [`None`] if no such file is found. +pub fn parse_dotenv

(value: P) -> Option where P: AsRef + Debug { - let mut file = File::open(&value) - .expect(&*format!("to be able to open {value:?}")); + let mut file = File::open(&value).ok()?; let mut contents: String = String::new(); file.read_to_string(&mut contents) @@ -64,7 +65,7 @@ pub fn parse_dotenv

(value: P) -> DotEnv }) .map(|(key, value)| keys.insert(key, value)); - keys + Some(keys) } /// Get the requested variable from a [`DotEnv`] structure. diff --git a/micronfig_macros/Cargo.toml b/micronfig_macros/Cargo.toml index f7c7499..38c309d 100644 --- a/micronfig_macros/Cargo.toml +++ b/micronfig_macros/Cargo.toml @@ -19,6 +19,7 @@ quote = "1.0" [dev-dependencies] micronfig = { version = "0.3.0", path = "../micronfig" } +trybuild = "1.0.87" [lib] proc-macro = true diff --git a/micronfig_macros/src/lib.rs b/micronfig_macros/src/lib.rs index 81e54b4..430d534 100644 --- a/micronfig_macros/src/lib.rs +++ b/micronfig_macros/src/lib.rs @@ -32,15 +32,22 @@ impl Parse for ConfigItem { fn parse(input: ParseStream) -> syn::Result { let identifier = input.parse::()?; - input.parse::()?; - input.parse::()?; + if input.lookahead1().peek(Token![:]) { + input.parse::()?; + input.parse::()?; - let mut types = vec![]; - while let Ok(typ) = input.parse::() { - types.push(typ) + let mut types = vec![]; + while let Ok(typ) = input.parse::() { + types.push(typ) + } + + Ok(Self { identifier, types }) + } + else { + let types = vec![]; + Ok(Self { identifier, types }) } - Ok(Self { identifier, types }) } } @@ -75,10 +82,12 @@ pub fn config(input: TokenStream) -> TokenStream { let input: Config = parse_macro_input!(input with syn::punctuated::Punctuated::parse_terminated); let cache_code = quote! { + #[allow(non_snake_case)] mod _cache { pub static lock: std::sync::OnceLock = std::sync::OnceLock::new(); } + #[allow(non_snake_case)] fn _cache() -> &'static micronfig::cache::Cache { _cache::lock.get_or_init(micronfig::cache::Cache::new) } @@ -124,10 +133,12 @@ pub fn config(input: TokenStream) -> TokenStream { }; quote! { + #[allow(non_snake_case)] mod #identifier { pub(super) static lock: std::sync::OnceLock> = std::sync::OnceLock::new(); } + #[allow(non_snake_case)] pub(crate) fn #identifier() -> &'static Option<#last_type> { #identifier::lock.get_or_init(|| { let key: std::ffi::OsString = #identifier_string.into(); @@ -154,7 +165,5 @@ pub fn config(input: TokenStream) -> TokenStream { #items_code }; - println!("{quote}"); - quote.into() } \ No newline at end of file diff --git a/micronfig_macros/tests/config.rs b/micronfig_macros/tests/config.rs deleted file mode 100644 index 65c0e5f..0000000 --- a/micronfig_macros/tests/config.rs +++ /dev/null @@ -1,41 +0,0 @@ -use micronfig_macros::config; - -#[test] -fn basic() { - config! { - GARAS: String, - AUTO: String, - BUS: String, - } -} - -#[test] -fn empty() { - config! {} -} - -#[test] -fn conversion_simple() { - config! { - GARAS: String > u32, - AUTO: String > u16, - } -} - -/* -#[test] -fn implicit() { - config! { - GARAS, - AUTO, - } -} - -#[test] -fn conversion_implicit() { - config! { - GARAS: > u32, - AUTO > u16, - } -} -*/ \ No newline at end of file diff --git a/micronfig_macros/tests/sources/empty.rs b/micronfig_macros/tests/sources/empty.rs new file mode 100644 index 0000000..4703da9 --- /dev/null +++ b/micronfig_macros/tests/sources/empty.rs @@ -0,0 +1,7 @@ +micronfig::config! { + +} + +fn main() { + +} \ No newline at end of file diff --git a/micronfig_macros/tests/sources/string_single_explicit.rs b/micronfig_macros/tests/sources/string_single_explicit.rs new file mode 100644 index 0000000..3d699ec --- /dev/null +++ b/micronfig_macros/tests/sources/string_single_explicit.rs @@ -0,0 +1,7 @@ +micronfig::config! { + GARASAUTO: String, +} + +fn main() { + println!("{:?}", GARASAUTO()) +} diff --git a/micronfig_macros/tests/tests.rs b/micronfig_macros/tests/tests.rs new file mode 100644 index 0000000..c1029be --- /dev/null +++ b/micronfig_macros/tests/tests.rs @@ -0,0 +1,20 @@ +macro_rules! pass { + ($id:ident) => { + #[test] + fn $id() { + trybuild::TestCases::new().pass(format!("tests/sources/{}.rs", stringify!($id))); + } + } +} + +macro_rules! fail { + ($id:ident) => { + #[test] + fn $id() { + trybuild::TestCases::new().compile_fail(format!("tests/sources/{}.rs", stringify!($id))); + } + } +} + +pass!(empty); +pass!(string_single_explicit);