use crate::env_layers::{AmbientLookup, LayeredEnv};
use std::collections::BTreeMap;
use std::sync::Arc;
fn ambient_from(map: &[(&str, &str)]) -> AmbientLookup {
let map: BTreeMap<String, String> = map
.iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect();
Arc::new(move |key| map.get(key).cloned())
}
#[test]
fn env_document_value_wins_over_unlisted_ambient() {
let doc = BTreeMap::from([("HTTP_PORT".to_string(), "18080".to_string())]);
let env = LayeredEnv::new(
doc,
BTreeMap::new(),
Vec::new(),
ambient_from(&[("HTTP_PORT", "8080")]),
);
assert_eq!(env.lookup("HTTP_PORT").as_deref(), Some("18080"));
}
#[test]
fn harness_provisioned_wins_over_doc() {
let env = LayeredEnv::new(
BTreeMap::from([("KEY".to_string(), "doc-value".to_string())]),
BTreeMap::from([("KEY".to_string(), "harness-value".to_string())]),
Vec::new(),
ambient_from(&[("KEY", "ambient-value")]),
);
assert_eq!(env.lookup("KEY").as_deref(), Some("harness-value"));
}
#[test]
fn env_unlisted_ambient_is_invisible() {
let env = LayeredEnv::new(
BTreeMap::new(),
BTreeMap::new(),
Vec::new(),
ambient_from(&[("NOPE", "leaked")]),
);
assert_eq!(env.lookup("NOPE"), None);
let lookup = |key: &str| env.lookup(key);
let mut tree = toml::Value::Table(toml::toml! { port = "${env:NOPE}" });
let err = camel_config::config::resolve_tree_with(&mut tree, &lookup)
.expect_err("unlisted ambient must not resolve");
assert!(
err.to_string().contains("NOPE"),
"error must name the variable: {err}"
);
}
#[test]
fn env_allowlisted_passthrough_visible() {
let env = LayeredEnv::new(
BTreeMap::new(),
BTreeMap::new(),
vec!["API_KEY".to_string()],
ambient_from(&[("API_KEY", "secret-value")]),
);
assert_eq!(env.lookup("API_KEY").as_deref(), Some("secret-value"));
}
#[test]
fn with_harness_var_extends_harness_layer() {
let base = LayeredEnv::new(
BTreeMap::from([("INBOUND".to_string(), "doc-value".to_string())]),
BTreeMap::new(),
Vec::new(),
ambient_from(&[]),
);
let extended = base.with_harness_var("INBOUND", "http://127.0.0.1:41000".to_string());
assert_eq!(
extended.lookup("INBOUND").as_deref(),
Some("http://127.0.0.1:41000"),
"the extension must land in the harness layer, above the doc map"
);
assert_eq!(
base.lookup("INBOUND").as_deref(),
Some("doc-value"),
"the receiver must stay untouched"
);
}