summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2022-09-17 15:53:13 +0200
committerGitHub <noreply@github.com>2022-09-17 15:53:13 +0200
commit0d58da27e7e8ff0e80d8088e26413a8bb3c8e372 (patch)
tree076d223c2b34f236ea7a0b46d654eac42e18cacd
parentbfe819a943d8d68124eeafe9b268c7c3036ddb11 (diff)
parentb2dfb937e2e212ce5809c8deb5af112e1aeb7651 (diff)
Merge pull request #354 from YounessBird/fix-uppercase-lowercase-isses
Fix uppercase lowercase isses
-rw-r--r--README.md8
-rw-r--r--src/config.rs10
-rw-r--r--src/de.rs2
-rw-r--r--src/path/mod.rs16
-rw-r--r--tests/Settings-enum-test.ini2
-rw-r--r--tests/Settings-enum-test.json3
-rw-r--r--tests/Settings-enum-test.json53
-rw-r--r--tests/Settings-enum-test.ron3
-rw-r--r--tests/Settings-enum-test.toml2
-rw-r--r--tests/Settings-enum-test.yaml2
-rw-r--r--tests/Settings-upper-struct.toml3
-rw-r--r--tests/Settings.ini2
-rw-r--r--tests/Settings.json4
-rw-r--r--tests/Settings.json54
-rw-r--r--tests/Settings.ron4
-rw-r--r--tests/Settings.toml4
-rw-r--r--tests/Settings.yaml3
-rw-r--r--tests/file_ini.rs103
-rw-r--r--tests/file_json.rs105
-rw-r--r--tests/file_json5.rs104
-rw-r--r--tests/file_ron.rs104
-rw-r--r--tests/file_toml.rs104
-rw-r--r--tests/file_yaml.rs105
23 files changed, 682 insertions, 18 deletions
diff --git a/README.md b/README.md
index 627cc87..b68813e 100644
--- a/README.md
+++ b/README.md
@@ -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()?;
diff --git a/src/de.rs b/src/de.rs
index 4794ec4..8d45140 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -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