Skip to content

Commit 1f8b78b

Browse files
HTTP Fetcher: Fix tests for digest function changes
These changes should make the tests less brittle, because it stops us needlessly mocking the io.ReadCloser we pass around. Instead we pass a buffer of the actual test data.
1 parent 00efe71 commit 1f8b78b

File tree

1 file changed

+64
-59
lines changed

1 file changed

+64
-59
lines changed

pkg/fetch/http_fetcher_test.go

Lines changed: 64 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package fetch_test
22

33
import (
4+
"bytes"
45
"context"
6+
"encoding/base64"
57
"fmt"
68
"io"
79
"net/http"
@@ -10,7 +12,7 @@ import (
1012
"github.com/buildbarn/bb-remote-asset/internal/mock"
1113
"github.com/buildbarn/bb-remote-asset/pkg/fetch"
1214
"github.com/buildbarn/bb-remote-asset/pkg/qualifier"
13-
bb_digest "github.com/buildbarn/bb-storage/pkg/digest"
15+
"github.com/buildbarn/bb-storage/pkg/digest"
1416
"github.com/buildbarn/bb-storage/pkg/testutil"
1517

1618
remoteasset "github.com/bazelbuild/remote-apis/build/bazel/remote/asset/v1"
@@ -50,85 +52,97 @@ func (hm *headerMatcher) Matches(x interface{}) bool {
5052
return true
5153
}
5254

55+
// Instance name used in the test
56+
const InstanceName = ""
57+
58+
// Data used as the blob
59+
const TestData = "Hello"
60+
61+
// Convert DigestFunction Enum to strings
62+
var HashNames = map[remoteexecution.DigestFunction_Value]string{
63+
remoteexecution.DigestFunction_SHA256: "sha256",
64+
remoteexecution.DigestFunction_SHA1: "sha1",
65+
remoteexecution.DigestFunction_MD5: "md5",
66+
remoteexecution.DigestFunction_SHA384: "sha384",
67+
remoteexecution.DigestFunction_SHA512: "sha512",
68+
remoteexecution.DigestFunction_SHA256TREE: "sha256tree",
69+
}
70+
71+
// Convert a Digest to the representation used by checksum.sri qualifiers. Note,
72+
// df must match the value used by d
73+
func digestToChecksumSri(df remoteexecution.DigestFunction_Value, d digest.Digest) string {
74+
return fmt.Sprintf("%s-%s", HashNames[df], base64.StdEncoding.EncodeToString(d.GetHashBytes()))
75+
}
76+
5377
func TestHTTPFetcherFetchBlobSuccessSHA256(t *testing.T) {
5478
testHTTPFetcherFetchBlobSuccessWithHasher(
5579
t,
5680
remoteexecution.DigestFunction_SHA256,
57-
"185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969",
58-
"sha256-GF+NsyJx/iX1Yab8k4suJkMG7DBO2lGAB9F2SCY4GWk=",
5981
)
6082
}
6183

6284
func TestHTTPFetcherFetchBlobSuccessSHA1(t *testing.T) {
6385
testHTTPFetcherFetchBlobSuccessWithHasher(
6486
t,
6587
remoteexecution.DigestFunction_SHA1,
66-
"f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0",
67-
"sha1-9/+ei3uy4Jtwk1pdeF4MxdnQq/A=",
6888
)
6989
}
7090

7191
func TestHTTPFetcherFetchBlobSuccessMD5(t *testing.T) {
7292
testHTTPFetcherFetchBlobSuccessWithHasher(
7393
t,
7494
remoteexecution.DigestFunction_MD5,
75-
"8b1a9953c4611296a827abf8c47804d7",
76-
"md5-ixqZU8RhEpaoJ6v4xHgE1w==",
7795
)
7896
}
7997

8098
func TestHTTPFetcherFetchBlobSuccessSHA384(t *testing.T) {
8199
testHTTPFetcherFetchBlobSuccessWithHasher(
82100
t,
83101
remoteexecution.DigestFunction_SHA384,
84-
"3519fe5ad2c596efe3e276a6f351b8fc0b03db861782490d45f7598ebd0ab5fd5520ed102f38c4a5ec834e98668035fc",
85-
"sha384-NRn+WtLFlu/j4nam81G4/AsD24YXgkkNRfdZjr0Ktf1VIO0QLzjEpeyDTphmgDX8",
86102
)
87103
}
88104

89105
func TestHTTPFetcherFetchBlobSuccessSHA512(t *testing.T) {
90106
testHTTPFetcherFetchBlobSuccessWithHasher(
91107
t,
92108
remoteexecution.DigestFunction_SHA512,
93-
"3615f80c9d293ed7402687f94b22d58e529b8cc7916f8fac7fddf7fbd5af4cf777d3d795a7a00a16bf7e7f3fb9561ee9baae480da9fe7a18769e71886b03f315",
94-
"sha512-NhX4DJ0pPtdAJof5SyLVjlKbjMeRb4+sf933+9WvTPd309eVp6AKFr9+fz+5Vh7puq5IDan+ehh2nnGIawPzFQ==",
95109
)
96110
}
97111

98112
func TestHTTPFetcherFetchBlobSuccessSha256tree(t *testing.T) {
99113
testHTTPFetcherFetchBlobSuccessWithHasher(
100114
t,
101115
remoteexecution.DigestFunction_SHA256TREE,
102-
"35b974ff55d4c41ca000ea35b974ff55d4c41ca000eacf29125544cf29125544",
103-
"sha256tree-Nbl0/1XUxBygAOo1uXT/VdTEHKAA6s8pElVEzykSVUQ=",
104116
)
105117
}
106118

107-
func testHTTPFetcherFetchBlobSuccessWithHasher(t *testing.T, digestFunctionEnum remoteexecution.DigestFunction_Value, hexHash, sriChecksum string) {
119+
func testHTTPFetcherFetchBlobSuccessWithHasher(t *testing.T, digestFunctionEnum remoteexecution.DigestFunction_Value) {
108120
ctrl, ctx := gomock.WithContext(context.Background(), t)
109121

122+
instance := digest.MustNewInstanceName(InstanceName)
123+
digestFunction, err := instance.GetDigestFunction(digestFunctionEnum, 0)
124+
require.NoError(t, err)
125+
digestGenerator := digestFunction.NewGenerator(int64(len(TestData)))
126+
digestGenerator.Write([]byte(TestData))
127+
helloDigest := digestGenerator.Sum()
128+
110129
request := &remoteasset.FetchBlobRequest{
111-
InstanceName: "",
130+
InstanceName: InstanceName,
112131
Uris: []string{"www.example.com"},
113132
Qualifiers: []*remoteasset.Qualifier{
114133
{
115134
Name: "checksum.sri",
116-
Value: sriChecksum,
135+
Value: digestToChecksumSri(digestFunctionEnum, helloDigest),
117136
},
118137
},
138+
DigestFunction: digestFunctionEnum,
119139
}
120140
casBlobAccess := mock.NewMockBlobAccess(ctrl)
121141
roundTripper := mock.NewMockRoundTripper(ctrl)
122142
HTTPFetcher := fetch.NewHTTPFetcher(&http.Client{Transport: roundTripper}, casBlobAccess)
123-
body := mock.NewMockReadCloser(ctrl)
124-
helloDigest := bb_digest.MustNewDigest(
125-
"",
126-
digestFunctionEnum,
127-
hexHash,
128-
5,
129-
)
130143

131144
t.Run("Success"+helloDigest.GetDigestFunction().GetEnumValue().String(), func(t *testing.T) {
145+
body := io.NopCloser(bytes.NewBuffer([]byte(TestData)))
132146
httpDoCall := roundTripper.EXPECT().RoundTrip(gomock.Any()).Return(&http.Response{
133147
Status: "200 Success",
134148
StatusCode: 200,
@@ -144,18 +158,14 @@ func testHTTPFetcherFetchBlobSuccessWithHasher(t *testing.T, digestFunctionEnum
144158
})
145159

146160
t.Run("SuccessNoContentLength", func(t *testing.T) {
147-
httpDoCall := roundTripper.EXPECT().RoundTrip(gomock.Any()).Return(&http.Response{
161+
body := io.NopCloser(bytes.NewBuffer([]byte(TestData)))
162+
roundTripper.EXPECT().RoundTrip(gomock.Any()).Return(&http.Response{
148163
Status: "200 Success",
149164
StatusCode: 200,
150165
Body: body,
151166
ContentLength: -1,
152167
}, nil)
153-
bodyReadCall := body.EXPECT().Read(gomock.Any()).DoAndReturn(func(p []byte) (int, error) {
154-
copy(p, "Hello")
155-
return 5, io.EOF
156-
}).After(httpDoCall)
157-
bodyCloseCall := body.EXPECT().Close().Return(nil).After(bodyReadCall)
158-
casBlobAccess.EXPECT().Put(ctx, helloDigest, gomock.Any()).Return(nil).After(bodyCloseCall)
168+
casBlobAccess.EXPECT().Put(ctx, helloDigest, gomock.Any()).Return(nil)
159169

160170
response, err := HTTPFetcher.FetchBlob(ctx, request)
161171
require.NoError(t, err)
@@ -167,31 +177,32 @@ func testHTTPFetcherFetchBlobSuccessWithHasher(t *testing.T, digestFunctionEnum
167177
func TestHTTPFetcherFetchBlob(t *testing.T) {
168178
ctrl, ctx := gomock.WithContext(context.Background(), t)
169179

180+
instance := digest.MustNewInstanceName(InstanceName)
181+
digestFunction, err := instance.GetDigestFunction(remoteexecution.DigestFunction_SHA256, 0)
182+
require.NoError(t, err)
183+
digestGenerator := digestFunction.NewGenerator(int64(len(TestData)))
184+
digestGenerator.Write([]byte(TestData))
185+
helloDigest := digestGenerator.Sum()
186+
170187
uri := "www.example.com"
171188
request := &remoteasset.FetchBlobRequest{
172-
InstanceName: "",
189+
InstanceName: InstanceName,
173190
Uris: []string{uri, "www.another.com"},
174191
Qualifiers: []*remoteasset.Qualifier{
175192
{
176193
Name: "checksum.sri",
177-
Value: "sha256-GF+NsyJx/iX1Yab8k4suJkMG7DBO2lGAB9F2SCY4GWk=",
194+
Value: digestToChecksumSri(remoteexecution.DigestFunction_SHA256, helloDigest),
178195
},
179196
},
180197
}
181198
casBlobAccess := mock.NewMockBlobAccess(ctrl)
182199
roundTripper := mock.NewMockRoundTripper(ctrl)
183200
HTTPFetcher := fetch.NewHTTPFetcher(&http.Client{Transport: roundTripper}, casBlobAccess)
184-
body := mock.NewMockReadCloser(ctrl)
185-
helloDigest := bb_digest.MustNewDigest(
186-
"",
187-
remoteexecution.DigestFunction_SHA256,
188-
"185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969",
189-
5,
190-
)
191201

192202
t.Run("SuccessNoExpectedDigest", func(t *testing.T) {
203+
body := io.NopCloser(bytes.NewBuffer([]byte(TestData)))
193204
request := &remoteasset.FetchBlobRequest{
194-
InstanceName: "",
205+
InstanceName: InstanceName,
195206
Uris: []string{uri, "www.another.com"},
196207
Qualifiers: []*remoteasset.Qualifier{},
197208
}
@@ -201,12 +212,7 @@ func TestHTTPFetcherFetchBlob(t *testing.T) {
201212
Body: body,
202213
ContentLength: 5,
203214
}, nil)
204-
bodyReadCall := body.EXPECT().Read(gomock.Any()).DoAndReturn(func(p []byte) (int, error) {
205-
copy(p, "Hello")
206-
return 5, io.EOF
207-
}).After(httpDoCall)
208-
bodyCloseCall := body.EXPECT().Close().Return(nil).After(bodyReadCall)
209-
casBlobAccess.EXPECT().Put(ctx, helloDigest, gomock.Any()).Return(nil).After(bodyCloseCall)
215+
casBlobAccess.EXPECT().Put(ctx, helloDigest, gomock.Any()).Return(nil).After(httpDoCall)
210216

211217
response, err := HTTPFetcher.FetchBlob(ctx, request)
212218
require.NoError(t, err)
@@ -215,8 +221,9 @@ func TestHTTPFetcherFetchBlob(t *testing.T) {
215221
})
216222

217223
t.Run("SuccessNoExpectedDigestOrContentLength", func(t *testing.T) {
224+
body := io.NopCloser(bytes.NewBuffer([]byte(TestData)))
218225
request := &remoteasset.FetchBlobRequest{
219-
InstanceName: "",
226+
InstanceName: InstanceName,
220227
Uris: []string{uri, "www.another.com"},
221228
Qualifiers: []*remoteasset.Qualifier{},
222229
}
@@ -226,12 +233,7 @@ func TestHTTPFetcherFetchBlob(t *testing.T) {
226233
Body: body,
227234
ContentLength: -1,
228235
}, nil)
229-
bodyReadCall := body.EXPECT().Read(gomock.Any()).DoAndReturn(func(p []byte) (int, error) {
230-
copy(p, "Hello")
231-
return 5, io.EOF
232-
}).After(httpDoCall)
233-
bodyCloseCall := body.EXPECT().Close().Return(nil).After(bodyReadCall)
234-
casBlobAccess.EXPECT().Put(ctx, helloDigest, gomock.Any()).Return(nil).After(bodyCloseCall)
236+
casBlobAccess.EXPECT().Put(ctx, helloDigest, gomock.Any()).Return(nil).After(httpDoCall)
235237

236238
response, err := HTTPFetcher.FetchBlob(ctx, request)
237239
require.NoError(t, err)
@@ -241,7 +243,7 @@ func TestHTTPFetcherFetchBlob(t *testing.T) {
241243

242244
t.Run("UnknownChecksumSriAlgo", func(t *testing.T) {
243245
request := &remoteasset.FetchBlobRequest{
244-
InstanceName: "",
246+
InstanceName: InstanceName,
245247
Uris: []string{uri, "www.another.com"},
246248
Qualifiers: []*remoteasset.Qualifier{
247249
{
@@ -258,7 +260,7 @@ func TestHTTPFetcherFetchBlob(t *testing.T) {
258260

259261
t.Run("BadChecksumSriAlgo", func(t *testing.T) {
260262
request := &remoteasset.FetchBlobRequest{
261-
InstanceName: "",
263+
InstanceName: InstanceName,
262264
Uris: []string{uri, "www.another.com"},
263265
Qualifiers: []*remoteasset.Qualifier{
264266
{
@@ -275,7 +277,7 @@ func TestHTTPFetcherFetchBlob(t *testing.T) {
275277

276278
t.Run("BadChecksumSriBase64Value", func(t *testing.T) {
277279
request := &remoteasset.FetchBlobRequest{
278-
InstanceName: "",
280+
InstanceName: InstanceName,
279281
Uris: []string{uri, "www.another.com"},
280282
Qualifiers: []*remoteasset.Qualifier{
281283
{
@@ -295,6 +297,7 @@ func TestHTTPFetcherFetchBlob(t *testing.T) {
295297
Status: "404 Not Found",
296298
StatusCode: 404,
297299
}, nil)
300+
body := io.NopCloser(bytes.NewBuffer([]byte(TestData)))
298301
httpSuccessCall := roundTripper.EXPECT().RoundTrip(gomock.Any()).Return(&http.Response{
299302
Status: "200 Success",
300303
StatusCode: 200,
@@ -322,7 +325,7 @@ func TestHTTPFetcherFetchBlob(t *testing.T) {
322325

323326
t.Run("WithLegacyAuthHeaders", func(t *testing.T) {
324327
request := &remoteasset.FetchBlobRequest{
325-
InstanceName: "",
328+
InstanceName: InstanceName,
326329
Uris: []string{uri},
327330
Qualifiers: []*remoteasset.Qualifier{
328331
{
@@ -331,7 +334,7 @@ func TestHTTPFetcherFetchBlob(t *testing.T) {
331334
},
332335
{
333336
Name: "checksum.sri",
334-
Value: "sha256-GF+NsyJx/iX1Yab8k4suJkMG7DBO2lGAB9F2SCY4GWk=",
337+
Value: digestToChecksumSri(remoteexecution.DigestFunction_SHA256, helloDigest),
335338
},
336339
},
337340
}
@@ -341,6 +344,7 @@ func TestHTTPFetcherFetchBlob(t *testing.T) {
341344
"Authorization": "Bearer letmein",
342345
},
343346
}
347+
body := io.NopCloser(bytes.NewBuffer([]byte(TestData)))
344348
httpDoCall := roundTripper.EXPECT().RoundTrip(matcher).Return(&http.Response{
345349
Status: "200 Success",
346350
StatusCode: 200,
@@ -374,7 +378,7 @@ func TestHTTPFetcherFetchBlob(t *testing.T) {
374378
},
375379
{
376380
Name: "checksum.sri",
377-
Value: "sha256-GF+NsyJx/iX1Yab8k4suJkMG7DBO2lGAB9F2SCY4GWk=",
381+
Value: digestToChecksumSri(remoteexecution.DigestFunction_SHA256, helloDigest),
378382
},
379383
},
380384
}
@@ -395,6 +399,7 @@ func TestHTTPFetcherFetchBlob(t *testing.T) {
395399
Status: "404 NotFound",
396400
StatusCode: 404,
397401
}, nil)
402+
body := io.NopCloser(bytes.NewBuffer([]byte(TestData)))
398403
httpDoCall2 := roundTripper.EXPECT().RoundTrip(matcherReq2).Return(&http.Response{
399404
Status: "200 Success",
400405
StatusCode: 200,

0 commit comments

Comments
 (0)