119 lines
2.2 KiB
Go
119 lines
2.2 KiB
Go
package snowflake
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"reflect"
|
|
"sort"
|
|
"sync/atomic"
|
|
"testing"
|
|
)
|
|
|
|
func TestEncode(t *testing.T) {
|
|
tests := []struct {
|
|
v uint64
|
|
exp string
|
|
}{
|
|
{0x000, "00000000000"},
|
|
{0x001, "00000000001"},
|
|
{0x03f, "0000000000~"},
|
|
{0x07f, "0000000001~"},
|
|
{0xf07f07f07f07f07f, "F1~1~1~1~1~"},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("0x%03x→%s", test.v, test.exp), func(t *testing.T) {
|
|
var s [11]byte
|
|
encode(&s, test.v)
|
|
if got, exp := string(s[:]), test.exp; got != exp {
|
|
t.Fatalf("got %q, expected %q", got, exp)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestSorting verifies numbers using base 63 encoding are ordered according to their numerical representation.
|
|
func TestSorting(t *testing.T) {
|
|
var (
|
|
vals = make([]string, 1000)
|
|
exp = make([]string, 1000)
|
|
)
|
|
|
|
for i := 0; i < len(vals); i++ {
|
|
var s [11]byte
|
|
encode(&s, uint64(i*47))
|
|
vals[i] = string(s[:])
|
|
exp[i] = string(s[:])
|
|
}
|
|
|
|
// randomize them
|
|
shuffle(len(vals), func(i, j int) {
|
|
vals[i], vals[j] = vals[j], vals[i]
|
|
})
|
|
|
|
sort.Strings(vals)
|
|
if !reflect.DeepEqual(vals, exp) {
|
|
t.Fatalf("got %v, expected %v", vals, exp)
|
|
}
|
|
}
|
|
|
|
func TestMachineID(t *testing.T) {
|
|
for i := 0; i < serverMax; i++ {
|
|
if got, exp := New(i).MachineID(), i; got != exp {
|
|
t.Fatalf("got %d, expected %d", got, exp)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNextMonotonic(t *testing.T) {
|
|
g := New(10)
|
|
out := make([]string, 10000)
|
|
|
|
for i := range out {
|
|
out[i] = g.NextString()
|
|
}
|
|
|
|
// ensure they are all distinct and increasing
|
|
for i := range out[1:] {
|
|
if out[i] >= out[i+1] {
|
|
t.Fatal("bad entries:", out[i], out[i+1])
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkEncode(b *testing.B) {
|
|
b.ReportAllocs()
|
|
var s [11]byte
|
|
for i := 0; i < b.N; i++ {
|
|
encode(&s, 100)
|
|
}
|
|
}
|
|
|
|
var blackhole uint64 // to make sure the g.Next calls are not removed
|
|
|
|
func BenchmarkNext(b *testing.B) {
|
|
g := New(10)
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
blackhole += g.Next()
|
|
}
|
|
}
|
|
|
|
func BenchmarkNextParallel(b *testing.B) {
|
|
g := New(1)
|
|
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
var lblackhole uint64
|
|
for pb.Next() {
|
|
lblackhole += g.Next()
|
|
}
|
|
atomic.AddUint64(&blackhole, lblackhole)
|
|
})
|
|
}
|
|
|
|
func shuffle(n int, swap func(i, j int)) {
|
|
for i := n - 1; i > 0; i-- {
|
|
j := rand.Intn(i + 1)
|
|
swap(i, j)
|
|
}
|
|
}
|