122 lines
2.5 KiB
Go
122 lines
2.5 KiB
Go
package arena_test
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
"unsafe"
|
|
|
|
"git.brut.systems/judah/xx/arena"
|
|
"git.brut.systems/judah/xx/mem"
|
|
"git.brut.systems/judah/xx/testx"
|
|
)
|
|
|
|
func TestArenas_ThatShouldPanicWhenOOM(t *testing.T) {
|
|
arenas := []arena.Arena{
|
|
arena.Linear(1),
|
|
arena.Nil(),
|
|
}
|
|
|
|
for _, a := range arenas {
|
|
testx.ShouldPanic(t, func() {
|
|
_ = arena.New[int](a)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestArenas_ThatShouldClearAfterReset(t *testing.T) {
|
|
arenas := []arena.Arena{
|
|
arena.Linear(16),
|
|
arena.Chunked(16),
|
|
arena.Ring[uint16](2),
|
|
}
|
|
|
|
for _, a := range arenas {
|
|
x := arena.New[uint16](a)
|
|
y := arena.New[uint16](a)
|
|
*x, *y = 100, 200
|
|
arena.Reset(a)
|
|
|
|
testx.Expect(t, *x == 0, "x = %d, expected 0", *x)
|
|
testx.Expect(t, *y == 0, "y = %d, expected 0", *y)
|
|
}
|
|
}
|
|
|
|
func TestArenas_ThatShouldReuseMemoryAfterReset(t *testing.T) {
|
|
arenas := []arena.Arena{
|
|
arena.Linear(16),
|
|
arena.Chunked(16),
|
|
arena.Ring[uint16](2),
|
|
}
|
|
|
|
for _, a := range arenas {
|
|
x1 := arena.New[uint16](a)
|
|
y1 := arena.New[uint16](a)
|
|
|
|
arena.Reset(a)
|
|
|
|
x2 := arena.New[uint16](a)
|
|
y2 := arena.New[uint16](a)
|
|
|
|
testx.Expect(t, x1 == x2, "x1 = %p, x2 = %p", x1, x2)
|
|
testx.Expect(t, y1 == y2, "y1 = %p, y2 = %p", y1, y2)
|
|
}
|
|
}
|
|
|
|
func TestArenas_WithRegion(t *testing.T) {
|
|
arenas := []arena.Arena{
|
|
arena.Linear(256),
|
|
arena.Chunked(256),
|
|
arena.Ring[uint16](16),
|
|
}
|
|
|
|
var baseptrs []*uint16
|
|
for i, a := range arenas {
|
|
v := arena.New[uint16](a)
|
|
*v = uint16(i)
|
|
baseptrs = append(baseptrs, v)
|
|
}
|
|
|
|
for _, a := range arenas {
|
|
a := arena.Region(a)
|
|
for range 10 {
|
|
_ = arena.New[uint16](a)
|
|
}
|
|
arena.Reset(a)
|
|
}
|
|
|
|
for i, a := range arenas {
|
|
testx.Expect(t, *baseptrs[i] == uint16(i), "baseptrs[%d] = %d, expected %d", i, *baseptrs[i], i)
|
|
|
|
base := uintptr(unsafe.Pointer(baseptrs[i]))
|
|
next := uintptr(unsafe.Pointer(arena.New[uint16](a)))
|
|
testx.Expect(t, next-base == mem.Sizeof[uint16](), "delta was %d", next-base)
|
|
}
|
|
}
|
|
|
|
func TestConcurrent(t *testing.T) {
|
|
a := arena.Concurrent(arena.Linear(16))
|
|
|
|
base, err := a(arena.ACTION_ALLOC, 0, 1, nil)
|
|
testx.Expect(t, err == nil, "ACTION_ALLOC failed: %v", err)
|
|
|
|
var wg sync.WaitGroup
|
|
wg.Go(func() {
|
|
_ = arena.New[uint8](a)
|
|
_ = arena.New[uint8](a)
|
|
_ = arena.New[uint8](a)
|
|
_ = arena.New[uint8](a)
|
|
})
|
|
|
|
wg.Go(func() {
|
|
_ = arena.New[uint16](a)
|
|
_ = arena.New[uint16](a)
|
|
_ = arena.New[uint16](a)
|
|
_ = arena.New[uint16](a)
|
|
})
|
|
|
|
wg.Wait()
|
|
|
|
after, err := a(arena.ACTION_ALLOC, 0, 1, nil)
|
|
testx.Expect(t, err == nil, "ACTION_ALLOC failed: %v", err)
|
|
testx.Expect(t, uintptr(after)-uintptr(base) == 12, "diff is: %v", uintptr(after)-uintptr(base))
|
|
}
|