From faf5b3e4998b2a5babf44e3dac7f6ebe1a85c4c0 Mon Sep 17 00:00:00 2001 From: Maxim Date: Sat, 20 Jul 2024 23:47:42 +0900 Subject: [PATCH] chore: Tests for `parse_spec` error messages --- Cargo.lock | 35 ++++++++ crates/env_filter/Cargo.toml | 3 + crates/env_filter/src/parser.rs | 152 ++++++++++++++++++++++++++++---- 3 files changed, 173 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 05bdc0c..4579123 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,6 +71,7 @@ version = "0.1.0" dependencies = [ "log", "regex", + "snapbox", ] [[package]] @@ -102,6 +103,12 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + [[package]] name = "regex" version = "1.7.0" @@ -119,6 +126,34 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +[[package]] +name = "similar" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640" + +[[package]] +name = "snapbox" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d656960fa127e80ade23c321d8c573bb9ba462c3a69e62ede635fc180ffc6cc" +dependencies = [ + "anstream", + "anstyle", + "normalize-line-endings", + "similar", + "snapbox-macros", +] + +[[package]] +name = "snapbox-macros" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f4c14672714436c09254801c934b203196a51182a5107fb76591c7cc56424d" +dependencies = [ + "anstream", +] + [[package]] name = "utf8parse" version = "0.2.1" diff --git a/crates/env_filter/Cargo.toml b/crates/env_filter/Cargo.toml index 94e864c..ba984da 100644 --- a/crates/env_filter/Cargo.toml +++ b/crates/env_filter/Cargo.toml @@ -33,5 +33,8 @@ regex = ["dep:regex"] log = { version = "0.4.8", features = ["std"] } regex = { version = "1.0.3", optional = true, default-features=false, features=["std", "perf"] } +[dev-dependencies] +snapbox = "0.6" + [lints] workspace = true diff --git a/crates/env_filter/src/parser.rs b/crates/env_filter/src/parser.rs index 846b3ce..b957e4a 100644 --- a/crates/env_filter/src/parser.rs +++ b/crates/env_filter/src/parser.rs @@ -87,6 +87,7 @@ pub(crate) fn parse_spec(spec: &str) -> ParseResult { #[cfg(test)] mod tests { use log::LevelFilter; + use snapbox::{assert_data_eq, str}; use super::{parse_spec, ParseResult}; @@ -95,7 +96,7 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec("crate1::mod1=error,crate1::mod2,crate2=debug"); assert_eq!(dirs.len(), 3); @@ -108,6 +109,8 @@ mod tests { assert_eq!(dirs[2].name, Some("crate2".to_owned())); assert_eq!(dirs[2].level, LevelFilter::Debug); assert!(filter.is_none()); + + assert!(errors.is_empty()); } #[test] @@ -116,13 +119,19 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec("crate1::mod1=warn=info,crate2=debug"); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, Some("crate2".to_owned())); assert_eq!(dirs[0].level, LevelFilter::Debug); assert!(filter.is_none()); + + assert_eq!(errors.len(), 1); + assert_data_eq!( + &errors[0], + str!["invalid logging spec 'crate1::mod1=warn=info'"] + ); } #[test] @@ -131,13 +140,16 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec("crate1::mod1=noNumber,crate2=debug"); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, Some("crate2".to_owned())); assert_eq!(dirs[0].level, LevelFilter::Debug); assert!(filter.is_none()); + + assert_eq!(errors.len(), 1); + assert_data_eq!(&errors[0], str!["invalid logging spec 'noNumber'"]); } #[test] @@ -146,13 +158,16 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec("crate1::mod1=wrong,crate2=warn"); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, Some("crate2".to_owned())); assert_eq!(dirs[0].level, LevelFilter::Warn); assert!(filter.is_none()); + + assert_eq!(errors.len(), 1); + assert_data_eq!(&errors[0], str!["invalid logging spec 'wrong'"]); } #[test] @@ -161,13 +176,16 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec("crate1::mod1=wrong,crate2="); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, Some("crate2".to_owned())); assert_eq!(dirs[0].level, LevelFilter::max()); assert!(filter.is_none()); + + assert_eq!(errors.len(), 1); + assert_data_eq!(&errors[0], str!["invalid logging spec 'wrong'"]); } #[test] @@ -176,10 +194,11 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec(""); // should be ignored assert_eq!(dirs.len(), 0); assert!(filter.is_none()); + assert!(errors.is_empty()); } #[test] @@ -189,10 +208,11 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec(" "); // should be ignored assert_eq!(dirs.len(), 0); assert!(filter.is_none()); + assert!(errors.is_empty()); } #[test] @@ -203,10 +223,11 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec(","); // should be ignored assert_eq!(dirs.len(), 0); assert!(filter.is_none()); + assert!(errors.is_empty()); } #[test] @@ -218,10 +239,11 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec(", "); // should be ignored assert_eq!(dirs.len(), 0); assert!(filter.is_none()); + assert!(errors.is_empty()); } #[test] @@ -233,10 +255,11 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec(" ,"); // should be ignored assert_eq!(dirs.len(), 0); assert!(filter.is_none()); + assert!(errors.is_empty()); } #[test] @@ -245,7 +268,7 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec("warn,crate2=debug"); assert_eq!(dirs.len(), 2); assert_eq!(dirs[0].name, None); @@ -253,6 +276,7 @@ mod tests { assert_eq!(dirs[1].name, Some("crate2".to_owned())); assert_eq!(dirs[1].level, LevelFilter::Debug); assert!(filter.is_none()); + assert!(errors.is_empty()); } #[test] @@ -261,12 +285,13 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec("warn"); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, None); assert_eq!(dirs[0].level, LevelFilter::Warn); assert!(filter.is_none()); + assert!(errors.is_empty()); } #[test] @@ -275,12 +300,13 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec("WARN"); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, None); assert_eq!(dirs[0].level, LevelFilter::Warn); assert!(filter.is_none()); + assert!(errors.is_empty()); } #[test] @@ -289,12 +315,13 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec("wArN"); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, None); assert_eq!(dirs[0].level, LevelFilter::Warn); assert!(filter.is_none()); + assert!(errors.is_empty()); } #[test] @@ -302,7 +329,7 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec("crate1::mod1=error,crate1::mod2,crate2=debug/abc"); assert_eq!(dirs.len(), 3); assert_eq!(dirs[0].name, Some("crate1::mod1".to_owned())); @@ -314,6 +341,7 @@ mod tests { assert_eq!(dirs[2].name, Some("crate2".to_owned())); assert_eq!(dirs[2].level, LevelFilter::Debug); assert!(filter.is_some() && filter.unwrap().to_string() == "abc"); + assert!(errors.is_empty()); } #[test] @@ -321,13 +349,19 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec("crate1::mod1=error=warn,crate2=debug/a.c"); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, Some("crate2".to_owned())); assert_eq!(dirs[0].level, LevelFilter::Debug); assert!(filter.is_some() && filter.unwrap().to_string() == "a.c"); + + assert_eq!(errors.len(), 1); + assert_data_eq!( + &errors[0], + str!["invalid logging spec 'crate1::mod1=error=warn'"] + ); } #[test] @@ -335,11 +369,95 @@ mod tests { let ParseResult { directives: dirs, filter, - .. + errors, } = parse_spec("crate1/a*c"); assert_eq!(dirs.len(), 1); assert_eq!(dirs[0].name, Some("crate1".to_owned())); assert_eq!(dirs[0].level, LevelFilter::max()); assert!(filter.is_some() && filter.unwrap().to_string() == "a*c"); + assert!(errors.is_empty()); + } + + #[test] + fn parse_spec_with_multiple_filters() { + let ParseResult { + directives: dirs, + filter, + errors, + } = parse_spec("debug/abc/a.c"); + assert!(dirs.is_empty()); + assert!(filter.is_none()); + + assert_eq!(errors.len(), 1); + assert_data_eq!( + &errors[0], + str!["invalid logging spec 'debug/abc/a.c' (too many '/'s)"] + ); + } + + #[test] + fn parse_spec_multiple_invalid_crates() { + // test parse_spec with multiple = in specification + let ParseResult { + directives: dirs, + filter, + errors, + } = parse_spec("crate1::mod1=warn=info,crate2=debug,crate3=error=error"); + + assert_eq!(dirs.len(), 1); + assert_eq!(dirs[0].name, Some("crate2".to_owned())); + assert_eq!(dirs[0].level, LevelFilter::Debug); + assert!(filter.is_none()); + + assert_eq!(errors.len(), 2); + assert_data_eq!( + &errors[0], + str!["invalid logging spec 'crate1::mod1=warn=info'"] + ); + assert_data_eq!( + &errors[1], + str!["invalid logging spec 'crate3=error=error'"] + ); + } + + #[test] + fn parse_spec_multiple_invalid_levels() { + // test parse_spec with 'noNumber' as log level + let ParseResult { + directives: dirs, + filter, + errors, + } = parse_spec("crate1::mod1=noNumber,crate2=debug,crate3=invalid"); + + assert_eq!(dirs.len(), 1); + assert_eq!(dirs[0].name, Some("crate2".to_owned())); + assert_eq!(dirs[0].level, LevelFilter::Debug); + assert!(filter.is_none()); + + assert_eq!(errors.len(), 2); + assert_data_eq!(&errors[0], str!["invalid logging spec 'noNumber'"]); + assert_data_eq!(&errors[1], str!["invalid logging spec 'invalid'"]); + } + + #[test] + fn parse_spec_invalid_crate_and_level() { + // test parse_spec with 'noNumber' as log level + let ParseResult { + directives: dirs, + filter, + errors, + } = parse_spec("crate1::mod1=debug=info,crate2=debug,crate3=invalid"); + + assert_eq!(dirs.len(), 1); + assert_eq!(dirs[0].name, Some("crate2".to_owned())); + assert_eq!(dirs[0].level, LevelFilter::Debug); + assert!(filter.is_none()); + + assert_eq!(errors.len(), 2); + assert_data_eq!( + &errors[0], + str!["invalid logging spec 'crate1::mod1=debug=info'"] + ); + assert_data_eq!(&errors[1], str!["invalid logging spec 'invalid'"]); } }