mirror of
https://github.com/xjasonlyu/tun2socks.git
synced 2024-12-30 02:37:01 +00:00
86 lines
1.8 KiB
Go
86 lines
1.8 KiB
Go
package pool
|
|
|
|
import (
|
|
"runtime/debug"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type pooledValue[T any] struct {
|
|
value T
|
|
}
|
|
|
|
func TestNew(t *testing.T) {
|
|
// Disable GC to avoid the victim cache during the test.
|
|
defer debug.SetGCPercent(debug.SetGCPercent(-1))
|
|
|
|
p := New(func() *pooledValue[string] {
|
|
return &pooledValue[string]{
|
|
value: "new",
|
|
}
|
|
})
|
|
|
|
// Probabilistically, 75% of sync.Pool.Put calls will succeed when -race
|
|
// is enabled (see ref below); attempt to make this quasi-deterministic by
|
|
// brute force (i.e., put significantly more objects in the pool than we
|
|
// will need for the test) in order to avoid testing without race enabled.
|
|
//
|
|
// ref: https://cs.opensource.google/go/go/+/refs/tags/go1.20.2:src/sync/pool.go;l=100-103
|
|
for i := 0; i < 1_000; i++ {
|
|
p.Put(&pooledValue[string]{
|
|
value: t.Name(),
|
|
})
|
|
}
|
|
|
|
// Ensure that we always get the expected value. Note that this must only
|
|
// run a fraction of the number of times that Put is called above.
|
|
for i := 0; i < 10; i++ {
|
|
func() {
|
|
x := p.Get()
|
|
defer p.Put(x)
|
|
require.Equal(t, t.Name(), x.value)
|
|
}()
|
|
}
|
|
|
|
// Depool all objects that might be in the pool to ensure that it's empty.
|
|
for i := 0; i < 1_000; i++ {
|
|
p.Get()
|
|
}
|
|
|
|
// Now that the pool is empty, it should use the value specified in the
|
|
// underlying sync.Pool.New func.
|
|
require.Equal(t, "new", p.Get().value)
|
|
}
|
|
|
|
func TestNew_Race(t *testing.T) {
|
|
p := New(func() *pooledValue[int] {
|
|
return &pooledValue[int]{
|
|
value: -1,
|
|
}
|
|
})
|
|
|
|
var wg sync.WaitGroup
|
|
defer wg.Wait()
|
|
|
|
// Run a number of goroutines that read and write pool object fields to
|
|
// tease out races.
|
|
for i := 0; i < 1_000; i++ {
|
|
i := i
|
|
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
|
|
x := p.Get()
|
|
defer p.Put(x)
|
|
|
|
// Must both read and write the field.
|
|
if n := x.value; n >= -1 {
|
|
x.value = i
|
|
}
|
|
}()
|
|
}
|
|
}
|