package util import ( "fmt" "sync" "testing" ) type Class struct { name string Id int } func (n *Class) GetKey() string { return n.name } func TestCollection(t *testing.T) { var cc Collection[string, *Class] for i := 0; i < 10; i++ { cc.Add(&Class{name: fmt.Sprintf("%d", i), Id: i}) } cc.RemoveByKey("1") if item, ok := cc.Get("1"); ok { fmt.Println(item) } else { fmt.Println("not found", item) } } func TestCollection_Range(t *testing.T) { var cc Collection[string, *Class] for i := 0; i < 10; i++ { cc.Add(&Class{name: fmt.Sprintf("%d", i), Id: i}) } for item := range cc.Range { fmt.Println(item) cc.Remove(item) } } // TestItem 是用于测试的结构体 type TestItem struct { ID string Data string } func (t TestItem) GetKey() string { return t.ID } func TestCollection_BasicOperations(t *testing.T) { c := &Collection[string, TestItem]{ L: &sync.RWMutex{}, } // 测试 Add item1 := TestItem{ID: "1", Data: "test1"} c.Add(item1) if c.Length != 1 { t.Errorf("Expected length 1, got %d", c.Length) } // 测试 Get got, ok := c.Get("1") if !ok || got != item1 { t.Errorf("Expected to get item1, got %v", got) } // 测试 AddUnique ok = c.AddUnique(item1) if ok || c.Length != 1 { t.Error("AddUnique should not add duplicate item") } // 测试 Set item1Modified := TestItem{ID: "1", Data: "test1-modified"} added := c.Set(item1Modified) if added { t.Error("Set should not return true for existing item") } got, _ = c.Get("1") if got.Data != "test1-modified" { t.Errorf("Expected modified data, got %s", got.Data) } // 测试 Remove if !c.Remove(item1) { t.Error("Remove should return true for existing item") } if c.Length != 0 { t.Errorf("Expected length 0 after remove, got %d", c.Length) } } func TestCollection_Events(t *testing.T) { c := &Collection[string, TestItem]{} var addCalled, removeCalled bool c.OnAdd(func(item TestItem) { addCalled = true if item.ID != "1" { t.Errorf("Expected item ID 1, got %s", item.ID) } }) c.OnRemove(func(item TestItem) { removeCalled = true if item.ID != "1" { t.Errorf("Expected item ID 1, got %s", item.ID) } }) item := TestItem{ID: "1", Data: "test"} c.Add(item) if !addCalled { t.Error("Add listener was not called") } c.Remove(item) if !removeCalled { t.Error("Remove listener was not called") } } func TestCollection_Search(t *testing.T) { c := &Collection[string, TestItem]{} items := []TestItem{ {ID: "1", Data: "test1"}, {ID: "2", Data: "test2"}, {ID: "3", Data: "test1"}, } for _, item := range items { c.Add(item) } // 测试 Find found, ok := c.Find(func(item TestItem) bool { return item.Data == "test1" }) if !ok || found.ID != "1" { t.Error("Find should return first matching item") } // 测试 Search count := 0 search := c.Search(func(item TestItem) bool { return item.Data == "test1" }) search(func(item TestItem) bool { count++ return true }) if count != 2 { t.Errorf("Search should find 2 items, found %d", count) } } func TestCollection_ConcurrentAccess(t *testing.T) { c := &Collection[string, TestItem]{ L: &sync.RWMutex{}, } var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(1) go func(id int) { defer wg.Done() item := TestItem{ID: string(rune(id)), Data: "test"} c.Add(item) }(i) } wg.Wait() if c.Length != 100 { t.Errorf("Expected 100 items, got %d", c.Length) } }