@@ -238,6 +238,119 @@ public function testRetryOptionsPassing()
238238 $ this ->assertTrue ($ retryListenerCalled );
239239 }
240240
241+ public function testUploadSendsGoogHashOnFinalChunk ()
242+ {
243+ $ hashValue = 'crc32c=abc123 ' ;
244+ $ resumeUri = 'http://some-resume-uri.example.com ' ;
245+
246+ $ this ->requestWrapper ->send (
247+ Argument::which ('getMethod ' , 'POST ' ),
248+ Argument::type ('array ' )
249+ )->willReturn (new Response (200 , ['Location ' => $ resumeUri ]));
250+
251+ $ this ->requestWrapper ->send (
252+ Argument::that (function (RequestInterface $ request ) use ($ hashValue ) {
253+ return $ request ->getHeaderLine ('X-Goog-Hash ' ) === $ hashValue ;
254+ }),
255+ Argument::type ('array ' )
256+ )->willReturn (new Response (200 , [], $ this ->successBody ));
257+
258+ $ uploader = new ResumableUploader (
259+ $ this ->requestWrapper ->reveal (),
260+ $ this ->stream ,
261+ 'http://www.example.com ' ,
262+ [
263+ 'restOptions ' => [
264+ 'headers ' => ['X-Goog-Hash ' => $ hashValue ]
265+ ]
266+ ]
267+ );
268+
269+ $ this ->assertEquals (json_decode ($ this ->successBody , true ), $ uploader ->upload ());
270+ }
271+
272+ public function testUploadDoesNotSendGoogHashOnIntermediateChunk ()
273+ {
274+ $ hashValue = 'crc32c=abc123 ' ;
275+ $ resumeUri = 'http://some-resume-uri.example.com ' ;
276+
277+ $ this ->requestWrapper ->send (
278+ Argument::which ('getMethod ' , 'POST ' ),
279+ Argument::type ('array ' )
280+ )->willReturn (new Response (200 , ['Location ' => $ resumeUri ]));
281+
282+ $ this ->requestWrapper ->send (
283+ Argument::that (function (RequestInterface $ request ) {
284+ return $ request ->getHeaderLine ('Content-Range ' ) === 'bytes 0-1/4 '
285+ && !$ request ->hasHeader ('X-Goog-Hash ' );
286+ }),
287+ Argument::type ('array ' )
288+ )->willReturn (new Response (308 , ['Range ' => 'bytes 0-1 ' ]));
289+
290+ $ this ->requestWrapper ->send (
291+ Argument::that (function (RequestInterface $ request ) {
292+ return $ request ->getHeaderLine ('Content-Range ' ) === 'bytes 2-3/4 ' ;
293+ }),
294+ Argument::type ('array ' )
295+ )->willReturn (new Response (200 , [], $ this ->successBody ));
296+
297+ $ uploader = new ResumableUploader (
298+ $ this ->requestWrapper ->reveal (),
299+ $ this ->stream , // size 4
300+ 'http://www.example.com ' ,
301+ [
302+ 'chunkSize ' => 2 , // Force multi-chunk upload
303+ 'restOptions ' => [
304+ 'headers ' => ['X-Goog-Hash ' => $ hashValue ]
305+ ]
306+ ]
307+ );
308+
309+ $ this ->assertEquals (json_decode ($ this ->successBody , true ), $ uploader ->upload ());
310+ }
311+
312+ public function testGoogHashOnlyOnFinalChunkOfMultiChunkUpload ()
313+ {
314+ $ hashValue = 'crc32c=abc123 ' ;
315+ $ resumeUri = 'http://some-resume-uri.example.com ' ;
316+ $ this ->stream = Utils::streamFor ('01234567 ' ); // 8 bytes total
317+
318+ $ this ->requestWrapper ->send (
319+ Argument::which ('getMethod ' , 'POST ' ),
320+ Argument::type ('array ' )
321+ )->willReturn (new Response (200 , ['Location ' => $ resumeUri ]));
322+
323+ $ this ->requestWrapper ->send (
324+ Argument::that (function (RequestInterface $ request ) {
325+ return $ request ->getHeaderLine ('Content-Range ' ) === 'bytes 0-3/8 '
326+ && !$ request ->hasHeader ('X-Goog-Hash ' );
327+ }),
328+ Argument::type ('array ' )
329+ )->willReturn (new Response (308 , ['Range ' => 'bytes 0-3 ' ]));
330+
331+ $ this ->requestWrapper ->send (
332+ Argument::that (function (RequestInterface $ request ) use ($ hashValue ) {
333+ return $ request ->getHeaderLine ('Content-Range ' ) === 'bytes 4-7/8 '
334+ && $ request ->getHeaderLine ('X-Goog-Hash ' ) === $ hashValue ;
335+ }),
336+ Argument::type ('array ' )
337+ )->willReturn (new Response (200 , [], $ this ->successBody ));
338+
339+ $ uploader = new ResumableUploader (
340+ $ this ->requestWrapper ->reveal (),
341+ $ this ->stream ,
342+ 'http://www.example.com ' ,
343+ [
344+ 'chunkSize ' => 4 ,
345+ 'restOptions ' => [
346+ 'headers ' => ['X-Goog-Hash ' => $ hashValue ]
347+ ]
348+ ]
349+ );
350+
351+ $ this ->assertEquals (json_decode ($ this ->successBody , true ), $ uploader ->upload ());
352+ }
353+
241354 public function testThrowsExceptionWhenAttemptsAsyncUpload ()
242355 {
243356 $ this ->expectException (GoogleException::class);
0 commit comments