GitBaby/tests/env.rs
zhenyi 680411c4fb chore: initialize gitbaby repository
gitbaby is an asynchronous Rust library wrapping git operations, built on
gix + tokio + async-trait.

Module layout:
- archive, blame, blob, branch, cleanup, commit, compare, config,
  conflict, diff, merge, refs, remote, setup, share, submodule, tags,
  tree (feature modules)
- command: command scheduler (cmd/env/pipe/context/error)
- repo: RepositoryFacade trait (consumers implement, exposing a
  gix::Repository)

Features:
- async API on tokio 1.53
- order-preserving Env (Vec<(String, String)>)
- hand-written BabyError / CmdError, not using thiserror derive
- integration tests covering cmd_run / context / env / pipe (env keys
  prefixed for isolation)

CI: none, standard cargo build / test / clippy / fmt only
2026-08-14 18:10:04 +08:00

138 lines
3.5 KiB
Rust

use gitbaby::command::env::Env;
use std::sync::{Mutex, MutexGuard, PoisonError};
static ENV_LOCK: Mutex<()> = Mutex::new(());
fn lock_or_recover() -> MutexGuard<'static, ()> {
match ENV_LOCK.lock() {
Ok(g) => g,
Err(PoisonError { .. }) => panic!("env lock poisoned"),
}
}
fn unique_key(suffix: &str) -> String {
format!("GITBABY_TEST_ENV_{suffix}")
}
unsafe fn set_var(key: &str, val: &str) {
unsafe { std::env::set_var(key, val) }
}
unsafe fn remove_var(key: &str) {
unsafe { std::env::remove_var(key) }
}
#[test]
fn from_current_env_includes_system_var() {
let _guard = lock_or_recover();
let key = unique_key("FROM_CUR");
unsafe { set_var(&key, "from-system") };
let env = Env::from_current_env();
assert_eq!(env.get(&key), Some("from-system"));
unsafe { remove_var(&key) };
}
#[test]
fn from_current_env_contains_path_like_var() {
let env = Env::from_current_env();
assert!(env.get("PATH").is_some() || env.get("Path").is_some() || !env.is_empty());
}
#[test]
fn set_overrides_system_var_after_from_current_env() {
let _guard = lock_or_recover();
let key = unique_key("OVERRIDE");
unsafe { set_var(&key, "system-value") };
let mut env = Env::from_current_env();
env.set(&key, "user-value");
assert_eq!(env.get(&key), Some("user-value"));
unsafe { remove_var(&key) };
}
#[test]
fn with_current_env_overrides_user_added_var() {
let _guard = lock_or_recover();
let key = unique_key("WC_OVERRIDE");
unsafe { set_var(&key, "system-wins") };
let env = Env::new().with(&key, "user-loses").with_current_env();
assert_eq!(env.get(&key), Some("system-wins"));
unsafe { remove_var(&key) };
}
#[test]
fn overlay_current_env_preserves_user_added_var() {
let _guard = lock_or_recover();
let key = unique_key("OVERLAY");
unsafe { set_var(&key, "system-value") };
let env = Env::new().with(&key, "user-keeps").overlay_current_env();
assert_eq!(env.get(&key), Some("user-keeps"));
unsafe { remove_var(&key) };
}
#[test]
fn overlay_current_env_fills_missing_keys() {
let _guard = lock_or_recover();
let mut iter = std::env::vars_os();
let known = match iter.next() {
Some(v) => v,
None => panic!("process should have at least one env var"),
};
let known_key = known.0.to_string_lossy().into_owned();
let env = Env::new().overlay_current_env();
assert!(env.get(&known_key).is_some());
}
#[test]
fn unset_removes_system_var_when_loaded() {
let _guard = lock_or_recover();
let key = unique_key("UNSET");
unsafe { set_var(&key, "temp") };
let mut env = Env::from_current_env();
assert_eq!(env.get(&key), Some("temp"));
env.unset(&key);
assert_eq!(env.get(&key), None);
unsafe { remove_var(&key) };
}
#[test]
fn from_current_env_is_cloneable() {
let _guard = lock_or_recover();
let key = unique_key("CLONE");
unsafe { set_var(&key, "v") };
let env = Env::from_current_env();
let copy = env.clone();
assert_eq!(env.get(&key), Some("v"));
assert_eq!(copy.get(&key), Some("v"));
unsafe { remove_var(&key) };
}
#[test]
fn set_after_from_current_env_does_not_grow_pairs_when_key_known() {
let _guard = lock_or_recover();
let key = unique_key("NOGROW");
unsafe { set_var(&key, "system") };
let mut env = Env::from_current_env();
let before = env.len();
env.set(&key, "user");
let after = env.len();
assert_eq!(before, after, "set 应替换而非新增");
assert_eq!(env.get(&key), Some("user"));
unsafe { remove_var(&key) };
}