package dataext import ( "sort" "sync" "testing" ) func TestSyncMap_SetGet(t *testing.T) { m := NewSyncMap[string, int]() m.Set("a", 1) v, ok := m.Get("a") if !ok || v != 1 { t.Fatalf("got (%d,%v)", v, ok) } if _, ok := m.Get("missing"); ok { t.Fatal("expected missing") } } func TestSyncMap_SetIfNotContains(t *testing.T) { m := NewSyncMap[string, int]() if !m.SetIfNotContains("a", 1) { t.Fatal("first set should succeed") } if m.SetIfNotContains("a", 2) { t.Fatal("second set should fail") } v, _ := m.Get("a") if v != 1 { t.Fatalf("expected unchanged got %d", v) } } func TestSyncMap_SetIfNotContainsFunc(t *testing.T) { m := NewSyncMap[string, int]() calls := 0 if !m.SetIfNotContainsFunc("a", func() int { calls++; return 5 }) { t.Fatal("first should succeed") } if m.SetIfNotContainsFunc("a", func() int { calls++; return 6 }) { t.Fatal("second should fail") } if calls != 1 { t.Fatalf("calls=%d want 1", calls) } } func TestSyncMap_GetAndSetIfNotContains(t *testing.T) { m := NewSyncMap[string, int]() if v := m.GetAndSetIfNotContains("a", 10); v != 10 { t.Fatalf("got %d", v) } if v := m.GetAndSetIfNotContains("a", 99); v != 10 { t.Fatalf("got %d", v) } } func TestSyncMap_GetAndSetIfNotContainsFunc(t *testing.T) { m := NewSyncMap[string, int]() calls := 0 if v := m.GetAndSetIfNotContainsFunc("a", func() int { calls++; return 1 }); v != 1 { t.Fatalf("got %d", v) } if v := m.GetAndSetIfNotContainsFunc("a", func() int { calls++; return 2 }); v != 1 { t.Fatalf("got %d", v) } if calls != 1 { t.Fatalf("calls=%d", calls) } } func TestSyncMap_Delete(t *testing.T) { m := NewSyncMap[string, int]() m.Set("a", 1) if !m.Delete("a") { t.Fatal("delete existing returned false") } if m.Delete("a") { t.Fatal("delete missing returned true") } } func TestSyncMap_DeleteIf(t *testing.T) { m := NewSyncMap[string, int]() m.Set("a", 1) m.Set("b", 2) m.Set("c", 3) rm := m.DeleteIf(func(k string, v int) bool { return v%2 == 1 }) if rm != 2 { t.Fatalf("removed=%d", rm) } if m.Count() != 1 { t.Fatalf("count=%d", m.Count()) } } func TestSyncMap_UpdateIfExists(t *testing.T) { m := NewSyncMap[string, int]() if m.UpdateIfExists("a", func(v int) int { return v + 1 }) { t.Fatal("should be false on missing key") } m.Set("a", 5) if !m.UpdateIfExists("a", func(v int) int { return v + 1 }) { t.Fatal("should be true on existing") } v, _ := m.Get("a") if v != 6 { t.Fatalf("v=%d", v) } } func TestSyncMap_UpdateOrInsert(t *testing.T) { m := NewSyncMap[string, int]() if m.UpdateOrInsert("a", func(v int) int { return v + 1 }, 100) { t.Fatal("should return false on insert") } if v, _ := m.Get("a"); v != 100 { t.Fatalf("v=%d", v) } if !m.UpdateOrInsert("a", func(v int) int { return v + 1 }, 100) { t.Fatal("should return true on update") } if v, _ := m.Get("a"); v != 101 { t.Fatalf("v=%d", v) } } func TestSyncMap_ClearContains(t *testing.T) { m := NewSyncMap[string, int]() m.Set("a", 1) if !m.Contains("a") { t.Fatal("Contains should be true") } m.Clear() if m.Contains("a") { t.Fatal("after Clear should be false") } if m.Count() != 0 { t.Fatalf("count=%d", m.Count()) } } func TestSyncMap_GetAllKeysValues(t *testing.T) { m := NewSyncMap[string, int]() m.Set("a", 1) m.Set("b", 2) m.Set("c", 3) keys := m.GetAllKeys() sort.Strings(keys) if len(keys) != 3 || keys[0] != "a" || keys[2] != "c" { t.Fatalf("keys=%v", keys) } vals := m.GetAllValues() sort.Ints(vals) if len(vals) != 3 || vals[0] != 1 || vals[2] != 3 { t.Fatalf("vals=%v", vals) } } func TestSyncMap_Concurrent(t *testing.T) { m := NewSyncMap[int, int]() var wg sync.WaitGroup const n = 200 wg.Add(n) for i := 0; i < n; i++ { go func(k int) { defer wg.Done() m.Set(k, k*2) }(i) } wg.Wait() if m.Count() != n { t.Fatalf("count=%d want %d", m.Count(), n) } }