Merge pull request #3775 from thaJeztah/remove_digestset
						commit
						9bb63e6e46
					
				|  | @ -0,0 +1,51 @@ | |||
| package digestset | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/opencontainers/go-digest" | ||||
| 	"github.com/opencontainers/go-digest/digestset" | ||||
| ) | ||||
| 
 | ||||
| // ErrDigestNotFound is used when a matching digest
 | ||||
| // could not be found in a set.
 | ||||
| //
 | ||||
| // Deprecated: use [digestset.ErrDigestNotFound].
 | ||||
| var ErrDigestNotFound = digestset.ErrDigestNotFound | ||||
| 
 | ||||
| // ErrDigestAmbiguous is used when multiple digests
 | ||||
| // are found in a set. None of the matching digests
 | ||||
| // should be considered valid matches.
 | ||||
| //
 | ||||
| // Deprecated: use [digestset.ErrDigestAmbiguous].
 | ||||
| var ErrDigestAmbiguous = digestset.ErrDigestAmbiguous | ||||
| 
 | ||||
| // Set is used to hold a unique set of digests which
 | ||||
| // may be easily referenced by a string
 | ||||
| // representation of the digest as well as short representation.
 | ||||
| // The uniqueness of the short representation is based on other
 | ||||
| // digests in the set. If digests are omitted from this set,
 | ||||
| // collisions in a larger set may not be detected, therefore it
 | ||||
| // is important to always do short representation lookups on
 | ||||
| // the complete set of digests. To mitigate collisions, an
 | ||||
| // appropriately long short code should be used.
 | ||||
| //
 | ||||
| // Deprecated: use [digestset.Set].
 | ||||
| type Set = digestset.Set | ||||
| 
 | ||||
| // NewSet creates an empty set of digests
 | ||||
| // which may have digests added.
 | ||||
| //
 | ||||
| // Deprecated: use [digestset.NewSet].
 | ||||
| func NewSet() *digestset.Set { | ||||
| 	return digestset.NewSet() | ||||
| } | ||||
| 
 | ||||
| // ShortCodeTable returns a map of Digest to unique short codes. The
 | ||||
| // length represents the minimum value, the maximum length may be the
 | ||||
| // entire value of digest if uniqueness cannot be achieved without the
 | ||||
| // full value. This function will attempt to make short codes as short
 | ||||
| // as possible to be unique.
 | ||||
| //
 | ||||
| // Deprecated: use [digestset.ShortCodeTable].
 | ||||
| func ShortCodeTable(dst *digestset.Set, length int) map[digest.Digest]string { | ||||
| 	return digestset.ShortCodeTable(dst, length) | ||||
| } | ||||
|  | @ -1,372 +0,0 @@ | |||
| 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) | ||||
| } | ||||
							
								
								
									
										15
									
								
								digestset/set.go → vendor/github.com/opencontainers/go-digest/digestset/set.go
								
								
									generated
								
								
									vendored
								
								
							
							
						
						
									
										15
									
								
								digestset/set.go → vendor/github.com/opencontainers/go-digest/digestset/set.go
								
								
									generated
								
								
									vendored
								
								
							|  | @ -1,3 +1,18 @@ | |||
| // Copyright 2020, 2020 OCI Contributors
 | ||||
| // Copyright 2017 Docker, Inc.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //     https://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| package digestset | ||||
| 
 | ||||
| import ( | ||||
|  | @ -181,6 +181,7 @@ github.com/ncw/swift/swifttest | |||
| # github.com/opencontainers/go-digest v1.0.0 | ||||
| ## explicit; go 1.13 | ||||
| github.com/opencontainers/go-digest | ||||
| github.com/opencontainers/go-digest/digestset | ||||
| # github.com/opencontainers/image-spec v1.0.2 | ||||
| ## explicit | ||||
| github.com/opencontainers/image-spec/specs-go | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue