rocketmq_common/utils/env_utils.rs
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17use std::ffi::OsStr;
18
19use crate::common::mix_all::ROCKETMQ_HOME_ENV;
20
21/// Utility functions related to environment variables.
22pub struct EnvUtils;
23
24impl EnvUtils {
25 /// Gets the value of the specified environment variable.
26 ///
27 /// # Arguments
28 ///
29 /// * `key` - The name of the environment variable to retrieve.
30 ///
31 /// # Returns
32 ///
33 /// An `Option` containing the value of the environment variable, or `None` if the variable is
34 /// not set.
35 pub fn get_property<K: AsRef<OsStr>>(key: K) -> Option<String> {
36 std::env::var(key).ok()
37 }
38
39 /// Retrieves the value of the specified environment variable or returns a default value if the
40 /// variable is not set.
41 ///
42 /// # Arguments
43 /// * `key` - The name of the environment variable to retrieve.
44 /// * `default` - The default value to return if the environment variable is not set.
45 ///
46 /// # Returns
47 /// A `String` containing the value of the environment variable, or the default value.
48 pub fn get_property_or_default<K: AsRef<OsStr>>(key: K, default: impl Into<String>) -> String {
49 std::env::var(key).unwrap_or_else(|_| default.into())
50 }
51
52 /// Retrieves the value of the specified environment variable as an `i32`, or returns a default
53 /// value if the variable is not set or cannot be parsed.
54 ///
55 /// # Arguments
56 /// * `key` - The name of the environment variable to retrieve.
57 /// * `default` - The default value to return if the environment variable is not set or cannot
58 /// be parsed.
59 ///
60 /// # Returns
61 /// An `i32` containing the value of the environment variable, or the default value.
62 pub fn get_property_as_i32<K: AsRef<OsStr>>(key: K, default: i32) -> i32 {
63 std::env::var(key)
64 .ok()
65 .and_then(|v| v.parse::<i32>().ok())
66 .unwrap_or(default)
67 }
68
69 /// Retrieves the value of the specified environment variable as a `bool`, or returns a default
70 /// value if the variable is not set or cannot be parsed.
71 ///
72 /// # Arguments
73 /// * `key` - The name of the environment variable to retrieve.
74 /// * `default` - The default value to return if the environment variable is not set or cannot
75 /// be parsed.
76 ///
77 /// # Returns
78 /// A `bool` containing the value of the environment variable, or the default value.
79 ///
80 /// # Notes
81 /// The function considers the following values as `true`: `"true"`, `"1"`.
82 /// The function considers the following values as `false`: `"false"`, `"0"`.
83 pub fn get_property_as_bool<K: AsRef<OsStr>>(key: K, default: bool) -> bool {
84 std::env::var(key)
85 .ok()
86 .and_then(|v| {
87 let lower = v.to_lowercase();
88 match lower.as_str() {
89 "true" | "1" => Some(true),
90 "false" | "0" => Some(false),
91 _ => None,
92 }
93 })
94 .unwrap_or(default)
95 }
96
97 /// Sets the value of the specified environment variable.
98 ///
99 /// # Arguments
100 ///
101 /// * `key` - The name of the environment variable to set.
102 /// * `value` - The value to set the environment variable to.
103 ///
104 /// # Safety
105 ///
106 /// This function uses `unsafe` because it modifies the environment variables,
107 /// which can have side effects on the entire process.
108 pub fn put_property<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
109 unsafe {
110 std::env::set_var(key, value);
111 }
112 }
113
114 /// Gets the value of the ROCKETMQ_HOME environment variable.
115 ///
116 /// If ROCKETMQ_HOME is not set, it defaults to the current directory and sets ROCKETMQ_HOME
117 /// accordingly.
118 ///
119 /// # Returns
120 ///
121 /// The value of the ROCKETMQ_HOME environment variable as a `String`.
122 pub fn get_rocketmq_home() -> String {
123 std::env::var(ROCKETMQ_HOME_ENV).unwrap_or_else(|_| unsafe {
124 // If ROCKETMQ_HOME is not set, use the current directory as the default value
125 let rocketmq_home_dir = std::env::current_dir()
126 .ok()
127 .and_then(|p| p.into_os_string().into_string().ok())
128 .unwrap_or_else(|| ".".to_string());
129
130 // Set ROCKETMQ_HOME to the current directory
131 std::env::set_var(ROCKETMQ_HOME_ENV, &rocketmq_home_dir);
132 rocketmq_home_dir
133 })
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use std::path::PathBuf;
140
141 use super::*;
142
143 #[test]
144 fn test_get_property_existing_variable() {
145 // Set up
146 let key = "HOME";
147 let expected_value = "/home/user";
148
149 unsafe {
150 std::env::set_var(key, expected_value);
151 }
152
153 // Test
154 let result = EnvUtils::get_property(key);
155
156 // Assert
157 assert_eq!(result, Some(expected_value.to_string()));
158 }
159
160 #[test]
161 fn test_get_property_non_existing_variable() {
162 // Set up
163 let key = "NON_EXISTING_VARIABLE";
164
165 // Test
166 let result = EnvUtils::get_property(key);
167
168 // Assert
169 assert_eq!(result, None);
170 }
171
172 /* #[test]
173 fn test_get_rocketmq_home_existing_variable() {
174 // Set up
175 let expected_value = PathBuf::from("/path/to/rocketmq_home");
176
177 std::env::set_var(ROCKETMQ_HOME_ENV, expected_value.clone());
178
179 // Test
180 let result = EnvUtils::get_rocketmq_home();
181
182 // Assert
183 assert_eq!(result, expected_value.to_string_lossy().to_string());
184 }*/
185
186 #[test]
187 fn test_get_rocketmq_home_non_existing_variable() {
188 // Set up
189 unsafe {
190 std::env::remove_var(ROCKETMQ_HOME_ENV);
191 }
192
193 // Test
194 let result = EnvUtils::get_rocketmq_home();
195
196 // Assert
197 assert_eq!(
198 result,
199 std::env::current_dir()
200 .unwrap()
201 .to_string_lossy()
202 .to_string()
203 );
204 }
205
206 #[test]
207 fn put_property_sets_value() {
208 let key = "TEST_ENV_VAR";
209 let value = "test_value";
210
211 EnvUtils::put_property(key, value);
212
213 let result = std::env::var(key).unwrap();
214 assert_eq!(result, value);
215 }
216
217 #[test]
218 fn put_property_overwrites_existing_value() {
219 let key = "TEST_ENV_VAR1";
220 let initial_value = "initial_value";
221 let new_value = "new_value";
222
223 unsafe {
224 std::env::set_var(key, initial_value);
225 }
226
227 EnvUtils::put_property(key, new_value);
228
229 let result = std::env::var(key).unwrap();
230 assert_eq!(result, new_value);
231 }
232
233 #[test]
234 fn put_property_handles_empty_value() {
235 let key = "TEST_ENV_VAR2";
236 let value = "";
237
238 EnvUtils::put_property(key, value);
239
240 let result = std::env::var(key).unwrap();
241 assert_eq!(result, value);
242 }
243
244 #[test]
245 fn retrieves_env_variable_value() {
246 std::env::set_var("TEST_KEY", "test_value");
247 assert_eq!(
248 EnvUtils::get_property_or_default("TEST_KEY", "default_value"),
249 "test_value"
250 );
251 std::env::remove_var("TEST_KEY");
252 }
253
254 #[test]
255 fn returns_default_when_env_variable_not_set() {
256 assert_eq!(
257 EnvUtils::get_property_or_default("NON_EXISTENT_KEY", "default_value"),
258 "default_value"
259 );
260 }
261
262 #[test]
263 fn retrieves_env_variable_as_i32() {
264 std::env::set_var("TEST_INT_KEY", "42");
265 assert_eq!(EnvUtils::get_property_as_i32("TEST_INT_KEY", 0), 42);
266 std::env::remove_var("TEST_INT_KEY");
267 }
268
269 #[test]
270 fn returns_default_when_env_variable_as_i32_not_set() {
271 assert_eq!(
272 EnvUtils::get_property_as_i32("NON_EXISTENT_INT_KEY", 10),
273 10
274 );
275 }
276
277 #[test]
278 fn returns_default_when_env_variable_as_i32_invalid() {
279 std::env::set_var("INVALID_INT_KEY", "not_a_number");
280 assert_eq!(EnvUtils::get_property_as_i32("INVALID_INT_KEY", 5), 5);
281 std::env::remove_var("INVALID_INT_KEY");
282 }
283
284 #[test]
285 fn returns_default_when_env_variable_as_bool_not_set() {
286 assert!(EnvUtils::get_property_as_bool(
287 "NON_EXISTENT_BOOL_KEY",
288 true
289 ));
290 assert!(!EnvUtils::get_property_as_bool(
291 "NON_EXISTENT_BOOL_KEY",
292 false
293 ));
294 }
295
296 #[test]
297 fn returns_default_when_env_variable_as_bool_invalid() {
298 std::env::set_var("INVALID_BOOL_KEY", "not_a_bool");
299 assert!(EnvUtils::get_property_as_bool("INVALID_BOOL_KEY", true));
300 assert!(!EnvUtils::get_property_as_bool("INVALID_BOOL_KEY", false));
301 std::env::remove_var("INVALID_BOOL_KEY");
302 }
303}