Skip to content

Commit ab8d006

Browse files
committed
more environment variable parsing tests
1 parent 320b841 commit ab8d006

File tree

1 file changed

+334
-18
lines changed

1 file changed

+334
-18
lines changed

tests/env.rs

Lines changed: 334 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
extern crate config;
2+
extern crate serde_derive;
23

34
use std::env;
4-
55
use config::*;
6+
use serde_derive::Deserialize;
7+
8+
/// Reminder that tests using env variables need to use different env variable names, since
9+
/// tests can be run in parallel
610
711
#[test]
812
fn test_default() {
@@ -84,29 +88,341 @@ fn test_custom_separator_behavior() {
8488
env::remove_var("C.B.A");
8589
}
8690

87-
fn test_parse_numbers() {
91+
fn test_parse_int() {
92+
// using a struct in an enum here to make serde use `deserialize_any`
93+
#[derive(Deserialize, Debug)]
94+
#[serde(tag = "tag")]
95+
enum TestIntEnum {
96+
Int(TestInt),
97+
}
98+
99+
#[derive(Deserialize, Debug)]
100+
struct TestInt {
101+
int_val: i32,
102+
}
103+
88104
env::set_var("INT_VAL", "42");
89-
env::set_var("FLOAT_VAL", "42.2");
90-
env::set_var("BOOL_VAL", "true");
91105

92106
let environment = Environment::new().try_parsing(true);
107+
let mut config = Config::new();
108+
109+
config.set("tag", "Int").unwrap();
110+
111+
config.merge(environment).unwrap();
112+
113+
let config: TestIntEnum = config.try_into().unwrap();
93114

94-
let values = environment.collect().unwrap();
95-
96-
assert_eq!(
97-
values.get("int_val").unwrap().clone().into_int().ok(),
98-
Some(42)
99-
);
100-
assert_eq!(
101-
values.get("float_val").unwrap().clone().into_float().ok(),
102-
Some(42.2)
103-
);
104-
assert_eq!(
105-
values.get("bool_val").unwrap().clone().into_bool().ok(),
106-
Some(true)
107-
);
115+
assert!(matches!(config, TestIntEnum::Int(TestInt { int_val: 42 })));
108116

109117
env::remove_var("INT_VAL");
118+
}
119+
120+
#[test]
121+
fn test_parse_float() {
122+
// using a struct in an enum here to make serde use `deserialize_any`
123+
#[derive(Deserialize, Debug)]
124+
#[serde(tag = "tag")]
125+
enum TestFloatEnum {
126+
Float(TestFloat),
127+
}
128+
129+
#[derive(Deserialize, Debug)]
130+
struct TestFloat {
131+
float_val: f64,
132+
}
133+
134+
env::set_var("FLOAT_VAL", "42.3");
135+
136+
let environment = Environment::new().try_parsing(true);
137+
let mut config = Config::new();
138+
139+
config.set("tag", "Float").unwrap();
140+
141+
config.merge(environment).unwrap();
142+
143+
let config: TestFloatEnum = config.try_into().unwrap();
144+
145+
// can't use `matches!` because of float value
146+
match config {
147+
TestFloatEnum::Float(TestFloat { float_val }) => assert_eq!(float_val, 42.3),
148+
}
149+
110150
env::remove_var("FLOAT_VAL");
151+
}
152+
153+
#[test]
154+
fn test_parse_bool() {
155+
// using a struct in an enum here to make serde use `deserialize_any`
156+
#[derive(Deserialize, Debug)]
157+
#[serde(tag = "tag")]
158+
enum TestBoolEnum {
159+
Bool(TestBool),
160+
}
161+
162+
#[derive(Deserialize, Debug)]
163+
struct TestBool {
164+
bool_val: bool,
165+
}
166+
167+
env::set_var("BOOL_VAL", "true");
168+
169+
let environment = Environment::new().try_parsing(true);
170+
let mut config = Config::new();
171+
172+
config.set("tag", "Bool").unwrap();
173+
174+
config.merge(environment).unwrap();
175+
176+
let config: TestBoolEnum = config.try_into().unwrap();
177+
178+
assert!(matches!(
179+
config,
180+
TestBoolEnum::Bool(TestBool { bool_val: true }),
181+
));
182+
111183
env::remove_var("BOOL_VAL");
112184
}
185+
186+
#[test]
187+
#[should_panic(expected = "invalid type: string \"42\", expected i32")]
188+
fn test_parse_off_int() {
189+
// using a struct in an enum here to make serde use `deserialize_any`
190+
#[derive(Deserialize, Debug)]
191+
#[serde(tag = "tag")]
192+
enum TestIntEnum {
193+
Int(TestInt),
194+
}
195+
196+
#[derive(Deserialize, Debug)]
197+
struct TestInt {
198+
int_val_1: i32,
199+
}
200+
201+
env::set_var("INT_VAL_1", "42");
202+
203+
let environment = Environment::new().try_parsing(false);
204+
let mut config = Config::new();
205+
206+
config.set("tag", "Int").unwrap();
207+
208+
config.merge(environment).unwrap();
209+
210+
env::remove_var("INT_VAL_1");
211+
212+
config.try_into::<TestIntEnum>().unwrap();
213+
}
214+
215+
#[test]
216+
#[should_panic(expected = "invalid type: string \"42.3\", expected f64")]
217+
fn test_parse_off_float() {
218+
// using a struct in an enum here to make serde use `deserialize_any`
219+
#[derive(Deserialize, Debug)]
220+
#[serde(tag = "tag")]
221+
enum TestFloatEnum {
222+
Float(TestFloat),
223+
}
224+
225+
#[derive(Deserialize, Debug)]
226+
struct TestFloat {
227+
float_val_1: f64,
228+
}
229+
230+
env::set_var("FLOAT_VAL_1", "42.3");
231+
232+
let environment = Environment::new().try_parsing(false);
233+
let mut config = Config::new();
234+
235+
config.set("tag", "Float").unwrap();
236+
237+
config.merge(environment).unwrap();
238+
239+
env::remove_var("FLOAT_VAL_1");
240+
241+
config.try_into::<TestFloatEnum>().unwrap();
242+
}
243+
244+
#[test]
245+
#[should_panic(expected = "invalid type: string \"true\", expected a boolean")]
246+
fn test_parse_off_bool() {
247+
// using a struct in an enum here to make serde use `deserialize_any`
248+
#[derive(Deserialize, Debug)]
249+
#[serde(tag = "tag")]
250+
enum TestBoolEnum {
251+
Bool(TestBool),
252+
}
253+
254+
#[derive(Deserialize, Debug)]
255+
struct TestBool {
256+
bool_val_1: bool,
257+
}
258+
259+
env::set_var("BOOL_VAL_1", "true");
260+
261+
let environment = Environment::new().try_parsing(false);
262+
let mut config = Config::new();
263+
264+
config.set("tag", "Bool").unwrap();
265+
266+
config.merge(environment).unwrap();
267+
268+
env::remove_var("BOOL_VAL_1");
269+
270+
config.try_into::<TestBoolEnum>().unwrap();
271+
}
272+
273+
#[test]
274+
#[should_panic(expected = "invalid type: string \"not an int\", expected i32")]
275+
fn test_parse_int_fail() {
276+
// using a struct in an enum here to make serde use `deserialize_any`
277+
#[derive(Deserialize, Debug)]
278+
#[serde(tag = "tag")]
279+
enum TestIntEnum {
280+
Int(TestInt),
281+
}
282+
283+
#[derive(Deserialize, Debug)]
284+
struct TestInt {
285+
int_val_2: i32,
286+
}
287+
288+
env::set_var("INT_VAL_2", "not an int");
289+
290+
let environment = Environment::new().try_parsing(true);
291+
let mut config = Config::new();
292+
293+
config.set("tag", "Int").unwrap();
294+
295+
config.merge(environment).unwrap();
296+
297+
env::remove_var("INT_VAL_2");
298+
299+
config.try_into::<TestIntEnum>().unwrap();
300+
}
301+
302+
#[test]
303+
#[should_panic(expected = "invalid type: string \"not a float\", expected f64")]
304+
fn test_parse_float_fail() {
305+
// using a struct in an enum here to make serde use `deserialize_any`
306+
#[derive(Deserialize, Debug)]
307+
#[serde(tag = "tag")]
308+
enum TestFloatEnum {
309+
Float(TestFloat),
310+
}
311+
312+
#[derive(Deserialize, Debug)]
313+
struct TestFloat {
314+
float_val_2: f64,
315+
}
316+
317+
env::set_var("FLOAT_VAL_2", "not a float");
318+
319+
let environment = Environment::new().try_parsing(true);
320+
let mut config = Config::new();
321+
322+
config.set("tag", "Float").unwrap();
323+
324+
config.merge(environment).unwrap();
325+
326+
env::remove_var("FLOAT_VAL_2");
327+
328+
config.try_into::<TestFloatEnum>().unwrap();
329+
}
330+
331+
#[test]
332+
#[should_panic(expected = "invalid type: string \"not a bool\", expected a boolean")]
333+
fn test_parse_bool_fail() {
334+
// using a struct in an enum here to make serde use `deserialize_any`
335+
#[derive(Deserialize, Debug)]
336+
#[serde(tag = "tag")]
337+
enum TestBoolEnum {
338+
Bool(TestBool),
339+
}
340+
341+
#[derive(Deserialize, Debug)]
342+
struct TestBool {
343+
bool_val_2: bool,
344+
}
345+
346+
env::set_var("BOOL_VAL_2", "not a bool");
347+
348+
let environment = Environment::new().try_parsing(true);
349+
let mut config = Config::new();
350+
351+
config.set("tag", "Bool").unwrap();
352+
353+
config.merge(environment).unwrap();
354+
355+
env::remove_var("BOOL_VAL_2");
356+
357+
config.try_into::<TestBoolEnum>().unwrap();
358+
}
359+
360+
#[test]
361+
fn test_parse_string() {
362+
// using a struct in an enum here to make serde use `deserialize_any`
363+
#[derive(Deserialize, Debug)]
364+
#[serde(tag = "tag")]
365+
enum TestStringEnum {
366+
String(TestString),
367+
}
368+
369+
#[derive(Deserialize, Debug)]
370+
struct TestString {
371+
string_val: String,
372+
}
373+
374+
env::set_var("STRING_VAL", "test string");
375+
376+
let environment = Environment::new().try_parsing(true);
377+
let mut config = Config::new();
378+
379+
config.set("tag", "String").unwrap();
380+
381+
config.merge(environment).unwrap();
382+
383+
let config: TestStringEnum = config.try_into().unwrap();
384+
385+
let test_string = String::from("test string");
386+
387+
match config {
388+
TestStringEnum::String(TestString { string_val }) => assert_eq!(test_string, string_val),
389+
}
390+
391+
env::remove_var("STRING_VAL");
392+
}
393+
394+
#[test]
395+
fn test_parse_off_string() {
396+
// using a struct in an enum here to make serde use `deserialize_any`
397+
#[derive(Deserialize, Debug)]
398+
#[serde(tag = "tag")]
399+
enum TestStringEnum {
400+
String(TestString),
401+
}
402+
403+
#[derive(Deserialize, Debug)]
404+
struct TestString {
405+
string_val_1: String,
406+
}
407+
408+
env::set_var("STRING_VAL_1", "test string");
409+
410+
let environment = Environment::new().try_parsing(false);
411+
let mut config = Config::new();
412+
413+
config.set("tag", "String").unwrap();
414+
415+
config.merge(environment).unwrap();
416+
417+
let config: TestStringEnum = config.try_into().unwrap();
418+
419+
let test_string = String::from("test string");
420+
421+
match config {
422+
TestStringEnum::String(TestString { string_val_1 }) => {
423+
assert_eq!(test_string, string_val_1)
424+
}
425+
}
426+
427+
env::remove_var("STRING_VAL_1");
428+
}

0 commit comments

Comments
 (0)