aquarium_control/watchmen/
memory_config_check.rs1use crate::watchmen::memory_config::MemoryConfig;
10use thiserror::Error;
11
12#[derive(Error, Debug)]
14pub enum MemoryConfigError {
15 #[error("environment variable for memory configuration check is not configured in .toml configuration file")]
17 ConfigEnvVarNameEmpty,
18
19 #[error(
21 "result of environment variable value request ({0}) could not be parsed to numeric value"
22 )]
23 EnvVarParseError(String),
24
25 #[error("environment variable value {0} is lower than configured minimum value {1}")]
27 EnvVarValueTooLow(u64, u64),
28
29 #[error("environment variable value {0} is higher than configured maximum value {1}")]
31 EnvVarValueTooHigh(u64, u64),
32
33 #[error("environment variable {0} is not set")]
35 EnvVarNotSet(String),
36}
37
38pub fn memory_config_check(
67 memory_config: &MemoryConfig,
68) -> Result<Option<(String, u64)>, MemoryConfigError> {
69 if memory_config.env_variable_name.is_empty() {
70 return Err(MemoryConfigError::ConfigEnvVarNameEmpty);
71 }
72
73 let var_name = &memory_config.env_variable_name;
74
75 let val_string =
77 std::env::var(var_name).map_err(|_| MemoryConfigError::EnvVarNotSet(var_name.clone()))?;
78
79 let val = val_string
81 .parse::<u64>()
82 .map_err(|_| MemoryConfigError::EnvVarParseError(val_string))?;
83
84 if val < memory_config.env_variable_min_val {
86 return Err(MemoryConfigError::EnvVarValueTooLow(
87 val,
88 memory_config.env_variable_min_val,
89 ));
90 }
91 if val > memory_config.env_variable_max_val {
92 return Err(MemoryConfigError::EnvVarValueTooHigh(
93 val,
94 memory_config.env_variable_max_val,
95 ));
96 }
97
98 Ok(Some((var_name.clone(), val)))
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105 use std::env;
106
107 fn create_test_config() -> MemoryConfig {
109 MemoryConfig {
110 active: true,
111 execute: false,
112 env_variable_name: "TEST_VAR".to_string(),
113 env_variable_min_val: 1,
114 env_variable_max_val: 10,
115 #[cfg(feature = "jemalloc")]
116 max_resident: 0,
117 #[cfg(feature = "jemalloc")]
118 max_allocated: 0,
119 check_interval: 0,
120 }
121 }
122
123 #[test]
125 fn test_empty_env_variable_name_returns_error() {
126 let mut config = create_test_config();
127 config.env_variable_name = String::new();
128
129 let result = memory_config_check(&config);
130 assert!(matches!(
131 result,
132 Err(MemoryConfigError::ConfigEnvVarNameEmpty)
133 ));
134 }
135
136 #[test]
138 fn test_unset_env_variable_returns_error() {
139 let mut config = create_test_config();
140 let exotic_name = "EXOTIC_VAR_NAME_THAT_DOES_NOT_EXIST_123";
141 config.env_variable_name = exotic_name.to_string();
142
143 env::remove_var(exotic_name);
145
146 let result = memory_config_check(&config);
147 match result {
148 Err(MemoryConfigError::EnvVarNotSet(name)) => {
149 assert_eq!(name, exotic_name);
150 }
151 _ => panic!("{}: Expected EnvVarNotSet error", module_path!()),
152 }
153 }
154
155 #[test]
157 fn test_non_numeric_env_variable_returns_parse_error() {
158 let mut config = create_test_config();
159 let var_name = "TEST_VAR_NON_NUMERIC";
160 let var_value = "not-a-number";
161 config.env_variable_name = var_name.to_string();
162
163 env::set_var(var_name, var_value);
164 let result = memory_config_check(&config);
165 env::remove_var(var_name); match result {
168 Err(MemoryConfigError::EnvVarParseError(val)) => {
169 assert_eq!(val, var_value);
170 }
171 _ => panic!("{}: Expected EnvVarParseError", module_path!()),
172 }
173 }
174
175 #[test]
177 fn test_value_below_minimum_returns_error() {
178 let mut config = create_test_config();
179 let var_name = "TEST_VAR_TOO_LOW";
180 config.env_variable_name = var_name.to_string();
181 config.env_variable_min_val = 5;
182 config.env_variable_max_val = 10;
183
184 env::set_var(var_name, "2");
185 let result = memory_config_check(&config);
186 env::remove_var(var_name); match result {
189 Err(MemoryConfigError::EnvVarValueTooLow(val, min)) => {
190 assert_eq!(val, 2);
191 assert_eq!(min, 5);
192 }
193 _ => panic!("{}: Expected EnvVarValueTooLow error", module_path!()),
194 }
195 }
196
197 #[test]
199 fn test_value_above_maximum_returns_error() {
200 let mut config = create_test_config();
201 let var_name = "TEST_VAR_TOO_HIGH";
202 config.env_variable_name = var_name.to_string();
203 config.env_variable_min_val = 5;
204 config.env_variable_max_val = 10;
205
206 env::set_var(var_name, "15");
207 let result = memory_config_check(&config);
208 env::remove_var(var_name); match result {
211 Err(MemoryConfigError::EnvVarValueTooHigh(val, max)) => {
212 assert_eq!(val, 15);
213 assert_eq!(max, 10);
214 }
215 _ => panic!("{}: Expected EnvVarValueTooHigh error", module_path!()),
216 }
217 }
218
219 #[test]
221 fn test_value_within_bounds_is_ok() {
222 let mut config = create_test_config();
223 let var_name = "TEST_VAR_IN_BOUNDS";
224 config.env_variable_name = var_name.to_string();
225 config.env_variable_min_val = 5;
226 config.env_variable_max_val = 10;
227
228 env::set_var(var_name, "8");
229 let result = memory_config_check(&config);
230 env::remove_var(var_name); match result {
233 Ok(Some((name, val))) => {
234 assert_eq!(name, var_name);
235 assert_eq!(val, 8);
236 }
237 _ => panic!("{}, Expected Ok(Some(...))", module_path!()),
238 }
239 }
240}