1pub trait EnvSource {
10 fn get(&self, name: &str) -> Option<String>;
12}
13
14#[derive(Debug, Default, Clone, Copy)]
16pub struct SystemEnvSource;
17
18impl EnvSource for SystemEnvSource {
19 fn get(&self, name: &str) -> Option<String> {
20 std::env::var(name).ok()
21 }
22}
23
24#[derive(Debug, Default, Clone)]
26pub struct MockEnvSource {
27 vars: std::collections::HashMap<String, String>,
28}
29
30impl MockEnvSource {
31 pub fn new() -> Self {
33 Self::default()
34 }
35
36 pub fn with(mut self, name: &str, value: &str) -> Self {
38 self.vars.insert(name.to_string(), value.to_string());
39 self
40 }
41}
42
43impl EnvSource for MockEnvSource {
44 fn get(&self, name: &str) -> Option<String> {
45 self.vars.get(name).cloned()
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn mock_env_source_reads_set_vars() {
55 let env = MockEnvSource::new().with("CI_TOKEN", "abc");
56 assert_eq!(env.get("CI_TOKEN").as_deref(), Some("abc"));
57 assert_eq!(env.get("MISSING"), None);
58 }
59}