github.com/uber/kraken@v0.1.4/lib/dockerregistry/transfer/rw_transferer_test.go (about) 1 // Copyright (c) 2016-2019 Uber Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 package transfer 15 16 import ( 17 "bytes" 18 "errors" 19 "io/ioutil" 20 "testing" 21 22 "github.com/uber/kraken/build-index/tagclient" 23 "github.com/uber/kraken/core" 24 "github.com/uber/kraken/lib/store" 25 "github.com/uber/kraken/mocks/build-index/tagclient" 26 "github.com/uber/kraken/mocks/origin/blobclient" 27 "github.com/uber/kraken/utils/dockerutil" 28 "github.com/uber/kraken/utils/mockutil" 29 "github.com/uber/kraken/utils/testutil" 30 31 "github.com/golang/mock/gomock" 32 "github.com/stretchr/testify/require" 33 "github.com/uber-go/tally" 34 ) 35 36 type proxyTransfererMocks struct { 37 tags *mocktagclient.MockClient 38 originCluster *mockblobclient.MockClusterClient 39 cas *store.CAStore 40 } 41 42 func newReadWriteTransfererMocks(t *testing.T) (*proxyTransfererMocks, func()) { 43 var cleanup testutil.Cleanup 44 45 ctrl := gomock.NewController(t) 46 cleanup.Add(ctrl.Finish) 47 48 tags := mocktagclient.NewMockClient(ctrl) 49 50 originCluster := mockblobclient.NewMockClusterClient(ctrl) 51 52 cas, c := store.CAStoreFixture() 53 cleanup.Add(c) 54 55 return &proxyTransfererMocks{tags, originCluster, cas}, cleanup.Run 56 } 57 58 func (m *proxyTransfererMocks) new() *ReadWriteTransferer { 59 return NewReadWriteTransferer(tally.NoopScope, m.tags, m.originCluster, m.cas) 60 } 61 62 func TestReadWriteTransfererDownloadCachesBlob(t *testing.T) { 63 require := require.New(t) 64 65 mocks, cleanup := newReadWriteTransfererMocks(t) 66 defer cleanup() 67 68 transferer := mocks.new() 69 70 namespace := "docker/test-image" 71 blob := core.NewBlobFixture() 72 73 mocks.originCluster.EXPECT().DownloadBlob( 74 namespace, blob.Digest, mockutil.MatchWriter(blob.Content)).Return(nil) 75 76 // Downloading multiple times should only call blob download once. 77 for i := 0; i < 10; i++ { 78 result, err := transferer.Download(namespace, blob.Digest) 79 require.NoError(err) 80 b, err := ioutil.ReadAll(result) 81 require.NoError(err) 82 require.Equal(blob.Content, b) 83 } 84 } 85 86 func TestReadWriteTransfererGetTag(t *testing.T) { 87 require := require.New(t) 88 89 mocks, cleanup := newReadWriteTransfererMocks(t) 90 defer cleanup() 91 92 transferer := mocks.new() 93 94 tag := "docker/some-tag" 95 manifest := core.DigestFixture() 96 97 mocks.tags.EXPECT().Get(tag).Return(manifest, nil) 98 99 d, err := transferer.GetTag(tag) 100 require.NoError(err) 101 require.Equal(manifest, d) 102 } 103 104 func TestReadWriteTransfererGetTagNotFound(t *testing.T) { 105 require := require.New(t) 106 107 mocks, cleanup := newReadWriteTransfererMocks(t) 108 defer cleanup() 109 110 transferer := mocks.new() 111 112 tag := "docker/some-tag" 113 114 mocks.tags.EXPECT().Get(tag).Return(core.Digest{}, tagclient.ErrTagNotFound) 115 116 _, err := transferer.GetTag(tag) 117 require.Error(err) 118 require.Equal(ErrTagNotFound, err) 119 } 120 121 func TestReadWriteTransfererPutTag(t *testing.T) { 122 require := require.New(t) 123 124 mocks, cleanup := newReadWriteTransfererMocks(t) 125 defer cleanup() 126 127 transferer := mocks.new() 128 129 config := core.DigestFixture() 130 layer1 := core.DigestFixture() 131 layer2 := core.DigestFixture() 132 133 manifestDigest, rawManifest := dockerutil.ManifestFixture(config, layer1, layer2) 134 135 require.NoError(mocks.cas.CreateCacheFile(manifestDigest.Hex(), bytes.NewReader(rawManifest))) 136 137 tag := "docker/some-tag" 138 139 mocks.tags.EXPECT().PutAndReplicate(tag, manifestDigest).Return(nil) 140 141 require.NoError(transferer.PutTag(tag, manifestDigest)) 142 } 143 144 func TestReadWriteTransfererStatLocalBlob(t *testing.T) { 145 require := require.New(t) 146 147 mocks, cleanup := newReadWriteTransfererMocks(t) 148 defer cleanup() 149 150 transferer := mocks.new() 151 152 namespace := "docker/test-image" 153 blob := core.NewBlobFixture() 154 155 require.NoError(mocks.cas.CreateCacheFile(blob.Digest.Hex(), bytes.NewReader(blob.Content))) 156 157 bi, err := transferer.Stat(namespace, blob.Digest) 158 require.NoError(err) 159 require.Equal(blob.Info(), bi) 160 } 161 162 func TestReadWriteTransfererStatRemoteBlob(t *testing.T) { 163 require := require.New(t) 164 165 mocks, cleanup := newReadWriteTransfererMocks(t) 166 defer cleanup() 167 168 transferer := mocks.new() 169 170 namespace := "docker/test-image" 171 blob := core.NewBlobFixture() 172 173 mocks.originCluster.EXPECT().Stat(namespace, blob.Digest).Return(blob.Info(), nil) 174 175 bi, err := transferer.Stat(namespace, blob.Digest) 176 require.NoError(err) 177 require.Equal(blob.Info(), bi) 178 } 179 180 func TestReadWriteTransfererStatNotFoundOnAnyOriginError(t *testing.T) { 181 require := require.New(t) 182 183 mocks, cleanup := newReadWriteTransfererMocks(t) 184 defer cleanup() 185 186 transferer := mocks.new() 187 188 namespace := "docker/test-image" 189 blob := core.NewBlobFixture() 190 191 mocks.originCluster.EXPECT().Stat(namespace, blob.Digest).Return(nil, errors.New("any error")) 192 193 _, err := transferer.Stat(namespace, blob.Digest) 194 require.Equal(ErrBlobNotFound, err) 195 }