package collections_test import ( "fmt" "slices" "testing" "efprojects.com/kitten-ipc/kitcom/internal/tsgo/collections" "github.com/go-json-experiment/json" "gotest.tools/v3/assert" ) func TestOrderedMap(t *testing.T) { t.Parallel() var m collections.OrderedMap[int, string] assert.Assert(t, !m.Has(1)) const ( N = 1000 start = 1 end = start + N ) // Seed the map with ascending keys and values for easier testing. for i := start; i < end; i++ { m.Set(i, padInt(i)) } assert.Equal(t, m.Size(), N) // Attempt to overwrite existing keys in reverse order. for i := end - 1; i >= start; i-- { m.Set(i, padInt(i)) } assert.Equal(t, m.Size(), N) for i := start; i < end; i++ { v, ok := m.Get(i) assert.Assert(t, ok) assert.Equal(t, v, padInt(i)) } for k, v := range m.Entries() { assert.Equal(t, v, padInt(k)) } keys := slices.Collect(m.Keys()) assert.Equal(t, len(keys), N) assert.Assert(t, slices.IsSorted(keys)) values := slices.Collect(m.Values()) assert.Equal(t, len(values), N) assert.Assert(t, slices.IsSorted(values)) var firstKey int for k := range m.Keys() { firstKey = k break } assert.Equal(t, firstKey, start) var firstValue string for v := range m.Values() { firstValue = v break } assert.Equal(t, firstValue, padInt(start)) for k, v := range m.Entries() { firstKey = k firstValue = v break } assert.Equal(t, firstKey, start) assert.Equal(t, firstValue, padInt(start)) for i := start + 1; i < end; i++ { v, ok := m.Delete(i) assert.Assert(t, ok) assert.Equal(t, v, padInt(i)) assert.Assert(t, !m.Has(i)) v, ok = m.Get(i) assert.Assert(t, !ok) assert.Equal(t, v, "") v, ok = m.Delete(i) assert.Assert(t, !ok) assert.Equal(t, v, "") } assert.Equal(t, m.Size(), 1) assert.Assert(t, m.Has(start)) v, ok := m.Delete(start) assert.Assert(t, ok) assert.Equal(t, v, padInt(start)) assert.Equal(t, m.Size(), 0) } func TestOrderedMapClone(t *testing.T) { t.Parallel() m := &collections.OrderedMap[int, string]{} m.Set(1, "one") m.Set(2, "two") clone := m.Clone() assert.Assert(t, clone != m) assert.Equal(t, clone.Size(), 2) assert.DeepEqual(t, slices.Collect(clone.Keys()), []int{1, 2}) assert.DeepEqual(t, slices.Collect(clone.Values()), []string{"one", "two"}) v, ok := clone.Get(1) assert.Assert(t, ok) assert.Equal(t, v, "one") m.Delete(1) assert.Equal(t, m.Size(), 1) assert.Equal(t, clone.Size(), 2) assert.DeepEqual(t, slices.Collect(clone.Keys()), []int{1, 2}) assert.DeepEqual(t, slices.Collect(clone.Values()), []string{"one", "two"}) } func TestOrderedMapClear(t *testing.T) { t.Parallel() var m collections.OrderedMap[int, string] m.Set(1, "one") m.Set(2, "two") m.Clear() assert.Equal(t, m.Size(), 0) } func padInt(n int) string { return fmt.Sprintf("%10d", n) } func TestOrderedMapWithSizeHint(t *testing.T) { //nolint:paralleltest const N = 1024 allocs := testing.AllocsPerRun(10, func() { m := collections.NewOrderedMapWithSizeHint[int, int](N) for i := range N { m.Set(i, i) } }) assert.Assert(t, allocs < 10, "allocs = %v", allocs) } func TestOrderedMapUnmarshalJSON(t *testing.T) { t.Parallel() t.Run("UnmarshalJSONV2", func(t *testing.T) { t.Parallel() testOrderedMapUnmarshalJSON(t, func(in []byte, out any) error { return json.Unmarshal(in, out) }) }) } func testOrderedMapUnmarshalJSON(t *testing.T, unmarshal func([]byte, any) error) { var m collections.OrderedMap[string, any] err := unmarshal([]byte(`{"a": 1, "b": "two", "c": { "d": 4 } }`), &m) assert.NilError(t, err) assert.Equal(t, m.Size(), 3) assert.Equal(t, m.GetOrZero("a"), float64(1)) err = unmarshal([]byte(`null`), &m) assert.NilError(t, err) err = unmarshal([]byte(`"foo"`), &m) assert.ErrorContains(t, err, "cannot unmarshal non-object JSON value into Map") var invalidMap collections.OrderedMap[int, any] err = unmarshal([]byte(`{"a": 1, "b": "two"}`), &invalidMap) assert.ErrorContains(t, err, "unmarshal") }