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