1
+ #![ cfg( feature = "json" ) ]
2
+
3
+ use serde_derive:: Deserialize ;
4
+
5
+ use config:: { Config , File , FileFormat , Map , Value } ;
6
+ use float_cmp:: ApproxEqUlps ;
7
+
8
+ #[ derive( Debug , Deserialize ) ]
9
+ struct Place {
10
+ name : String ,
11
+ longitude : f64 ,
12
+ latitude : f64 ,
13
+ favorite : bool ,
14
+ telephone : Option < String > ,
15
+ reviews : u64 ,
16
+ creator : Map < String , Value > ,
17
+ rating : Option < f32 > ,
18
+ }
19
+
20
+ #[ derive( Debug , Deserialize ) ]
21
+ struct Settings {
22
+ debug : f64 ,
23
+ production : Option < String > ,
24
+ place : Place ,
25
+ #[ serde( rename = "arr" ) ]
26
+ elements : Vec < String > ,
27
+ }
28
+
29
+ fn make ( ) -> Config {
30
+ Config :: builder ( )
31
+ . add_source ( File :: new ( "tests/Settings" , FileFormat :: Gura ) )
32
+ . build ( )
33
+ . unwrap ( )
34
+ }
35
+
36
+ #[ test]
37
+ fn test_file ( ) {
38
+ let c = make ( ) ;
39
+
40
+ // Deserialize the entire file as single struct
41
+ let s: Settings = c. try_deserialize ( ) . unwrap ( ) ;
42
+
43
+ assert ! ( s. debug. approx_eq_ulps( & 1.0 , 2 ) ) ;
44
+ assert_eq ! ( s. production, Some ( "false" . to_string( ) ) ) ;
45
+ assert_eq ! ( s. place. name, "Torre di Pisa" ) ;
46
+ assert ! ( s. place. longitude. approx_eq_ulps( & 43.722_498_5 , 2 ) ) ;
47
+ assert ! ( s. place. latitude. approx_eq_ulps( & 10.397_052_2 , 2 ) ) ;
48
+ assert ! ( !s. place. favorite) ;
49
+ assert_eq ! ( s. place. reviews, 3866 ) ;
50
+ assert_eq ! ( s. place. rating, Some ( 4.5 ) ) ;
51
+ assert_eq ! ( s. place. telephone, None ) ;
52
+ assert_eq ! ( s. elements. len( ) , 10 ) ;
53
+ assert_eq ! ( s. elements[ 3 ] , "4" . to_string( ) ) ;
54
+ if cfg ! ( feature = "preserve_order" ) {
55
+ assert_eq ! (
56
+ s. place
57
+ . creator
58
+ . into_iter( )
59
+ . collect:: <Vec <( String , config:: Value ) >>( ) ,
60
+ vec![
61
+ ( "name" . to_string( ) , "John Smith" . into( ) ) ,
62
+ ( "username" . into( ) , "jsmith" . into( ) ) ,
63
+ ( "email" . into( ) , "jsmith@localhost" . into( ) ) ,
64
+ ]
65
+ ) ;
66
+ } else {
67
+ assert_eq ! (
68
+ s. place. creator[ "name" ] . clone( ) . into_string( ) . unwrap( ) ,
69
+ "John Smith" . to_string( )
70
+ ) ;
71
+ }
72
+ }
73
+
74
+ #[ test]
75
+ fn test_gura_vec ( ) {
76
+ let c = Config :: builder ( )
77
+ . add_source ( File :: from_str (
78
+ r#"
79
+ hosts: [
80
+ "alpha",
81
+ "omega"
82
+ ]
83
+ "# ,
84
+ FileFormat :: Gura ,
85
+ ) )
86
+ . build ( )
87
+ . unwrap ( ) ;
88
+
89
+ let v = c. get_array ( "hosts" ) . unwrap ( ) ;
90
+ let mut vi = v. into_iter ( ) ;
91
+ assert_eq ! ( vi. next( ) . unwrap( ) . into_string( ) . unwrap( ) , "alpha" ) ;
92
+ assert_eq ! ( vi. next( ) . unwrap( ) . into_string( ) . unwrap( ) , "omega" ) ;
93
+ assert ! ( vi. next( ) . is_none( ) ) ;
94
+ }
95
+
96
+ #[ derive( Debug , Deserialize , PartialEq ) ]
97
+ enum EnumSettings {
98
+ Bar ( String ) ,
99
+ }
100
+
101
+ #[ derive( Debug , Deserialize , PartialEq ) ]
102
+ struct StructSettings {
103
+ foo : String ,
104
+ bar : String ,
105
+ }
106
+ #[ derive( Debug , Deserialize , PartialEq ) ]
107
+ #[ allow( non_snake_case) ]
108
+ struct CapSettings {
109
+ FOO : String ,
110
+ }
111
+
112
+ #[ test]
113
+ fn test_override_uppercase_value_for_struct ( ) {
114
+ std:: env:: set_var ( "APP_FOO" , "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE" ) ;
115
+
116
+ let cfg = Config :: builder ( )
117
+ . add_source ( File :: new ( "tests/Settings" , FileFormat :: Gura ) )
118
+ . add_source ( config:: Environment :: with_prefix ( "APP" ) . separator ( "_" ) )
119
+ . build ( )
120
+ . unwrap ( ) ;
121
+
122
+ let cap_settings = cfg. clone ( ) . try_deserialize :: < CapSettings > ( ) ;
123
+ let lower_settings = cfg. try_deserialize :: < StructSettings > ( ) . unwrap ( ) ;
124
+
125
+ match cap_settings {
126
+ Ok ( v) => {
127
+ // this assertion will ensure that the map has only lowercase keys
128
+ assert_ne ! ( v. FOO , "FOO should be overridden" ) ;
129
+ assert_eq ! (
130
+ lower_settings. foo,
131
+ "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE" . to_string( )
132
+ ) ;
133
+ }
134
+ Err ( e) => {
135
+ if e. to_string ( ) . contains ( "missing field `FOO`" ) {
136
+ println ! ( "triggered error {:?}" , e) ;
137
+ assert_eq ! (
138
+ lower_settings. foo,
139
+ "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE" . to_string( )
140
+ ) ;
141
+ } else {
142
+ panic ! ( "{}" , e) ;
143
+ }
144
+ }
145
+ }
146
+ }
147
+
148
+ #[ test]
149
+ fn test_override_lowercase_value_for_struct ( ) {
150
+ std:: env:: set_var ( "config_foo" , "I have been overridden_with_lower_case" ) ;
151
+
152
+ let cfg = Config :: builder ( )
153
+ . add_source ( File :: new ( "tests/Settings" , FileFormat :: Gura ) )
154
+ . add_source ( config:: Environment :: with_prefix ( "config" ) . separator ( "_" ) )
155
+ . build ( )
156
+ . unwrap ( ) ;
157
+
158
+ let values: StructSettings = cfg. try_deserialize ( ) . unwrap ( ) ;
159
+ assert_eq ! (
160
+ values. foo,
161
+ "I have been overridden_with_lower_case" . to_string( )
162
+ ) ;
163
+ assert_ne ! ( values. foo, "I am bar" . to_string( ) ) ;
164
+ }
165
+
166
+ #[ test]
167
+ fn test_override_uppercase_value_for_enums ( ) {
168
+ std:: env:: set_var ( "APPS_BAR" , "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE" ) ;
169
+
170
+ let cfg = Config :: builder ( )
171
+ . add_source ( File :: new ( "tests/Settings-enum-test" , FileFormat :: Gura ) )
172
+ . add_source ( config:: Environment :: with_prefix ( "APPS" ) . separator ( "_" ) )
173
+ . build ( )
174
+ . unwrap ( ) ;
175
+ let val: EnumSettings = cfg. try_deserialize ( ) . unwrap ( ) ;
176
+
177
+ assert_eq ! (
178
+ val,
179
+ EnumSettings :: Bar ( "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE" . to_string( ) )
180
+ ) ;
181
+ }
182
+
183
+ #[ test]
184
+ fn test_override_lowercase_value_for_enums ( ) {
185
+ std:: env:: set_var ( "test_bar" , "I have been overridden_with_lower_case" ) ;
186
+
187
+ let cfg = Config :: builder ( )
188
+ . add_source ( File :: new ( "tests/Settings-enum-test" , FileFormat :: Json ) )
189
+ . add_source ( config:: Environment :: with_prefix ( "test" ) . separator ( "_" ) )
190
+ . build ( )
191
+ . unwrap ( ) ;
192
+
193
+ let param: EnumSettings = cfg. try_deserialize ( ) . unwrap ( ) ;
194
+
195
+ assert_eq ! (
196
+ param,
197
+ EnumSettings :: Bar ( "I have been overridden_with_lower_case" . to_string( ) )
198
+ ) ;
199
+ }
0 commit comments