mirror of
https://github.com/darwincereska/envkit.git
synced 2026-06-11 10:23:23 -05:00
161 lines
4.6 KiB
Rust
161 lines
4.6 KiB
Rust
use envkit::{EnvLoader, error::EnvError};
|
|
use std::path::PathBuf;
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
|
|
fn unique_key(name: &str) -> String {
|
|
let nanos = SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.expect("system time should be after the Unix epoch")
|
|
.as_nanos();
|
|
|
|
format!("ENVKIT_TEST_{name}_{nanos}")
|
|
}
|
|
|
|
#[test]
|
|
fn get_reads_required_typed_values() {
|
|
let env = EnvLoader::new();
|
|
let name_key = unique_key("NAME");
|
|
let port_key = unique_key("PORT");
|
|
let debug_key = unique_key("DEBUG");
|
|
let list_key = unique_key("PORTS");
|
|
|
|
unsafe {
|
|
std::env::set_var(&name_key, "envkit");
|
|
std::env::set_var(&port_key, "3000");
|
|
std::env::set_var(&debug_key, "yes");
|
|
std::env::set_var(&list_key, "3000, 3001, 3002");
|
|
}
|
|
|
|
assert_eq!(env.get::<String>(&name_key), Ok("envkit".to_string()));
|
|
assert_eq!(env.get::<u16>(&port_key), Ok(3000));
|
|
assert_eq!(env.get::<bool>(&debug_key), Ok(true));
|
|
assert_eq!(env.get::<Vec<u16>>(&list_key), Ok(vec![3000, 3001, 3002]));
|
|
|
|
unsafe {
|
|
std::env::remove_var(name_key);
|
|
std::env::remove_var(port_key);
|
|
std::env::remove_var(debug_key);
|
|
std::env::remove_var(list_key);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn get_reports_missing_and_invalid_values() {
|
|
let env = EnvLoader::new();
|
|
let missing_key = unique_key("MISSING");
|
|
let invalid_key = unique_key("INVALID");
|
|
|
|
unsafe {
|
|
std::env::remove_var(&missing_key);
|
|
std::env::set_var(&invalid_key, "not-a-port");
|
|
}
|
|
|
|
assert_eq!(
|
|
env.get::<String>(&missing_key),
|
|
Err(EnvError::MissingVar(missing_key.clone()))
|
|
);
|
|
|
|
assert!(matches!(
|
|
env.get::<u16>(&invalid_key),
|
|
Err(EnvError::Invalid { key, value, .. })
|
|
if key == "u16" && value == "not-a-port"
|
|
));
|
|
|
|
unsafe {
|
|
std::env::remove_var(invalid_key);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn get_or_and_get_opt_handle_fallbacks() {
|
|
let env = EnvLoader::new();
|
|
let present_key = unique_key("PRESENT");
|
|
let missing_key = unique_key("DEFAULT");
|
|
let invalid_key = unique_key("BAD_BOOL");
|
|
|
|
unsafe {
|
|
std::env::set_var(&present_key, "42");
|
|
std::env::remove_var(&missing_key);
|
|
std::env::set_var(&invalid_key, "maybe");
|
|
}
|
|
|
|
assert_eq!(env.get_or::<u8>(&present_key, 7), 42);
|
|
assert_eq!(env.get_or::<u8>(&missing_key, 7), 7);
|
|
assert_eq!(env.get_or::<bool>(&invalid_key, false), false);
|
|
|
|
assert_eq!(env.get_opt::<u8>(&present_key), Some(42));
|
|
assert_eq!(env.get_opt::<u8>(&missing_key), None);
|
|
assert_eq!(env.get_opt::<bool>(&invalid_key), None);
|
|
|
|
unsafe {
|
|
std::env::remove_var(present_key);
|
|
std::env::remove_var(invalid_key);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn prefixed_loader_reads_namespaced_variables() {
|
|
let env = EnvLoader::new();
|
|
let prefix = unique_key("APP_");
|
|
let host_key = format!("{prefix}HOST");
|
|
let enabled_key = format!("{prefix}ENABLED");
|
|
|
|
unsafe {
|
|
std::env::set_var(&host_key, "127.0.0.1");
|
|
std::env::set_var(&enabled_key, "1");
|
|
}
|
|
|
|
let app = env.with_prefix(prefix);
|
|
|
|
assert_eq!(app.get::<String>("HOST"), Ok("127.0.0.1".to_string()));
|
|
assert_eq!(app.get::<bool>("ENABLED"), Ok(true));
|
|
assert_eq!(app.get_or::<u16>("PORT", 8080), 8080);
|
|
|
|
unsafe {
|
|
std::env::remove_var(host_key);
|
|
std::env::remove_var(enabled_key);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn load_file_sets_environment_variables() {
|
|
let env = EnvLoader::new();
|
|
let prefix = unique_key("FILE_");
|
|
let port_key = format!("{prefix}PORT");
|
|
let debug_key = format!("{prefix}DEBUG");
|
|
let names_key = format!("{prefix}NAMES");
|
|
let path = temp_env_file(&prefix, &port_key, &debug_key, &names_key);
|
|
|
|
env.load_file(path.to_str().expect("test path should be UTF-8"))
|
|
.expect("env file should load");
|
|
|
|
assert_eq!(env.get::<u16>(&port_key), Ok(8080));
|
|
assert_eq!(env.get::<bool>(&debug_key), Ok(true));
|
|
assert_eq!(
|
|
env.get::<Vec<String>>(&names_key),
|
|
Ok(vec!["api".to_string(), "worker".to_string()])
|
|
);
|
|
|
|
std::fs::remove_file(path).expect("test env file should be removable");
|
|
unsafe {
|
|
std::env::remove_var(port_key);
|
|
std::env::remove_var(debug_key);
|
|
std::env::remove_var(names_key);
|
|
}
|
|
}
|
|
|
|
fn temp_env_file(prefix: &str, port_key: &str, debug_key: &str, names_key: &str) -> PathBuf {
|
|
let path = std::env::temp_dir().join(format!("{prefix}.env"));
|
|
let contents = format!(
|
|
r#"
|
|
# comments and blank lines are ignored
|
|
{port_key} = 8080
|
|
{debug_key}= yes
|
|
{names_key}= api, worker
|
|
"#
|
|
);
|
|
|
|
std::fs::write(&path, contents).expect("test env file should be writable");
|
|
path
|
|
}
|