1pub fn get_env_var(key: &str) -> anyhow::Result<String> {
27 match std::env::var(key) {
28 Ok(var) => Ok(var),
29 Err(_) => anyhow::bail!("environment variable '{key}' must be set"),
30 }
31}
32
33pub fn get_or_env_var(value: Option<String>, key: &str) -> anyhow::Result<String> {
43 match value {
44 Some(v) => Ok(v),
45 None => get_env_var(key),
46 }
47}
48
49#[must_use]
56pub fn get_or_env_var_opt(value: Option<String>, key: &str) -> Option<String> {
57 value.or_else(|| std::env::var(key).ok())
58}
59
60#[cfg(test)]
61mod tests {
62 use rstest::*;
63
64 use super::*;
65
66 #[rstest]
67 fn test_get_env_var_success() {
68 if let Ok(path) = std::env::var("PATH") {
70 let result = get_env_var("PATH");
71 assert!(result.is_ok());
72 assert_eq!(result.unwrap(), path);
73 }
74 }
75
76 #[rstest]
77 fn test_get_env_var_not_set() {
78 let result = get_env_var("NONEXISTENT_ENV_VAR_THAT_SHOULD_NOT_EXIST_12345");
80 assert!(result.is_err());
81 assert!(result.unwrap_err().to_string().contains(
82 "environment variable 'NONEXISTENT_ENV_VAR_THAT_SHOULD_NOT_EXIST_12345' must be set"
83 ));
84 }
85
86 #[rstest]
87 fn test_get_env_var_error_message_format() {
88 let var_name = "DEFINITELY_NONEXISTENT_VAR_123456789";
89 let result = get_env_var(var_name);
90 assert!(result.is_err());
91 let error_msg = result.unwrap_err().to_string();
92 assert!(error_msg.contains(var_name));
93 assert!(error_msg.contains("must be set"));
94 }
95
96 #[rstest]
97 fn test_get_or_env_var_with_some_value() {
98 let provided_value = Some("provided_value".to_string());
99 let result = get_or_env_var(provided_value, "PATH");
100 assert!(result.is_ok());
101 assert_eq!(result.unwrap(), "provided_value");
102 }
103
104 #[rstest]
105 fn test_get_or_env_var_with_none_and_env_var_set() {
106 if let Ok(path) = std::env::var("PATH") {
108 let result = get_or_env_var(None, "PATH");
109 assert!(result.is_ok());
110 assert_eq!(result.unwrap(), path);
111 }
112 }
113
114 #[rstest]
115 fn test_get_or_env_var_with_none_and_env_var_not_set() {
116 let result = get_or_env_var(None, "NONEXISTENT_ENV_VAR_THAT_SHOULD_NOT_EXIST_67890");
117 assert!(result.is_err());
118 assert!(result.unwrap_err().to_string().contains(
119 "environment variable 'NONEXISTENT_ENV_VAR_THAT_SHOULD_NOT_EXIST_67890' must be set"
120 ));
121 }
122
123 #[rstest]
124 fn test_get_or_env_var_empty_string_value() {
125 let provided_value = Some(String::new());
127 let result = get_or_env_var(provided_value, "PATH");
128 assert!(result.is_ok());
129 assert_eq!(result.unwrap(), "");
130 }
131
132 #[rstest]
133 fn test_get_or_env_var_priority() {
134 if std::env::var("PATH").is_ok() {
137 let provided = Some("custom_value_takes_priority".to_string());
138 let result = get_or_env_var(provided, "PATH");
139 assert!(result.is_ok());
140 assert_eq!(result.unwrap(), "custom_value_takes_priority");
141 }
142 }
143
144 #[rstest]
145 fn test_get_or_env_var_opt_with_some_value() {
146 let provided_value = Some("provided_value".to_string());
147 let result = get_or_env_var_opt(provided_value, "PATH");
148 assert_eq!(result, Some("provided_value".to_string()));
149 }
150
151 #[rstest]
152 fn test_get_or_env_var_opt_with_none_and_env_var_set() {
153 if let Ok(path) = std::env::var("PATH") {
154 let result = get_or_env_var_opt(None, "PATH");
155 assert_eq!(result, Some(path));
156 }
157 }
158
159 #[rstest]
160 fn test_get_or_env_var_opt_with_none_and_env_var_not_set() {
161 let result = get_or_env_var_opt(None, "NONEXISTENT_ENV_VAR_OPT_12345");
162 assert_eq!(result, None);
163 }
164
165 #[rstest]
166 fn test_get_or_env_var_opt_priority() {
167 if std::env::var("PATH").is_ok() {
169 let provided = Some("custom_value".to_string());
170 let result = get_or_env_var_opt(provided, "PATH");
171 assert_eq!(result, Some("custom_value".to_string()));
172 }
173 }
174}