mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-12-24 13:48:04 +08:00
180 lines
3.4 KiB
Go
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)
|
|
}
|
|
}
|