1 
2 use config::{Config};
3 use serde_derive::Deserialize;
4 use std::env;
5 
6 /// Reminder that tests using env variables need to use different env variable names, since
7 /// tests can be run in parallel
8 
9 
10 #[test]
test_parse_int()11 fn test_parse_int() {
12     // using a struct in an enum here to make serde use `deserialize_any`
13     #[derive(Deserialize, Debug)]
14     #[serde(tag = "tag")]
15     enum TestIntEnum {
16         Int(TestInt),
17     }
18 
19     #[derive(Deserialize, Debug)]
20     struct TestInt {
21         int_val: i32,
22     }
23 
24     env::set_var("INT_VAL", "42");
25 
26     let environment = Environment::new().try_parsing(true);
27     let mut config = Config::default();
28 
29     config.set("tag", "Int").unwrap();
30 
31     config.merge(environment).unwrap();
32 
33     let config: TestIntEnum = config.try_deserialize().unwrap();
34 
35     assert!(matches!(config, TestIntEnum::Int(TestInt { int_val: 42 })));
36 
37     env::remove_var("INT_VAL");
38 }
39 
40 #[test]
test_parse_float()41 fn test_parse_float() {
42     // using a struct in an enum here to make serde use `deserialize_any`
43     #[derive(Deserialize, Debug)]
44     #[serde(tag = "tag")]
45     enum TestFloatEnum {
46         Float(TestFloat),
47     }
48 
49     #[derive(Deserialize, Debug)]
50     struct TestFloat {
51         float_val: f64,
52     }
53 
54     env::set_var("FLOAT_VAL", "42.3");
55 
56     let environment = Environment::new().try_parsing(true);
57     let mut config = Config::default();
58 
59     config.set("tag", "Float").unwrap();
60 
61     config.merge(environment).unwrap();
62 
63     let config: TestFloatEnum = config.try_deserialize().unwrap();
64 
65     // can't use `matches!` because of float value
66     match config {
67         TestFloatEnum::Float(TestFloat { float_val }) => assert_eq!(float_val, 42.3),
68     }
69 
70     env::remove_var("FLOAT_VAL");
71 }
72 
73 #[test]
test_parse_bool()74 fn test_parse_bool() {
75     // using a struct in an enum here to make serde use `deserialize_any`
76     #[derive(Deserialize, Debug)]
77     #[serde(tag = "tag")]
78     enum TestBoolEnum {
79         Bool(TestBool),
80     }
81 
82     #[derive(Deserialize, Debug)]
83     struct TestBool {
84         bool_val: bool,
85     }
86 
87     env::set_var("BOOL_VAL", "true");
88 
89     let environment = Environment::new().try_parsing(true);
90     let mut config = Config::default();
91 
92     config.set("tag", "Bool").unwrap();
93 
94     config.merge(environment).unwrap();
95 
96     let config: TestBoolEnum = config.try_deserialize().unwrap();
97 
98     assert!(matches!(
99         config,
100         TestBoolEnum::Bool(TestBool { bool_val: true }),
101     ));
102 
103     env::remove_var("BOOL_VAL");
104 }
105 
106 #[test]
107 #[should_panic(expected = "invalid type: string \"42\", expected i32")]
test_parse_off_int()108 fn test_parse_off_int() {
109     // using a struct in an enum here to make serde use `deserialize_any`
110     #[derive(Deserialize, Debug)]
111     #[serde(tag = "tag")]
112     enum TestIntEnum {
113         Int(TestInt),
114     }
115 
116     #[derive(Deserialize, Debug)]
117     struct TestInt {
118         int_val_1: i32,
119     }
120 
121     env::set_var("INT_VAL_1", "42");
122 
123     let environment = Environment::new().try_parsing(false);
124     let mut config = Config::default();
125 
126     config.set("tag", "Int").unwrap();
127 
128     config.merge(environment).unwrap();
129 
130     env::remove_var("INT_VAL_1");
131 
132     config.try_deserialize::<TestIntEnum>().unwrap();
133 }
134 
135 #[test]
136 #[should_panic(expected = "invalid type: string \"42.3\", expected f64")]
test_parse_off_float()137 fn test_parse_off_float() {
138     // using a struct in an enum here to make serde use `deserialize_any`
139     #[derive(Deserialize, Debug)]
140     #[serde(tag = "tag")]
141     enum TestFloatEnum {
142         Float(TestFloat),
143     }
144 
145     #[derive(Deserialize, Debug)]
146     struct TestFloat {
147         float_val_1: f64,
148     }
149 
150     env::set_var("FLOAT_VAL_1", "42.3");
151 
152     let environment = Environment::new().try_parsing(false);
153     let mut config = Config::default();
154 
155     config.set("tag", "Float").unwrap();
156 
157     config.merge(environment).unwrap();
158 
159     env::remove_var("FLOAT_VAL_1");
160 
161     config.try_deserialize::<TestFloatEnum>().unwrap();
162 }
163 
164 #[test]
165 #[should_panic(expected = "invalid type: string \"true\", expected a boolean")]
test_parse_off_bool()166 fn test_parse_off_bool() {
167     // using a struct in an enum here to make serde use `deserialize_any`
168     #[derive(Deserialize, Debug)]
169     #[serde(tag = "tag")]
170     enum TestBoolEnum {
171         Bool(TestBool),
172     }
173 
174     #[derive(Deserialize, Debug)]
175     struct TestBool {
176         bool_val_1: bool,
177     }
178 
179     env::set_var("BOOL_VAL_1", "true");
180 
181     let environment = Environment::new().try_parsing(false);
182     let mut config = Config::default();
183 
184     config.set("tag", "Bool").unwrap();
185 
186     config.merge(environment).unwrap();
187 
188     env::remove_var("BOOL_VAL_1");
189 
190     config.try_deserialize::<TestBoolEnum>().unwrap();
191 }
192 
193 #[test]
194 #[should_panic(expected = "invalid type: string \"not an int\", expected i32")]
test_parse_int_fail()195 fn test_parse_int_fail() {
196     // using a struct in an enum here to make serde use `deserialize_any`
197     #[derive(Deserialize, Debug)]
198     #[serde(tag = "tag")]
199     enum TestIntEnum {
200         Int(TestInt),
201     }
202 
203     #[derive(Deserialize, Debug)]
204     struct TestInt {
205         int_val_2: i32,
206     }
207 
208     env::set_var("INT_VAL_2", "not an int");
209 
210     let environment = Environment::new().try_parsing(true);
211     let mut config = Config::default();
212 
213     config.set("tag", "Int").unwrap();
214 
215     config.merge(environment).unwrap();
216 
217     env::remove_var("INT_VAL_2");
218 
219     config.try_deserialize::<TestIntEnum>().unwrap();
220 }
221 
222 #[test]
223 #[should_panic(expected = "invalid type: string \"not a float\", expected f64")]
test_parse_float_fail()224 fn test_parse_float_fail() {
225     // using a struct in an enum here to make serde use `deserialize_any`
226     #[derive(Deserialize, Debug)]
227     #[serde(tag = "tag")]
228     enum TestFloatEnum {
229         Float(TestFloat),
230     }
231 
232     #[derive(Deserialize, Debug)]
233     struct TestFloat {
234         float_val_2: f64,
235     }
236 
237     env::set_var("FLOAT_VAL_2", "not a float");
238 
239     let environment = Environment::new().try_parsing(true);
240     let mut config = Config::default();
241 
242     config.set("tag", "Float").unwrap();
243 
244     config.merge(environment).unwrap();
245 
246     env::remove_var("FLOAT_VAL_2");
247 
248     config.try_deserialize::<TestFloatEnum>().unwrap();
249 }
250 
251 #[test]
252 #[should_panic(expected = "invalid type: string \"not a bool\", expected a boolean")]
test_parse_bool_fail()253 fn test_parse_bool_fail() {
254     // using a struct in an enum here to make serde use `deserialize_any`
255     #[derive(Deserialize, Debug)]
256     #[serde(tag = "tag")]
257     enum TestBoolEnum {
258         Bool(TestBool),
259     }
260 
261     #[derive(Deserialize, Debug)]
262     struct TestBool {
263         bool_val_2: bool,
264     }
265 
266     env::set_var("BOOL_VAL_2", "not a bool");
267 
268     let environment = Environment::new().try_parsing(true);
269     let mut config = Config::default();
270 
271     config.set("tag", "Bool").unwrap();
272 
273     config.merge(environment).unwrap();
274 
275     env::remove_var("BOOL_VAL_2");
276 
277     config.try_deserialize::<TestBoolEnum>().unwrap();
278 }
279 
280 #[test]
test_parse_string()281 fn test_parse_string() {
282     // using a struct in an enum here to make serde use `deserialize_any`
283     #[derive(Deserialize, Debug)]
284     #[serde(tag = "tag")]
285     enum TestStringEnum {
286         String(TestString),
287     }
288 
289     #[derive(Deserialize, Debug)]
290     struct TestString {
291         string_val: String,
292     }
293 
294     env::set_var("STRING_VAL", "test string");
295 
296     let environment = Environment::new().try_parsing(true);
297     let mut config = Config::default();
298 
299     config.set("tag", "String").unwrap();
300 
301     config.merge(environment).unwrap();
302 
303     let config: TestStringEnum = config.try_deserialize().unwrap();
304 
305     let test_string = String::from("test string");
306 
307     match config {
308         TestStringEnum::String(TestString { string_val }) => assert_eq!(test_string, string_val),
309     }
310 
311     env::remove_var("STRING_VAL");
312 }
313 
314 #[test]
test_parse_off_string()315 fn test_parse_off_string() {
316     // using a struct in an enum here to make serde use `deserialize_any`
317     #[derive(Deserialize, Debug)]
318     #[serde(tag = "tag")]
319     enum TestStringEnum {
320         String(TestString),
321     }
322 
323     #[derive(Deserialize, Debug)]
324     struct TestString {
325         string_val_1: String,
326     }
327 
328     env::set_var("STRING_VAL_1", "test string");
329 
330     let environment = Environment::new().try_parsing(false);
331     let mut config = Config::default();
332 
333     config.set("tag", "String").unwrap();
334 
335     config.merge(environment).unwrap();
336 
337     let config: TestStringEnum = config.try_deserialize().unwrap();
338 
339     let test_string = String::from("test string");
340 
341     match config {
342         TestStringEnum::String(TestString { string_val_1 }) => {
343             assert_eq!(test_string, string_val_1)
344         }
345     }
346 
347     env::remove_var("STRING_VAL_1");
348 }
349