github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/internal/base/comparer_test.go (about) 1 // Copyright 2011 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 package base 6 7 import ( 8 "fmt" 9 "slices" 10 "testing" 11 "time" 12 13 "golang.org/x/exp/rand" 14 ) 15 16 func TestDefAppendSeparator(t *testing.T) { 17 testCases := []struct { 18 a, b, want string 19 }{ 20 // Examples from the doc comments. 21 {"black", "blue", "blb"}, 22 {"green", "", "green"}, 23 // Non-empty b values. The C++ Level-DB code calls these separators. 24 {"", "2", ""}, 25 {"1", "2", "1"}, 26 {"1", "29", "2"}, 27 {"13", "19", "14"}, 28 {"13", "99", "2"}, 29 {"135", "19", "14"}, 30 {"1357", "19", "14"}, 31 {"1357", "2", "14"}, 32 {"13\xff", "14", "13\xff"}, 33 {"13\xff", "19", "14"}, 34 {"1\xff\xff", "19", "1\xff\xff"}, 35 {"1\xff\xff", "2", "1\xff\xff"}, 36 {"1\xff\xff", "9", "2"}, 37 // Empty b values. The C++ Level-DB code calls these successors. 38 {"", "", ""}, 39 {"1", "", "1"}, 40 {"11", "", "11"}, 41 {"11\xff", "", "11\xff"}, 42 {"1\xff", "", "1\xff"}, 43 {"1\xff\xff", "", "1\xff\xff"}, 44 {"\xff", "", "\xff"}, 45 {"\xff\xff", "", "\xff\xff"}, 46 {"\xff\xff\xff", "", "\xff\xff\xff"}, 47 } 48 for _, tc := range testCases { 49 t.Run("", func(t *testing.T) { 50 got := string(DefaultComparer.Separator(nil, []byte(tc.a), []byte(tc.b))) 51 if got != tc.want { 52 t.Errorf("a, b = %q, %q: got %q, want %q", tc.a, tc.b, got, tc.want) 53 } 54 }) 55 } 56 } 57 58 func TestAbbreviatedKey(t *testing.T) { 59 rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano()))) 60 randBytes := func(size int) []byte { 61 data := make([]byte, size) 62 for i := range data { 63 data[i] = byte(rng.Int() & 0xff) 64 } 65 return data 66 } 67 68 keys := make([][]byte, 10000) 69 for i := range keys { 70 keys[i] = randBytes(rng.Intn(16)) 71 } 72 slices.SortFunc(keys, DefaultComparer.Compare) 73 74 for i := 1; i < len(keys); i++ { 75 last := DefaultComparer.AbbreviatedKey(keys[i-1]) 76 cur := DefaultComparer.AbbreviatedKey(keys[i]) 77 cmp := DefaultComparer.Compare(keys[i-1], keys[i]) 78 if cmp == 0 { 79 if last != cur { 80 t.Fatalf("expected equal abbreviated keys: %x[%x] != %x[%x]", 81 last, keys[i-1], cur, keys[i]) 82 } 83 } else { 84 if last > cur { 85 t.Fatalf("unexpected abbreviated key ordering: %x[%x] > %x[%x]", 86 last, keys[i-1], cur, keys[i]) 87 } 88 } 89 } 90 } 91 92 func BenchmarkAbbreviatedKey(b *testing.B) { 93 rng := rand.New(rand.NewSource(1449168817)) 94 randBytes := func(size int) []byte { 95 data := make([]byte, size) 96 for i := range data { 97 data[i] = byte(rng.Int() & 0xff) 98 } 99 return data 100 } 101 keys := make([][]byte, 10000) 102 for i := range keys { 103 keys[i] = randBytes(8) 104 } 105 106 b.ResetTimer() 107 var sum uint64 108 for i := 0; i < b.N; i++ { 109 j := i % len(keys) 110 sum += DefaultComparer.AbbreviatedKey(keys[j]) 111 } 112 113 if testing.Verbose() { 114 // Ensure the compiler doesn't optimize away our benchmark. 115 fmt.Println(sum) 116 } 117 }