@@ -189,11 +189,20 @@ func assertCMAB(t *testing.T, cmab config.CMABConfig) {
189189 // Base assertions
190190 assert .Equal (t , 15 * time .Second , cmab .RequestTimeout )
191191
192- // Check cache configuration
192+ // Check cache configuration (now a map[string]interface{})
193193 cache := cmab .Cache
194- assert .Equal (t , "redis" , cache .Type )
195- assert .Equal (t , 2000 , cache .Size )
196- assert .Equal (t , 45 * time .Minute , cache .TTL )
194+ assert .NotNil (t , cache )
195+ assert .Equal (t , "redis" , cache ["default" ])
196+
197+ // Check services configuration
198+ if services , ok := cache ["services" ].(map [string ]interface {}); ok {
199+ if redisConfig , ok := services ["redis" ].(map [string ]interface {}); ok {
200+ // Redis config should have host, database, and timeout fields
201+ assert .NotNil (t , redisConfig ["host" ])
202+ assert .NotNil (t , redisConfig ["database" ])
203+ assert .NotNil (t , redisConfig ["timeout" ])
204+ }
205+ }
197206
198207 // Check retry configuration
199208 retry := cmab .RetryConfig
@@ -207,9 +216,14 @@ func TestCMABEnvDebug(t *testing.T) {
207216 _ = os .Setenv ("OPTIMIZELY_CMAB" , `{
208217 "requestTimeout": "15s",
209218 "cache": {
210- "type": "redis",
211- "size": 2000,
212- "ttl": "45m"
219+ "default": "redis",
220+ "services": {
221+ "redis": {
222+ "host": "localhost:6379",
223+ "database": 0,
224+ "timeout": "45m"
225+ }
226+ }
213227 },
214228 "retryConfig": {
215229 "maxRetries": 5,
@@ -246,17 +260,20 @@ func TestCMABPartialConfig(t *testing.T) {
246260 os .Unsetenv ("OPTIMIZELY_CMAB_RETRYCONFIG" )
247261
248262 // Set partial configuration through CMAB_CACHE and CMAB_RETRYCONFIG
249- _ = os .Setenv ("OPTIMIZELY_CMAB_CACHE" , `{"type": "redis", "size": 3000}` )
263+ // Note: Cache is now a service-based map config
264+ _ = os .Setenv ("OPTIMIZELY_CMAB_CACHE" , `{"default": "redis", "services": {"redis": {"host": "localhost:6379", "database": 0}}}` )
250265 _ = os .Setenv ("OPTIMIZELY_CMAB_RETRYCONFIG" , `{"maxRetries": 10}` )
251266
252267 // Load config
253268 v := viper .New ()
254269 assert .NoError (t , initConfig (v ))
255270 conf := loadConfig (v )
256271
257- // Cache assertions
258- assert .Equal (t , "redis" , conf .CMAB .Cache .Type )
259- assert .Equal (t , 3000 , conf .CMAB .Cache .Size )
272+ // Cache assertions (cache is now map[string]interface{})
273+ assert .NotNil (t , conf .CMAB .Cache )
274+ if defaultCache , ok := conf .CMAB .Cache ["default" ].(string ); ok {
275+ assert .Equal (t , "redis" , defaultCache )
276+ }
260277
261278 // RetryConfig assertions
262279 assert .Equal (t , 10 , conf .CMAB .RetryConfig .MaxRetries )
@@ -267,6 +284,50 @@ func TestCMABPartialConfig(t *testing.T) {
267284 os .Unsetenv ("OPTIMIZELY_CMAB_RETRYCONFIG" )
268285}
269286
287+ func TestCMABRetryConfigAllFields (t * testing.T ) {
288+ // Clean any existing environment variables
289+ os .Unsetenv ("OPTIMIZELY_CMAB" )
290+ os .Unsetenv ("OPTIMIZELY_CMAB_CACHE" )
291+ os .Unsetenv ("OPTIMIZELY_CMAB_RETRYCONFIG" )
292+
293+ // Set all retry config fields via CMAB_RETRYCONFIG to cover lines 154-165
294+ _ = os .Setenv ("OPTIMIZELY_CMAB_RETRYCONFIG" , `{
295+ "maxRetries": 5,
296+ "initialBackoff": "500ms",
297+ "maxBackoff": "45s",
298+ "backoffMultiplier": 2.5
299+ }` )
300+
301+ defer func () {
302+ os .Unsetenv ("OPTIMIZELY_CMAB_RETRYCONFIG" )
303+ }()
304+
305+ v := viper .New ()
306+ assert .NoError (t , initConfig (v ))
307+ conf := loadConfig (v )
308+
309+ // Verify all retry config fields were parsed correctly
310+ assert .Equal (t , 5 , conf .CMAB .RetryConfig .MaxRetries )
311+ assert .Equal (t , 500 * time .Millisecond , conf .CMAB .RetryConfig .InitialBackoff )
312+ assert .Equal (t , 45 * time .Second , conf .CMAB .RetryConfig .MaxBackoff )
313+ assert .Equal (t , 2.5 , conf .CMAB .RetryConfig .BackoffMultiplier )
314+ }
315+
316+ func TestCMABRetryConfigIntMaxRetries (t * testing.T ) {
317+ // Test the int type path for maxRetries (line 150) by using viper's Set method
318+ // which will preserve the int type instead of converting to float64
319+ v := viper .New ()
320+ assert .NoError (t , initConfig (v ))
321+
322+ // Set via viper directly to ensure it's an int, not float64
323+ v .Set ("cmab.retryConfig.maxRetries" , 7 )
324+
325+ conf := loadConfig (v )
326+
327+ // Verify maxRetries was parsed as int
328+ assert .Equal (t , 7 , conf .CMAB .RetryConfig .MaxRetries )
329+ }
330+
270331func TestViperYaml (t * testing.T ) {
271332 v := viper .New ()
272333 v .Set ("config.filename" , "./testdata/default.yaml" )
@@ -484,9 +545,14 @@ func TestViperEnv(t *testing.T) {
484545 _ = os .Setenv ("OPTIMIZELY_CMAB" , `{
485546 "requestTimeout": "15s",
486547 "cache": {
487- "type": "redis",
488- "size": 2000,
489- "ttl": "45m"
548+ "default": "redis",
549+ "services": {
550+ "redis": {
551+ "host": "localhost:6379",
552+ "database": 0,
553+ "timeout": "45m"
554+ }
555+ }
490556 },
491557 "retryConfig": {
492558 "maxRetries": 5,
@@ -622,8 +688,8 @@ func TestCMABComplexJSON(t *testing.T) {
622688 os .Unsetenv ("OPTIMIZELY_CMAB_CACHE_REDIS_PASSWORD" )
623689 os .Unsetenv ("OPTIMIZELY_CMAB_CACHE_REDIS_DATABASE" )
624690
625- // Set complex JSON environment variable for CMAB cache
626- _ = os .Setenv ("OPTIMIZELY_CMAB_CACHE" , `{"type ":"redis","size":5000,"ttl":" 3h"}` )
691+ // Set complex JSON environment variable for CMAB cache (using new service-based format)
692+ _ = os .Setenv ("OPTIMIZELY_CMAB_CACHE" , `{"default ":"redis","services":{"redis":{"host":"localhost:6379","database":0,"timeout":" 3h"}} }` )
627693
628694 defer func () {
629695 // Clean up
@@ -634,9 +700,13 @@ func TestCMABComplexJSON(t *testing.T) {
634700 assert .NoError (t , initConfig (v ))
635701 actual := loadConfig (v )
636702
637- // Test cache settings from JSON environment variable
703+ // Test cache settings from JSON environment variable (cache is now map[string]interface{})
638704 cache := actual .CMAB .Cache
639- assert .Equal (t , "redis" , cache .Type )
640- assert .Equal (t , 5000 , cache .Size )
641- assert .Equal (t , 3 * time .Hour , cache .TTL )
705+ assert .NotNil (t , cache )
706+ if defaultCache , ok := cache ["default" ].(string ); ok {
707+ assert .Equal (t , "redis" , defaultCache )
708+ }
709+ if services , ok := cache ["services" ].(map [string ]interface {}); ok {
710+ assert .NotNil (t , services ["redis" ])
711+ }
642712}
0 commit comments