@@ -3631,78 +3631,87 @@ func TestIntegration_ReadCRC(t *testing.T) {
36313631 offset , length int64
36323632 readCompressed bool // don't decompress a gzipped file
36333633
3634- wantErr bool
3635- wantCheck bool // Should Reader try to check the CRC?
3634+ wantErr bool
3635+ wantCheck bool // Should Reader try to check the CRC?
3636+ wantDecompressed bool
36363637 }{
36373638 {
3638- desc : "uncompressed, entire file" ,
3639- obj : client .Bucket (uncompressedBucket ).Object (uncompressedObject ),
3640- offset : 0 ,
3641- length : - 1 ,
3642- readCompressed : false ,
3643- wantCheck : true ,
3639+ desc : "uncompressed, entire file" ,
3640+ obj : client .Bucket (uncompressedBucket ).Object (uncompressedObject ),
3641+ offset : 0 ,
3642+ length : - 1 ,
3643+ readCompressed : false ,
3644+ wantCheck : true ,
3645+ wantDecompressed : false ,
36443646 },
36453647 {
3646- desc : "uncompressed, entire file, don't decompress" ,
3647- obj : client .Bucket (uncompressedBucket ).Object (uncompressedObject ),
3648- offset : 0 ,
3649- length : - 1 ,
3650- readCompressed : true ,
3651- wantCheck : true ,
3648+ desc : "uncompressed, entire file, don't decompress" ,
3649+ obj : client .Bucket (uncompressedBucket ).Object (uncompressedObject ),
3650+ offset : 0 ,
3651+ length : - 1 ,
3652+ readCompressed : true ,
3653+ wantCheck : true ,
3654+ wantDecompressed : false ,
36523655 },
36533656 {
3654- desc : "uncompressed, suffix" ,
3655- obj : client .Bucket (uncompressedBucket ).Object (uncompressedObject ),
3656- offset : 1 ,
3657- length : - 1 ,
3658- readCompressed : false ,
3659- wantCheck : false ,
3657+ desc : "uncompressed, suffix" ,
3658+ obj : client .Bucket (uncompressedBucket ).Object (uncompressedObject ),
3659+ offset : 1 ,
3660+ length : - 1 ,
3661+ readCompressed : false ,
3662+ wantCheck : false ,
3663+ wantDecompressed : false ,
36603664 },
36613665 {
3662- desc : "uncompressed, prefix" ,
3663- obj : client .Bucket (uncompressedBucket ).Object (uncompressedObject ),
3664- offset : 0 ,
3665- length : 18 ,
3666- readCompressed : false ,
3667- wantCheck : false ,
3666+ desc : "uncompressed, prefix" ,
3667+ obj : client .Bucket (uncompressedBucket ).Object (uncompressedObject ),
3668+ offset : 0 ,
3669+ length : 18 ,
3670+ readCompressed : false ,
3671+ wantCheck : false ,
3672+ wantDecompressed : false ,
36683673 },
36693674 {
36703675 // When a gzipped file is unzipped on read, we can't verify the checksum
36713676 // because it was computed against the zipped contents. We can detect
36723677 // this case using http.Response.Uncompressed.
3673- desc : "compressed, entire file, unzipped" ,
3674- obj : client .Bucket (bucket ).Object (gzippedObject ),
3675- offset : 0 ,
3676- length : - 1 ,
3677- readCompressed : false ,
3678- wantCheck : false ,
3678+ desc : "compressed, entire file, unzipped" ,
3679+ obj : client .Bucket (bucket ).Object (gzippedObject ),
3680+ offset : 0 ,
3681+ length : - 1 ,
3682+ readCompressed : false ,
3683+ wantCheck : false ,
3684+ wantDecompressed : true ,
36793685 },
36803686 {
36813687 // When we read a gzipped file uncompressed, it's like reading a regular file:
36823688 // the served content and the CRC match.
3683- desc : "compressed, entire file, read compressed" ,
3684- obj : client .Bucket (bucket ).Object (gzippedObject ),
3685- offset : 0 ,
3686- length : - 1 ,
3687- readCompressed : true ,
3688- wantCheck : true ,
3689+ desc : "compressed, entire file, read compressed" ,
3690+ obj : client .Bucket (bucket ).Object (gzippedObject ),
3691+ offset : 0 ,
3692+ length : - 1 ,
3693+ readCompressed : true ,
3694+ wantCheck : true ,
3695+ wantDecompressed : false ,
36893696 },
36903697 {
3691- desc : "compressed, partial, server unzips" ,
3692- obj : client .Bucket (bucket ).Object (gzippedObject ),
3693- offset : 1 ,
3694- length : 8 ,
3695- readCompressed : false ,
3696- wantErr : true , // GCS can't serve part of a gzipped object
3697- wantCheck : false ,
3698+ desc : "compressed, partial, server unzips" ,
3699+ obj : client .Bucket (bucket ).Object (gzippedObject ),
3700+ offset : 1 ,
3701+ length : 8 ,
3702+ readCompressed : false ,
3703+ wantErr : true , // GCS can't serve part of a gzipped object
3704+ wantCheck : false ,
3705+ wantDecompressed : true ,
36983706 },
36993707 {
3700- desc : "compressed, partial, read compressed" ,
3701- obj : client .Bucket (bucket ).Object (gzippedObject ),
3702- offset : 1 ,
3703- length : 8 ,
3704- readCompressed : true ,
3705- wantCheck : false ,
3708+ desc : "compressed, partial, read compressed" ,
3709+ obj : client .Bucket (bucket ).Object (gzippedObject ),
3710+ offset : 1 ,
3711+ length : 8 ,
3712+ readCompressed : true ,
3713+ wantCheck : false ,
3714+ wantDecompressed : false ,
37063715 },
37073716 } {
37083717 t .Run (test .desc , func (t * testing.T ) {
@@ -3720,13 +3729,17 @@ func TestIntegration_ReadCRC(t *testing.T) {
37203729 if got , want := r .checkCRC , test .wantCheck ; got != want {
37213730 t .Errorf ("%s, checkCRC: got %t, want %t" , test .desc , got , want )
37223731 }
3732+
3733+ if got , want := r .Attrs .Decompressed , test .wantDecompressed ; got != want {
3734+ t .Errorf ("Attrs.Decompressed: got %t, want %t" , got , want )
3735+ }
3736+
37233737 _ , err = c .readFunc (r )
37243738 _ = r .Close ()
37253739 if err != nil {
37263740 t .Fatalf ("%s: %v" , test .desc , err )
37273741 }
37283742 })
3729-
37303743 }
37313744 })
37323745 }
@@ -4767,6 +4780,10 @@ func TestIntegration_Reader(t *testing.T) {
47674780 if got , want := rc .ContentType (), "text/plain" ; got != want {
47684781 t .Errorf ("ContentType (%q) = %q; want %q" , obj , got , want )
47694782 }
4783+
4784+ if got , want := rc .Attrs .CRC32C , crc32c (contents [obj ]); got != want {
4785+ t .Errorf ("CRC32C (%q) = %d; want %d" , obj , got , want )
4786+ }
47704787 rc .Close ()
47714788
47724789 // Check early close.
@@ -4831,6 +4848,15 @@ func TestIntegration_Reader(t *testing.T) {
48314848 if len (slurp ) != int (r .want ) {
48324849 t .Fatalf ("%+v: RangeReader (%d, %d): Read %d bytes, wanted %d bytes" , r .desc , r .offset , r .length , len (slurp ), r .want )
48334850 }
4851+ // JSON does not return the crc32c on partial reads, so
4852+ // allow got == 0.
4853+ if got , want := rc .Attrs .CRC32C , crc32c (contents [obj ]); got != 0 && got != want {
4854+ t .Errorf ("RangeReader CRC32C (%q) = %d; want %d" , obj , got , want )
4855+ }
4856+
4857+ if rc .Attrs .Decompressed {
4858+ t .Errorf ("RangeReader Decompressed (%q) = want false, got %v" , obj , rc .Attrs .Decompressed )
4859+ }
48344860
48354861 switch {
48364862 case r .offset < 0 : // The case of reading the last N bytes.
@@ -4912,6 +4938,7 @@ func TestIntegration_ReaderAttrs(t *testing.T) {
49124938 LastModified : got .LastModified , // ignored, tested separately
49134939 Generation : attrs .Generation ,
49144940 Metageneration : attrs .Metageneration ,
4941+ CRC32C : crc32c (c ),
49154942 }
49164943 if got != want {
49174944 t .Fatalf ("got\t %v,\n wanted\t %v" , got , want )
@@ -5211,6 +5238,10 @@ func TestIntegration_NewReaderWithContentEncodingGzip(t *testing.T) {
52115238 if g , w := blob2kBTo3kB , original ; ! bytes .Equal (g , w ) {
52125239 t .Fatalf ("Body mismatch\n Got:\n %s\n \n Want:\n %s" , g , w )
52135240 }
5241+
5242+ if ! r2kBTo3kB .Attrs .Decompressed {
5243+ t .Errorf ("Attrs.Decompressed: want true, got %v" , r2kBTo3kB .Attrs .Decompressed )
5244+ }
52145245 })
52155246 }
52165247 })
@@ -6350,3 +6381,7 @@ func setUpRequesterPaysBucket(ctx context.Context, t *testing.T, bucket, object
63506381 }
63516382 })
63526383}
6384+
6385+ func crc32c (b []byte ) uint32 {
6386+ return crc32 .Checksum (b , crc32 .MakeTable (crc32 .Castagnoli ))
6387+ }
0 commit comments