github.com/vvnotw/moby@v1.13.1/pkg/truncindex/truncindex_test.go (about) 1 package truncindex 2 3 import ( 4 "math/rand" 5 "testing" 6 7 "github.com/docker/docker/pkg/stringid" 8 ) 9 10 // Test the behavior of TruncIndex, an index for querying IDs from a non-conflicting prefix. 11 func TestTruncIndex(t *testing.T) { 12 ids := []string{} 13 index := NewTruncIndex(ids) 14 // Get on an empty index 15 if _, err := index.Get("foobar"); err == nil { 16 t.Fatal("Get on an empty index should return an error") 17 } 18 19 // Spaces should be illegal in an id 20 if err := index.Add("I have a space"); err == nil { 21 t.Fatalf("Adding an id with ' ' should return an error") 22 } 23 24 id := "99b36c2c326ccc11e726eee6ee78a0baf166ef96" 25 // Add an id 26 if err := index.Add(id); err != nil { 27 t.Fatal(err) 28 } 29 30 // Add an empty id (should fail) 31 if err := index.Add(""); err == nil { 32 t.Fatalf("Adding an empty id should return an error") 33 } 34 35 // Get a non-existing id 36 assertIndexGet(t, index, "abracadabra", "", true) 37 // Get an empty id 38 assertIndexGet(t, index, "", "", true) 39 // Get the exact id 40 assertIndexGet(t, index, id, id, false) 41 // The first letter should match 42 assertIndexGet(t, index, id[:1], id, false) 43 // The first half should match 44 assertIndexGet(t, index, id[:len(id)/2], id, false) 45 // The second half should NOT match 46 assertIndexGet(t, index, id[len(id)/2:], "", true) 47 48 id2 := id[:6] + "blabla" 49 // Add an id 50 if err := index.Add(id2); err != nil { 51 t.Fatal(err) 52 } 53 // Both exact IDs should work 54 assertIndexGet(t, index, id, id, false) 55 assertIndexGet(t, index, id2, id2, false) 56 57 // 6 characters or less should conflict 58 assertIndexGet(t, index, id[:6], "", true) 59 assertIndexGet(t, index, id[:4], "", true) 60 assertIndexGet(t, index, id[:1], "", true) 61 62 // An ambiguous id prefix should return an error 63 if _, err := index.Get(id[:4]); err == nil { 64 t.Fatal("An ambiguous id prefix should return an error") 65 } 66 67 // 7 characters should NOT conflict 68 assertIndexGet(t, index, id[:7], id, false) 69 assertIndexGet(t, index, id2[:7], id2, false) 70 71 // Deleting a non-existing id should return an error 72 if err := index.Delete("non-existing"); err == nil { 73 t.Fatalf("Deleting a non-existing id should return an error") 74 } 75 76 // Deleting an empty id should return an error 77 if err := index.Delete(""); err == nil { 78 t.Fatal("Deleting an empty id should return an error") 79 } 80 81 // Deleting id2 should remove conflicts 82 if err := index.Delete(id2); err != nil { 83 t.Fatal(err) 84 } 85 // id2 should no longer work 86 assertIndexGet(t, index, id2, "", true) 87 assertIndexGet(t, index, id2[:7], "", true) 88 assertIndexGet(t, index, id2[:11], "", true) 89 90 // conflicts between id and id2 should be gone 91 assertIndexGet(t, index, id[:6], id, false) 92 assertIndexGet(t, index, id[:4], id, false) 93 assertIndexGet(t, index, id[:1], id, false) 94 95 // non-conflicting substrings should still not conflict 96 assertIndexGet(t, index, id[:7], id, false) 97 assertIndexGet(t, index, id[:15], id, false) 98 assertIndexGet(t, index, id, id, false) 99 100 assertIndexIterate(t) 101 } 102 103 func assertIndexIterate(t *testing.T) { 104 ids := []string{ 105 "19b36c2c326ccc11e726eee6ee78a0baf166ef96", 106 "28b36c2c326ccc11e726eee6ee78a0baf166ef96", 107 "37b36c2c326ccc11e726eee6ee78a0baf166ef96", 108 "46b36c2c326ccc11e726eee6ee78a0baf166ef96", 109 } 110 111 index := NewTruncIndex(ids) 112 113 index.Iterate(func(targetId string) { 114 for _, id := range ids { 115 if targetId == id { 116 return 117 } 118 } 119 120 t.Fatalf("An unknown ID '%s'", targetId) 121 }) 122 } 123 124 func assertIndexGet(t *testing.T, index *TruncIndex, input, expectedResult string, expectError bool) { 125 if result, err := index.Get(input); err != nil && !expectError { 126 t.Fatalf("Unexpected error getting '%s': %s", input, err) 127 } else if err == nil && expectError { 128 t.Fatalf("Getting '%s' should return an error, not '%s'", input, result) 129 } else if result != expectedResult { 130 t.Fatalf("Getting '%s' returned '%s' instead of '%s'", input, result, expectedResult) 131 } 132 } 133 134 func BenchmarkTruncIndexAdd100(b *testing.B) { 135 var testSet []string 136 for i := 0; i < 100; i++ { 137 testSet = append(testSet, stringid.GenerateNonCryptoID()) 138 } 139 b.ResetTimer() 140 for i := 0; i < b.N; i++ { 141 index := NewTruncIndex([]string{}) 142 for _, id := range testSet { 143 if err := index.Add(id); err != nil { 144 b.Fatal(err) 145 } 146 } 147 } 148 } 149 150 func BenchmarkTruncIndexAdd250(b *testing.B) { 151 var testSet []string 152 for i := 0; i < 250; i++ { 153 testSet = append(testSet, stringid.GenerateNonCryptoID()) 154 } 155 b.ResetTimer() 156 for i := 0; i < b.N; i++ { 157 index := NewTruncIndex([]string{}) 158 for _, id := range testSet { 159 if err := index.Add(id); err != nil { 160 b.Fatal(err) 161 } 162 } 163 } 164 } 165 166 func BenchmarkTruncIndexAdd500(b *testing.B) { 167 var testSet []string 168 for i := 0; i < 500; i++ { 169 testSet = append(testSet, stringid.GenerateNonCryptoID()) 170 } 171 b.ResetTimer() 172 for i := 0; i < b.N; i++ { 173 index := NewTruncIndex([]string{}) 174 for _, id := range testSet { 175 if err := index.Add(id); err != nil { 176 b.Fatal(err) 177 } 178 } 179 } 180 } 181 182 func BenchmarkTruncIndexGet100(b *testing.B) { 183 var testSet []string 184 var testKeys []string 185 for i := 0; i < 100; i++ { 186 testSet = append(testSet, stringid.GenerateNonCryptoID()) 187 } 188 index := NewTruncIndex([]string{}) 189 for _, id := range testSet { 190 if err := index.Add(id); err != nil { 191 b.Fatal(err) 192 } 193 l := rand.Intn(12) + 12 194 testKeys = append(testKeys, id[:l]) 195 } 196 b.ResetTimer() 197 for i := 0; i < b.N; i++ { 198 for _, id := range testKeys { 199 if res, err := index.Get(id); err != nil { 200 b.Fatal(res, err) 201 } 202 } 203 } 204 } 205 206 func BenchmarkTruncIndexGet250(b *testing.B) { 207 var testSet []string 208 var testKeys []string 209 for i := 0; i < 250; i++ { 210 testSet = append(testSet, stringid.GenerateNonCryptoID()) 211 } 212 index := NewTruncIndex([]string{}) 213 for _, id := range testSet { 214 if err := index.Add(id); err != nil { 215 b.Fatal(err) 216 } 217 l := rand.Intn(12) + 12 218 testKeys = append(testKeys, id[:l]) 219 } 220 b.ResetTimer() 221 for i := 0; i < b.N; i++ { 222 for _, id := range testKeys { 223 if res, err := index.Get(id); err != nil { 224 b.Fatal(res, err) 225 } 226 } 227 } 228 } 229 230 func BenchmarkTruncIndexGet500(b *testing.B) { 231 var testSet []string 232 var testKeys []string 233 for i := 0; i < 500; i++ { 234 testSet = append(testSet, stringid.GenerateNonCryptoID()) 235 } 236 index := NewTruncIndex([]string{}) 237 for _, id := range testSet { 238 if err := index.Add(id); err != nil { 239 b.Fatal(err) 240 } 241 l := rand.Intn(12) + 12 242 testKeys = append(testKeys, id[:l]) 243 } 244 b.ResetTimer() 245 for i := 0; i < b.N; i++ { 246 for _, id := range testKeys { 247 if res, err := index.Get(id); err != nil { 248 b.Fatal(res, err) 249 } 250 } 251 } 252 } 253 254 func BenchmarkTruncIndexDelete100(b *testing.B) { 255 var testSet []string 256 for i := 0; i < 100; i++ { 257 testSet = append(testSet, stringid.GenerateNonCryptoID()) 258 } 259 b.ResetTimer() 260 for i := 0; i < b.N; i++ { 261 b.StopTimer() 262 index := NewTruncIndex([]string{}) 263 for _, id := range testSet { 264 if err := index.Add(id); err != nil { 265 b.Fatal(err) 266 } 267 } 268 b.StartTimer() 269 for _, id := range testSet { 270 if err := index.Delete(id); err != nil { 271 b.Fatal(err) 272 } 273 } 274 } 275 } 276 277 func BenchmarkTruncIndexDelete250(b *testing.B) { 278 var testSet []string 279 for i := 0; i < 250; i++ { 280 testSet = append(testSet, stringid.GenerateNonCryptoID()) 281 } 282 b.ResetTimer() 283 for i := 0; i < b.N; i++ { 284 b.StopTimer() 285 index := NewTruncIndex([]string{}) 286 for _, id := range testSet { 287 if err := index.Add(id); err != nil { 288 b.Fatal(err) 289 } 290 } 291 b.StartTimer() 292 for _, id := range testSet { 293 if err := index.Delete(id); err != nil { 294 b.Fatal(err) 295 } 296 } 297 } 298 } 299 300 func BenchmarkTruncIndexDelete500(b *testing.B) { 301 var testSet []string 302 for i := 0; i < 500; i++ { 303 testSet = append(testSet, stringid.GenerateNonCryptoID()) 304 } 305 b.ResetTimer() 306 for i := 0; i < b.N; i++ { 307 b.StopTimer() 308 index := NewTruncIndex([]string{}) 309 for _, id := range testSet { 310 if err := index.Add(id); err != nil { 311 b.Fatal(err) 312 } 313 } 314 b.StartTimer() 315 for _, id := range testSet { 316 if err := index.Delete(id); err != nil { 317 b.Fatal(err) 318 } 319 } 320 } 321 } 322 323 func BenchmarkTruncIndexNew100(b *testing.B) { 324 var testSet []string 325 for i := 0; i < 100; i++ { 326 testSet = append(testSet, stringid.GenerateNonCryptoID()) 327 } 328 b.ResetTimer() 329 for i := 0; i < b.N; i++ { 330 NewTruncIndex(testSet) 331 } 332 } 333 334 func BenchmarkTruncIndexNew250(b *testing.B) { 335 var testSet []string 336 for i := 0; i < 250; i++ { 337 testSet = append(testSet, stringid.GenerateNonCryptoID()) 338 } 339 b.ResetTimer() 340 for i := 0; i < b.N; i++ { 341 NewTruncIndex(testSet) 342 } 343 } 344 345 func BenchmarkTruncIndexNew500(b *testing.B) { 346 var testSet []string 347 for i := 0; i < 500; i++ { 348 testSet = append(testSet, stringid.GenerateNonCryptoID()) 349 } 350 b.ResetTimer() 351 for i := 0; i < b.N; i++ { 352 NewTruncIndex(testSet) 353 } 354 } 355 356 func BenchmarkTruncIndexAddGet100(b *testing.B) { 357 var testSet []string 358 var testKeys []string 359 for i := 0; i < 500; i++ { 360 id := stringid.GenerateNonCryptoID() 361 testSet = append(testSet, id) 362 l := rand.Intn(12) + 12 363 testKeys = append(testKeys, id[:l]) 364 } 365 b.ResetTimer() 366 for i := 0; i < b.N; i++ { 367 index := NewTruncIndex([]string{}) 368 for _, id := range testSet { 369 if err := index.Add(id); err != nil { 370 b.Fatal(err) 371 } 372 } 373 for _, id := range testKeys { 374 if res, err := index.Get(id); err != nil { 375 b.Fatal(res, err) 376 } 377 } 378 } 379 } 380 381 func BenchmarkTruncIndexAddGet250(b *testing.B) { 382 var testSet []string 383 var testKeys []string 384 for i := 0; i < 500; i++ { 385 id := stringid.GenerateNonCryptoID() 386 testSet = append(testSet, id) 387 l := rand.Intn(12) + 12 388 testKeys = append(testKeys, id[:l]) 389 } 390 b.ResetTimer() 391 for i := 0; i < b.N; i++ { 392 index := NewTruncIndex([]string{}) 393 for _, id := range testSet { 394 if err := index.Add(id); err != nil { 395 b.Fatal(err) 396 } 397 } 398 for _, id := range testKeys { 399 if res, err := index.Get(id); err != nil { 400 b.Fatal(res, err) 401 } 402 } 403 } 404 } 405 406 func BenchmarkTruncIndexAddGet500(b *testing.B) { 407 var testSet []string 408 var testKeys []string 409 for i := 0; i < 500; i++ { 410 id := stringid.GenerateNonCryptoID() 411 testSet = append(testSet, id) 412 l := rand.Intn(12) + 12 413 testKeys = append(testKeys, id[:l]) 414 } 415 b.ResetTimer() 416 for i := 0; i < b.N; i++ { 417 index := NewTruncIndex([]string{}) 418 for _, id := range testSet { 419 if err := index.Add(id); err != nil { 420 b.Fatal(err) 421 } 422 } 423 for _, id := range testKeys { 424 if res, err := index.Get(id); err != nil { 425 b.Fatal(res, err) 426 } 427 } 428 } 429 }