github.com/npaton/distribution@v2.3.1-rc.0+incompatible/digest/set_test.go (about)

     1  package digest
     2  
     3  import (
     4  	"crypto/sha256"
     5  	"encoding/binary"
     6  	"math/rand"
     7  	"testing"
     8  )
     9  
    10  func assertEqualDigests(t *testing.T, d1, d2 Digest) {
    11  	if d1 != d2 {
    12  		t.Fatalf("Digests do not match:\n\tActual: %s\n\tExpected: %s", d1, d2)
    13  	}
    14  }
    15  
    16  func TestLookup(t *testing.T) {
    17  	digests := []Digest{
    18  		"sha256:1234511111111111111111111111111111111111111111111111111111111111",
    19  		"sha256:1234111111111111111111111111111111111111111111111111111111111111",
    20  		"sha256:1234611111111111111111111111111111111111111111111111111111111111",
    21  		"sha256:5432111111111111111111111111111111111111111111111111111111111111",
    22  		"sha256:6543111111111111111111111111111111111111111111111111111111111111",
    23  		"sha256:6432111111111111111111111111111111111111111111111111111111111111",
    24  		"sha256:6542111111111111111111111111111111111111111111111111111111111111",
    25  		"sha256:6532111111111111111111111111111111111111111111111111111111111111",
    26  	}
    27  
    28  	dset := NewSet()
    29  	for i := range digests {
    30  		if err := dset.Add(digests[i]); err != nil {
    31  			t.Fatal(err)
    32  		}
    33  	}
    34  
    35  	dgst, err := dset.Lookup("54")
    36  	if err != nil {
    37  		t.Fatal(err)
    38  	}
    39  	assertEqualDigests(t, dgst, digests[3])
    40  
    41  	dgst, err = dset.Lookup("1234")
    42  	if err == nil {
    43  		t.Fatal("Expected ambiguous error looking up: 1234")
    44  	}
    45  	if err != ErrDigestAmbiguous {
    46  		t.Fatal(err)
    47  	}
    48  
    49  	dgst, err = dset.Lookup("9876")
    50  	if err == nil {
    51  		t.Fatal("Expected ambiguous error looking up: 9876")
    52  	}
    53  	if err != ErrDigestNotFound {
    54  		t.Fatal(err)
    55  	}
    56  
    57  	dgst, err = dset.Lookup("sha256:1234")
    58  	if err == nil {
    59  		t.Fatal("Expected ambiguous error looking up: sha256:1234")
    60  	}
    61  	if err != ErrDigestAmbiguous {
    62  		t.Fatal(err)
    63  	}
    64  
    65  	dgst, err = dset.Lookup("sha256:12345")
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	assertEqualDigests(t, dgst, digests[0])
    70  
    71  	dgst, err = dset.Lookup("sha256:12346")
    72  	if err != nil {
    73  		t.Fatal(err)
    74  	}
    75  	assertEqualDigests(t, dgst, digests[2])
    76  
    77  	dgst, err = dset.Lookup("12346")
    78  	if err != nil {
    79  		t.Fatal(err)
    80  	}
    81  	assertEqualDigests(t, dgst, digests[2])
    82  
    83  	dgst, err = dset.Lookup("12345")
    84  	if err != nil {
    85  		t.Fatal(err)
    86  	}
    87  	assertEqualDigests(t, dgst, digests[0])
    88  }
    89  
    90  func TestAddDuplication(t *testing.T) {
    91  	digests := []Digest{
    92  		"sha256:1234111111111111111111111111111111111111111111111111111111111111",
    93  		"sha256:1234511111111111111111111111111111111111111111111111111111111111",
    94  		"sha256:1234611111111111111111111111111111111111111111111111111111111111",
    95  		"sha256:5432111111111111111111111111111111111111111111111111111111111111",
    96  		"sha256:6543111111111111111111111111111111111111111111111111111111111111",
    97  		"sha512:65431111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
    98  		"sha512:65421111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
    99  		"sha512:65321111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
   100  	}
   101  
   102  	dset := NewSet()
   103  	for i := range digests {
   104  		if err := dset.Add(digests[i]); err != nil {
   105  			t.Fatal(err)
   106  		}
   107  	}
   108  
   109  	if len(dset.entries) != 8 {
   110  		t.Fatal("Invalid dset size")
   111  	}
   112  
   113  	if err := dset.Add(Digest("sha256:1234511111111111111111111111111111111111111111111111111111111111")); err != nil {
   114  		t.Fatal(err)
   115  	}
   116  
   117  	if len(dset.entries) != 8 {
   118  		t.Fatal("Duplicate digest insert allowed")
   119  	}
   120  
   121  	if err := dset.Add(Digest("sha384:123451111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")); err != nil {
   122  		t.Fatal(err)
   123  	}
   124  
   125  	if len(dset.entries) != 9 {
   126  		t.Fatal("Insert with different algorithm not allowed")
   127  	}
   128  }
   129  
   130  func TestRemove(t *testing.T) {
   131  	digests, err := createDigests(10)
   132  	if err != nil {
   133  		t.Fatal(err)
   134  	}
   135  
   136  	dset := NewSet()
   137  	for i := range digests {
   138  		if err := dset.Add(digests[i]); err != nil {
   139  			t.Fatal(err)
   140  		}
   141  	}
   142  
   143  	dgst, err := dset.Lookup(digests[0].String())
   144  	if err != nil {
   145  		t.Fatal(err)
   146  	}
   147  	if dgst != digests[0] {
   148  		t.Fatalf("Unexpected digest value:\n\tExpected: %s\n\tActual: %s", digests[0], dgst)
   149  	}
   150  
   151  	if err := dset.Remove(digests[0]); err != nil {
   152  		t.Fatal(err)
   153  	}
   154  
   155  	if _, err := dset.Lookup(digests[0].String()); err != ErrDigestNotFound {
   156  		t.Fatalf("Expected error %v when looking up removed digest, got %v", ErrDigestNotFound, err)
   157  	}
   158  }
   159  
   160  func TestAll(t *testing.T) {
   161  	digests, err := createDigests(100)
   162  	if err != nil {
   163  		t.Fatal(err)
   164  	}
   165  
   166  	dset := NewSet()
   167  	for i := range digests {
   168  		if err := dset.Add(digests[i]); err != nil {
   169  			t.Fatal(err)
   170  		}
   171  	}
   172  
   173  	all := map[Digest]struct{}{}
   174  	for _, dgst := range dset.All() {
   175  		all[dgst] = struct{}{}
   176  	}
   177  
   178  	if len(all) != len(digests) {
   179  		t.Fatalf("Unexpected number of unique digests found:\n\tExpected: %d\n\tActual: %d", len(digests), len(all))
   180  	}
   181  
   182  	for i, dgst := range digests {
   183  		if _, ok := all[dgst]; !ok {
   184  			t.Fatalf("Missing element at position %d: %s", i, dgst)
   185  		}
   186  	}
   187  
   188  }
   189  
   190  func assertEqualShort(t *testing.T, actual, expected string) {
   191  	if actual != expected {
   192  		t.Fatalf("Unexpected short value:\n\tExpected: %s\n\tActual: %s", expected, actual)
   193  	}
   194  }
   195  
   196  func TestShortCodeTable(t *testing.T) {
   197  	digests := []Digest{
   198  		"sha256:1234111111111111111111111111111111111111111111111111111111111111",
   199  		"sha256:1234511111111111111111111111111111111111111111111111111111111111",
   200  		"sha256:1234611111111111111111111111111111111111111111111111111111111111",
   201  		"sha256:5432111111111111111111111111111111111111111111111111111111111111",
   202  		"sha256:6543111111111111111111111111111111111111111111111111111111111111",
   203  		"sha256:6432111111111111111111111111111111111111111111111111111111111111",
   204  		"sha256:6542111111111111111111111111111111111111111111111111111111111111",
   205  		"sha256:6532111111111111111111111111111111111111111111111111111111111111",
   206  	}
   207  
   208  	dset := NewSet()
   209  	for i := range digests {
   210  		if err := dset.Add(digests[i]); err != nil {
   211  			t.Fatal(err)
   212  		}
   213  	}
   214  
   215  	dump := ShortCodeTable(dset, 2)
   216  
   217  	if len(dump) < len(digests) {
   218  		t.Fatalf("Error unexpected size: %d, expecting %d", len(dump), len(digests))
   219  	}
   220  	assertEqualShort(t, dump[digests[0]], "12341")
   221  	assertEqualShort(t, dump[digests[1]], "12345")
   222  	assertEqualShort(t, dump[digests[2]], "12346")
   223  	assertEqualShort(t, dump[digests[3]], "54")
   224  	assertEqualShort(t, dump[digests[4]], "6543")
   225  	assertEqualShort(t, dump[digests[5]], "64")
   226  	assertEqualShort(t, dump[digests[6]], "6542")
   227  	assertEqualShort(t, dump[digests[7]], "653")
   228  }
   229  
   230  func createDigests(count int) ([]Digest, error) {
   231  	r := rand.New(rand.NewSource(25823))
   232  	digests := make([]Digest, count)
   233  	for i := range digests {
   234  		h := sha256.New()
   235  		if err := binary.Write(h, binary.BigEndian, r.Int63()); err != nil {
   236  			return nil, err
   237  		}
   238  		digests[i] = NewDigest("sha256", h)
   239  	}
   240  	return digests, nil
   241  }
   242  
   243  func benchAddNTable(b *testing.B, n int) {
   244  	digests, err := createDigests(n)
   245  	if err != nil {
   246  		b.Fatal(err)
   247  	}
   248  	b.ResetTimer()
   249  	for i := 0; i < b.N; i++ {
   250  		dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))}
   251  		for j := range digests {
   252  			if err = dset.Add(digests[j]); err != nil {
   253  				b.Fatal(err)
   254  			}
   255  		}
   256  	}
   257  }
   258  
   259  func benchLookupNTable(b *testing.B, n int, shortLen int) {
   260  	digests, err := createDigests(n)
   261  	if err != nil {
   262  		b.Fatal(err)
   263  	}
   264  	dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))}
   265  	for i := range digests {
   266  		if err := dset.Add(digests[i]); err != nil {
   267  			b.Fatal(err)
   268  		}
   269  	}
   270  	shorts := make([]string, 0, n)
   271  	for _, short := range ShortCodeTable(dset, shortLen) {
   272  		shorts = append(shorts, short)
   273  	}
   274  
   275  	b.ResetTimer()
   276  	for i := 0; i < b.N; i++ {
   277  		if _, err = dset.Lookup(shorts[i%n]); err != nil {
   278  			b.Fatal(err)
   279  		}
   280  	}
   281  }
   282  
   283  func benchRemoveNTable(b *testing.B, n int) {
   284  	digests, err := createDigests(n)
   285  	if err != nil {
   286  		b.Fatal(err)
   287  	}
   288  	b.ResetTimer()
   289  	for i := 0; i < b.N; i++ {
   290  		dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))}
   291  		b.StopTimer()
   292  		for j := range digests {
   293  			if err = dset.Add(digests[j]); err != nil {
   294  				b.Fatal(err)
   295  			}
   296  		}
   297  		b.StartTimer()
   298  		for j := range digests {
   299  			if err = dset.Remove(digests[j]); err != nil {
   300  				b.Fatal(err)
   301  			}
   302  		}
   303  	}
   304  }
   305  
   306  func benchShortCodeNTable(b *testing.B, n int, shortLen int) {
   307  	digests, err := createDigests(n)
   308  	if err != nil {
   309  		b.Fatal(err)
   310  	}
   311  	dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))}
   312  	for i := range digests {
   313  		if err := dset.Add(digests[i]); err != nil {
   314  			b.Fatal(err)
   315  		}
   316  	}
   317  
   318  	b.ResetTimer()
   319  	for i := 0; i < b.N; i++ {
   320  		ShortCodeTable(dset, shortLen)
   321  	}
   322  }
   323  
   324  func BenchmarkAdd10(b *testing.B) {
   325  	benchAddNTable(b, 10)
   326  }
   327  
   328  func BenchmarkAdd100(b *testing.B) {
   329  	benchAddNTable(b, 100)
   330  }
   331  
   332  func BenchmarkAdd1000(b *testing.B) {
   333  	benchAddNTable(b, 1000)
   334  }
   335  
   336  func BenchmarkRemove10(b *testing.B) {
   337  	benchRemoveNTable(b, 10)
   338  }
   339  
   340  func BenchmarkRemove100(b *testing.B) {
   341  	benchRemoveNTable(b, 100)
   342  }
   343  
   344  func BenchmarkRemove1000(b *testing.B) {
   345  	benchRemoveNTable(b, 1000)
   346  }
   347  
   348  func BenchmarkLookup10(b *testing.B) {
   349  	benchLookupNTable(b, 10, 12)
   350  }
   351  
   352  func BenchmarkLookup100(b *testing.B) {
   353  	benchLookupNTable(b, 100, 12)
   354  }
   355  
   356  func BenchmarkLookup1000(b *testing.B) {
   357  	benchLookupNTable(b, 1000, 12)
   358  }
   359  
   360  func BenchmarkShortCode10(b *testing.B) {
   361  	benchShortCodeNTable(b, 10, 12)
   362  }
   363  func BenchmarkShortCode100(b *testing.B) {
   364  	benchShortCodeNTable(b, 100, 12)
   365  }
   366  func BenchmarkShortCode1000(b *testing.B) {
   367  	benchShortCodeNTable(b, 1000, 12)
   368  }