@@ -253,6 +253,154 @@ func TestCompositeProvider_GetData(t *testing.T) {
253
253
func TestCompositeProvider_AddDataToContext (t * testing.T ) {
254
254
t .Parallel ()
255
255
256
+ t .Run ("multiple ContextProviders with same key" , func (t * testing.T ) {
257
+ // Create multiple context providers with the same key
258
+ contextProvider1 := NewContextProvider (constants .EvalData )
259
+ contextProvider2 := NewContextProvider (constants .EvalData )
260
+
261
+ // Composite provider with both context providers
262
+ provider := NewCompositeProvider (contextProvider1 , contextProvider2 )
263
+
264
+ // Start with empty context
265
+ ctx := context .Background ()
266
+
267
+ // Add data with first call (should use the first provider)
268
+ data1 := map [string ]any {
269
+ "user" : map [string ]any {
270
+ "name" : "Alice" ,
271
+ "settings" : map [string ]any {
272
+ "theme" : "dark" ,
273
+ },
274
+ },
275
+ "shared" : "first" ,
276
+ }
277
+ ctx1 , err1 := provider .AddDataToContext (ctx , data1 )
278
+ require .NoError (t , err1 )
279
+
280
+ // Add more data with second call (should use first provider again, since its earlier in the chain)
281
+ data2 := map [string ]any {
282
+ "user" : map [string ]any {
283
+ "age" : 30 ,
284
+ "settings" : map [string ]any {
285
+ "notifications" : true ,
286
+ },
287
+ },
288
+ "shared" : "second" , // This should override "first"
289
+ }
290
+ ctx2 , err2 := provider .AddDataToContext (ctx1 , data2 )
291
+ require .NoError (t , err2 )
292
+
293
+ // Verify the data was merged correctly
294
+ result , err := provider .GetData (ctx2 )
295
+ require .NoError (t , err )
296
+
297
+ // Check that both data sets were merged
298
+ userMap , ok := result ["user" ].(map [string ]any )
299
+ assert .True (t , ok , "User should be a map" )
300
+ assert .Equal (t , "Alice" , userMap ["name" ], "Name should be preserved" )
301
+ assert .Equal (t , 30 , userMap ["age" ], "Age should be added" )
302
+
303
+ settings , ok := userMap ["settings" ].(map [string ]any )
304
+ assert .True (t , ok , "Settings should be a map" )
305
+ assert .Equal (t , "dark" , settings ["theme" ], "Theme should be preserved" )
306
+ assert .Equal (t , true , settings ["notifications" ], "Notifications should be added" )
307
+
308
+ // Check that shared value was overridden
309
+ assert .Equal (t , "second" , result ["shared" ], "Shared value should be overridden" )
310
+ })
311
+
312
+ t .Run ("complex interaction between multiple ContextProviders" , func (t * testing.T ) {
313
+ // Create three context providers with the same key
314
+ provider1 := NewContextProvider (constants .EvalData )
315
+ provider2 := NewContextProvider (constants .EvalData )
316
+ provider3 := NewContextProvider (constants .EvalData )
317
+
318
+ // Create composite provider with a specific order
319
+ composite := NewCompositeProvider (provider1 , provider2 , provider3 )
320
+
321
+ // Setup initial context with data in each provider's storage
322
+ ctx := context .Background ()
323
+
324
+ // Setup data for first provider (this should be accessible by all providers)
325
+ initialData := map [string ]any {
326
+ "config" : map [string ]any {
327
+ "mode" : "production" ,
328
+ "features" : map [string ]any {
329
+ "feature1" : true ,
330
+ "feature2" : false ,
331
+ },
332
+ },
333
+ "counter" : 1 ,
334
+ }
335
+ ctx = context .WithValue (ctx , constants .EvalData , initialData )
336
+
337
+ // First AddDataToContext call (uses provider1)
338
+ data1 := map [string ]any {
339
+ "config" : map [string ]any {
340
+ "features" : map [string ]any {
341
+ "feature2" : true , // Override feature2
342
+ "feature3" : true , // Add feature3
343
+ },
344
+ "timeout" : 30 , // Add timeout
345
+ },
346
+ "counter" : 2 , // Override counter
347
+ }
348
+ ctx , err := composite .AddDataToContext (ctx , data1 )
349
+ require .NoError (t , err )
350
+
351
+ // Second AddDataToContext call (uses provider1 again)
352
+ data2 := map [string ]any {
353
+ "config" : map [string ]any {
354
+ "mode" : "development" , // Override mode
355
+ "features" : map [string ]any {
356
+ "feature1" : false , // Override feature1
357
+ },
358
+ },
359
+ "counter" : 3 , // Override counter again
360
+ "user" : "admin" , // Add new field
361
+ }
362
+ ctx , err = composite .AddDataToContext (ctx , data2 )
363
+ require .NoError (t , err )
364
+
365
+ // Verify the final state
366
+ result , err := composite .GetData (ctx )
367
+ require .NoError (t , err )
368
+
369
+ // Check counter (simplest case - should be last value)
370
+ assert .Equal (t , 3 , result ["counter" ])
371
+
372
+ // Check user (added in second call)
373
+ assert .Equal (t , "admin" , result ["user" ])
374
+
375
+ // Check config (complex nested structure with multiple updates)
376
+ config , ok := result ["config" ].(map [string ]any )
377
+ require .True (t , ok )
378
+
379
+ // Check mode (updated in second call)
380
+ assert .Equal (t , "development" , config ["mode" ])
381
+
382
+ // Check timeout (added in first call, not touched in second)
383
+ assert .Equal (t , 30 , config ["timeout" ])
384
+
385
+ // Check features (updated across multiple calls)
386
+ features , ok := config ["features" ].(map [string ]any )
387
+ require .True (t , ok )
388
+
389
+ assert .Equal (
390
+ t ,
391
+ false ,
392
+ features ["feature1" ],
393
+ "feature1 should be false (updated in second call)" ,
394
+ )
395
+ assert .Equal (
396
+ t ,
397
+ true ,
398
+ features ["feature2" ],
399
+ "feature2 should be true (updated in first call)" ,
400
+ )
401
+ assert .Equal (t , true , features ["feature3" ], "feature3 should be true (added in first call)" )
402
+ })
403
+
256
404
t .Run ("empty providers list" , func (t * testing.T ) {
257
405
provider := NewCompositeProvider ()
258
406
require .NotNil (t , provider )
@@ -396,6 +544,48 @@ func TestCompositeProvider_NestedStructures(t *testing.T) {
396
544
setupContext func () context.Context
397
545
expectedResult map [string ]any
398
546
}{
547
+ {
548
+ name : "multiple ContextProviders with same context key" ,
549
+ setupProviders : func () * CompositeProvider {
550
+ // Create multiple context providers with the same key
551
+ contextProvider1 := NewContextProvider (constants .EvalData )
552
+ contextProvider2 := NewContextProvider (constants .EvalData )
553
+ contextProvider3 := NewContextProvider (constants .EvalData )
554
+
555
+ // Composite provider with all three context providers
556
+ return NewCompositeProvider (contextProvider1 , contextProvider2 , contextProvider3 )
557
+ },
558
+ setupContext : func () context.Context {
559
+ // Create a context with data for each provider to access/modify
560
+ ctx := context .Background ()
561
+
562
+ // First provider data
563
+ ctx = context .WithValue (ctx , constants .EvalData , map [string ]any {
564
+ "user" : map [string ]any {
565
+ "name" : "Alice" ,
566
+ "role" : "admin" ,
567
+ "settings" : map [string ]any {
568
+ "theme" : "dark" ,
569
+ },
570
+ },
571
+ "version" : "1.0" ,
572
+ "shared" : "first" ,
573
+ })
574
+
575
+ return ctx
576
+ },
577
+ expectedResult : map [string ]any {
578
+ "user" : map [string ]any {
579
+ "name" : "Alice" ,
580
+ "role" : "admin" ,
581
+ "settings" : map [string ]any {
582
+ "theme" : "dark" ,
583
+ },
584
+ },
585
+ "version" : "1.0" ,
586
+ "shared" : "first" ,
587
+ },
588
+ },
399
589
{
400
590
name : "nested composite providers with static data" ,
401
591
setupProviders : func () * CompositeProvider {
0 commit comments