diff options
Diffstat (limited to 'container/view_test.go')
-rw-r--r-- | container/view_test.go | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/container/view_test.go b/container/view_test.go index 290282c907..099da49df9 100644 --- a/container/view_test.go +++ b/container/view_test.go @@ -1,12 +1,14 @@ package container // import "github.com/docker/docker/container" import ( + "math/rand" "os" "path/filepath" "testing" "github.com/docker/docker/api/types" containertypes "github.com/docker/docker/api/types/container" + "github.com/docker/docker/pkg/stringid" "github.com/google/uuid" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -183,3 +185,300 @@ func TestViewWithHealthCheck(t *testing.T) { t.Fatalf("expected Health=starting. Got: %+v", s) } } + +func TestTruncIndex(t *testing.T) { + db, err := NewViewDB() + if err != nil { + t.Fatal(err) + } + + // Get on an empty index + if _, err := db.GetByPrefix("foobar"); err == nil { + t.Fatal("Get on an empty index should return an error") + } + + id := "99b36c2c326ccc11e726eee6ee78a0baf166ef96" + // Add an id + if err := db.Save(&Container{ID: id}); err != nil { + t.Fatal(err) + } + + type testacase struct { + name string + input string + expectedResult string + expectError bool + } + + for _, tc := range []testacase{ + { + name: "Get a non-existing id", + input: "abracadabra", + expectError: true, + }, + { + name: "Get an empty id", + input: "", + expectedResult: "", + expectError: true, + }, + { + name: "Get the exact id", + input: id, + expectedResult: id, + expectError: false, + }, + { + name: "The first letter should match", + input: id[:1], + expectedResult: id, + expectError: false, + }, + { + name: "The first half should match", + input: id[:len(id)/2], + expectedResult: id, + expectError: false, + }, + { + name: "The second half should NOT match", + input: id[len(id)/2:], + expectError: true, + }, + } { + t.Run(tc.name, func(t *testing.T) { + assertIndexGet(t, db, tc.input, tc.expectedResult, tc.expectError) + }) + } + + id2 := id[:6] + "blabla" + // Add an id + if err := db.Save(&Container{ID: id2}); err != nil { + t.Fatal(err) + } + + for _, tc := range []testacase{ + { + name: "id should work", + input: id, + expectedResult: id, + expectError: false, + }, + { + name: "id2 should work", + input: id2, + expectedResult: id2, + expectError: false, + }, + { + name: "6 characters should conflict", + input: id[:6], + expectedResult: "", + expectError: true, + }, + { + name: "4 characters should conflict", + input: id[:4], + expectedResult: "", + expectError: true, + }, + { + name: "1 character should conflict", + input: id[:6], + expectedResult: "", + expectError: true, + }, + { + name: "7 characters of id should not conflict", + input: id[:7], + expectedResult: id, + expectError: false, + }, + { + name: "7 characters of id2 should not conflict", + input: id2[:7], + expectedResult: id2, + expectError: false, + }, + } { + t.Run(tc.name, func(t *testing.T) { + assertIndexGet(t, db, tc.input, tc.expectedResult, tc.expectError) + }) + } + + // Deleting id2 should remove conflicts + if err := db.Delete(&Container{ID: id2}); err != nil { + t.Fatal(err) + } + + for _, tc := range []testacase{ + { + name: "id2 should no longer work", + input: id2, + expectedResult: "", + expectError: true, + }, + { + name: "7 characters id2 should no longer work", + input: id2[:7], + expectedResult: "", + expectError: true, + }, + { + name: "11 characters id2 should no longer work", + input: id2[:11], + expectedResult: "", + expectError: true, + }, + { + name: "conflicts between id[:6] and id2 should be gone", + input: id[:6], + expectedResult: id, + expectError: false, + }, + { + name: "conflicts between id[:4] and id2 should be gone", + input: id[:4], + expectedResult: id, + expectError: false, + }, + { + name: "conflicts between id[:1] and id2 should be gone", + input: id[:1], + expectedResult: id, + expectError: false, + }, + { + name: "non-conflicting 7 character substrings should still not conflict", + input: id[:7], + expectedResult: id, + expectError: false, + }, + { + name: "non-conflicting 15 character substrings should still not conflict", + input: id[:15], + expectedResult: id, + expectError: false, + }, + { + name: "non-conflicting substrings should still not conflict", + input: id, + expectedResult: id, + expectError: false, + }, + } { + t.Run(tc.name, func(t *testing.T) { + assertIndexGet(t, db, tc.input, tc.expectedResult, tc.expectError) + }) + } +} + +func assertIndexGet(t *testing.T, snapshot ViewDB, input, expectedResult string, expectError bool) { + if result, err := snapshot.GetByPrefix(input); err != nil && !expectError { + t.Fatalf("Unexpected error getting '%s': %s", input, err) + } else if err == nil && expectError { + t.Fatalf("Getting '%s' should return an error, not '%s'", input, result) + } else if result != expectedResult { + t.Fatalf("Getting '%s' returned '%s' instead of '%s'", input, result, expectedResult) + } +} + +func BenchmarkDBAdd100(b *testing.B) { + var testSet []string + for i := 0; i < 100; i++ { + testSet = append(testSet, stringid.GenerateRandomID()) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + db, err := NewViewDB() + if err != nil { + b.Fatal(err) + } + for _, id := range testSet { + if err := db.Save(&Container{ID: id}); err != nil { + b.Fatal(err) + } + } + } +} + +func BenchmarkDBGetByPrefix100(b *testing.B) { + var testSet []string + var testKeys []string + for i := 0; i < 100; i++ { + testSet = append(testSet, stringid.GenerateRandomID()) + } + db, err := NewViewDB() + if err != nil { + b.Fatal(err) + } + for _, id := range testSet { + if err := db.Save(&Container{ID: id}); err != nil { + b.Fatal(err) + } + l := rand.Intn(12) + 12 + testKeys = append(testKeys, id[:l]) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + for _, id := range testKeys { + if res, err := db.GetByPrefix(id); err != nil { + b.Fatal(res, err) + } + } + } +} + +func BenchmarkDBGetByPrefix250(b *testing.B) { + var testSet []string + var testKeys []string + for i := 0; i < 250; i++ { + testSet = append(testSet, stringid.GenerateRandomID()) + } + db, err := NewViewDB() + if err != nil { + b.Fatal(err) + } + for _, id := range testSet { + if err := db.Save(&Container{ID: id}); err != nil { + b.Fatal(err) + } + l := rand.Intn(12) + 12 + testKeys = append(testKeys, id[:l]) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + for _, id := range testKeys { + if res, err := db.GetByPrefix(id); err != nil { + b.Fatal(res, err) + } + } + } +} + +func BenchmarkDBGetByPrefix500(b *testing.B) { + var testSet []string + var testKeys []string + for i := 0; i < 500; i++ { + testSet = append(testSet, stringid.GenerateRandomID()) + } + db, err := NewViewDB() + if err != nil { + b.Fatal(err) + } + for _, id := range testSet { + if err := db.Save(&Container{ID: id}); err != nil { + b.Fatal(err) + } + l := rand.Intn(12) + 12 + testKeys = append(testKeys, id[:l]) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + for _, id := range testKeys { + if res, err := db.GetByPrefix(id); err != nil { + b.Fatal(res, err) + } + } + } +} |