1- use config:: { Config , ConfigError , File , FileFormat } ;
2- use serde:: Deserialize ;
31use std:: str;
42
3+ use config:: { Config , ConfigError , Environment , File , FileFormat } ;
4+ use serde:: Deserialize ;
5+
56#[ derive( Debug , Deserialize ) ]
67#[ allow( unused) ]
78pub struct AdServer {
@@ -37,27 +38,29 @@ impl Settings {
3738 let toml_bytes = include_bytes ! ( "../../../trusted-server.toml" ) ;
3839 let toml_str = str:: from_utf8 ( toml_bytes) . unwrap ( ) ;
3940
40- let s = Config :: builder ( )
41- . add_source ( File :: from_str ( toml_str, FileFormat :: Toml ) )
41+ Self :: from_toml ( toml_str)
42+ }
43+
44+ pub fn from_toml ( toml_str : & str ) -> Result < Self , ConfigError > {
45+ let environment = Environment :: default ( )
46+ . prefix ( "TRUSTED_SERVER" )
47+ . separator ( "__" ) ;
48+
49+ let toml = File :: from_str ( toml_str, FileFormat :: Toml ) ;
50+ let config = Config :: builder ( )
51+ . add_source ( toml)
52+ . add_source ( environment)
4253 . build ( ) ?;
4354
4455 // You can deserialize (and thus freeze) the entire configuration as
45- s . try_deserialize ( )
56+ config . try_deserialize ( )
4657 }
4758}
4859
4960#[ cfg( test) ]
5061mod tests {
5162 use super :: * ;
5263
53- fn create_test_settings ( toml_str : & str ) -> Result < Settings , ConfigError > {
54- let s = Config :: builder ( )
55- . add_source ( File :: from_str ( toml_str, FileFormat :: Toml ) )
56- . build ( ) ?;
57-
58- s. try_deserialize ( )
59- }
60-
6164 #[ test]
6265 fn test_settings_new ( ) {
6366 // Test that Settings::new() loads successfully
@@ -92,7 +95,7 @@ mod tests {
9295 template = "{{client_ip}}:{{user_agent}}:{{first_party_id}}:{{auth_user_id}}:{{publisher_domain}}:{{accept_language}}"
9396 "# ;
9497
95- let settings = create_test_settings ( toml_str) ;
98+ let settings = Settings :: from_toml ( toml_str) ;
9699 assert ! ( settings. is_ok( ) ) ;
97100
98101 let settings = settings. unwrap ( ) ;
@@ -114,21 +117,21 @@ mod tests {
114117 #[ test]
115118 fn test_settings_missing_required_fields ( ) {
116119 let toml_str = r#"
117- [ad_server]
118- ad_partner_url = "https://example-ad.com/serve"
119- # Missing sync_url
120+ [ad_server]
121+ ad_partner_url = "https://example-ad.com/serve"
122+ # Missing sync_url
120123
121- [prebid]
122- server_url = "https://prebid.example.com/openrtb2/auction"
124+ [prebid]
125+ server_url = "https://prebid.example.com/openrtb2/auction"
123126
124- [synthetic]
125- counter_store = "test-counter-store"
126- opid_store = "test-opid-store"
127- secret_key = "test-secret-key"
128- template = "{{client_ip}}"
129- "# ;
127+ [synthetic]
128+ counter_store = "test-counter-store"
129+ opid_store = "test-opid-store"
130+ secret_key = "test-secret-key"
131+ template = "{{client_ip}}"
132+ "#;
130133
131- let settings = create_test_settings ( toml_str) ;
134+ let settings = Settings :: from_toml ( toml_str) ;
132135 assert ! (
133136 settings. is_err( ) ,
134137 "Should fail when required fields are missing"
@@ -138,85 +141,117 @@ template = "{{client_ip}}"
138141 #[ test]
139142 fn test_settings_empty_toml ( ) {
140143 let toml_str = "" ;
141- let settings = create_test_settings ( toml_str) ;
144+ let settings = Settings :: from_toml ( toml_str) ;
145+
142146 assert ! ( settings. is_err( ) , "Should fail with empty TOML" ) ;
143147 }
144148
145149 #[ test]
146150 fn test_settings_invalid_toml_syntax ( ) {
147151 let toml_str = r#"
148- [ad_server
149- ad_partner_url = "https://example-ad.com/serve"
150- "# ;
151- let settings = create_test_settings ( toml_str) ;
152+ [ad_server
153+ ad_partner_url = "https://example-ad.com/serve"
154+ "# ;
155+
156+ let settings = Settings :: from_toml ( toml_str) ;
152157 assert ! ( settings. is_err( ) , "Should fail with invalid TOML syntax" ) ;
153158 }
154159
155160 #[ test]
156161 fn test_settings_partial_config ( ) {
157162 let toml_str = r#"
158- [ad_server]
159- ad_partner_url = "https://example-ad.com/serve"
160- sync_url = "https://example-ad.com/sync"
161- "# ;
162- let settings = create_test_settings ( toml_str) ;
163+ [ad_server]
164+ ad_partner_url = "https://example-ad.com/serve"
165+ sync_url = "https://example-ad.com/sync"
166+ "# ;
167+
168+ let settings = Settings :: from_toml ( toml_str) ;
163169 assert ! ( settings. is_err( ) , "Should fail when sections are missing" ) ;
164170 }
165171
166172 #[ test]
167173 fn test_settings_extra_fields ( ) {
168174 let toml_str = r#"
169- [ad_server]
170- ad_partner_url = "https://example-ad.com/serve"
171- sync_url = "https://example-ad.com/sync"
172- extra_field = "should be ignored"
173-
174- [prebid]
175- server_url = "https://prebid.example.com/openrtb2/auction"
176-
177- [synthetic]
178- counter_store = "test-counter-store"
179- opid_store = "test-opid-store"
180- secret_key = "test-secret-key-1234567890"
181- template = "{{client_ip}}"
182- "# ;
183-
184- let settings = create_test_settings ( toml_str) ;
175+ [ad_server]
176+ ad_partner_url = "https://example-ad.com/serve"
177+ sync_url = "https://example-ad.com/sync"
178+ extra_field = "should be ignored"
179+
180+ [prebid]
181+ server_url = "https://prebid.example.com/openrtb2/auction"
182+
183+ [synthetic]
184+ counter_store = "test-counter-store"
185+ opid_store = "test-opid-store"
186+ secret_key = "test-secret-key-1234567890"
187+ template = "{{client_ip}}"
188+ "#;
189+
190+ let settings = Settings :: from_toml ( toml_str) ;
185191 assert ! ( settings. is_ok( ) , "Extra fields should be ignored" ) ;
186192 }
187193
188194 #[ test]
189- fn test_ad_server_debug_format ( ) {
190- let ad_server = AdServer {
191- ad_partner_url : "https://test.com" . to_string ( ) ,
192- sync_url : "https://sync.test.com" . to_string ( ) ,
193- } ;
194- let debug_str = format ! ( "{:?}" , ad_server) ;
195- assert ! ( debug_str. contains( "AdServer" ) ) ;
196- assert ! ( debug_str. contains( "https://test.com" ) ) ;
197- }
195+ fn test_set_env ( ) {
196+ let toml_str = r#"
197+ [ad_server]
198+ # ad_partner_url will be set by env variable
199+ sync_url = "https://example-ad.com/sync"
198200
199- #[ test]
200- fn test_prebid_debug_format ( ) {
201- let prebid = Prebid {
202- server_url : "https://prebid.test.com" . to_string ( ) ,
203- } ;
204- let debug_str = format ! ( "{:?}" , prebid) ;
205- assert ! ( debug_str. contains( "Prebid" ) ) ;
206- assert ! ( debug_str. contains( "https://prebid.test.com" ) ) ;
201+ [prebid]
202+ server_url = "https://prebid.example.com/openrtb2/auction"
203+
204+ [synthetic]
205+ counter_store = "test-counter-stor e"
206+ opid_store = "test-opid-store"
207+ secret_key = "test-secret-key-1234567890"
208+ template = "{{client_ip}}"
209+ "# ;
210+
211+ temp_env:: with_var (
212+ "TRUSTED_SERVER__AD_SERVER__AD_PARTNER_URL" ,
213+ Some ( "https://change-ad.com/serve" ) ,
214+ || {
215+ let settings = Settings :: from_toml ( toml_str) ;
216+
217+ assert ! ( settings. is_ok( ) , "Settings should load from embedded TOML" ) ;
218+ assert_eq ! (
219+ settings. unwrap( ) . ad_server. ad_partner_url,
220+ "https://change-ad.com/serve"
221+ ) ;
222+ } ,
223+ ) ;
207224 }
208225
209226 #[ test]
210- fn test_synthetic_debug_format ( ) {
211- let synthetic = Synthetic {
212- counter_store : "counter" . to_string ( ) ,
213- opid_store : "opid" . to_string ( ) ,
214- secret_key : "secret" . to_string ( ) ,
215- template : "{{test}}" . to_string ( ) ,
216- } ;
217- let debug_str = format ! ( "{:?}" , synthetic) ;
218- assert ! ( debug_str. contains( "Synthetic" ) ) ;
219- assert ! ( debug_str. contains( "counter" ) ) ;
220- assert ! ( debug_str. contains( "secret" ) ) ;
227+ fn test_override_env ( ) {
228+ let toml_str = r#"
229+ [ad_server]
230+ ad_partner_url = "https://example-ad.com/serve"
231+ sync_url = "https://example-ad.com/sync"
232+
233+ [prebid]
234+ server_url = "https://prebid.example.com/openrtb2/auction"
235+
236+ [synthetic]
237+ counter_store = "test-counter-stor e"
238+ opid_store = "test-opid-store"
239+ secret_key = "test-secret-key-1234567890"
240+ template = "{{client_ip}}"
241+ "# ;
242+
243+ temp_env:: with_var (
244+ "TRUSTED_SERVER__AD_SERVER__AD_PARTNER_URL" ,
245+ Some ( "https://change-ad.com/serve" ) ,
246+ || {
247+ let settings = Settings :: from_toml ( toml_str) ;
248+
249+ assert ! ( settings. is_ok( ) , "Settings should load from embedded TOML" ) ;
250+ assert_eq ! (
251+ settings. unwrap( ) . ad_server. ad_partner_url,
252+ "https://change-ad.com/serve"
253+ ) ;
254+ } ,
255+ ) ;
221256 }
222257}
0 commit comments