use pound::{
Error,
Parse,
};
#[derive(Parse)]
#[pound(name = "app")]
struct Cli {
#[pound(long, env = "POUND_TOKEN")]
token: Option<String>,
#[pound(long, env = "POUND_LEVEL", default = "info")]
level: String,
}
#[derive(Parse)]
#[pound(name = "req")]
struct Req {
#[pound(long, env = "POUND_REQ")]
req: String,
}
#[derive(Parse, Debug)]
#[pound(name = "bounded")]
struct Bounded {
#[pound(long, env = "POUND_BOUNDED", max_len = "3")]
value: String,
}
fn set(k: &str, v: &str) {
unsafe { std::env::set_var(k, v) };
}
fn clear(k: &str) {
unsafe { std::env::remove_var(k) };
}
const fn no_args() -> Vec<&'static str> {
Vec::new()
}
#[test]
fn env_fallback_precedence() {
clear("POUND_TOKEN");
clear("POUND_LEVEL");
clear("POUND_REQ");
clear("POUND_BOUNDED");
let c = Cli::try_parse_from(no_args()).unwrap();
assert_eq!(c.token, None);
assert_eq!(c.level, "info");
set("POUND_TOKEN", "from-env");
set("POUND_LEVEL", "debug");
let c = Cli::try_parse_from(no_args()).unwrap();
assert_eq!(c.token.as_deref(), Some("from-env"));
assert_eq!(c.level, "debug");
let c = Cli::try_parse_from(["--token", "cli", "--level", "trace"]).unwrap();
assert_eq!(c.token.as_deref(), Some("cli"));
assert_eq!(c.level, "trace");
assert!(Req::try_parse_from(no_args()).is_err());
set("POUND_REQ", "ok");
assert_eq!(Req::try_parse_from(no_args()).unwrap().req, "ok");
set("POUND_BOUNDED", "toolong");
match Bounded::try_parse_from(no_args()) {
Err(Error::Value { value, msg, .. }) => {
assert_eq!(value, "toolong");
assert_eq!(msg, "must be at most 3 chars");
},
other => panic!("expected env validation error, got {other:?}"),
}
assert_eq!(
Bounded::try_parse_from(["--value", "cli"]).unwrap().value,
"cli"
);
clear("POUND_TOKEN");
clear("POUND_LEVEL");
clear("POUND_REQ");
clear("POUND_BOUNDED");
}