xx/arena/arenas_test.go
2025-12-14 14:13:51 -07:00

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))
}