github.com/zuoyebang/bitalostable@v1.0.1-0.20240229032404-e3b99a834294/internal/testkeys/testkeys_test.go (about) 1 // Copyright 2021 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 testkeys 6 7 import ( 8 "bytes" 9 "fmt" 10 "testing" 11 12 "github.com/stretchr/testify/require" 13 "github.com/zuoyebang/bitalostable/internal/datadriven" 14 ) 15 16 func TestGenerateAlphabetKey(t *testing.T) { 17 testCases := []struct { 18 alphabet string 19 i int 20 depth int 21 want string 22 }{ 23 {"abc", 0, 1, "a"}, 24 {"abc", 0, 2, "a"}, 25 {"abc", 0, 3, "a"}, 26 27 {"abc", 1, 1, "b"}, 28 {"abc", 2, 1, "c"}, 29 30 {"abc", 0, 2, "a"}, 31 {"abc", 1, 2, "aa"}, 32 {"abc", 2, 2, "ab"}, 33 {"abc", 3, 2, "ac"}, 34 {"abc", 4, 2, "b"}, 35 {"abc", 5, 2, "ba"}, 36 {"abc", 6, 2, "bb"}, 37 {"abc", 7, 2, "bc"}, 38 {"abc", 8, 2, "c"}, 39 {"abc", 9, 2, "ca"}, 40 {"abc", 10, 2, "cb"}, 41 {"abc", 11, 2, "cc"}, 42 } 43 44 buf := make([]byte, 10) 45 for _, tc := range testCases { 46 kc := keyCount(len(tc.alphabet), tc.depth) 47 n := generateAlphabetKey(buf, []byte(tc.alphabet), tc.i, kc) 48 got := string(buf[:n]) 49 if got != tc.want { 50 t.Errorf("generateAlphabetKey(%q, %d, %d) = %q, want %q", tc.alphabet, tc.i, kc, got, tc.want) 51 } 52 } 53 } 54 55 func TestKeyCount(t *testing.T) { 56 type params struct { 57 n, l int 58 } 59 testCases := map[params]int{ 60 {26, 1}: 26, 61 {52, 1}: 52, 62 {2, 2}: 6, 63 {2, 3}: 14, 64 {2, 4}: 30, 65 {3, 2}: 12, 66 } 67 for p, want := range testCases { 68 got := keyCount(p.n, p.l) 69 if got != want { 70 t.Errorf("keyCount(%d, %d) = %d, want %d", p.n, p.l, got, want) 71 } 72 } 73 } 74 75 func TestFullKeyspaces(t *testing.T) { 76 testCases := []struct { 77 ks Keyspace 78 want string 79 }{ 80 { 81 Alpha(1), 82 "a b c d e f g h i j k l m n o p q r s t u v w x y z", 83 }, 84 { 85 alphabet{[]byte("abc"), 2, 0, 0, 1}, 86 "a aa ab ac b ba bb bc c ca cb cc", 87 }, 88 { 89 alphabet{[]byte("abc"), 2, 0, 0, 2}, 90 "a ab b bb c cb", 91 }, 92 { 93 alphabet{[]byte("abc"), 3, 0, 0, 1}, 94 "a aa aaa aab aac ab aba abb abc ac aca acb acc b ba baa bab bac bb bba bbb bbc bc bca bcb bcc c ca caa cab cac cb cba cbb cbc cc cca ccb ccc", 95 }, 96 { 97 alphabet{[]byte("abc"), 3, 7, 10, 1}, 98 "abb abc ac aca acb acc b ba baa bab bac bb bba bbb bbc bc bca bcb bcc c ca caa", 99 }, 100 } 101 for _, tc := range testCases { 102 require.Equal(t, tc.want, keyspaceToString(tc.ks)) 103 } 104 } 105 106 func TestSlice(t *testing.T) { 107 testCases := []struct { 108 orig Keyspace 109 i, j int 110 want string 111 }{ 112 {Alpha(1), 1, 25, "b c d e f g h i j k l m n o p q r s t u v w x y"}, 113 {Alpha(1).Slice(1, 25), 1, 23, "c d e f g h i j k l m n o p q r s t u v w x"}, 114 {Alpha(1).Slice(1, 25).Slice(1, 23), 10, 22, "m n o p q r s t u v w x"}, 115 } 116 for _, tc := range testCases { 117 got := keyspaceToString(tc.orig.Slice(tc.i, tc.j)) 118 if got != tc.want { 119 t.Errorf("(%q).Slice(%d, %d) = %q, want %q", 120 keyspaceToString(tc.orig), tc.i, tc.j, got, tc.want) 121 } 122 } 123 } 124 125 func TestSuffix(t *testing.T) { 126 ks := Alpha(3) 127 require.Equal(t, "a@1", string(KeyAt(ks, 0, 1))) 128 require.Equal(t, "a@10", string(KeyAt(ks, 0, 10))) 129 require.Equal(t, "aab@5", string(KeyAt(ks, 3, 5))) 130 131 assertCmp := func(want int, a, b []byte) { 132 got := Comparer.Compare(a, b) 133 if got != want { 134 t.Helper() 135 t.Errorf("Compare(%q, %q) = %d, want %d", a, b, got, want) 136 } 137 } 138 139 for i := 1; i < ks.Count(); i++ { 140 assertCmp(-1, KeyAt(ks, i-1, 1), KeyAt(ks, i, 1)) 141 assertCmp(-1, Key(ks, i-1), Key(ks, i)) 142 assertCmp(0, Key(ks, i), Key(ks, i)) 143 for ts := 2; ts < 11; ts++ { 144 assertCmp(+1, KeyAt(ks, i, ts-1), KeyAt(ks, i, ts)) 145 assertCmp(-1, KeyAt(ks, i-1, ts-1), KeyAt(ks, i, ts)) 146 } 147 } 148 149 // Suffixes should be comparable on their own too. 150 a, b := make([]byte, MaxSuffixLen), make([]byte, MaxSuffixLen) 151 for ts := 2; ts < 150; ts++ { 152 an := WriteSuffix(a, ts-1) 153 bn := WriteSuffix(b, ts) 154 assertCmp(+1, a[:an], b[:bn]) 155 } 156 } 157 158 func TestSuffixLen(t *testing.T) { 159 testCases := map[int]int{ 160 0: 2, 161 1: 2, 162 5: 2, 163 9: 2, 164 10: 3, 165 17: 3, 166 20: 3, 167 99: 3, 168 100: 4, 169 101: 4, 170 999: 4, 171 1000: 5, 172 } 173 for ts, want := range testCases { 174 if got := SuffixLen(ts); got != want { 175 t.Errorf("SuffixLen(%d) = %d, want %d", ts, got, want) 176 } 177 } 178 } 179 180 func TestDivvy(t *testing.T) { 181 var buf bytes.Buffer 182 datadriven.RunTest(t, "testdata/divvy", func(d *datadriven.TestData) string { 183 buf.Reset() 184 switch d.Cmd { 185 case "divvy": 186 var alphaLen, portions int 187 d.ScanArgs(t, "alpha", &alphaLen) 188 d.ScanArgs(t, "portions", &portions) 189 190 input := Alpha(alphaLen) 191 for _, ks := range Divvy(input, portions) { 192 fmt.Fprintln(&buf, keyspaceToString(ks)) 193 } 194 return buf.String() 195 default: 196 return fmt.Sprintf("unrecognized command %q", d.Cmd) 197 } 198 }) 199 } 200 201 func keyspaceToString(ks Keyspace) string { 202 var buf bytes.Buffer 203 b := make([]byte, ks.MaxLen()) 204 for i := 0; i < ks.Count(); i++ { 205 n := ks.key(b, i) 206 if i > 0 { 207 buf.WriteRune(' ') 208 } 209 buf.Write(b[:n]) 210 } 211 return buf.String() 212 }