gouring/queue_test.go
Nugraha 793e0b8cbd
queue: impl wait cqe, and tests
Signed-off-by: Nugraha <richiisei@gmail.com>
2022-07-07 08:24:46 +07:00

153 lines
3.2 KiB
Go

package gouring
import (
"fmt"
"os"
"sync"
"syscall"
"testing"
"unsafe"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func testNewIoUring(t *testing.T, entries uint32, flags uint32) *IoUring {
h, err := New(entries, flags)
assert.NoError(t, err)
assert.NotNil(t, h)
return h
}
func TestRingQueueGetSQE(t *testing.T) {
h := testNewIoUring(t, 256, 0)
defer h.Close()
assert.NotEqual(t, 0, h.RingFd)
assert.NotEqual(t, 0, h.EnterRingFd)
sqe := h.io_uring_get_sqe()
assert.NotNil(t, sqe)
fmt.Printf("%+#v\n", sqe)
}
func TestRingQueueSubmitSingleConsumer(t *testing.T) {
ts := []int{
8,
32,
64,
128 + 2,
256,
// we can have other test for queue overflow.
}
for i := range ts {
jobCount := ts[i]
t.Run(fmt.Sprintf("jobsz-%d", jobCount), func(t *testing.T) {
ftmp, err := os.CreateTemp(os.TempDir(), "test_iouring_queue_sc_*")
require.NoError(t, err)
defer ftmp.Close()
fdTemp := ftmp.Fd()
bufPool := sync.Pool{
New: func() any {
x := make([]byte, 0, 32)
return &x
},
}
consumer := func(h *IoUring, wg *sync.WaitGroup) {
var cqe *IoUringCqe
var err error
for {
err = h.io_uring_wait_cqe(&cqe)
if err == syscall.EINTR {
// ignore interrupt
continue
}
if err != nil {
panic(err)
}
if cqe.Res < 0 {
panic(syscall.Errno(-cqe.Res))
}
// cqe data check
if int(cqe.Res) < len("data ") {
panic(fmt.Sprintf("write less that it should"))
}
if (cqe.UserData>>(8<<2))&0xff == 0x00 {
panic(fmt.Sprintf("cqe userdata should contain canonical address got %+#v", cqe.UserData))
}
// put back buf
bufPool.Put((*[]byte)(unsafe.Pointer(uintptr(cqe.UserData))))
h.io_uring_cqe_seen(cqe) // necessary
wg.Done()
}
}
submit := func(t *testing.T, h *IoUring, expectedSubmitCount int) {
submitted, err := h.io_uringn_submit()
assert.NoError(t, err)
assert.Equal(t, expectedSubmitCount, submitted)
}
t.Run("submit_single", func(t *testing.T) {
var wg sync.WaitGroup
h := testNewIoUring(t, 256, 0)
defer h.Close()
wg.Add(jobCount)
go consumer(h, &wg)
for i := 0; i < jobCount; i++ {
sqe := h.io_uring_get_sqe()
if sqe == nil {
// spin until we got one
continue
}
bufptr := bufPool.Get().(*[]byte)
buf := (*bufptr)[:0]
buf = append(buf, []byte(fmt.Sprintf("data %d\n", i))...)
PrepWrite(sqe, int(fdTemp), &buf[0], len(buf), 0)
sqe.UserData = uint64(uintptr(unsafe.Pointer(bufptr)))
// submit
submit(t, h, 1)
}
wg.Wait()
})
t.Run("submit_bulk", func(t *testing.T) {
var wg sync.WaitGroup
h := testNewIoUring(t, 256, 0)
defer h.Close()
wg.Add(jobCount)
go consumer(h, &wg)
for i := 0; i < jobCount; i++ {
sqe := h.io_uring_get_sqe()
if sqe == nil {
// spin until we got one
continue
}
bufptr := bufPool.Get().(*[]byte)
buf := (*bufptr)[:0]
buf = append(buf, []byte(fmt.Sprintf("data %d\n", i))...)
PrepWrite(sqe, int(fdTemp), &buf[0], len(buf), 0)
sqe.UserData = uint64(uintptr(unsafe.Pointer(bufptr)))
}
submit(t, h, jobCount)
wg.Wait()
})
})
}
}