| package digestset |
| |
| import ( |
| "crypto/sha256" |
| _ "crypto/sha512" |
| "encoding/binary" |
| "math/rand" |
| "testing" |
| |
| digest "github.com/opencontainers/go-digest" |
| ) |
| |
| func assertEqualDigests(t *testing.T, d1, d2 digest.Digest) { |
| if d1 != d2 { |
| t.Fatalf("Digests do not match:\n\tActual: %s\n\tExpected: %s", d1, d2) |
| } |
| } |
| |
| func TestLookup(t *testing.T) { |
| digests := []digest.Digest{ |
| "sha256:1234511111111111111111111111111111111111111111111111111111111111", |
| "sha256:1234111111111111111111111111111111111111111111111111111111111111", |
| "sha256:1234611111111111111111111111111111111111111111111111111111111111", |
| "sha256:5432111111111111111111111111111111111111111111111111111111111111", |
| "sha256:6543111111111111111111111111111111111111111111111111111111111111", |
| "sha256:6432111111111111111111111111111111111111111111111111111111111111", |
| "sha256:6542111111111111111111111111111111111111111111111111111111111111", |
| "sha256:6532111111111111111111111111111111111111111111111111111111111111", |
| } |
| |
| dset := NewSet() |
| for i := range digests { |
| if err := dset.Add(digests[i]); err != nil { |
| t.Fatal(err) |
| } |
| } |
| |
| dgst, err := dset.Lookup("54") |
| if err != nil { |
| t.Fatal(err) |
| } |
| assertEqualDigests(t, dgst, digests[3]) |
| |
| _, err = dset.Lookup("1234") |
| if err == nil { |
| t.Fatal("Expected ambiguous error looking up: 1234") |
| } |
| if err != ErrDigestAmbiguous { |
| t.Fatal(err) |
| } |
| |
| _, err = dset.Lookup("9876") |
| if err == nil { |
| t.Fatal("Expected not found error looking up: 9876") |
| } |
| if err != ErrDigestNotFound { |
| t.Fatal(err) |
| } |
| |
| _, err = dset.Lookup("sha256:1234") |
| if err == nil { |
| t.Fatal("Expected ambiguous error looking up: sha256:1234") |
| } |
| if err != ErrDigestAmbiguous { |
| t.Fatal(err) |
| } |
| |
| dgst, err = dset.Lookup("sha256:12345") |
| if err != nil { |
| t.Fatal(err) |
| } |
| assertEqualDigests(t, dgst, digests[0]) |
| |
| dgst, err = dset.Lookup("sha256:12346") |
| if err != nil { |
| t.Fatal(err) |
| } |
| assertEqualDigests(t, dgst, digests[2]) |
| |
| dgst, err = dset.Lookup("12346") |
| if err != nil { |
| t.Fatal(err) |
| } |
| assertEqualDigests(t, dgst, digests[2]) |
| |
| dgst, err = dset.Lookup("12345") |
| if err != nil { |
| t.Fatal(err) |
| } |
| assertEqualDigests(t, dgst, digests[0]) |
| } |
| |
| func TestAddDuplication(t *testing.T) { |
| digests := []digest.Digest{ |
| "sha256:1234111111111111111111111111111111111111111111111111111111111111", |
| "sha256:1234511111111111111111111111111111111111111111111111111111111111", |
| "sha256:1234611111111111111111111111111111111111111111111111111111111111", |
| "sha256:5432111111111111111111111111111111111111111111111111111111111111", |
| "sha256:6543111111111111111111111111111111111111111111111111111111111111", |
| "sha512:65431111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", |
| "sha512:65421111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", |
| "sha512:65321111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", |
| } |
| |
| dset := NewSet() |
| for i := range digests { |
| if err := dset.Add(digests[i]); err != nil { |
| t.Fatal(err) |
| } |
| } |
| |
| if len(dset.entries) != 8 { |
| t.Fatal("Invalid dset size") |
| } |
| |
| if err := dset.Add(digest.Digest("sha256:1234511111111111111111111111111111111111111111111111111111111111")); err != nil { |
| t.Fatal(err) |
| } |
| |
| if len(dset.entries) != 8 { |
| t.Fatal("Duplicate digest insert should not increase entries size") |
| } |
| |
| if err := dset.Add(digest.Digest("sha384:123451111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")); err != nil { |
| t.Fatal(err) |
| } |
| |
| if len(dset.entries) != 9 { |
| t.Fatal("Insert with different algorithm should be allowed") |
| } |
| } |
| |
| func TestRemove(t *testing.T) { |
| digests, err := createDigests(10) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| dset := NewSet() |
| for i := range digests { |
| if err := dset.Add(digests[i]); err != nil { |
| t.Fatal(err) |
| } |
| } |
| |
| dgst, err := dset.Lookup(digests[0].String()) |
| if err != nil { |
| t.Fatal(err) |
| } |
| if dgst != digests[0] { |
| t.Fatalf("Unexpected digest value:\n\tExpected: %s\n\tActual: %s", digests[0], dgst) |
| } |
| |
| if err := dset.Remove(digests[0]); err != nil { |
| t.Fatal(err) |
| } |
| |
| if _, err := dset.Lookup(digests[0].String()); err != ErrDigestNotFound { |
| t.Fatalf("Expected error %v when looking up removed digest, got %v", ErrDigestNotFound, err) |
| } |
| } |
| |
| func TestAll(t *testing.T) { |
| digests, err := createDigests(100) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| dset := NewSet() |
| for i := range digests { |
| if err := dset.Add(digests[i]); err != nil { |
| t.Fatal(err) |
| } |
| } |
| |
| all := map[digest.Digest]struct{}{} |
| for _, dgst := range dset.All() { |
| all[dgst] = struct{}{} |
| } |
| |
| if len(all) != len(digests) { |
| t.Fatalf("Unexpected number of unique digests found:\n\tExpected: %d\n\tActual: %d", len(digests), len(all)) |
| } |
| |
| for i, dgst := range digests { |
| if _, ok := all[dgst]; !ok { |
| t.Fatalf("Missing element at position %d: %s", i, dgst) |
| } |
| } |
| |
| } |
| |
| func assertEqualShort(t *testing.T, actual, expected string) { |
| if actual != expected { |
| t.Fatalf("Unexpected short value:\n\tExpected: %s\n\tActual: %s", expected, actual) |
| } |
| } |
| |
| func TestShortCodeTable(t *testing.T) { |
| digests := []digest.Digest{ |
| "sha256:1234111111111111111111111111111111111111111111111111111111111111", |
| "sha256:1234511111111111111111111111111111111111111111111111111111111111", |
| "sha256:1234611111111111111111111111111111111111111111111111111111111111", |
| "sha256:5432111111111111111111111111111111111111111111111111111111111111", |
| "sha256:6543111111111111111111111111111111111111111111111111111111111111", |
| "sha256:6432111111111111111111111111111111111111111111111111111111111111", |
| "sha256:6542111111111111111111111111111111111111111111111111111111111111", |
| "sha256:6532111111111111111111111111111111111111111111111111111111111111", |
| } |
| |
| dset := NewSet() |
| for i := range digests { |
| if err := dset.Add(digests[i]); err != nil { |
| t.Fatal(err) |
| } |
| } |
| |
| dump := ShortCodeTable(dset, 2) |
| |
| if len(dump) < len(digests) { |
| t.Fatalf("Error unexpected size: %d, expecting %d", len(dump), len(digests)) |
| } |
| assertEqualShort(t, dump[digests[0]], "12341") |
| assertEqualShort(t, dump[digests[1]], "12345") |
| assertEqualShort(t, dump[digests[2]], "12346") |
| assertEqualShort(t, dump[digests[3]], "54") |
| assertEqualShort(t, dump[digests[4]], "6543") |
| assertEqualShort(t, dump[digests[5]], "64") |
| assertEqualShort(t, dump[digests[6]], "6542") |
| assertEqualShort(t, dump[digests[7]], "653") |
| } |
| |
| func createDigests(count int) ([]digest.Digest, error) { |
| r := rand.New(rand.NewSource(25823)) |
| digests := make([]digest.Digest, count) |
| for i := range digests { |
| h := sha256.New() |
| if err := binary.Write(h, binary.BigEndian, r.Int63()); err != nil { |
| return nil, err |
| } |
| digests[i] = digest.NewDigest("sha256", h) |
| } |
| return digests, nil |
| } |
| |
| func benchAddNTable(b *testing.B, n int) { |
| digests, err := createDigests(n) |
| if err != nil { |
| b.Fatal(err) |
| } |
| b.ResetTimer() |
| for i := 0; i < b.N; i++ { |
| dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))} |
| for j := range digests { |
| if err = dset.Add(digests[j]); err != nil { |
| b.Fatal(err) |
| } |
| } |
| } |
| } |
| |
| func benchLookupNTable(b *testing.B, n int, shortLen int) { |
| digests, err := createDigests(n) |
| if err != nil { |
| b.Fatal(err) |
| } |
| dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))} |
| for i := range digests { |
| if err := dset.Add(digests[i]); err != nil { |
| b.Fatal(err) |
| } |
| } |
| shorts := make([]string, 0, n) |
| for _, short := range ShortCodeTable(dset, shortLen) { |
| shorts = append(shorts, short) |
| } |
| |
| b.ResetTimer() |
| for i := 0; i < b.N; i++ { |
| if _, err = dset.Lookup(shorts[i%n]); err != nil { |
| b.Fatal(err) |
| } |
| } |
| } |
| |
| func benchRemoveNTable(b *testing.B, n int) { |
| digests, err := createDigests(n) |
| if err != nil { |
| b.Fatal(err) |
| } |
| b.ResetTimer() |
| for i := 0; i < b.N; i++ { |
| dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))} |
| b.StopTimer() |
| for j := range digests { |
| if err = dset.Add(digests[j]); err != nil { |
| b.Fatal(err) |
| } |
| } |
| b.StartTimer() |
| for j := range digests { |
| if err = dset.Remove(digests[j]); err != nil { |
| b.Fatal(err) |
| } |
| } |
| } |
| } |
| |
| func benchShortCodeNTable(b *testing.B, n int, shortLen int) { |
| digests, err := createDigests(n) |
| if err != nil { |
| b.Fatal(err) |
| } |
| dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))} |
| for i := range digests { |
| if err := dset.Add(digests[i]); err != nil { |
| b.Fatal(err) |
| } |
| } |
| |
| b.ResetTimer() |
| for i := 0; i < b.N; i++ { |
| ShortCodeTable(dset, shortLen) |
| } |
| } |
| |
| func BenchmarkAdd10(b *testing.B) { |
| benchAddNTable(b, 10) |
| } |
| |
| func BenchmarkAdd100(b *testing.B) { |
| benchAddNTable(b, 100) |
| } |
| |
| func BenchmarkAdd1000(b *testing.B) { |
| benchAddNTable(b, 1000) |
| } |
| |
| func BenchmarkRemove10(b *testing.B) { |
| benchRemoveNTable(b, 10) |
| } |
| |
| func BenchmarkRemove100(b *testing.B) { |
| benchRemoveNTable(b, 100) |
| } |
| |
| func BenchmarkRemove1000(b *testing.B) { |
| benchRemoveNTable(b, 1000) |
| } |
| |
| func BenchmarkLookup10(b *testing.B) { |
| benchLookupNTable(b, 10, 12) |
| } |
| |
| func BenchmarkLookup100(b *testing.B) { |
| benchLookupNTable(b, 100, 12) |
| } |
| |
| func BenchmarkLookup1000(b *testing.B) { |
| benchLookupNTable(b, 1000, 12) |
| } |
| |
| func BenchmarkShortCode10(b *testing.B) { |
| benchShortCodeNTable(b, 10, 12) |
| } |
| func BenchmarkShortCode100(b *testing.B) { |
| benchShortCodeNTable(b, 100, 12) |
| } |
| func BenchmarkShortCode1000(b *testing.B) { |
| benchShortCodeNTable(b, 1000, 12) |
| } |