Skip to content

Commit d035daa

Browse files
committed
Fix tests for handling env key overlaps / errors
1 parent e49b3ae commit d035daa

File tree

2 files changed

+34
-24
lines changed

2 files changed

+34
-24
lines changed

src/cargo/util/config/de.rs

+2-11
Original file line numberDiff line numberDiff line change
@@ -298,20 +298,11 @@ impl<'config> ConfigMapAccess<'config> {
298298
// If the caller is interested in a field which we can provide from
299299
// the environment, get it from there.
300300
for field in given_fields {
301-
let is_prefix = given_fields
302-
.iter()
303-
.any(|f| f != field && f.starts_with(field));
304301
let mut field_key = de.key.clone();
305302
field_key.push(field);
306303
for env_key in de.config.env.keys() {
307-
if is_prefix {
308-
if env_key == field_key.as_env_key() {
309-
fields.insert(KeyKind::Normal(field.to_string()));
310-
}
311-
} else {
312-
if env_key.starts_with(field_key.as_env_key()) {
313-
fields.insert(KeyKind::Normal(field.to_string()));
314-
}
304+
if env_key.starts_with(field_key.as_env_key()) {
305+
fields.insert(KeyKind::Normal(field.to_string()));
315306
}
316307
}
317308
}

tests/testsuite/config.rs

+32-13
Original file line numberDiff line numberDiff line change
@@ -1299,8 +1299,13 @@ fn overlapping_env_config() {
12991299
}
13001300

13011301
#[cargo_test]
1302-
fn overlapping_env_with_defaults() {
1302+
fn overlapping_env_with_defaults_errors_out() {
13031303
// Issue where one key is a prefix of another.
1304+
// This is a limitation of mapping environment variables on to a hierarchy.
1305+
// Check that we error out when we hit ambiguity in this way, rather than
1306+
// the more-surprising defaulting through.
1307+
// If, in the future, we can handle this more correctly, feel free to delete
1308+
// this test.
13041309
#[derive(Deserialize, Default)]
13051310
#[serde(default, rename_all = "kebab-case")]
13061311
struct Ambig {
@@ -1310,10 +1315,8 @@ fn overlapping_env_with_defaults() {
13101315
let config = ConfigBuilder::new()
13111316
.env("CARGO_AMBIG_DEBUG_ASSERTIONS", "true")
13121317
.build();
1313-
1314-
let s: Ambig = config.get("ambig").unwrap();
1315-
assert_eq!(s.debug_assertions, true);
1316-
assert_eq!(s.debug, u32::default());
1318+
let err = config.get::<Ambig>("ambig").err().unwrap();
1319+
assert!(format!("{}", err).contains("missing config key `ambig.debug`"));
13171320

13181321
let config = ConfigBuilder::new().env("CARGO_AMBIG_DEBUG", "5").build();
13191322
let s: Ambig = config.get("ambig").unwrap();
@@ -1340,7 +1343,12 @@ fn struct_with_overlapping_inner_struct_and_defaults() {
13401343
}
13411344

13421345
// Containing struct with a prefix of inner
1343-
// Check that the nested struct can have fields defined by env
1346+
//
1347+
// This is a limitation of mapping environment variables on to a hierarchy.
1348+
// Check that we error out when we hit ambiguity in this way, rather than
1349+
// the more-surprising defaulting through.
1350+
// If, in the future, we can handle this more correctly, feel free to delete
1351+
// this case.
13441352
#[derive(Deserialize, Default)]
13451353
#[serde(default)]
13461354
struct PrefixContainer {
@@ -1350,27 +1358,38 @@ fn struct_with_overlapping_inner_struct_and_defaults() {
13501358
let config = ConfigBuilder::new()
13511359
.env("CARGO_PREFIXCONTAINER_INNER_VALUE", "12")
13521360
.build();
1361+
let err = config
1362+
.get::<PrefixContainer>("prefixcontainer")
1363+
.err()
1364+
.unwrap();
1365+
assert!(format!("{}", err).contains("missing config key `prefixcontainer.inn`"));
1366+
let config = ConfigBuilder::new()
1367+
.env("CARGO_PREFIXCONTAINER_INNER_VALUE", "12")
1368+
.env("CARGO_PREFIXCONTAINER_INN", "true")
1369+
.build();
13531370
let f: PrefixContainer = config.get("prefixcontainer").unwrap();
1354-
assert_eq!(f.inn, bool::default());
13551371
assert_eq!(f.inner.value, 12);
1372+
assert_eq!(f.inn, true);
13561373

13571374
// Containing struct where the inner value's field is a prefix of another
1358-
// Check that the nested struct can have fields defined by env
1375+
//
1376+
// This is a limitation of mapping environment variables on to a hierarchy.
1377+
// Check that we error out when we hit ambiguity in this way, rather than
1378+
// the more-surprising defaulting through.
1379+
// If, in the future, we can handle this more correctly, feel free to delete
1380+
// this case.
13591381
#[derive(Deserialize, Default)]
13601382
#[serde(default)]
13611383
struct InversePrefixContainer {
13621384
inner_field: bool,
13631385
inner: Inner,
13641386
}
13651387
let config = ConfigBuilder::new()
1366-
.env("CARGO_INVERSEREFIXCONTAINER_INNER_VALUE", "12")
1388+
.env("CARGO_INVERSEPREFIXCONTAINER_INNER_VALUE", "12")
13671389
.build();
13681390
let f: InversePrefixContainer = config.get("inverseprefixcontainer").unwrap();
13691391
assert_eq!(f.inner_field, bool::default());
1370-
// NB. This is a limitation of our env variable parsing. We can't currently
1371-
// handle situations where just a value of the inner struct is set, but
1372-
// it's also named as a prefix of another field on the outer struct.
1373-
// assert_eq!(f.inner.value, 12);
1392+
assert_eq!(f.inner.value, 12);
13741393
}
13751394

13761395
#[cargo_test]

0 commit comments

Comments
 (0)