175 lines
3.5 KiB
Go
175 lines
3.5 KiB
Go
package radix
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
// generateUUID is used to generate a random UUID
|
|
func generateUUID() string {
|
|
buf := make([]byte, 16)
|
|
if _, err := rand.Read(buf); err != nil {
|
|
panic(fmt.Errorf("failed to read random bytes: %v", err))
|
|
}
|
|
|
|
return fmt.Sprintf("%08x-%04x-%04x-%04x-%12x",
|
|
buf[0:4],
|
|
buf[4:6],
|
|
buf[6:8],
|
|
buf[8:10],
|
|
buf[10:16])
|
|
}
|
|
|
|
func TestRadix(t *testing.T) {
|
|
var min, max string
|
|
inp := make(map[string]int)
|
|
for i := 0; i < 1000; i++ {
|
|
gen := generateUUID()
|
|
inp[gen] = i
|
|
if gen < min || i == 0 {
|
|
min = gen
|
|
}
|
|
if gen > max || i == 0 {
|
|
max = gen
|
|
}
|
|
}
|
|
|
|
r := NewFromMap(inp)
|
|
if r.Len() != len(inp) {
|
|
t.Fatalf("bad length: %v %v", r.Len(), len(inp))
|
|
}
|
|
|
|
// Check min and max
|
|
outMin, _, _ := r.Minimum()
|
|
if string(outMin) != min {
|
|
t.Fatalf("bad minimum: %s %v", outMin, min)
|
|
}
|
|
outMax, _, _ := r.Maximum()
|
|
if string(outMax) != max {
|
|
t.Fatalf("bad maximum: %s %v", outMax, max)
|
|
}
|
|
|
|
for k, v := range inp {
|
|
out, ok := r.Get([]byte(k))
|
|
if !ok {
|
|
t.Fatalf("missing key: %v", k)
|
|
}
|
|
if out != v {
|
|
t.Fatalf("value mis-match: %v %v", out, v)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestDeletePrefix(t *testing.T) {
|
|
type exp struct {
|
|
inp []string
|
|
prefix string
|
|
out []string
|
|
numDeleted int
|
|
}
|
|
|
|
cases := []exp{
|
|
{[]string{"", "A", "AB", "ABC", "R", "S"}, "A", []string{"", "R", "S"}, 3},
|
|
{[]string{"", "A", "AB", "ABC", "R", "S"}, "ABC", []string{"", "A", "AB", "R", "S"}, 1},
|
|
{[]string{"", "A", "AB", "ABC", "R", "S"}, "", []string{}, 6},
|
|
{[]string{"", "A", "AB", "ABC", "R", "S"}, "S", []string{"", "A", "AB", "ABC", "R"}, 1},
|
|
{[]string{"", "A", "AB", "ABC", "R", "S"}, "SS", []string{"", "A", "AB", "ABC", "R", "S"}, 0},
|
|
}
|
|
|
|
for _, test := range cases {
|
|
r := New()
|
|
for _, ss := range test.inp {
|
|
r.Insert([]byte(ss), 1)
|
|
}
|
|
|
|
deleted := r.DeletePrefix([]byte(test.prefix))
|
|
if deleted != test.numDeleted {
|
|
t.Fatalf("Bad delete, expected %v to be deleted but got %v", test.numDeleted, deleted)
|
|
}
|
|
|
|
out := []string{}
|
|
fn := func(s []byte, v int) bool {
|
|
out = append(out, string(s))
|
|
return false
|
|
}
|
|
recursiveWalk(r.root, fn)
|
|
|
|
if !reflect.DeepEqual(out, test.out) {
|
|
t.Fatalf("mis-match: %v %v", out, test.out)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestInsert_Duplicate(t *testing.T) {
|
|
r := New()
|
|
vv, ok := r.Insert([]byte("cpu"), 1)
|
|
if vv != 1 {
|
|
t.Fatalf("value mismatch: got %v, exp %v", vv, 1)
|
|
}
|
|
|
|
if !ok {
|
|
t.Fatalf("value mismatch: got %v, exp %v", ok, true)
|
|
}
|
|
|
|
// Insert a dup with a different type should fail
|
|
vv, ok = r.Insert([]byte("cpu"), 2)
|
|
if vv != 1 {
|
|
t.Fatalf("value mismatch: got %v, exp %v", vv, 1)
|
|
}
|
|
|
|
if ok {
|
|
t.Fatalf("value mismatch: got %v, exp %v", ok, false)
|
|
}
|
|
}
|
|
|
|
//
|
|
// benchmarks
|
|
//
|
|
|
|
func BenchmarkTree_Insert(b *testing.B) {
|
|
t := New()
|
|
|
|
keys := make([][]byte, 0, 10000)
|
|
for i := 0; i < cap(keys); i++ {
|
|
k := []byte(fmt.Sprintf("cpu,host=%d", i))
|
|
if v, ok := t.Insert(k, 1); v != 1 || !ok {
|
|
b.Fatalf("insert failed: %v != 1 || !%v", v, ok)
|
|
}
|
|
keys = append(keys, k)
|
|
}
|
|
|
|
b.SetBytes(int64(len(keys)))
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
|
|
for j := 0; j < b.N; j++ {
|
|
for _, key := range keys {
|
|
if v, ok := t.Insert(key, 1); v != 1 || ok {
|
|
b.Fatalf("insert failed: %v != 1 || !%v", v, ok)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkTree_InsertNew(b *testing.B) {
|
|
keys := make([][]byte, 0, 10000)
|
|
for i := 0; i < cap(keys); i++ {
|
|
k := []byte(fmt.Sprintf("cpu,host=%d", i))
|
|
keys = append(keys, k)
|
|
}
|
|
|
|
b.SetBytes(int64(len(keys)))
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
|
|
for j := 0; j < b.N; j++ {
|
|
t := New()
|
|
for _, key := range keys {
|
|
t.Insert(key, 1)
|
|
}
|
|
}
|
|
}
|