diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2022-09-17 15:53:13 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-17 15:53:13 +0200 |
commit | 0d58da27e7e8ff0e80d8088e26413a8bb3c8e372 (patch) | |
tree | 076d223c2b34f236ea7a0b46d654eac42e18cacd | |
parent | bfe819a943d8d68124eeafe9b268c7c3036ddb11 (diff) | |
parent | b2dfb937e2e212ce5809c8deb5af112e1aeb7651 (diff) |
Merge pull request #354 from YounessBird/fix-uppercase-lowercase-isses
Fix uppercase lowercase isses
-rw-r--r-- | README.md | 8 | ||||
-rw-r--r-- | src/config.rs | 10 | ||||
-rw-r--r-- | src/de.rs | 2 | ||||
-rw-r--r-- | src/path/mod.rs | 16 | ||||
-rw-r--r-- | tests/Settings-enum-test.ini | 2 | ||||
-rw-r--r-- | tests/Settings-enum-test.json | 3 | ||||
-rw-r--r-- | tests/Settings-enum-test.json5 | 3 | ||||
-rw-r--r-- | tests/Settings-enum-test.ron | 3 | ||||
-rw-r--r-- | tests/Settings-enum-test.toml | 2 | ||||
-rw-r--r-- | tests/Settings-enum-test.yaml | 2 | ||||
-rw-r--r-- | tests/Settings-upper-struct.toml | 3 | ||||
-rw-r--r-- | tests/Settings.ini | 2 | ||||
-rw-r--r-- | tests/Settings.json | 4 | ||||
-rw-r--r-- | tests/Settings.json5 | 4 | ||||
-rw-r--r-- | tests/Settings.ron | 4 | ||||
-rw-r--r-- | tests/Settings.toml | 4 | ||||
-rw-r--r-- | tests/Settings.yaml | 3 | ||||
-rw-r--r-- | tests/file_ini.rs | 103 | ||||
-rw-r--r-- | tests/file_json.rs | 105 | ||||
-rw-r--r-- | tests/file_json5.rs | 104 | ||||
-rw-r--r-- | tests/file_ron.rs | 104 | ||||
-rw-r--r-- | tests/file_toml.rs | 104 | ||||
-rw-r--r-- | tests/file_yaml.rs | 105 |
23 files changed, 682 insertions, 18 deletions
@@ -23,8 +23,10 @@ [RON]: https://github.com/ron-rs/ron [JSON5]: https://github.com/callum-oakley/json5-rs -Please note that this library can not be used to write changed configuration -values back to the configuration file(s)! +Please note this library + + - can not be used to write changed configuration values back to the configuration file(s)! + - Is case insensitive and all the keys are converted to lowercase internally ## Usage @@ -63,4 +65,4 @@ We currently support Rust 1.56.1 and newer. config-rs is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0). -See LICENSE-APACHE and LICENSE-MIT for details. +See LICENSE-APACHE and LICENSE-MIT for details.
\ No newline at end of file diff --git a/src/config.rs b/src/config.rs index 27b318d..320b72e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -110,7 +110,8 @@ impl Config { where T: Into<Value>, { - self.defaults.insert(key.parse()?, value.into()); + self.defaults + .insert(key.to_lowercase().as_str().parse()?, value.into()); #[allow(deprecated)] self.refresh() @@ -129,7 +130,8 @@ impl Config { where T: Into<Value>, { - self.overrides.insert(key.parse()?, value.into()); + self.overrides + .insert(key.to_lowercase().as_str().parse()?, value.into()); #[allow(deprecated)] self.refresh() @@ -137,7 +139,7 @@ impl Config { #[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")] pub fn set_once(&mut self, key: &str, value: Value) -> Result<()> { - let expr: path::Expression = key.parse()?; + let expr: path::Expression = key.to_lowercase().as_str().parse()?; // Traverse the cache using the path to (possibly) retrieve a value if let Some(ref mut val) = expr.get_mut(&mut self.cache) { @@ -149,6 +151,8 @@ impl Config { } pub fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> { + let k = key.to_lowercase(); + let key = k.as_str(); // Parse the key into a path expression let expr: path::Expression = key.parse()?; @@ -272,7 +272,7 @@ impl EnumAccess { fn variant_deserializer(&self, name: &str) -> Result<StrDeserializer> { self.variants .iter() - .find(|&&s| s == name) + .find(|&&s| s.to_lowercase() == name.to_lowercase()) // changing to lowercase will enable deserialization of lowercase values to enums .map(|&s| StrDeserializer(s)) .ok_or_else(|| self.no_constructor_error(name)) } diff --git a/src/path/mod.rs b/src/path/mod.rs index 7456aa3..b3773d1 100644 --- a/src/path/mod.rs +++ b/src/path/mod.rs @@ -120,7 +120,7 @@ impl Expression { match *self { Self::Identifier(ref id) => match root.kind { ValueKind::Table(ref mut map) => Some( - map.entry(id.clone()) + map.entry(id.to_lowercase()) .or_insert_with(|| Value::new(None, ValueKind::Nil)), ), @@ -131,7 +131,7 @@ impl Expression { Some(value) => { if let ValueKind::Table(ref mut map) = value.kind { Some( - map.entry(key.clone()) + map.entry(key.to_lowercase()) .or_insert_with(|| Value::new(None, ValueKind::Nil)), ) } else { @@ -139,7 +139,7 @@ impl Expression { if let ValueKind::Table(ref mut map) = value.kind { Some( - map.entry(key.clone()) + map.entry(key.to_lowercase()) .or_insert_with(|| Value::new(None, ValueKind::Nil)), ) } else { @@ -194,7 +194,7 @@ impl Expression { ValueKind::Table(ref incoming_map) => { // Pull out another table let target = if let ValueKind::Table(ref mut map) = root.kind { - map.entry(id.clone()) + map.entry(id.to_lowercase()) .or_insert_with(|| Map::<String, Value>::new().into()) } else { unreachable!(); @@ -202,17 +202,17 @@ impl Expression { // Continue the deep merge for (key, val) in incoming_map { - Self::Identifier(key.clone()).set(target, val.clone()); + Self::Identifier(key.to_lowercase()).set(target, val.clone()); } } _ => { if let ValueKind::Table(ref mut map) = root.kind { // Just do a simple set - if let Some(existing) = map.get_mut(id) { + if let Some(existing) = map.get_mut(&id.to_lowercase()) { *existing = value; } else { - map.insert(id.clone(), value); + map.insert(id.to_lowercase(), value); } } } @@ -225,7 +225,7 @@ impl Expression { // Didn't find a table. Oh well. Make a table and do this anyway *parent = Map::<String, Value>::new().into(); } - Self::Identifier(key.clone()).set(parent, value); + Self::Identifier(key.to_lowercase()).set(parent, value); } } diff --git a/tests/Settings-enum-test.ini b/tests/Settings-enum-test.ini new file mode 100644 index 0000000..778e772 --- /dev/null +++ b/tests/Settings-enum-test.ini @@ -0,0 +1,2 @@ +# Test for Enum deserialization. See file_tomls.rs override tests +bar = "bar is a lowercase param"
\ No newline at end of file diff --git a/tests/Settings-enum-test.json b/tests/Settings-enum-test.json new file mode 100644 index 0000000..5616949 --- /dev/null +++ b/tests/Settings-enum-test.json @@ -0,0 +1,3 @@ +{ + "bar": "bar is a lowercase param" +} diff --git a/tests/Settings-enum-test.json5 b/tests/Settings-enum-test.json5 new file mode 100644 index 0000000..098be56 --- /dev/null +++ b/tests/Settings-enum-test.json5 @@ -0,0 +1,3 @@ +{ + bar: "bar is a lowercase param", +} diff --git a/tests/Settings-enum-test.ron b/tests/Settings-enum-test.ron new file mode 100644 index 0000000..845149d --- /dev/null +++ b/tests/Settings-enum-test.ron @@ -0,0 +1,3 @@ +( + bar: "bar is a lowercase param" +)
\ No newline at end of file diff --git a/tests/Settings-enum-test.toml b/tests/Settings-enum-test.toml new file mode 100644 index 0000000..778e772 --- /dev/null +++ b/tests/Settings-enum-test.toml @@ -0,0 +1,2 @@ +# Test for Enum deserialization. See file_tomls.rs override tests +bar = "bar is a lowercase param"
\ No newline at end of file diff --git a/tests/Settings-enum-test.yaml b/tests/Settings-enum-test.yaml new file mode 100644 index 0000000..7126b98 --- /dev/null +++ b/tests/Settings-enum-test.yaml @@ -0,0 +1,2 @@ +# Test for Enum deserialization. See file_yaml.rs override tests +bar: bar is a lowercase param diff --git a/tests/Settings-upper-struct.toml b/tests/Settings-upper-struct.toml new file mode 100644 index 0000000..341a5e0 --- /dev/null +++ b/tests/Settings-upper-struct.toml @@ -0,0 +1,3 @@ +# For override tests +FOO = "FOO should be overridden" +bar = "I am bar"
\ No newline at end of file diff --git a/tests/Settings.ini b/tests/Settings.ini index 16badd4..d707568 100644 --- a/tests/Settings.ini +++ b/tests/Settings.ini @@ -1,5 +1,7 @@ debug = true
production = false
+FOO = FOO should be overridden
+bar = I am bar
[place]
name = Torre di Pisa
longitude = 43.7224985
diff --git a/tests/Settings.json b/tests/Settings.json index babb0ba..8f2f4e5 100644 --- a/tests/Settings.json +++ b/tests/Settings.json @@ -15,5 +15,7 @@ "username": "jsmith", "email": "jsmith@localhost" } - } + }, + "FOO": "FOO should be overridden", + "bar": "I am bar" } diff --git a/tests/Settings.json5 b/tests/Settings.json5 index 4c93e42..cc2dab8 100644 --- a/tests/Settings.json5 +++ b/tests/Settings.json5 @@ -16,5 +16,7 @@ "username": "jsmith", "email": "jsmith@localhost", } - } + }, + FOO: "FOO should be overridden", + bar: "I am bar", } diff --git a/tests/Settings.ron b/tests/Settings.ron index 7882840..ed3009e 100644 --- a/tests/Settings.ron +++ b/tests/Settings.ron @@ -16,5 +16,7 @@ "username": "jsmith", "email": "jsmith@localhost" } - ) + ), + FOO: "FOO should be overridden", + bar: "I am bar" ) diff --git a/tests/Settings.toml b/tests/Settings.toml index bb53808..65b3c4e 100644 --- a/tests/Settings.toml +++ b/tests/Settings.toml @@ -8,6 +8,10 @@ code = 53 # errors boolean_s_parse = "fals" +# For override tests +FOO="FOO should be overridden" +bar="I am bar" + arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] quarks = ["up", "down", "strange", "charm", "bottom", "top"] diff --git a/tests/Settings.yaml b/tests/Settings.yaml index 8e79c29..c7b1549 100644 --- a/tests/Settings.yaml +++ b/tests/Settings.yaml @@ -12,3 +12,6 @@ place: name: John Smith username: jsmith email: jsmith@localhost +# For override tests +FOO: FOO should be overridden +bar: I am bar diff --git a/tests/file_ini.rs b/tests/file_ini.rs index 4ebf6e3..e7f369a 100644 --- a/tests/file_ini.rs +++ b/tests/file_ini.rs @@ -66,3 +66,106 @@ fn test_error_parse() { ) ); } + +#[derive(Debug, Deserialize, PartialEq)] +enum EnumSettings { + Bar(String), +} + +#[derive(Debug, Deserialize, PartialEq)] +struct StructSettings { + foo: String, + bar: String, +} +#[derive(Debug, Deserialize, PartialEq)] +#[allow(non_snake_case)] +struct CapSettings { + FOO: String, +} + +#[test] +fn test_override_uppercase_value_for_struct() { + std::env::set_var("APP_FOO", "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings", FileFormat::Ini)) + .add_source(config::Environment::with_prefix("APP").separator("_")) + .build() + .unwrap(); + let cap_settings = cfg.clone().try_deserialize::<CapSettings>(); + let lower_settings = cfg.try_deserialize::<StructSettings>().unwrap(); + + match cap_settings { + Ok(v) => { + // this assertion will ensure that the map has only lowercase keys + assert_ne!(v.FOO, "FOO should be overridden"); + assert_eq!( + lower_settings.foo, + "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string() + ); + } + Err(e) => { + if e.to_string().contains("missing field `FOO`") { + assert_eq!( + lower_settings.foo, + "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string() + ); + } else { + panic!("{}", e); + } + } + } +} + +#[test] +fn test_override_lowercase_value_for_struct() { + std::env::set_var("config_foo", "I have been overridden_with_lower_case"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings", FileFormat::Ini)) + .add_source(config::Environment::with_prefix("config").separator("_")) + .build() + .unwrap(); + + let values: StructSettings = cfg.try_deserialize().unwrap(); + assert_eq!( + values.foo, + "I have been overridden_with_lower_case".to_string() + ); + assert_ne!(values.foo, "I am bar".to_string()); +} + +#[test] +fn test_override_uppercase_value_for_enums() { + std::env::set_var("APPS_BAR", "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings-enum-test", FileFormat::Ini)) + .add_source(config::Environment::with_prefix("APPS").separator("_")) + .build() + .unwrap(); + let val: EnumSettings = cfg.try_deserialize().unwrap(); + + assert_eq!( + val, + EnumSettings::Bar("I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string()) + ); +} + +#[test] +fn test_override_lowercase_value_for_enums() { + std::env::set_var("test_bar", "I have been overridden_with_lower_case"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings-enum-test", FileFormat::Ini)) + .add_source(config::Environment::with_prefix("test").separator("_")) + .build() + .unwrap(); + + let param: EnumSettings = cfg.try_deserialize().unwrap(); + + assert_eq!( + param, + EnumSettings::Bar("I have been overridden_with_lower_case".to_string()) + ); +} diff --git a/tests/file_json.rs b/tests/file_json.rs index e660997..91cbc9b 100644 --- a/tests/file_json.rs +++ b/tests/file_json.rs @@ -111,3 +111,108 @@ fn test_json_vec() { assert_eq!(vi.next().unwrap().into_string().unwrap(), "example_dir2"); assert!(vi.next().is_none()); } + +#[derive(Debug, Deserialize, PartialEq)] +enum EnumSettings { + Bar(String), +} + +#[derive(Debug, Deserialize, PartialEq)] +struct StructSettings { + foo: String, + bar: String, +} +#[derive(Debug, Deserialize, PartialEq)] +#[allow(non_snake_case)] +struct CapSettings { + FOO: String, +} + +#[test] +fn test_override_uppercase_value_for_struct() { + std::env::set_var("APP_FOO", "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings", FileFormat::Json)) + .add_source(config::Environment::with_prefix("APP").separator("_")) + .build() + .unwrap(); + + let cap_settings = cfg.clone().try_deserialize::<CapSettings>(); + let lower_settings = cfg.try_deserialize::<StructSettings>().unwrap(); + + match cap_settings { + Ok(v) => { + // this assertion will ensure that the map has only lowercase keys + assert_ne!(v.FOO, "FOO should be overridden"); + assert_eq!( + lower_settings.foo, + "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string() + ); + } + Err(e) => { + if e.to_string().contains("missing field `FOO`") { + println!("triggered error {:?}", e); + assert_eq!( + lower_settings.foo, + "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string() + ); + } else { + panic!("{}", e); + } + } + } +} + +#[test] +fn test_override_lowercase_value_for_struct() { + std::env::set_var("config_foo", "I have been overridden_with_lower_case"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings", FileFormat::Json)) + .add_source(config::Environment::with_prefix("config").separator("_")) + .build() + .unwrap(); + + let values: StructSettings = cfg.try_deserialize().unwrap(); + assert_eq!( + values.foo, + "I have been overridden_with_lower_case".to_string() + ); + assert_ne!(values.foo, "I am bar".to_string()); +} + +#[test] +fn test_override_uppercase_value_for_enums() { + std::env::set_var("APPS_BAR", "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings-enum-test", FileFormat::Json)) + .add_source(config::Environment::with_prefix("APPS").separator("_")) + .build() + .unwrap(); + let val: EnumSettings = cfg.try_deserialize().unwrap(); + + assert_eq!( + val, + EnumSettings::Bar("I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string()) + ); +} + +#[test] +fn test_override_lowercase_value_for_enums() { + std::env::set_var("test_bar", "I have been overridden_with_lower_case"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings-enum-test", FileFormat::Json)) + .add_source(config::Environment::with_prefix("test").separator("_")) + .build() + .unwrap(); + + let param: EnumSettings = cfg.try_deserialize().unwrap(); + + assert_eq!( + param, + EnumSettings::Bar("I have been overridden_with_lower_case".to_string()) + ); +} diff --git a/tests/file_json5.rs b/tests/file_json5.rs index a1cb733..bdeb3ea 100644 --- a/tests/file_json5.rs +++ b/tests/file_json5.rs @@ -89,3 +89,107 @@ fn test_error_parse() { ) ); } + +#[derive(Debug, Deserialize, PartialEq)] +enum EnumSettings { + Bar(String), +} + +#[derive(Debug, Deserialize, PartialEq)] +struct StructSettings { + foo: String, + bar: String, +} +#[derive(Debug, Deserialize, PartialEq)] +#[allow(non_snake_case)] +struct CapSettings { + FOO: String, +} + +#[test] +fn test_override_uppercase_value_for_struct() { + std::env::set_var("APP_FOO", "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings", FileFormat::Json5)) + .add_source(config::Environment::with_prefix("APP").separator("_")) + .build() + .unwrap(); + + let cap_settings = cfg.clone().try_deserialize::<CapSettings>(); + let lower_settings = cfg.try_deserialize::<StructSettings>().unwrap(); + + match cap_settings { + Ok(v) => { + // this assertion will ensure that the map has only lowercase keys + assert_ne!(v.FOO, "FOO should be overridden"); + assert_eq!( + lower_settings.foo, + "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string() + ); + } + Err(e) => { + if e.to_string().contains("missing field `FOO`") { + assert_eq!( + lower_settings.foo, + "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string() + ); + } else { + panic!("{}", e); + } + } + } +} + +#[test] +fn test_override_lowercase_value_for_struct() { + std::env::set_var("config_foo", "I have been overridden_with_lower_case"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings", FileFormat::Json5)) + .add_source(config::Environment::with_prefix("config").separator("_")) + .build() + .unwrap(); + + let values: StructSettings = cfg.try_deserialize().unwrap(); + assert_eq!( + values.foo, + "I have been overridden_with_lower_case".to_string() + ); + assert_ne!(values.foo, "I am bar".to_string()); +} + +#[test] +fn test_override_uppercase_value_for_enums() { + std::env::set_var("APPS_BAR", "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings-enum-test", FileFormat::Json5)) + .add_source(config::Environment::with_prefix("APPS").separator("_")) + .build() + .unwrap(); + let val: EnumSettings = cfg.try_deserialize().unwrap(); + + assert_eq!( + val, + EnumSettings::Bar("I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string()) + ); +} + +#[test] +fn test_override_lowercase_value_for_enums() { + std::env::set_var("test_bar", "I have been overridden_with_lower_case"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings-enum-test", FileFormat::Json5)) + .add_source(config::Environment::with_prefix("test").separator("_")) + .build() + .unwrap(); + + let param: EnumSettings = cfg.try_deserialize().unwrap(); + + assert_eq!( + param, + EnumSettings::Bar("I have been overridden_with_lower_case".to_string()) + ); +} diff --git a/tests/file_ron.rs b/tests/file_ron.rs index 64e2cae..9f1ea35 100644 --- a/tests/file_ron.rs +++ b/tests/file_ron.rs @@ -89,3 +89,107 @@ fn test_error_parse() { format!("4:1: Expected colon in {}", path_with_extension.display()) ); } + +#[derive(Debug, Deserialize, PartialEq)] +enum EnumSettings { + Bar(String), +} + +#[derive(Debug, Deserialize, PartialEq)] +struct StructSettings { + foo: String, + bar: String, +} +#[derive(Debug, Deserialize, PartialEq)] +#[allow(non_snake_case)] +struct CapSettings { + FOO: String, +} + +#[test] +fn test_override_uppercase_value_for_struct() { + std::env::set_var("APP_FOO", "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings", FileFormat::Ron)) + .add_source(config::Environment::with_prefix("APP").separator("_")) + .build() + .unwrap(); + + let cap_settings = cfg.clone().try_deserialize::<CapSettings>(); + let lower_settings = cfg.try_deserialize::<StructSettings>().unwrap(); + + match cap_settings { + Ok(v) => { + // this assertion will ensure that the map has only lowercase keys + assert_ne!(v.FOO, "FOO should be overridden"); + assert_eq!( + lower_settings.foo, + "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string() + ); + } + Err(e) => { + if e.to_string().contains("missing field `FOO`") { + assert_eq!( + lower_settings.foo, + "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string() + ); + } else { + panic!("{}", e); + } + } + } +} + +#[test] +fn test_override_lowercase_value_for_struct() { + std::env::set_var("config_foo", "I have been overridden_with_lower_case"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings", FileFormat::Ron)) + .add_source(config::Environment::with_prefix("config").separator("_")) + .build() + .unwrap(); + + let values: StructSettings = cfg.try_deserialize().unwrap(); + assert_eq!( + values.foo, + "I have been overridden_with_lower_case".to_string() + ); + assert_ne!(values.foo, "I am bar".to_string()); +} + +#[test] +fn test_override_uppercase_value_for_enums() { + std::env::set_var("APPS_BAR", "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings-enum-test", FileFormat::Ron)) + .add_source(config::Environment::with_prefix("APPS").separator("_")) + .build() + .unwrap(); + let val: EnumSettings = cfg.try_deserialize().unwrap(); + + assert_eq!( + val, + EnumSettings::Bar("I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string()) + ); +} + +#[test] +fn test_override_lowercase_value_for_enums() { + std::env::set_var("test_bar", "I have been overridden_with_lower_case"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings-enum-test", FileFormat::Ron)) + .add_source(config::Environment::with_prefix("test").separator("_")) + .build() + .unwrap(); + + let param: EnumSettings = cfg.try_deserialize().unwrap(); + + assert_eq!( + param, + EnumSettings::Bar("I have been overridden_with_lower_case".to_string()) + ); +} diff --git a/tests/file_toml.rs b/tests/file_toml.rs index 9c5ee57..6ab1a2c 100644 --- a/tests/file_toml.rs +++ b/tests/file_toml.rs @@ -101,3 +101,107 @@ fn test_error_parse() { ) ); } + +#[derive(Debug, Deserialize, PartialEq)] +enum EnumSettings { + Bar(String), +} +#[derive(Debug, Deserialize, PartialEq)] +struct StructSettings { + foo: String, + bar: String, +} +#[derive(Debug, Deserialize, PartialEq)] +#[allow(non_snake_case)] +struct CapSettings { + FOO: String, +} + +#[test] +fn test_override_uppercase_value_for_struct() { + std::env::set_var("APP_FOO", "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings.toml", FileFormat::Toml)) + .add_source(config::Environment::with_prefix("APP").separator("_")) + .build() + .unwrap(); + + let cap_settings = cfg.clone().try_deserialize::<CapSettings>(); + let lower_settings = cfg.try_deserialize::<StructSettings>().unwrap(); + + match cap_settings { + Ok(v) => { + // this assertion will ensure that the map has only lowercase keys + assert_ne!(v.FOO, "FOO should be overridden"); + assert_eq!( + lower_settings.foo, + "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string() + ); + } + Err(e) => { + if e.to_string().contains("missing field `FOO`") { + assert_eq!( + lower_settings.foo, + "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string() + ); + } else { + panic!("{}", e); + } + } + } +} + +#[test] +fn test_override_lowercase_value_for_struct() { + std::env::set_var("config_bar", "I have been overridden_with_lower_case"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings.toml", FileFormat::Toml)) + .add_source(config::Environment::with_prefix("config").separator("_")) + .build() + .unwrap(); + + let values: StructSettings = cfg.try_deserialize().unwrap(); + assert_eq!( + values.bar, + "I have been overridden_with_lower_case".to_string() + ); + assert_ne!(values.bar, "I am bar".to_string()); +} + +#[test] +fn test_override_uppercase_value_for_enums() { + std::env::set_var("APPS_BAR", "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE"); + + let cfg = Config::builder() + .add_source(File::new("tests/Settings-enum-test.toml", FileFormat::Toml)) + .add_source(config::Environment::with_prefix("APPS").separator("_")) + .build() + .unwrap(); + + let values: EnumSettings = cfg.try_deserialize().unwrap(); + + assert_eq!( + values, + EnumSettings::Bar("I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE".to_string()) + ); +} + +#[test] +fn test_override_lowercase_value_for_enums() { + std::env::set_var("test_bar", "I have been overridden_with_lower_case"); + + let cfg = Config::builder() + .add_source(File::new("tests |