refactor(client): use map.Copy for cleaner map handling (backport #24022) (#24048)

Co-authored-by: petersssong <petersssong@proton.me>
Co-authored-by: aljo242 <alex@interchainlabs.io>
This commit is contained in:
mergify[bot] 2025-03-18 11:48:15 -04:00 committed by GitHub
parent 7bba055c34
commit 5a71f927fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 127 additions and 6 deletions

View File

@ -1,9 +1,9 @@
package maps
import (
"fmt"
"maps"
"strings"
"github.com/cockroachdb/errors"
)
type genericMapValueOptions[K comparable, V any] struct {
@ -31,7 +31,7 @@ func (gm *genericMapValue[K, V]) Set(val string) error {
for _, pair := range ss {
kv := strings.SplitN(pair, "=", 2)
if len(kv) != 2 {
return errors.Errorf("%s must be formatted as key=value", pair)
return fmt.Errorf("%s must be formatted as key=value", pair)
}
key, err := gm.Options.keyParser(kv[0])
if err != nil {
@ -45,9 +45,7 @@ func (gm *genericMapValue[K, V]) Set(val string) error {
if !gm.changed {
*gm.value = out
} else {
for k, v := range out {
(*gm.value)[k] = v
}
maps.Copy(*gm.value, out)
}
gm.changed = true
return nil

View File

@ -0,0 +1,123 @@
package maps
import (
"maps"
"strconv"
"testing"
"github.com/stretchr/testify/require"
)
func TestGenericMapValue_Set(t *testing.T) {
tests := []struct {
name string
input string
initialMap map[string]int
expectMap map[string]int
expectError bool
changed bool
}{
{
name: "basic key-value pairs",
input: "key1=1,key2=2",
initialMap: map[string]int{},
expectMap: map[string]int{"key1": 1, "key2": 2},
},
{
name: "invalid format missing value",
input: "key1",
initialMap: map[string]int{},
expectError: true,
},
{
name: "invalid format wrong separator",
input: "key1:1",
initialMap: map[string]int{},
expectError: true,
},
{
name: "overwrite existing map first time",
input: "key3=3",
initialMap: map[string]int{"key1": 1, "key2": 2},
expectMap: map[string]int{"key3": 3},
},
{
name: "invalid value format",
input: "key1=invalid",
initialMap: map[string]int{},
expectError: true,
},
{
name: "empty string input",
input: "",
initialMap: map[string]int{},
expectError: true,
},
{
name: "empty value",
input: "key=",
initialMap: map[string]int{},
expectError: true,
},
{
name: "append to existing map",
input: "key3=3",
initialMap: map[string]int{"key1": 1, "key2": 2},
expectMap: map[string]int{"key1": 1, "key2": 2, "key3": 3},
changed: true,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// Create a map value with string keys and int values
mapVal := make(map[string]int)
maps.Copy(mapVal, tc.initialMap)
gm := newGenericMapValue(mapVal, &mapVal)
gm.changed = tc.changed
gm.Options = genericMapValueOptions[string, int]{
keyParser: func(s string) (string, error) {
return s, nil
},
valueParser: strconv.Atoi,
genericType: "map[string]int",
}
err := gm.Set(tc.input)
if tc.expectError {
require.Error(t, err)
return
}
require.NoError(t, err)
require.Equal(t, tc.expectMap, mapVal)
})
}
}
func TestGenericMapValue_Changed(t *testing.T) {
mapVal := make(map[string]int)
gm := newGenericMapValue(mapVal, &mapVal)
gm.Options = genericMapValueOptions[string, int]{
keyParser: func(s string) (string, error) {
return s, nil
},
valueParser: strconv.Atoi,
genericType: "map[string]int",
}
require.False(t, gm.changed)
// First Set should replace the map entirely
err := gm.Set("key1=1")
require.NoError(t, err)
require.True(t, gm.changed)
require.Equal(t, map[string]int{"key1": 1}, mapVal)
// Second Set should merge with existing map
err = gm.Set("key2=2")
require.NoError(t, err)
require.Equal(t, map[string]int{"key1": 1, "key2": 2}, mapVal)
}