test: 完善 hub.ObjectPool 测试用例
This commit is contained in:
parent
161fbfe4e3
commit
c439ef6424
|
@ -1,16 +1,14 @@
|
||||||
package hub
|
package hub
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewObjectPool 创建一个线程安全的对象缓冲池
|
// NewObjectPool 创建一个 ObjectPool
|
||||||
// - 通过 Get 获取一个对象,如果缓冲区内存在可用对象则直接返回,否则新建一个进行返回
|
|
||||||
// - 通过 Release 将使用完成的对象放回缓冲区,超出缓冲区大小的对象将被放弃
|
|
||||||
func NewObjectPool[T any](generator func() *T, releaser func(data *T)) *ObjectPool[*T] {
|
func NewObjectPool[T any](generator func() *T, releaser func(data *T)) *ObjectPool[*T] {
|
||||||
if generator == nil || releaser == nil {
|
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]{
|
return &ObjectPool[*T]{
|
||||||
releaser: releaser,
|
releaser: releaser,
|
||||||
|
@ -22,10 +20,8 @@ func NewObjectPool[T any](generator func() *T, releaser func(data *T)) *ObjectPo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectPool 线程安全的对象缓冲池
|
// ObjectPool 基于 sync.Pool 实现的线程安全的对象池
|
||||||
// - 一些高频临时生成使用的对象可以通过 ObjectPool 进行管理,例如属性计算等
|
// - 一些高频临时生成使用的对象可以通过 ObjectPool 进行管理,例如属性计算等
|
||||||
// - 缓冲区内存在可用对象时直接返回,否则新建一个进行返回
|
|
||||||
// - 通过 Release 将使用完成的对象放回缓冲区,超出缓冲区大小的对象将被放弃
|
|
||||||
type ObjectPool[T any] struct {
|
type ObjectPool[T any] struct {
|
||||||
p sync.Pool
|
p sync.Pool
|
||||||
releaser func(data T)
|
releaser func(data T)
|
||||||
|
|
|
@ -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[]
|
||||||
|
}
|
|
@ -1 +1,93 @@
|
||||||
package hub_test
|
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")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue