11package fetch_test
22
33import (
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+
5377func TestHTTPFetcherFetchBlobSuccessSHA256 (t * testing.T ) {
5478 testHTTPFetcherFetchBlobSuccessWithHasher (
5579 t ,
5680 remoteexecution .DigestFunction_SHA256 ,
57- "185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969" ,
58- "sha256-GF+NsyJx/iX1Yab8k4suJkMG7DBO2lGAB9F2SCY4GWk=" ,
5981 )
6082}
6183
6284func TestHTTPFetcherFetchBlobSuccessSHA1 (t * testing.T ) {
6385 testHTTPFetcherFetchBlobSuccessWithHasher (
6486 t ,
6587 remoteexecution .DigestFunction_SHA1 ,
66- "f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0" ,
67- "sha1-9/+ei3uy4Jtwk1pdeF4MxdnQq/A=" ,
6888 )
6989}
7090
7191func TestHTTPFetcherFetchBlobSuccessMD5 (t * testing.T ) {
7292 testHTTPFetcherFetchBlobSuccessWithHasher (
7393 t ,
7494 remoteexecution .DigestFunction_MD5 ,
75- "8b1a9953c4611296a827abf8c47804d7" ,
76- "md5-ixqZU8RhEpaoJ6v4xHgE1w==" ,
7795 )
7896}
7997
8098func TestHTTPFetcherFetchBlobSuccessSHA384 (t * testing.T ) {
8199 testHTTPFetcherFetchBlobSuccessWithHasher (
82100 t ,
83101 remoteexecution .DigestFunction_SHA384 ,
84- "3519fe5ad2c596efe3e276a6f351b8fc0b03db861782490d45f7598ebd0ab5fd5520ed102f38c4a5ec834e98668035fc" ,
85- "sha384-NRn+WtLFlu/j4nam81G4/AsD24YXgkkNRfdZjr0Ktf1VIO0QLzjEpeyDTphmgDX8" ,
86102 )
87103}
88104
89105func 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
98112func 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
167177func 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