@@ -4,39 +4,46 @@ use serde_derive::Deserialize;
4
4
5
5
use config:: { Config , File , FileFormat , Map , Value } ;
6
6
use float_cmp:: ApproxEqUlps ;
7
- use std:: path:: PathBuf ;
8
-
9
- #[ derive( Debug , Deserialize ) ]
10
- struct Place {
11
- name : String ,
12
- longitude : f64 ,
13
- latitude : f64 ,
14
- favorite : bool ,
15
- telephone : Option < String > ,
16
- reviews : u64 ,
17
- creator : Map < String , Value > ,
18
- rating : Option < f32 > ,
19
- }
20
-
21
- #[ derive( Debug , Deserialize ) ]
22
- struct Settings {
23
- debug : f64 ,
24
- production : Option < String > ,
25
- place : Place ,
26
- #[ serde( rename = "arr" ) ]
27
- elements : Vec < String > ,
28
- }
29
-
30
- fn make ( ) -> Config {
31
- Config :: builder ( )
32
- . add_source ( File :: new ( "tests/Settings" , FileFormat :: Jsonc ) )
33
- . build ( )
34
- . unwrap ( )
7
+ use snapbox:: { assert_data_eq, str} ;
8
+
9
+ fn get_config_file_path ( suffix : & str ) -> String {
10
+ let path = std:: path:: Path :: new ( file ! ( ) ) ;
11
+ format ! (
12
+ "{}/{}/{}{}.jsonc" ,
13
+ env!( "CARGO_MANIFEST_DIR" ) ,
14
+ path. parent( ) . unwrap( ) . to_str( ) . unwrap( ) ,
15
+ path. file_stem( ) . unwrap( ) . to_str( ) . unwrap( ) ,
16
+ suffix
17
+ )
35
18
}
36
19
37
20
#[ test]
38
21
fn test_file ( ) {
39
- let c = make ( ) ;
22
+ #[ derive( Debug , Deserialize ) ]
23
+ struct Place {
24
+ name : String ,
25
+ longitude : f64 ,
26
+ latitude : f64 ,
27
+ favorite : bool ,
28
+ telephone : Option < String > ,
29
+ reviews : u64 ,
30
+ creator : Map < String , Value > ,
31
+ rating : Option < f32 > ,
32
+ }
33
+
34
+ #[ derive( Debug , Deserialize ) ]
35
+ struct Settings {
36
+ debug : f64 ,
37
+ production : Option < String > ,
38
+ place : Place ,
39
+ #[ serde( rename = "arr" ) ]
40
+ elements : Vec < String > ,
41
+ }
42
+
43
+ let c = Config :: builder ( )
44
+ . add_source ( File :: new ( & get_config_file_path ( "" ) , FileFormat :: Jsonc ) )
45
+ . build ( )
46
+ . unwrap ( ) ;
40
47
41
48
// Deserialize the entire file as single struct
42
49
let s: Settings = c. try_deserialize ( ) . unwrap ( ) ;
@@ -52,12 +59,12 @@ fn test_file() {
52
59
assert_eq ! ( s. place. telephone, None ) ;
53
60
assert_eq ! ( s. elements. len( ) , 10 ) ;
54
61
assert_eq ! ( s. elements[ 3 ] , "4" . to_string( ) ) ;
55
- if cfg ! ( feature = "TODO: preserve_order" ) {
62
+ if cfg ! ( feature = "preserve_order" ) {
56
63
assert_eq ! (
57
64
s. place
58
65
. creator
59
66
. into_iter( )
60
- . collect:: <Vec <( String , config :: Value ) >>( ) ,
67
+ . collect:: <Vec <( String , Value ) >>( ) ,
61
68
vec![
62
69
( "name" . to_string( ) , "John Smith" . into( ) ) ,
63
70
( "username" . into( ) , "jsmith" . into( ) ) ,
@@ -74,69 +81,52 @@ fn test_file() {
74
81
75
82
#[ test]
76
83
fn test_error_parse ( ) {
84
+ let f = get_config_file_path ( ".error" ) ;
77
85
let res = Config :: builder ( )
78
- . add_source ( File :: new ( "tests/Settings-invalid" , FileFormat :: Jsonc ) )
86
+ . add_source ( File :: new ( & f , FileFormat :: Jsonc ) )
79
87
. build ( ) ;
80
88
81
- let path_with_extension: PathBuf = [ "tests" , "Settings-invalid.jsonc" ] . iter ( ) . collect ( ) ;
82
-
83
89
assert ! ( res. is_err( ) ) ;
84
90
assert_eq ! (
85
91
res. unwrap_err( ) . to_string( ) ,
86
92
format!(
87
93
"Expected a colon after the string or word in an object property on line 4 column 1. in {}" ,
88
- path_with_extension. display( )
94
+ std:: path:: Path :: new( & f)
95
+ . strip_prefix( std:: env:: current_dir( ) . unwrap( ) )
96
+ . unwrap_or( std:: path:: Path :: new( & f) )
97
+ . display( )
89
98
)
90
99
) ;
91
100
}
92
101
93
- #[ derive( Debug , Deserialize , PartialEq ) ]
94
- enum EnumSettings {
95
- Bar ( String ) ,
96
- }
97
-
98
- #[ derive( Debug , Deserialize , PartialEq ) ]
99
- struct StructSettings {
100
- foo : String ,
101
- bar : String ,
102
- }
103
102
#[ derive( Debug , Deserialize , PartialEq ) ]
104
103
#[ allow( non_snake_case) ]
105
- struct CapSettings {
104
+ struct OverrideSettings {
105
+ foo : String ,
106
106
FOO : String ,
107
+ bar : String ,
107
108
}
108
109
109
110
#[ test]
110
111
fn test_override_uppercase_value_for_struct ( ) {
111
112
std:: env:: set_var ( "APP_FOO" , "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE" ) ;
112
113
113
114
let cfg = Config :: builder ( )
114
- . add_source ( File :: new ( "tests/Settings" , FileFormat :: Jsonc ) )
115
+ . add_source ( File :: new ( & get_config_file_path ( "" ) , FileFormat :: Jsonc ) )
115
116
. add_source ( config:: Environment :: with_prefix ( "APP" ) . separator ( "_" ) )
116
117
. build ( )
117
118
. unwrap ( ) ;
118
119
119
- let cap_settings = cfg. clone ( ) . try_deserialize :: < CapSettings > ( ) ;
120
- let lower_settings = cfg. try_deserialize :: < StructSettings > ( ) . unwrap ( ) ;
120
+ let settings = cfg. try_deserialize :: < OverrideSettings > ( ) ;
121
121
122
- match cap_settings {
122
+ match settings {
123
123
Ok ( v) => {
124
124
// this assertion will ensure that the map has only lowercase keys
125
- assert_ne ! ( v. FOO , "FOO should be overridden" ) ;
126
- assert_eq ! (
127
- lower_settings. foo,
128
- "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE" . to_string( )
129
- ) ;
125
+ assert_eq ! ( v. FOO , "FOO should be overridden" ) ;
126
+ assert_eq ! ( v. foo, "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE" . to_string( ) ) ;
130
127
}
131
128
Err ( e) => {
132
- if e. to_string ( ) . contains ( "missing field `FOO`" ) {
133
- assert_eq ! (
134
- lower_settings. foo,
135
- "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE" . to_string( )
136
- ) ;
137
- } else {
138
- panic ! ( "{}" , e) ;
139
- }
129
+ panic ! ( "{}" , e) ;
140
130
}
141
131
}
142
132
}
@@ -146,33 +136,36 @@ fn test_override_lowercase_value_for_struct() {
146
136
std:: env:: set_var ( "config_foo" , "I have been overridden_with_lower_case" ) ;
147
137
148
138
let cfg = Config :: builder ( )
149
- . add_source ( File :: new ( "tests/Settings" , FileFormat :: Jsonc ) )
139
+ . add_source ( File :: new ( & get_config_file_path ( "" ) , FileFormat :: Jsonc ) )
150
140
. add_source ( config:: Environment :: with_prefix ( "config" ) . separator ( "_" ) )
151
141
. build ( )
152
142
. unwrap ( ) ;
153
143
154
- let values: StructSettings = cfg. try_deserialize ( ) . unwrap ( ) ;
155
- assert_eq ! (
156
- values. foo,
157
- "I have been overridden_with_lower_case" . to_string( )
144
+ let values: OverrideSettings = cfg. try_deserialize ( ) . unwrap ( ) ;
145
+ assert_eq ! ( values. foo, "I have been overridden_with_lower_case" . to_string( )
158
146
) ;
159
- assert_ne ! ( values. foo, "I am bar" . to_string( ) ) ;
147
+ }
148
+
149
+ #[ derive( Debug , Deserialize , PartialEq ) ]
150
+ enum EnumSettings {
151
+ Bar ( String ) ,
160
152
}
161
153
162
154
#[ test]
163
155
fn test_override_uppercase_value_for_enums ( ) {
164
156
std:: env:: set_var ( "APPS_BAR" , "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE" ) ;
165
157
166
158
let cfg = Config :: builder ( )
167
- . add_source ( File :: new ( "tests/Settings- enum-test" , FileFormat :: Jsonc ) )
159
+ . add_source ( File :: new ( & get_config_file_path ( ". enum" ) , FileFormat :: Jsonc ) )
168
160
. add_source ( config:: Environment :: with_prefix ( "APPS" ) . separator ( "_" ) )
169
161
. build ( )
170
162
. unwrap ( ) ;
171
- let val: EnumSettings = cfg. try_deserialize ( ) . unwrap ( ) ;
172
163
173
- assert_eq ! (
174
- val,
175
- EnumSettings :: Bar ( "I HAVE BEEN OVERRIDDEN_WITH_UPPER_CASE" . to_string( ) )
164
+ let param = cfg. try_deserialize :: < EnumSettings > ( ) ;
165
+ assert ! ( param. is_err( ) ) ;
166
+ assert_data_eq ! (
167
+ param. unwrap_err( ) . to_string( ) ,
168
+ str ![ "enum EnumSettings does not have variant constructor bar" ]
176
169
) ;
177
170
}
178
171
@@ -181,15 +174,15 @@ fn test_override_lowercase_value_for_enums() {
181
174
std:: env:: set_var ( "test_bar" , "I have been overridden_with_lower_case" ) ;
182
175
183
176
let cfg = Config :: builder ( )
184
- . add_source ( File :: new ( "tests/Settings- enum-test" , FileFormat :: Jsonc ) )
177
+ . add_source ( File :: new ( & get_config_file_path ( ". enum" ) , FileFormat :: Jsonc ) )
185
178
. add_source ( config:: Environment :: with_prefix ( "test" ) . separator ( "_" ) )
186
179
. build ( )
187
180
. unwrap ( ) ;
188
181
189
- let param: EnumSettings = cfg. try_deserialize ( ) . unwrap ( ) ;
190
-
191
- assert_eq ! (
192
- param,
193
- EnumSettings :: Bar ( "I have been overridden_with_lower_case" . to_string ( ) )
182
+ let param = cfg. try_deserialize :: < EnumSettings > ( ) ;
183
+ assert ! ( param . is_err ( ) ) ;
184
+ assert_data_eq ! (
185
+ param. unwrap_err ( ) . to_string ( ) ,
186
+ str ! [ "enum EnumSettings does not have variant constructor bar" ]
194
187
) ;
195
188
}
0 commit comments