Files
monibuca/pkg/util/collection_test.go
2025-01-14 19:16:01 +08:00

180 lines
3.4 KiB
Go

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)
}
}