mirror of
https://github.com/aykhans/go-utils.git
synced 2025-10-15 18:25:57 +00:00
318 lines
6.9 KiB
Go
318 lines
6.9 KiB
Go
package maps
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestInitMap(t *testing.T) {
|
|
t.Run("initializes nil map", func(t *testing.T) {
|
|
var m map[string]int
|
|
require.Nil(t, m)
|
|
|
|
InitMap(&m)
|
|
|
|
assert.NotNil(t, m)
|
|
assert.Empty(t, m)
|
|
assert.Empty(t, m)
|
|
})
|
|
|
|
t.Run("does not reinitialize existing map", func(t *testing.T) {
|
|
m := map[string]int{"key": 42}
|
|
originalLen := len(m)
|
|
|
|
InitMap(&m)
|
|
|
|
assert.Len(t, m, originalLen)
|
|
assert.Equal(t, 42, m["key"])
|
|
})
|
|
|
|
t.Run("allows adding entries after initialization", func(t *testing.T) {
|
|
var m map[string]int
|
|
InitMap(&m)
|
|
|
|
m["test"] = 100
|
|
assert.Equal(t, 100, m["test"])
|
|
assert.Len(t, m, 1)
|
|
})
|
|
|
|
t.Run("works with empty initialized map", func(t *testing.T) {
|
|
m := make(map[string]int)
|
|
InitMap(&m)
|
|
|
|
assert.NotNil(t, m)
|
|
assert.Empty(t, m)
|
|
})
|
|
|
|
t.Run("works with different key types", func(t *testing.T) {
|
|
t.Run("int keys", func(t *testing.T) {
|
|
var m map[int]string
|
|
InitMap(&m)
|
|
|
|
assert.NotNil(t, m)
|
|
m[1] = "one"
|
|
assert.Equal(t, "one", m[1])
|
|
})
|
|
|
|
t.Run("struct keys", func(t *testing.T) {
|
|
type Key struct {
|
|
ID int
|
|
Name string
|
|
}
|
|
var m map[Key]bool
|
|
InitMap(&m)
|
|
|
|
assert.NotNil(t, m)
|
|
k := Key{ID: 1, Name: "test"}
|
|
m[k] = true
|
|
assert.True(t, m[k])
|
|
})
|
|
})
|
|
|
|
t.Run("works with different value types", func(t *testing.T) {
|
|
t.Run("string values", func(t *testing.T) {
|
|
var m map[string]string
|
|
InitMap(&m)
|
|
|
|
assert.NotNil(t, m)
|
|
m["key"] = "value"
|
|
assert.Equal(t, "value", m["key"])
|
|
})
|
|
|
|
t.Run("struct values", func(t *testing.T) {
|
|
type Value struct {
|
|
Count int
|
|
Name string
|
|
}
|
|
var m map[string]Value
|
|
InitMap(&m)
|
|
|
|
assert.NotNil(t, m)
|
|
m["test"] = Value{Count: 5, Name: "foo"}
|
|
assert.Equal(t, 5, m["test"].Count)
|
|
})
|
|
|
|
t.Run("slice values", func(t *testing.T) {
|
|
var m map[string][]int
|
|
InitMap(&m)
|
|
|
|
assert.NotNil(t, m)
|
|
m["numbers"] = []int{1, 2, 3}
|
|
assert.Equal(t, []int{1, 2, 3}, m["numbers"])
|
|
})
|
|
|
|
t.Run("pointer values", func(t *testing.T) {
|
|
var m map[string]*int
|
|
InitMap(&m)
|
|
|
|
assert.NotNil(t, m)
|
|
val := 42
|
|
m["ptr"] = &val
|
|
assert.Equal(t, 42, *m["ptr"])
|
|
})
|
|
})
|
|
|
|
t.Run("works with custom map types", func(t *testing.T) {
|
|
type CustomMap map[string]int
|
|
var m CustomMap
|
|
InitMap(&m)
|
|
|
|
assert.NotNil(t, m)
|
|
m["custom"] = 99
|
|
assert.Equal(t, 99, m["custom"])
|
|
})
|
|
}
|
|
|
|
func TestUpdateMap(t *testing.T) {
|
|
t.Run("merges new entries into existing map", func(t *testing.T) {
|
|
oldMap := map[string]int{"a": 1, "b": 2}
|
|
newMap := map[string]int{"c": 3, "d": 4}
|
|
|
|
UpdateMap(&oldMap, newMap)
|
|
|
|
assert.Len(t, oldMap, 4)
|
|
assert.Equal(t, 1, oldMap["a"])
|
|
assert.Equal(t, 2, oldMap["b"])
|
|
assert.Equal(t, 3, oldMap["c"])
|
|
assert.Equal(t, 4, oldMap["d"])
|
|
})
|
|
|
|
t.Run("overwrites existing keys", func(t *testing.T) {
|
|
oldMap := map[string]int{"a": 1, "b": 2}
|
|
newMap := map[string]int{"b": 3, "c": 4}
|
|
|
|
UpdateMap(&oldMap, newMap)
|
|
|
|
assert.Len(t, oldMap, 3)
|
|
assert.Equal(t, 1, oldMap["a"])
|
|
assert.Equal(t, 3, oldMap["b"], "existing key 'b' should be overwritten")
|
|
assert.Equal(t, 4, oldMap["c"])
|
|
})
|
|
|
|
t.Run("initializes nil map before merging", func(t *testing.T) {
|
|
var oldMap map[string]int
|
|
newMap := map[string]int{"a": 1, "b": 2}
|
|
|
|
require.Nil(t, oldMap)
|
|
UpdateMap(&oldMap, newMap)
|
|
|
|
assert.NotNil(t, oldMap)
|
|
assert.Len(t, oldMap, 2)
|
|
assert.Equal(t, 1, oldMap["a"])
|
|
assert.Equal(t, 2, oldMap["b"])
|
|
})
|
|
|
|
t.Run("handles empty new map", func(t *testing.T) {
|
|
oldMap := map[string]int{"a": 1}
|
|
newMap := map[string]int{}
|
|
|
|
UpdateMap(&oldMap, newMap)
|
|
|
|
assert.Len(t, oldMap, 1)
|
|
assert.Equal(t, 1, oldMap["a"])
|
|
})
|
|
|
|
t.Run("handles empty old map", func(t *testing.T) {
|
|
oldMap := map[string]int{}
|
|
newMap := map[string]int{"a": 1, "b": 2}
|
|
|
|
UpdateMap(&oldMap, newMap)
|
|
|
|
assert.Len(t, oldMap, 2)
|
|
assert.Equal(t, 1, oldMap["a"])
|
|
assert.Equal(t, 2, oldMap["b"])
|
|
})
|
|
|
|
t.Run("handles both empty maps", func(t *testing.T) {
|
|
oldMap := map[string]int{}
|
|
newMap := map[string]int{}
|
|
|
|
UpdateMap(&oldMap, newMap)
|
|
|
|
assert.NotNil(t, oldMap)
|
|
assert.Empty(t, oldMap)
|
|
})
|
|
|
|
t.Run("works with different types", func(t *testing.T) {
|
|
t.Run("string values", func(t *testing.T) {
|
|
oldMap := map[string]string{"key1": "value1"}
|
|
newMap := map[string]string{"key2": "value2"}
|
|
|
|
UpdateMap(&oldMap, newMap)
|
|
|
|
assert.Len(t, oldMap, 2)
|
|
assert.Equal(t, "value1", oldMap["key1"])
|
|
assert.Equal(t, "value2", oldMap["key2"])
|
|
})
|
|
|
|
t.Run("struct values", func(t *testing.T) {
|
|
type Person struct {
|
|
Name string
|
|
Age int
|
|
}
|
|
oldMap := map[string]Person{
|
|
"john": {Name: "John", Age: 30},
|
|
}
|
|
newMap := map[string]Person{
|
|
"jane": {Name: "Jane", Age: 25},
|
|
}
|
|
|
|
UpdateMap(&oldMap, newMap)
|
|
|
|
assert.Len(t, oldMap, 2)
|
|
assert.Equal(t, "John", oldMap["john"].Name)
|
|
assert.Equal(t, "Jane", oldMap["jane"].Name)
|
|
})
|
|
|
|
t.Run("int keys", func(t *testing.T) {
|
|
oldMap := map[int]string{1: "one"}
|
|
newMap := map[int]string{2: "two"}
|
|
|
|
UpdateMap(&oldMap, newMap)
|
|
|
|
assert.Len(t, oldMap, 2)
|
|
assert.Equal(t, "one", oldMap[1])
|
|
assert.Equal(t, "two", oldMap[2])
|
|
})
|
|
})
|
|
|
|
t.Run("modifies map in place", func(t *testing.T) {
|
|
oldMap := map[string]int{"a": 1}
|
|
originalMap := oldMap
|
|
newMap := map[string]int{"b": 2}
|
|
|
|
UpdateMap(&oldMap, newMap)
|
|
|
|
// Verify it's the same map (modified in place)
|
|
assert.Equal(t, 2, oldMap["b"])
|
|
// Note: originalMap is pointing to the same underlying map
|
|
// so it should also have the new value
|
|
assert.Equal(t, 2, originalMap["b"])
|
|
})
|
|
|
|
t.Run("does not modify new map", func(t *testing.T) {
|
|
oldMap := map[string]int{"a": 1}
|
|
newMap := map[string]int{"b": 2, "c": 3}
|
|
newLen := len(newMap)
|
|
|
|
UpdateMap(&oldMap, newMap)
|
|
|
|
assert.Len(t, newMap, newLen, "new map should not be modified")
|
|
assert.Equal(t, 2, newMap["b"])
|
|
assert.Equal(t, 3, newMap["c"])
|
|
_, hasA := newMap["a"]
|
|
assert.False(t, hasA, "new map should not contain keys from old map")
|
|
})
|
|
|
|
t.Run("works with custom map types", func(t *testing.T) {
|
|
type CustomMap map[string]int
|
|
oldMap := CustomMap{"a": 1}
|
|
newMap := CustomMap{"b": 2}
|
|
|
|
UpdateMap(&oldMap, newMap)
|
|
|
|
assert.Len(t, oldMap, 2)
|
|
assert.Equal(t, 1, oldMap["a"])
|
|
assert.Equal(t, 2, oldMap["b"])
|
|
})
|
|
|
|
t.Run("overwrites with zero values", func(t *testing.T) {
|
|
oldMap := map[string]int{"a": 10, "b": 20}
|
|
newMap := map[string]int{"a": 0}
|
|
|
|
UpdateMap(&oldMap, newMap)
|
|
|
|
assert.Len(t, oldMap, 2)
|
|
assert.Equal(t, 0, oldMap["a"], "should overwrite with zero value")
|
|
assert.Equal(t, 20, oldMap["b"])
|
|
})
|
|
|
|
t.Run("complex merge scenario", func(t *testing.T) {
|
|
oldMap := map[string]int{
|
|
"a": 1,
|
|
"b": 2,
|
|
"c": 3,
|
|
}
|
|
newMap := map[string]int{
|
|
"b": 20, // overwrite
|
|
"c": 30, // overwrite
|
|
"d": 40, // new
|
|
"e": 50, // new
|
|
}
|
|
|
|
UpdateMap(&oldMap, newMap)
|
|
|
|
expected := map[string]int{
|
|
"a": 1, // preserved
|
|
"b": 20, // overwritten
|
|
"c": 30, // overwritten
|
|
"d": 40, // new
|
|
"e": 50, // new
|
|
}
|
|
|
|
assert.Equal(t, expected, oldMap)
|
|
})
|
|
}
|