1use std::env;
2
3pub struct EnvVars;
6
7impl EnvVars {
8 pub const RUST_LOG: &'static str = "RUST_LOG";
17
18 pub const ZERV_FORCE_RUST_LOG_OFF: &'static str = "ZERV_FORCE_RUST_LOG_OFF";
23
24 pub const ZERV_TEST_NATIVE_GIT: &'static str = "ZERV_TEST_NATIVE_GIT";
28
29 pub const ZERV_TEST_DOCKER: &'static str = "ZERV_TEST_DOCKER";
33
34 pub const PAGER: &'static str = "PAGER";
43}
44
45#[derive(Debug, Clone, Default)]
46pub struct ZervConfig {
47 pub test_native_git: bool,
48 pub test_docker: bool,
49 pub force_rust_log_off: bool,
50}
51
52impl ZervConfig {
53 pub fn load() -> Result<Self, Box<dyn std::error::Error>> {
54 let test_native_git = Self::parse_bool_env(EnvVars::ZERV_TEST_NATIVE_GIT, false)?;
55 let test_docker = Self::parse_bool_env(EnvVars::ZERV_TEST_DOCKER, true)?;
56 let force_rust_log_off = Self::parse_bool_env(EnvVars::ZERV_FORCE_RUST_LOG_OFF, false)?;
57
58 Ok(ZervConfig {
59 test_native_git,
60 test_docker,
61 force_rust_log_off,
62 })
63 }
64
65 pub fn parse_bool_env(
66 var_name: &str,
67 default: bool,
68 ) -> Result<bool, Box<dyn std::error::Error>> {
69 match env::var(var_name) {
70 Ok(val) => Ok(val == "true" || val == "1"),
71 Err(_) => Ok(default),
72 }
73 }
74
75 pub fn should_use_native_git(&self) -> bool {
76 self.test_native_git
77 }
78
79 pub fn should_run_docker_tests(&self) -> bool {
80 self.test_docker
81 }
82
83 pub fn should_force_rust_log_off(&self) -> bool {
84 self.force_rust_log_off
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use std::env;
91
92 use serial_test::serial;
93
94 use super::*;
95
96 struct EnvGuard {
97 vars: Vec<(String, Option<String>)>,
98 }
99
100 impl EnvGuard {
101 fn new(var_names: &[&str]) -> Self {
102 let vars = var_names
103 .iter()
104 .map(|&name| (name.to_string(), env::var(name).ok()))
105 .collect();
106 Self { vars }
107 }
108 }
109
110 impl Drop for EnvGuard {
111 fn drop(&mut self) {
112 for (name, value) in &self.vars {
113 unsafe {
114 match value {
115 Some(val) => env::set_var(name, val),
116 None => env::remove_var(name),
117 }
118 }
119 }
120 }
121 }
122
123 #[test]
124 #[serial]
125 fn test_default_config() {
126 let _guard = EnvGuard::new(&[
127 EnvVars::ZERV_TEST_NATIVE_GIT,
128 EnvVars::ZERV_TEST_DOCKER,
129 EnvVars::ZERV_FORCE_RUST_LOG_OFF,
130 ]);
131 unsafe {
132 env::remove_var(EnvVars::ZERV_TEST_NATIVE_GIT);
133 env::remove_var(EnvVars::ZERV_TEST_DOCKER);
134 env::remove_var(EnvVars::ZERV_FORCE_RUST_LOG_OFF);
135 }
136
137 let config = ZervConfig::load().expect("Failed to load default config");
138 assert!(!config.should_use_native_git());
139 assert!(config.should_run_docker_tests());
140 assert!(!config.should_force_rust_log_off());
141 }
142
143 #[test]
144 #[serial]
145 fn test_native_git_env_var() {
146 let _guard = EnvGuard::new(&[
147 EnvVars::ZERV_TEST_NATIVE_GIT,
148 EnvVars::ZERV_TEST_DOCKER,
149 EnvVars::ZERV_FORCE_RUST_LOG_OFF,
150 ]);
151 unsafe {
152 env::remove_var(EnvVars::ZERV_TEST_DOCKER);
153 env::remove_var(EnvVars::ZERV_FORCE_RUST_LOG_OFF);
154 env::set_var(EnvVars::ZERV_TEST_NATIVE_GIT, "true");
155 }
156
157 let config = ZervConfig::load().expect("Failed to load config with native git enabled");
158 assert!(config.should_use_native_git());
159 assert!(config.should_run_docker_tests());
160 assert!(!config.should_force_rust_log_off());
161 }
162
163 #[test]
164 #[serial]
165 fn test_docker_tests_env_var() {
166 let _guard = EnvGuard::new(&[
167 EnvVars::ZERV_TEST_NATIVE_GIT,
168 EnvVars::ZERV_TEST_DOCKER,
169 EnvVars::ZERV_FORCE_RUST_LOG_OFF,
170 ]);
171 unsafe {
172 env::remove_var(EnvVars::ZERV_TEST_NATIVE_GIT);
173 env::remove_var(EnvVars::ZERV_FORCE_RUST_LOG_OFF);
174 env::set_var(EnvVars::ZERV_TEST_DOCKER, "true");
175 }
176
177 let config = ZervConfig::load().expect("Failed to load config with docker tests enabled");
178 assert!(!config.should_use_native_git());
179 assert!(config.should_run_docker_tests());
180 assert!(!config.should_force_rust_log_off());
181 }
182
183 #[test]
184 #[serial]
185 fn test_both_env_vars() {
186 let _guard = EnvGuard::new(&[
187 EnvVars::ZERV_TEST_NATIVE_GIT,
188 EnvVars::ZERV_TEST_DOCKER,
189 EnvVars::ZERV_FORCE_RUST_LOG_OFF,
190 ]);
191 unsafe {
192 env::set_var(EnvVars::ZERV_TEST_NATIVE_GIT, "true");
193 env::set_var(EnvVars::ZERV_TEST_DOCKER, "true");
194 env::remove_var(EnvVars::ZERV_FORCE_RUST_LOG_OFF);
195 }
196
197 let config = ZervConfig::load().expect("Failed to load config with both env vars set");
198 assert!(config.should_use_native_git());
199 assert!(config.should_run_docker_tests());
200 assert!(!config.should_force_rust_log_off());
201 }
202
203 #[test]
204 #[serial]
205 fn test_false_values() {
206 let _guard = EnvGuard::new(&[
207 EnvVars::ZERV_TEST_NATIVE_GIT,
208 EnvVars::ZERV_TEST_DOCKER,
209 EnvVars::ZERV_FORCE_RUST_LOG_OFF,
210 ]);
211 unsafe {
212 env::set_var(EnvVars::ZERV_TEST_NATIVE_GIT, "false");
213 env::set_var(EnvVars::ZERV_TEST_DOCKER, "false");
214 env::set_var(EnvVars::ZERV_FORCE_RUST_LOG_OFF, "false");
215 }
216
217 let config = ZervConfig::load().expect("Failed to load config with false values");
218 assert!(!config.should_use_native_git());
219 assert!(!config.should_run_docker_tests());
220 assert!(!config.should_force_rust_log_off());
221 }
222
223 #[test]
224 #[serial]
225 fn test_force_rust_log_off_env_var() {
226 let _guard = EnvGuard::new(&[
227 EnvVars::ZERV_TEST_NATIVE_GIT,
228 EnvVars::ZERV_TEST_DOCKER,
229 EnvVars::ZERV_FORCE_RUST_LOG_OFF,
230 ]);
231 unsafe {
232 env::remove_var(EnvVars::ZERV_TEST_NATIVE_GIT);
233 env::remove_var(EnvVars::ZERV_TEST_DOCKER);
234 env::set_var(EnvVars::ZERV_FORCE_RUST_LOG_OFF, "true");
235 }
236
237 let config =
238 ZervConfig::load().expect("Failed to load config with force rust log off enabled");
239 assert!(!config.should_use_native_git());
240 assert!(config.should_run_docker_tests());
241 assert!(config.should_force_rust_log_off());
242 }
243}