Skip to content

Commit

Permalink
test: 完善 hub.ObjectPool 测试用例
Browse files Browse the repository at this point in the history
  • Loading branch information
kercylan98 committed Jan 12, 2024
1 parent 161fbfe commit c439ef6
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 8 deletions.
12 changes: 4 additions & 8 deletions utils/hub/object_pool.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package hub

import (
"errors"
"fmt"
"sync"
)

// NewObjectPool 创建一个线程安全的对象缓冲池
// - 通过 Get 获取一个对象,如果缓冲区内存在可用对象则直接返回,否则新建一个进行返回
// - 通过 Release 将使用完成的对象放回缓冲区,超出缓冲区大小的对象将被放弃
// NewObjectPool 创建一个 ObjectPool
func NewObjectPool[T any](generator func() *T, releaser func(data *T)) *ObjectPool[*T] {
if generator == nil || releaser == nil {
panic(errors.New("generator or releaser is nil"))
panic(fmt.Errorf("generator and releaser can not be nil, generator check: %v, releaser check: %v", generator != nil, releaser != nil))
}
return &ObjectPool[*T]{
releaser: releaser,
Expand All @@ -22,10 +20,8 @@ func NewObjectPool[T any](generator func() *T, releaser func(data *T)) *ObjectPo
}
}

// ObjectPool 线程安全的对象缓冲池
// ObjectPool 基于 sync.Pool 实现的线程安全的对象池
// - 一些高频临时生成使用的对象可以通过 ObjectPool 进行管理,例如属性计算等
// - 缓冲区内存在可用对象时直接返回,否则新建一个进行返回
// - 通过 Release 将使用完成的对象放回缓冲区,超出缓冲区大小的对象将被放弃
type ObjectPool[T any] struct {
p sync.Pool
releaser func(data T)
Expand Down
22 changes: 22 additions & 0 deletions utils/hub/object_pool_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package hub_test

import (
"fmt"
"github.com/kercylan98/minotaur/utils/collection"
"github.com/kercylan98/minotaur/utils/hub"
)

func ExampleNewObjectPool() {
var p = hub.NewObjectPool[map[int]int](func() *map[int]int {
return &map[int]int{}
}, func(data *map[int]int) {
collection.ClearMap(*data)
})

m := *p.Get()
m[1] = 1
p.Release(&m)
fmt.Println(m)
// Output:
// map[]
}
92 changes: 92 additions & 0 deletions utils/hub/object_pool_test.go
Original file line number Diff line number Diff line change
@@ -1 +1,93 @@
package hub_test

import (
"github.com/kercylan98/minotaur/utils/hub"
"testing"
)

func TestNewObjectPool(t *testing.T) {
var cases = []struct {
name string
generator func() *map[string]int
releaser func(data *map[string]int)
shouldPanic bool
}{
{name: "TestNewObjectPool_NilGenerator", generator: nil, releaser: func(data *map[string]int) {}, shouldPanic: true},
{name: "TestNewObjectPool_NilReleaser", generator: func() *map[string]int { return &map[string]int{} }, releaser: nil, shouldPanic: true},
{name: "TestNewObjectPool_NilGeneratorAndReleaser", generator: nil, releaser: nil, shouldPanic: true},
{name: "TestNewObjectPool_Normal", generator: func() *map[string]int { return &map[string]int{} }, releaser: func(data *map[string]int) {}, shouldPanic: false},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
defer func() {
if err := recover(); c.shouldPanic && err == nil {
t.Error("TestNewObjectPool should panic")
}
}()
_ = hub.NewObjectPool[map[string]int](c.generator, c.releaser)
})
}
}

func TestObjectPool_Get(t *testing.T) {
var cases = []struct {
name string
generator func() *map[string]int
releaser func(data *map[string]int)
}{
{
name: "TestObjectPool_Get_Normal",
generator: func() *map[string]int {
return &map[string]int{}
},
releaser: func(data *map[string]int) {
for k := range *data {
delete(*data, k)
}
},
},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
pool := hub.NewObjectPool[map[string]int](c.generator, c.releaser)
if actual := pool.Get(); len(*actual) != 0 {
t.Error("TestObjectPool_Get failed")
}
})
}
}

func TestObjectPool_Release(t *testing.T) {
var cases = []struct {
name string
generator func() *map[string]int
releaser func(data *map[string]int)
}{
{
name: "TestObjectPool_Release_Normal",
generator: func() *map[string]int {
return &map[string]int{}
},
releaser: func(data *map[string]int) {
for k := range *data {
delete(*data, k)
}
},
},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
pool := hub.NewObjectPool[map[string]int](c.generator, c.releaser)
msg := pool.Get()
m := *msg
m["test"] = 1
pool.Release(msg)
if len(m) != 0 {
t.Error("TestObjectPool_Release failed")
}
})
}
}

0 comments on commit c439ef6

Please sign in to comment.