@@ -605,3 +605,184 @@ func TestWith_MultipleOptions(t *testing.T) {
605605 t .Error ("Original error was modified" )
606606 }
607607}
608+
609+ func TestWith_KeyPrecedence (t * testing.T ) {
610+ t .Run ("same key within single With call" , func (t * testing.T ) {
611+ original := goerr .New ("original error" )
612+
613+ // Same key specified multiple times in single With call
614+ enhanced := goerr .With (original ,
615+ goerr .Value ("key1" , "first_value" ),
616+ goerr .Value ("key1" , "second_value" ), // Should override first_value
617+ goerr .Value ("key1" , "final_value" ), // Should override second_value
618+ )
619+
620+ values := enhanced .Values ()
621+ if values ["key1" ] != "final_value" {
622+ t .Errorf ("Expected 'final_value', got %v" , values ["key1" ])
623+ }
624+
625+ // Original should remain unchanged
626+ if len (original .Values ()) != 0 {
627+ t .Error ("Original error was modified" )
628+ }
629+ })
630+
631+ t .Run ("consecutive With calls with same key" , func (t * testing.T ) {
632+ original := goerr .New ("original error" )
633+
634+ // Multiple With calls with same key
635+ step1 := goerr .With (original , goerr .Value ("key1" , "first_value" ))
636+ step2 := goerr .With (step1 , goerr .Value ("key1" , "second_value" ))
637+ final := goerr .With (step2 , goerr .Value ("key1" , "final_value" ))
638+
639+ values := final .Values ()
640+ if values ["key1" ] != "final_value" {
641+ t .Errorf ("Expected 'final_value', got %v" , values ["key1" ])
642+ }
643+
644+ // Previous steps should have their own values
645+ if step1 .Values ()["key1" ] != "first_value" {
646+ t .Errorf ("Step1 should have 'first_value', got %v" , step1 .Values ()["key1" ])
647+ }
648+ if step2 .Values ()["key1" ] != "second_value" {
649+ t .Errorf ("Step2 should have 'second_value', got %v" , step2 .Values ()["key1" ])
650+ }
651+
652+ // Original should remain unchanged
653+ if len (original .Values ()) != 0 {
654+ t .Error ("Original error was modified" )
655+ }
656+ })
657+
658+ t .Run ("overwrite existing error key with With" , func (t * testing.T ) {
659+ // Create error with existing key
660+ original := goerr .New ("original error" , goerr .Value ("existing_key" , "original_value" ))
661+
662+ // Override existing key with With
663+ enhanced := goerr .With (original , goerr .Value ("existing_key" , "new_value" ))
664+
665+ values := enhanced .Values ()
666+ if values ["existing_key" ] != "new_value" {
667+ t .Errorf ("Expected 'new_value', got %v" , values ["existing_key" ])
668+ }
669+
670+ // Original should keep its value
671+ originalValues := original .Values ()
672+ if originalValues ["existing_key" ] != "original_value" {
673+ t .Errorf ("Original should keep 'original_value', got %v" , originalValues ["existing_key" ])
674+ }
675+ })
676+
677+ t .Run ("TypedValue key precedence" , func (t * testing.T ) {
678+ stringKey := goerr.NewTypedKey [string ]("typed_key" )
679+
680+ original := goerr .New ("original error" )
681+
682+ // Multiple TypedValue with same key
683+ enhanced := goerr .With (original ,
684+ goerr .TV (stringKey , "first_typed_value" ),
685+ goerr .TV (stringKey , "final_typed_value" ), // Should override first
686+ )
687+
688+ // Check via GetTypedValue
689+ if value , ok := goerr .GetTypedValue (enhanced , stringKey ); ! ok || value != "final_typed_value" {
690+ t .Errorf ("Expected 'final_typed_value', got %v (ok=%v)" , value , ok )
691+ }
692+
693+ // Check via TypedValues
694+ typedValues := enhanced .TypedValues ()
695+ if typedValues ["typed_key" ] != "final_typed_value" {
696+ t .Errorf ("Expected 'final_typed_value' in TypedValues, got %v" , typedValues ["typed_key" ])
697+ }
698+
699+ // Original should remain unchanged
700+ if len (original .TypedValues ()) != 0 {
701+ t .Error ("Original error was modified" )
702+ }
703+ })
704+
705+ t .Run ("mixed Value and TypedValue with same key name" , func (t * testing.T ) {
706+ stringKey := goerr.NewTypedKey [string ]("same_key" )
707+
708+ original := goerr .New ("original error" )
709+
710+ // Mix string-based Value and TypedValue with same key name
711+ enhanced := goerr .With (original ,
712+ goerr .Value ("same_key" , "string_value" ),
713+ goerr .TV (stringKey , "typed_value" ),
714+ )
715+
716+ // Both should exist independently
717+ values := enhanced .Values ()
718+ typedValues := enhanced .TypedValues ()
719+
720+ if values ["same_key" ] != "string_value" {
721+ t .Errorf ("Expected 'string_value' in Values, got %v" , values ["same_key" ])
722+ }
723+ if typedValues ["same_key" ] != "typed_value" {
724+ t .Errorf ("Expected 'typed_value' in TypedValues, got %v" , typedValues ["same_key" ])
725+ }
726+
727+ // GetTypedValue should return typed value
728+ if value , ok := goerr .GetTypedValue (enhanced , stringKey ); ! ok || value != "typed_value" {
729+ t .Errorf ("Expected 'typed_value' from GetTypedValue, got %v (ok=%v)" , value , ok )
730+ }
731+ })
732+
733+ t .Run ("complex With chain with multiple overwrites" , func (t * testing.T ) {
734+ stringKey := goerr.NewTypedKey [string ]("chain_key" )
735+
736+ // Start with error having some values
737+ original := goerr .New ("original error" ,
738+ goerr .Value ("key1" , "orig1" ),
739+ goerr .Value ("key2" , "orig2" ),
740+ goerr .TV (stringKey , "orig_typed" ),
741+ )
742+
743+ // Chain multiple With calls with overlapping keys
744+ step1 := goerr .With (original ,
745+ goerr .Value ("key1" , "step1_val1" ), // Override key1
746+ goerr .Value ("key3" , "step1_val3" ), // New key
747+ )
748+
749+ step2 := goerr .With (step1 ,
750+ goerr .Value ("key2" , "step2_val2" ), // Override key2
751+ goerr .TV (stringKey , "step2_typed" ), // Override typed
752+ )
753+
754+ finalStep := goerr .With (step2 ,
755+ goerr .Value ("key1" , "final_val1" ), // Override key1 again
756+ goerr .Value ("key4" , "final_val4" ), // New key
757+ )
758+
759+ // Check final values
760+ values := finalStep .Values ()
761+ expectedValues := map [string ]any {
762+ "key1" : "final_val1" , // Final override
763+ "key2" : "step2_val2" , // From step2
764+ "key3" : "step1_val3" , // From step1
765+ "key4" : "final_val4" , // From final step
766+ }
767+
768+ for key , expected := range expectedValues {
769+ if values [key ] != expected {
770+ t .Errorf ("Key %s: expected %v, got %v" , key , expected , values [key ])
771+ }
772+ }
773+
774+ // Check typed value
775+ if value , ok := goerr .GetTypedValue (finalStep , stringKey ); ! ok || value != "step2_typed" {
776+ t .Errorf ("Expected 'step2_typed' from GetTypedValue, got %v (ok=%v)" , value , ok )
777+ }
778+
779+ // Original should remain unchanged
780+ originalValues := original .Values ()
781+ if originalValues ["key1" ] != "orig1" || originalValues ["key2" ] != "orig2" {
782+ t .Error ("Original error values were modified" )
783+ }
784+ if value , ok := goerr .GetTypedValue (original , stringKey ); ! ok || value != "orig_typed" {
785+ t .Error ("Original error typed values were modified" )
786+ }
787+ })
788+ }
0 commit comments