use std::env;
use std::fs;
use std::path::PathBuf;
const ABSENT_KEY: &str = "DOTENV_VERBATIM_TEST_ABSENT";
const PRESET_KEY: &str = "DOTENV_VERBATIM_TEST_PRESET";
const DUPLICATE_KEY: &str = "DOTENV_VERBATIM_TEST_DUPLICATE";
const PRESET_DUPLICATE_KEY: &str = "DOTENV_VERBATIM_TEST_PRESET_DUPLICATE";
const BEFORE_BAD_LINE_KEY: &str = "DOTENV_VERBATIM_TEST_BEFORE_BAD_LINE";
const AFTER_BAD_LINE_KEY: &str = "DOTENV_VERBATIM_TEST_AFTER_BAD_LINE";
const MISSING_FILE_KEY: &str = "DOTENV_VERBATIM_TEST_MISSING_FILE";
const EMPTY_VALUE_KEY: &str = "DOTENV_VERBATIM_TEST_EMPTY_VALUE";
#[test]
fn load_reports_what_it_applied() {
applies_a_variable_the_process_does_not_carry();
reports_a_variable_the_process_carries_as_overridden();
reports_a_second_occurrence_as_repeated();
reports_an_overridden_key_repeated_in_the_file();
reports_an_unusable_line_by_number_and_applies_the_rest();
reports_a_missing_file_as_not_found();
applies_an_empty_value_as_an_empty_string();
}
fn applies_a_variable_the_process_does_not_carry() {
let loaded = load_content("absent", &format!("{ABSENT_KEY}=from-file\n"));
assert_eq!(loaded.applied, vec![ABSENT_KEY]);
assert!(loaded.overridden.is_empty());
assert_eq!(env::var(ABSENT_KEY).unwrap(), "from-file");
}
fn reports_a_variable_the_process_carries_as_overridden() {
env::set_var(PRESET_KEY, "from-process");
let loaded = load_content("preset", &format!("{PRESET_KEY}=from-file\n"));
assert_eq!(loaded.overridden, vec![PRESET_KEY]);
assert!(loaded.applied.is_empty());
assert_eq!(env::var(PRESET_KEY).unwrap(), "from-process");
}
fn reports_a_second_occurrence_as_repeated() {
let content = format!("{DUPLICATE_KEY}=first\n{DUPLICATE_KEY}=second\n");
let loaded = load_content("duplicate", &content);
assert_eq!(loaded.applied, vec![DUPLICATE_KEY]);
assert_eq!(loaded.repeated, vec![DUPLICATE_KEY]);
assert_eq!(env::var(DUPLICATE_KEY).unwrap(), "first");
}
fn reports_an_overridden_key_repeated_in_the_file() {
env::set_var(PRESET_DUPLICATE_KEY, "from-process");
let content = format!("{PRESET_DUPLICATE_KEY}=first\n{PRESET_DUPLICATE_KEY}=second\n");
let loaded = load_content("preset-duplicate", &content);
assert_eq!(loaded.overridden, vec![PRESET_DUPLICATE_KEY]);
assert_eq!(loaded.repeated, vec![PRESET_DUPLICATE_KEY]);
assert!(loaded.applied.is_empty());
assert_eq!(env::var(PRESET_DUPLICATE_KEY).unwrap(), "from-process");
}
fn reports_an_unusable_line_by_number_and_applies_the_rest() {
let content = format!("{BEFORE_BAD_LINE_KEY}=1\nnosep\n{AFTER_BAD_LINE_KEY}=2\n");
let loaded = load_content("unusable-line", &content);
assert_eq!(loaded.skipped, vec![2]);
assert_eq!(
loaded.applied,
vec![BEFORE_BAD_LINE_KEY, AFTER_BAD_LINE_KEY]
);
assert_eq!(env::var(AFTER_BAD_LINE_KEY).unwrap(), "2");
}
fn reports_a_missing_file_as_not_found() {
let env_file = temp_path("missing");
fs::write(&env_file, format!("{MISSING_FILE_KEY}=from-file\n")).unwrap();
fs::remove_file(&env_file).unwrap();
let loaded = dotenv_verbatim::load(&env_file);
assert!(!loaded.found);
assert!(loaded.applied.is_empty());
assert!(loaded.overridden.is_empty());
assert!(loaded.repeated.is_empty());
assert!(loaded.skipped.is_empty());
assert!(env::var_os(MISSING_FILE_KEY).is_none());
}
fn applies_an_empty_value_as_an_empty_string() {
let loaded = load_content("empty-value", &format!("{EMPTY_VALUE_KEY}=\n"));
assert_eq!(loaded.applied, vec![EMPTY_VALUE_KEY]);
assert_eq!(env::var(EMPTY_VALUE_KEY).unwrap(), "");
}
fn load_content(tag: &str, content: &str) -> dotenv_verbatim::Loaded {
let env_file = temp_path(tag);
fs::write(&env_file, content).unwrap();
let loaded = dotenv_verbatim::load(&env_file);
fs::remove_file(&env_file).unwrap();
assert!(loaded.found);
loaded
}
fn temp_path(tag: &str) -> PathBuf {
env::temp_dir().join(format!("dotenv-verbatim-{}-{tag}.env", std::process::id()))
}