package dataext import ( "slices" "testing" "git.blackforestbytes.com/BlackForestBytes/goext/tst" ) func TestOrderedMapNew(t *testing.T) { m := NewOrderedMap[string, int](4) tst.AssertEqual(t, m.Size(), 0) tst.AssertArrayEqual(t, m.Keys(), []string{}) tst.AssertArrayEqual(t, m.Array(), []int{}) } func TestOrderedMapNewNoCap(t *testing.T) { m := NewOrderedMap[string, int]() tst.AssertEqual(t, m.Size(), 0) tst.AssertArrayEqual(t, m.Keys(), []string{}) tst.AssertArrayEqual(t, m.Array(), []int{}) } func TestOrderedMapNewWIthCap(t *testing.T) { m := NewOrderedMap[string, int](4) tst.AssertEqual(t, m.Size(), 0) tst.AssertArrayEqual(t, m.Keys(), []string{}) tst.AssertArrayEqual(t, m.Array(), []int{}) } func TestOrderedMapAddAndGet(t *testing.T) { m := NewOrderedMap[string, int](0) tst.AssertFalse(t, m.Add("a", 1)) tst.AssertFalse(t, m.Add("b", 2)) tst.AssertFalse(t, m.Add("c", 3)) tst.AssertEqual(t, m.Size(), 3) v, ok := m.Get("a") tst.AssertTrue(t, ok) tst.AssertEqual(t, v, 1) v, ok = m.Get("b") tst.AssertTrue(t, ok) tst.AssertEqual(t, v, 2) v, ok = m.Get("c") tst.AssertTrue(t, ok) tst.AssertEqual(t, v, 3) v, ok = m.Get("missing") tst.AssertFalse(t, ok) tst.AssertEqual(t, v, 0) } func TestOrderedMapOrderPreserved(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("first", 1) m.Add("second", 2) m.Add("third", 3) m.Add("fourth", 4) tst.AssertArrayEqual(t, m.Keys(), []string{"first", "second", "third", "fourth"}) tst.AssertArrayEqual(t, m.Array(), []int{1, 2, 3, 4}) } func TestOrderedMapAddMovesExistingToEnd(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) m.Add("c", 3) tst.AssertTrue(t, m.Add("a", 10)) tst.AssertArrayEqual(t, m.Keys(), []string{"b", "c", "a"}) tst.AssertArrayEqual(t, m.Array(), []int{2, 3, 10}) v, ok := m.Get("a") tst.AssertTrue(t, ok) tst.AssertEqual(t, v, 10) } func TestOrderedMapAddOrReplaceKeepsOrder(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) m.Add("c", 3) tst.AssertTrue(t, m.AddOrReplace("b", 99)) tst.AssertArrayEqual(t, m.Keys(), []string{"a", "b", "c"}) tst.AssertArrayEqual(t, m.Array(), []int{1, 99, 3}) v, ok := m.Get("b") tst.AssertTrue(t, ok) tst.AssertEqual(t, v, 99) } func TestOrderedMapAddOrReplaceNew(t *testing.T) { m := NewOrderedMap[string, int](0) tst.AssertFalse(t, m.AddOrReplace("a", 1)) tst.AssertFalse(t, m.AddOrReplace("b", 2)) tst.AssertArrayEqual(t, m.Keys(), []string{"a", "b"}) tst.AssertArrayEqual(t, m.Array(), []int{1, 2}) } func TestOrderedMapGetOrNil(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 42) v := m.GetOrNil("a") if v == nil { t.Errorf("expected non-nil pointer") return } tst.AssertEqual(t, *v, 42) v = m.GetOrNil("missing") if v != nil { t.Errorf("expected nil pointer") } } func TestOrderedMapGetOrDefault(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 42) tst.AssertEqual(t, m.GetOrDefault("a", -1), 42) tst.AssertEqual(t, m.GetOrDefault("missing", -1), -1) } func TestOrderedMapRemove(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) m.Add("c", 3) tst.AssertTrue(t, m.Remove("b")) tst.AssertEqual(t, m.Size(), 2) tst.AssertArrayEqual(t, m.Keys(), []string{"a", "c"}) tst.AssertArrayEqual(t, m.Array(), []int{1, 3}) _, ok := m.Get("b") tst.AssertFalse(t, ok) tst.AssertFalse(t, m.Contains("b")) } func TestOrderedMapRemoveMissing(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) tst.AssertFalse(t, m.Remove("missing")) tst.AssertEqual(t, m.Size(), 1) tst.AssertArrayEqual(t, m.Keys(), []string{"a"}) } func TestOrderedMapRemoveFirstAndLast(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) m.Add("c", 3) m.Add("d", 4) tst.AssertTrue(t, m.Remove("a")) tst.AssertTrue(t, m.Remove("d")) tst.AssertArrayEqual(t, m.Keys(), []string{"b", "c"}) tst.AssertArrayEqual(t, m.Array(), []int{2, 3}) } func TestOrderedMapContains(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) tst.AssertTrue(t, m.Contains("a")) tst.AssertFalse(t, m.Contains("b")) m.Remove("a") tst.AssertFalse(t, m.Contains("a")) } func TestOrderedMapIndexOf(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) m.Add("c", 3) tst.AssertEqual(t, m.IndexOf("a"), 0) tst.AssertEqual(t, m.IndexOf("b"), 1) tst.AssertEqual(t, m.IndexOf("c"), 2) tst.AssertEqual(t, m.IndexOf("missing"), -1) m.Add("a", 10) // moves to end tst.AssertEqual(t, m.IndexOf("a"), 2) tst.AssertEqual(t, m.IndexOf("b"), 0) tst.AssertEqual(t, m.IndexOf("c"), 1) } func TestOrderedMapClear(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) m.Add("c", 3) m.Clear() tst.AssertEqual(t, m.Size(), 0) tst.AssertArrayEqual(t, m.Keys(), []string{}) tst.AssertArrayEqual(t, m.Array(), []int{}) tst.AssertFalse(t, m.Contains("a")) m.Add("x", 99) tst.AssertEqual(t, m.Size(), 1) tst.AssertArrayEqual(t, m.Keys(), []string{"x"}) } func TestOrderedMapSize(t *testing.T) { m := NewOrderedMap[string, int](0) tst.AssertEqual(t, m.Size(), 0) m.Add("a", 1) tst.AssertEqual(t, m.Size(), 1) m.Add("b", 2) tst.AssertEqual(t, m.Size(), 2) m.Add("a", 10) // replaces, size stays tst.AssertEqual(t, m.Size(), 2) m.AddOrReplace("b", 20) // replaces, size stays tst.AssertEqual(t, m.Size(), 2) m.Remove("a") tst.AssertEqual(t, m.Size(), 1) } func TestOrderedMapIterate(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) m.Add("c", 3) got := make([]int, 0) for v := range m.IterateValues() { got = append(got, v) } tst.AssertArrayEqual(t, got, []int{1, 2, 3}) } func TestOrderedMapIterateBreak(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) m.Add("c", 3) got := make([]int, 0) for v := range m.IterateValues() { got = append(got, v) if v == 2 { break } } tst.AssertArrayEqual(t, got, []int{1, 2}) } func TestOrderedMapIterateSeq2(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) m.Add("c", 3) gotKeys := make([]string, 0) gotVals := make([]int, 0) for k, v := range m.Iterate() { gotKeys = append(gotKeys, k) gotVals = append(gotVals, v) } tst.AssertArrayEqual(t, gotKeys, []string{"a", "b", "c"}) tst.AssertArrayEqual(t, gotVals, []int{1, 2, 3}) } func TestOrderedMapIterateSeq2Break(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) m.Add("c", 3) gotKeys := make([]string, 0) gotVals := make([]int, 0) for k, v := range m.Iterate() { gotKeys = append(gotKeys, k) gotVals = append(gotVals, v) if k == "b" { break } } tst.AssertArrayEqual(t, gotKeys, []string{"a", "b"}) tst.AssertArrayEqual(t, gotVals, []int{1, 2}) } func TestOrderedMapIterateSeq2AfterReorder(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) m.Add("c", 3) m.Add("a", 10) // moves "a" to end with new value gotKeys := make([]string, 0) gotVals := make([]int, 0) for k, v := range m.Iterate() { gotKeys = append(gotKeys, k) gotVals = append(gotVals, v) } tst.AssertArrayEqual(t, gotKeys, []string{"b", "c", "a"}) tst.AssertArrayEqual(t, gotVals, []int{2, 3, 10}) } func TestOrderedMapIterateKeys(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) m.Add("c", 3) got := make([]string, 0) for k := range m.IterateKeys() { got = append(got, k) } tst.AssertArrayEqual(t, got, []string{"a", "b", "c"}) } func TestOrderedMapIterateKeysBreak(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) m.Add("c", 3) got := make([]string, 0) for k := range m.IterateKeys() { got = append(got, k) if k == "b" { break } } tst.AssertArrayEqual(t, got, []string{"a", "b"}) } func TestOrderedMapArrayIsCopy(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) arr := m.Array() arr[0] = 999 tst.AssertArrayEqual(t, m.Array(), []int{1, 2}) } func TestOrderedMapKeysIsCopy(t *testing.T) { m := NewOrderedMap[string, int](0) m.Add("a", 1) m.Add("b", 2) keys := m.Keys() keys[0] = "zzz" tst.AssertArrayEqual(t, m.Keys(), []string{"a", "b"}) } func TestOrderedMapIntKey(t *testing.T) { m := NewOrderedMap[int, string](0) m.Add(3, "three") m.Add(1, "one") m.Add(2, "two") tst.AssertArrayEqual(t, m.Keys(), []int{3, 1, 2}) tst.AssertArrayEqual(t, m.Array(), []string{"three", "one", "two"}) v, ok := m.Get(1) tst.AssertTrue(t, ok) tst.AssertEqual(t, v, "one") } func TestOrderedMapStress(t *testing.T) { m := NewOrderedMap[int, int](0) for i := 0; i < 100; i++ { m.Add(i, i*10) } tst.AssertEqual(t, m.Size(), 100) for i := 0; i < 100; i++ { v, ok := m.Get(i) tst.AssertTrue(t, ok) tst.AssertEqual(t, v, i*10) } for i := 0; i < 50; i++ { m.Remove(i * 2) } tst.AssertEqual(t, m.Size(), 50) expected := make([]int, 0, 50) for i := 0; i < 50; i++ { expected = append(expected, i*2+1) } keys := m.Keys() slices.Sort(keys) tst.AssertArrayEqual(t, keys, expected) }