80 lines
1.5 KiB
Go
80 lines
1.5 KiB
Go
package push
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestCursorGeneratorMonotonicAndConcurrent(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var g cursorGenerator
|
|
const goroutines = 64
|
|
const perGoroutine = 1000
|
|
results := make(chan uint64, goroutines*perGoroutine)
|
|
var wg sync.WaitGroup
|
|
wg.Add(goroutines)
|
|
for range goroutines {
|
|
go func() {
|
|
defer wg.Done()
|
|
for range perGoroutine {
|
|
results <- g.next()
|
|
}
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
close(results)
|
|
|
|
seen := make(map[uint64]struct{}, goroutines*perGoroutine)
|
|
var max uint64
|
|
for n := range results {
|
|
_, dup := seen[n]
|
|
require.Falsef(t, dup, "duplicate cursor %d", n)
|
|
seen[n] = struct{}{}
|
|
if n > max {
|
|
max = n
|
|
}
|
|
}
|
|
assert.EqualValues(t, goroutines*perGoroutine, max)
|
|
}
|
|
|
|
func TestFormatAndParseCursor(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
cases := []struct {
|
|
in uint64
|
|
out string
|
|
}{
|
|
{0, "00000000000000000000"},
|
|
{1, "00000000000000000001"},
|
|
{1234567890, "00000000001234567890"},
|
|
}
|
|
for _, tc := range cases {
|
|
s := formatCursor(tc.in)
|
|
assert.Equal(t, tc.out, s)
|
|
assert.Len(t, s, cursorWidth)
|
|
n, ok := parseCursor(s)
|
|
require.True(t, ok)
|
|
assert.Equal(t, tc.in, n)
|
|
}
|
|
|
|
n, ok := parseCursor("")
|
|
assert.True(t, ok)
|
|
assert.Zero(t, n)
|
|
|
|
n, ok = parseCursor("not-a-number")
|
|
assert.False(t, ok)
|
|
assert.Zero(t, n)
|
|
}
|
|
|
|
func TestFormatCursorLexicographicOrder(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
a := formatCursor(9)
|
|
b := formatCursor(10)
|
|
assert.Less(t, a, b, "lexicographic order must match numeric order")
|
|
}
|