mirror of
https://github.com/mochi-mqtt/server.git
synced 2025-10-05 08:07:06 +08:00
179 lines
4.0 KiB
Go
179 lines
4.0 KiB
Go
package circ
|
|
|
|
import (
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestNewBuffer(t *testing.T) {
|
|
var size int64 = 16
|
|
var block int64 = 4
|
|
buf := newBuffer(size, block)
|
|
|
|
require.NotNil(t, buf.buf)
|
|
require.NotNil(t, buf.rcond)
|
|
require.NotNil(t, buf.wcond)
|
|
require.Equal(t, size, int64(len(buf.buf)))
|
|
require.Equal(t, size, buf.size)
|
|
require.Equal(t, block, buf.block)
|
|
}
|
|
|
|
func TestSet(t *testing.T) {
|
|
buf := newBuffer(8, 4)
|
|
require.Equal(t, make([]byte, 4), buf.buf[0:4])
|
|
p := []byte{'1', '2', '3', '4'}
|
|
buf.Set(p, 0, 4)
|
|
require.Equal(t, p, buf.buf[0:4])
|
|
|
|
buf.Set(p, 2, 6)
|
|
require.Equal(t, p, buf.buf[2:6])
|
|
}
|
|
|
|
func TestGetPos(t *testing.T) {
|
|
buf := newBuffer(8, 4)
|
|
buf.tail, buf.head = 1, 3
|
|
tail, head := buf.GetPos()
|
|
require.Equal(t, int64(1), tail)
|
|
require.Equal(t, int64(3), head)
|
|
}
|
|
|
|
func TestSetPos(t *testing.T) {
|
|
buf := newBuffer(8, 4)
|
|
buf.SetPos(1, 3)
|
|
require.Equal(t, int64(3), buf.head)
|
|
require.Equal(t, int64(1), buf.tail)
|
|
}
|
|
|
|
func TestCommitHead(t *testing.T) {
|
|
//buf := newBuffer(16, 4)
|
|
|
|
}
|
|
|
|
func TestAwaitCapacity(t *testing.T) {
|
|
tests := []struct {
|
|
tail int64
|
|
head int64
|
|
await int
|
|
desc string
|
|
}{
|
|
{0, 0, 0, "OK 4, 0"},
|
|
{6, 6, 0, "OK 6, 10"},
|
|
{12, 16, 0, "OK 16, 4"},
|
|
{16, 12, 0, "OK 16 16"},
|
|
{3, 6, 0, "OK 3, 10"},
|
|
{12, 0, 0, "OK 16, 0"},
|
|
{1, 16, 4, "next is more than tail, wait for tail incr"},
|
|
{7, 5, 2, "tail is great than head, wrapped and caught up with tail, wait for tail incr"},
|
|
}
|
|
|
|
buf := newBuffer(16, 4)
|
|
for i, tt := range tests {
|
|
buf.tail, buf.head = tt.tail, tt.head
|
|
o := make(chan []interface{})
|
|
var start int64 = -1
|
|
var err error
|
|
go func() {
|
|
start, err = buf.awaitCapacity(4)
|
|
o <- []interface{}{start, err}
|
|
}()
|
|
|
|
time.Sleep(time.Millisecond)
|
|
for j := 0; j < tt.await; j++ {
|
|
atomic.AddInt64(&buf.tail, 1)
|
|
buf.rcond.L.Lock()
|
|
buf.rcond.Broadcast()
|
|
buf.rcond.L.Unlock()
|
|
}
|
|
|
|
time.Sleep(time.Millisecond) // wait for await capacity to actually exit
|
|
if start == -1 {
|
|
atomic.StoreInt64(&buf.done, 1)
|
|
buf.rcond.L.Lock()
|
|
buf.rcond.Broadcast()
|
|
buf.rcond.L.Unlock()
|
|
}
|
|
done := <-o
|
|
require.Equal(t, tt.head, done[0].(int64), "Head-Start mismatch [i:%d] %s", i, tt.desc)
|
|
require.Nil(t, done[1], "Unexpected Error [i:%d] %s", i, tt.desc)
|
|
}
|
|
}
|
|
|
|
func TestAwaitFilled(t *testing.T) {
|
|
tests := []struct {
|
|
tail int64
|
|
head int64
|
|
next int64
|
|
await int
|
|
desc string
|
|
}{
|
|
{0, 4, 4, 0, "OK 0, 4"},
|
|
{6, 10, 10, 0, "OK 6, 10"},
|
|
{14, 2, 2, 0, "OK 14, 2 wrapped"},
|
|
{6, 8, 10, 2, "Wait 6, 8"},
|
|
{14, 1, 4, 3, "Wait 14, 1 wrapped"},
|
|
}
|
|
|
|
buf := newBuffer(16, 4)
|
|
for i, tt := range tests {
|
|
buf.tail, buf.head = tt.tail, tt.head
|
|
o := make(chan []interface{})
|
|
var start int64 = -1
|
|
var err error
|
|
go func() {
|
|
start, err = buf.awaitFilled(4)
|
|
o <- []interface{}{start, err}
|
|
}()
|
|
|
|
time.Sleep(time.Millisecond)
|
|
for j := 0; j < tt.await; j++ {
|
|
atomic.AddInt64(&buf.head, 1)
|
|
buf.wcond.L.Lock()
|
|
buf.wcond.Broadcast()
|
|
buf.wcond.L.Unlock()
|
|
}
|
|
|
|
done := <-o
|
|
require.Equal(t, tt.tail, done[0].(int64), "tail start [i:%d] %s", i, tt.desc)
|
|
require.Equal(t, tt.next, buf.head, "Head-next mismatch [i:%d] %s", i, tt.desc)
|
|
require.Nil(t, done[1], "Unexpected Error [i:%d] %s", i, tt.desc)
|
|
}
|
|
}
|
|
|
|
func TestCommitTail(t *testing.T) {
|
|
tests := []struct {
|
|
tail int64
|
|
head int64
|
|
next int64
|
|
await int
|
|
desc string
|
|
}{
|
|
{0, 5, 4, 0, "OK 0, 4"},
|
|
{6, 10, 10, 0, "OK 6, 10"},
|
|
{14, 2, 2, 0, "OK 14, 2 wrapped"},
|
|
{6, 8, 10, 2, "Wait 6, 8"},
|
|
{14, 1, 2, 2, "Wait 14, 1 wrapped"},
|
|
}
|
|
|
|
buf := newBuffer(16, 4)
|
|
for i, tt := range tests {
|
|
buf.tail, buf.head = tt.tail, tt.head
|
|
o := make(chan error)
|
|
go func() {
|
|
o <- buf.CommitTail(4)
|
|
}()
|
|
|
|
time.Sleep(time.Millisecond)
|
|
for j := 0; j < tt.await; j++ {
|
|
atomic.AddInt64(&buf.head, 1)
|
|
buf.wcond.L.Lock()
|
|
buf.wcond.Broadcast()
|
|
buf.wcond.L.Unlock()
|
|
}
|
|
require.NoError(t, <-o, "Unexpected Error [i:%d] %s", i, tt.desc)
|
|
require.Equal(t, tt.next, buf.tail, "Tail-next mismatch [i:%d] %s", i, tt.desc)
|
|
}
|
|
}
|