diff --git a/Cargo.lock b/Cargo.lock index cd4fcc01..ada170a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -50,6 +50,55 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + [[package]] name = "arraydeque" version = "0.5.1" @@ -178,6 +227,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + [[package]] name = "config" version = "0.14.1" @@ -200,6 +255,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", + "snapbox", "temp-env", "tokio", "toml", @@ -863,6 +919,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itoa" version = "1.0.9" @@ -1052,6 +1114,12 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + [[package]] name = "notify" version = "7.0.0" @@ -1647,6 +1715,12 @@ dependencies = [ "digest", ] +[[package]] +name = "similar" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" + [[package]] name = "slab" version = "0.4.9" @@ -1662,6 +1736,28 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "snapbox" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96dcfc4581e3355d70ac2ee14cfdf81dce3d85c85f1ed9e2c1d3013f53b3436b" +dependencies = [ + "anstream", + "anstyle", + "normalize-line-endings", + "similar", + "snapbox-macros", +] + +[[package]] +name = "snapbox-macros" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16569f53ca23a41bb6f62e0a5084aa1661f4814a67fa33696a79073e03a664af" +dependencies = [ + "anstream", +] + [[package]] name = "socket2" version = "0.4.10" @@ -2050,6 +2146,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "vcpkg" version = "0.2.15" @@ -2283,6 +2385,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.48.5" diff --git a/Cargo.toml b/Cargo.toml index d9397b86..50cae5f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -148,6 +148,7 @@ glob = "0.3" notify = "7.0" temp-env = "0.3" log = { version = "0.4", features = ["serde"] } +snapbox = "0.6.21" [[example]] name = "async_source" diff --git a/tests/testsuite/errors.rs b/tests/testsuite/errors.rs index 6d2f215c..aa17d0fa 100644 --- a/tests/testsuite/errors.rs +++ b/tests/testsuite/errors.rs @@ -1,5 +1,7 @@ -use config::{Config, ConfigError, File, FileFormat, Map, Value}; use serde_derive::Deserialize; +use snapbox::{assert_data_eq, str}; + +use config::{Config, ConfigError, File, FileFormat, Map, Value}; #[test] #[cfg(feature = "json")] @@ -16,8 +18,10 @@ fn test_error_parse() { .build(); assert!(res.is_err()); - let err = res.unwrap_err(); - assert_eq!(err.to_string(), "trailing comma at line 4 column 1"); + assert_data_eq!( + res.unwrap_err().to_string(), + str!["trailing comma at line 4 column 1"] + ); } #[test] @@ -38,9 +42,9 @@ fn test_error_type() { let res = c.get::("boolean_s_parse"); assert!(res.is_err()); - assert_eq!( + assert_data_eq!( res.unwrap_err().to_string(), - format!("invalid type: string \"fals\", expected a boolean for key `boolean_s_parse`",) + str![[r#"invalid type: string "fals", expected a boolean for key `boolean_s_parse`"#]] ); } @@ -73,10 +77,10 @@ fn test_error_deser_whole() { .build() .unwrap(); - let err = c.try_deserialize::().unwrap_err().to_string(); - assert_eq!( - err, - "invalid type: string \"Torre di Pisa\", expected an integer for key `place.name`", + let res = c.try_deserialize::(); + assert_data_eq!( + res.unwrap_err().to_string(), + str![[r#"invalid type: string "Torre di Pisa", expected an integer for key `place.name`"#]] ); } @@ -99,9 +103,9 @@ fn test_error_type_detached() { let res = value.try_deserialize::(); assert!(res.is_err()); - assert_eq!( + assert_data_eq!( res.unwrap_err().to_string(), - "invalid type: string \"fals\", expected a boolean".to_owned() + str![[r#"invalid type: string "fals", expected a boolean"#]] ); } @@ -123,9 +127,9 @@ fn test_error_type_get_bool() { let res = c.get_bool("boolean_s_parse"); assert!(res.is_err()); - assert_eq!( + assert_data_eq!( res.unwrap_err().to_string(), - format!("invalid type: string \"fals\", expected a boolean for key `boolean_s_parse`",) + str![[r#"invalid type: string "fals", expected a boolean for key `boolean_s_parse`"#]] ); } @@ -147,9 +151,9 @@ fn test_error_type_get_table() { let res = c.get_table("debug"); assert!(res.is_err()); - assert_eq!( + assert_data_eq!( res.unwrap_err().to_string(), - format!("invalid type: boolean `true`, expected a map for key `debug`",) + str!["invalid type: boolean `true`, expected a map for key `debug`"] ); } @@ -171,9 +175,9 @@ fn test_error_type_get_array() { let res = c.get_array("debug"); assert!(res.is_err()); - assert_eq!( + assert_data_eq!( res.unwrap_err().to_string(), - format!("invalid type: boolean `true`, expected an array for key `debug`",) + str!["invalid type: boolean `true`, expected an array for key `debug`"] ); } @@ -189,17 +193,14 @@ fn test_error_enum_de() { let on_v: Value = "on".into(); let on_d = on_v.try_deserialize::(); - assert_eq!( + assert_data_eq!( on_d.unwrap_err().to_string(), - "enum Diode does not have variant constructor on".to_owned() + str!["enum Diode does not have variant constructor on"] ); let array_v: Value = vec![100, 100].into(); let array_d = array_v.try_deserialize::(); - assert_eq!( - array_d.unwrap_err().to_string(), - "value of enum Diode should be represented by either string or table with exactly one key" - ); + assert_data_eq!(array_d.unwrap_err().to_string(), str!["value of enum Diode should be represented by either string or table with exactly one key"]); let confused_v: Value = [ ("Brightness".to_owned(), 100.into()), @@ -210,10 +211,7 @@ fn test_error_enum_de() { .collect::>() .into(); let confused_d = confused_v.try_deserialize::(); - assert_eq!( - confused_d.unwrap_err().to_string(), - "value of enum Diode should be represented by either string or table with exactly one key" - ); + assert_data_eq!(confused_d.unwrap_err().to_string(), str!["value of enum Diode should be represented by either string or table with exactly one key"]); } #[test] diff --git a/tests/testsuite/file.rs b/tests/testsuite/file.rs index 414c3d59..33077852 100644 --- a/tests/testsuite/file.rs +++ b/tests/testsuite/file.rs @@ -1,3 +1,5 @@ +use snapbox::{assert_data_eq, str}; + use config::{Config, File, FileFormat}; #[test] @@ -21,9 +23,9 @@ fn test_file_required_not_found() { .build(); assert!(res.is_err()); - assert_eq!( + assert_data_eq!( res.unwrap_err().to_string(), - "configuration file \"tests/testsuite/file-nonexistent\" not found".to_owned() + str![[r#"configuration file "tests/testsuite/file-nonexistent" not found"#]] ); } @@ -47,9 +49,9 @@ fn test_file_auto_not_found() { .build(); assert!(res.is_err()); - assert_eq!( + assert_data_eq!( res.unwrap_err().to_string(), - "configuration file \"tests/testsuite/file-nonexistent\" not found".to_owned() + str![[r#"configuration file "tests/testsuite/file-nonexistent" not found"#]] ); } diff --git a/tests/testsuite/file_ini.rs b/tests/testsuite/file_ini.rs index 78bd6b35..c4c2eba4 100644 --- a/tests/testsuite/file_ini.rs +++ b/tests/testsuite/file_ini.rs @@ -2,6 +2,7 @@ use chrono::{DateTime, TimeZone, Utc}; use serde_derive::Deserialize; +use snapbox::{assert_data_eq, str}; use config::{Config, File, FileFormat}; @@ -72,9 +73,9 @@ error .build(); assert!(res.is_err()); - assert_eq!( + assert_data_eq!( res.unwrap_err().to_string(), - format!(r#"4:1 expecting "[Some('='), Some(':')]" but found EOF."#,) + str![[r#"4:1 expecting "[Some('='), Some(':')]" but found EOF."#]] ); } diff --git a/tests/testsuite/file_json.rs b/tests/testsuite/file_json.rs index 57157052..029d687d 100644 --- a/tests/testsuite/file_json.rs +++ b/tests/testsuite/file_json.rs @@ -3,6 +3,7 @@ use chrono::{DateTime, TimeZone, Utc}; use float_cmp::ApproxEqUlps; use serde_derive::Deserialize; +use snapbox::{assert_data_eq, str}; use config::{Config, File, FileFormat, Map, Value}; @@ -108,9 +109,9 @@ fn test_error_parse() { .build(); assert!(res.is_err()); - assert_eq!( + assert_data_eq!( res.unwrap_err().to_string(), - format!("expected `:` at line 5 column 1",) + str!["expected `:` at line 5 column 1"] ); } diff --git a/tests/testsuite/file_json5.rs b/tests/testsuite/file_json5.rs index 116c0251..0e64de29 100644 --- a/tests/testsuite/file_json5.rs +++ b/tests/testsuite/file_json5.rs @@ -3,6 +3,7 @@ use chrono::{DateTime, TimeZone, Utc}; use float_cmp::ApproxEqUlps; use serde_derive::Deserialize; +use snapbox::{assert_data_eq, str}; use config::{Config, File, FileFormat, Map, Value}; @@ -109,9 +110,16 @@ fn test_error_parse() { .build(); assert!(res.is_err()); - assert_eq!( + assert_data_eq!( res.unwrap_err().to_string(), - format!(" --> 3:7\n |\n3 | ok: true\n | ^---\n |\n = expected null",) + str![[r#" + --> 3:7 + | +3 | ok: true + | ^--- + | + = expected null +"#]] ); } diff --git a/tests/testsuite/file_ron.rs b/tests/testsuite/file_ron.rs index d31441c8..154b806b 100644 --- a/tests/testsuite/file_ron.rs +++ b/tests/testsuite/file_ron.rs @@ -3,6 +3,7 @@ use chrono::{DateTime, TimeZone, Utc}; use float_cmp::ApproxEqUlps; use serde_derive::Deserialize; +use snapbox::{assert_data_eq, str}; use config::{Config, File, FileFormat, Map, Value}; @@ -111,7 +112,7 @@ fn test_error_parse() { .build(); assert!(res.is_err()); - assert_eq!(res.unwrap_err().to_string(), format!("5:1: Expected colon")); + assert_data_eq!(res.unwrap_err().to_string(), str!["5:1: Expected colon"]); } #[test] diff --git a/tests/testsuite/file_toml.rs b/tests/testsuite/file_toml.rs index c6f210f0..43fa391e 100644 --- a/tests/testsuite/file_toml.rs +++ b/tests/testsuite/file_toml.rs @@ -3,6 +3,7 @@ use chrono::{DateTime, TimeZone, Utc}; use float_cmp::ApproxEqUlps; use serde_derive::Deserialize; +use snapbox::{assert_data_eq, str}; use config::{Config, File, FileFormat, Map, Value}; @@ -154,10 +155,18 @@ error = tru .build(); assert!(res.is_err()); - assert!(res - .unwrap_err() - .to_string() - .contains("TOML parse error at line 3, column 9")); + assert_data_eq!( + res.unwrap_err().to_string(), + str![[r#" +TOML parse error at line 3, column 9 + | +3 | error = tru + | ^ +invalid string +expected `"`, `'` + +"#]] + ); } #[test] diff --git a/tests/testsuite/file_yaml.rs b/tests/testsuite/file_yaml.rs index d36ce079..505245dd 100644 --- a/tests/testsuite/file_yaml.rs +++ b/tests/testsuite/file_yaml.rs @@ -5,6 +5,7 @@ use std::collections::HashMap; use chrono::{DateTime, TimeZone, Utc}; use float_cmp::ApproxEqUlps; use serde_derive::Deserialize; +use snapbox::{assert_data_eq, str}; use config::{Config, File, FileFormat, Map, Value}; @@ -105,9 +106,9 @@ error false .build(); assert!(res.is_err()); - assert_eq!( + assert_data_eq!( res.unwrap_err().to_string(), - "simple key expect ':' at byte 22 line 4 column 1", + str!["simple key expect ':' at byte 22 line 4 column 1"] ); } diff --git a/tests/testsuite/get.rs b/tests/testsuite/get.rs index ae7da271..5f01f397 100644 --- a/tests/testsuite/get.rs +++ b/tests/testsuite/get.rs @@ -1,8 +1,10 @@ use std::collections::HashSet; -use config::{Config, File, FileFormat, Map, Value}; use float_cmp::ApproxEqUlps; use serde_derive::Deserialize; +use snapbox::{assert_data_eq, str}; + +use config::{Config, File, FileFormat, Map, Value}; #[test] #[cfg(feature = "json")] @@ -14,9 +16,9 @@ fn test_not_found() { let res = c.get::("not_found"); assert!(res.is_err()); - assert_eq!( + assert_data_eq!( res.unwrap_err().to_string(), - "configuration property \"not_found\" not found".to_owned() + str![[r#"configuration property "not_found" not found"#]] ); }