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