@@ -611,32 +611,32 @@ func TestIntegration_BucketPolicyOnly(t *testing.T) {
611611 t .Fatal ("got a zero time value, want a populated value" )
612612 }
613613
614- // Confirm BucketAccessControl returns error.
615- err = retry (ctx , func () error {
616- _ , err = bkt .ACL ().List (ctx )
617- return nil
618- }, func () error {
619- if err == nil {
620- return fmt .Errorf ("ACL.List: expected bucket ACL list to fail" )
621- }
622- return nil
623- })
624- if err != nil {
625- t .Fatal (err )
614+ // Confirm BucketAccessControl returns error, since we cannot get legacy ACL
615+ // for a bucket that has uniform bucket-level access.
616+
617+ // Metadata updates may be delayed up to 10s. Since we expect an error from
618+ // this call, we retry on a nil error until we get the non-retryable error
619+ // that we are expecting.
620+ idempotentOrNilRetry := func (err error ) bool {
621+ return err == nil || ShouldRetry (err )
626622 }
627623
628- // Confirm ObjectAccessControl returns error.
629- err = retry (ctx , func () error {
630- _ , err = o .ACL ().List (ctx )
631- return nil
632- }, func () error {
633- if err == nil {
634- return fmt .Errorf ("ACL.List: expected object ACL list to fail" )
635- }
636- return nil
637- })
638- if err != nil {
639- t .Fatal (err )
624+ ctxWithTimeout , cancelCtx := context .WithTimeout (ctx , time .Second * 10 )
625+
626+ b := bkt .Retryer (WithErrorFunc (idempotentOrNilRetry ))
627+ _ , err = b .ACL ().List (ctxWithTimeout )
628+ cancelCtx ()
629+ if err == nil {
630+ t .Errorf ("ACL.List: expected bucket ACL list to fail" )
631+ }
632+
633+ // Confirm ObjectAccessControl returns error, for same reason as above.
634+ ctxWithTimeout , cancelCtx = context .WithTimeout (ctx , time .Second * 10 )
635+
636+ _ , err = o .Retryer (WithErrorFunc (idempotentOrNilRetry )).ACL ().List (ctxWithTimeout )
637+ cancelCtx ()
638+ if err == nil {
639+ t .Errorf ("ACL.List: expected object ACL list to fail" )
640640 }
641641
642642 // Disable BucketPolicyOnly.
@@ -647,21 +647,15 @@ func TestIntegration_BucketPolicyOnly(t *testing.T) {
647647 }
648648
649649 // Check that the object ACLs are the same.
650- var acls []ACLRule
651- err = retry (ctx , func () error {
652- acls , err = o .ACL ().List (ctx )
653- if err != nil {
654- return fmt .Errorf ("ACL.List: object ACL list failed: %v" , err )
655- }
656- return nil
657- }, func () error {
658- if ! containsACL (acls , aclEntity , RoleReader ) {
659- return fmt .Errorf ("containsACL: expected ACLs %v to include custom ACL entity %v" , acls , aclEntity )
660- }
661- return nil
662- })
650+ ctxWithTimeout , cancelCtx = context .WithTimeout (ctx , time .Second * 10 )
651+ acls , err := o .Retryer (WithPolicy (RetryAlways )).ACL ().List (ctxWithTimeout )
652+ cancelCtx ()
663653 if err != nil {
664- t .Fatal (err )
654+ t .Errorf ("ACL.List: object ACL list failed: %v" , err )
655+ }
656+
657+ if ! containsACL (acls , aclEntity , RoleReader ) {
658+ t .Errorf ("containsACL: expected ACLs %v to include custom ACL entity %v" , acls , aclEntity )
665659 }
666660}
667661
@@ -702,31 +696,27 @@ func TestIntegration_UniformBucketLevelAccess(t *testing.T) {
702696 }
703697
704698 // Confirm BucketAccessControl returns error.
705- err = retry (ctx , func () error {
706- _ , err = bkt .ACL ().List (ctx )
707- return nil
708- }, func () error {
709- if err == nil {
710- return fmt .Errorf ("ACL.List: expected bucket ACL list to fail" )
711- }
712- return nil
713- })
714- if err != nil {
715- t .Fatal (err )
699+ // We retry on nil to account for propagation delay in metadata update.
700+ idempotentOrNilRetry := func (err error ) bool {
701+ return err == nil || ShouldRetry (err )
702+ }
703+
704+ ctxWithTimeout , cancelCtx := context .WithTimeout (ctx , time .Second * 10 )
705+
706+ b := bkt .Retryer (WithErrorFunc (idempotentOrNilRetry ))
707+ _ , err = b .ACL ().List (ctxWithTimeout )
708+ cancelCtx ()
709+ if err == nil {
710+ t .Errorf ("ACL.List: expected bucket ACL list to fail" )
716711 }
717712
718713 // Confirm ObjectAccessControl returns error.
719- err = retry (ctx , func () error {
720- _ , err = o .ACL ().List (ctx )
721- return nil
722- }, func () error {
723- if err == nil {
724- return fmt .Errorf ("ACL.List: expected object ACL list to fail" )
725- }
726- return nil
727- })
728- if err != nil {
729- t .Fatal (err )
714+ ctxWithTimeout , cancelCtx = context .WithTimeout (ctx , time .Second * 10 )
715+
716+ _ , err = o .Retryer (WithErrorFunc (idempotentOrNilRetry )).ACL ().List (ctxWithTimeout )
717+ cancelCtx ()
718+ if err == nil {
719+ t .Errorf ("ACL.List: expected object ACL list to fail" )
730720 }
731721
732722 // Disable UniformBucketLevelAccess.
@@ -737,21 +727,15 @@ func TestIntegration_UniformBucketLevelAccess(t *testing.T) {
737727 }
738728
739729 // Check that the object ACLs are the same.
740- var acls []ACLRule
741- err = retry (ctx , func () error {
742- acls , err = o .ACL ().List (ctx )
743- if err != nil {
744- return fmt .Errorf ("ACL.List: object ACL list failed: %v" , err )
745- }
746- return nil
747- }, func () error {
748- if ! containsACL (acls , aclEntity , RoleReader ) {
749- return fmt .Errorf ("containsACL: expected ACLs %v to include custom ACL entity %v" , acls , aclEntity )
750- }
751- return nil
752- })
730+ ctxWithTimeout , cancelCtx = context .WithTimeout (ctx , time .Second * 10 )
731+ acls , err := o .Retryer (WithPolicy (RetryAlways )).ACL ().List (ctxWithTimeout )
732+ cancelCtx ()
753733 if err != nil {
754- t .Fatal (err )
734+ t .Errorf ("ACL.List: object ACL list failed: %v" , err )
735+ }
736+
737+ if ! containsACL (acls , aclEntity , RoleReader ) {
738+ t .Errorf ("containsACL: expected ACLs %v to include custom ACL entity %v" , acls , aclEntity )
755739 }
756740}
757741
@@ -808,14 +792,19 @@ func TestIntegration_PublicAccessPrevention(t *testing.T) {
808792
809793 // Now, making object public or making bucket public should succeed. Run with
810794 // retry because ACL settings may take time to propagate.
811- if err := retry (ctx ,
812- func () error {
813- a = o .ACL ()
814- return a .Set (ctx , AllUsers , RoleReader )
815- },
816- nil ); err != nil {
795+ idempotentOrNilRetry := func (err error ) bool {
796+ return err == nil || ShouldRetry (err )
797+ }
798+
799+ ctxWithTimeout , cancelCtx := context .WithTimeout (ctx , time .Second * 10 )
800+
801+ a = o .Retryer (WithErrorFunc (idempotentOrNilRetry )).ACL ()
802+ a .Set (ctxWithTimeout , AllUsers , RoleReader )
803+ cancelCtx ()
804+ if err != nil {
817805 t .Errorf ("ACL.Set: making object public failed: %v" , err )
818806 }
807+
819808 policy , err = bkt .IAM ().V3 ().Policy (ctx )
820809 if err != nil {
821810 t .Fatalf ("fetching bucket IAM policy: %v" , err )
@@ -880,17 +869,12 @@ func TestIntegration_ObjectsRangeReader(t *testing.T) {
880869 obj := bkt .Object (objName )
881870 contents := []byte ("Hello, world this is a range request" )
882871
883- if err := retry (ctx , func () error {
884- w := obj .NewWriter (ctx )
885- if _ , err := w .Write (contents ); err != nil {
886- return fmt .Errorf ("Failed to write contents: %v" , err )
887- }
888- if err := w .Close (); err != nil {
889- return fmt .Errorf ("Failed to close writer: %v" , err )
890- }
891- return nil
892- }, nil ); err != nil {
893- t .Fatal (err )
872+ w := obj .If (Conditions {DoesNotExist : true }).NewWriter (ctx )
873+ if _ , err := w .Write (contents ); err != nil {
874+ t .Errorf ("Failed to write contents: %v" , err )
875+ }
876+ if err := w .Close (); err != nil {
877+ t .Errorf ("Failed to close writer: %v" , err )
894878 }
895879
896880 last5s := []struct {
@@ -2369,27 +2353,26 @@ func TestIntegration_ACL(t *testing.T) {
23692353 aclObjects := []string {"acl1" , "acl2" }
23702354 name := aclObjects [0 ]
23712355 o := bkt .Object (name )
2372- err = retry (ctx , func () error {
2373- for _ , obj := range aclObjects {
2374- c := randomContents ()
2375- if err := writeObject (ctx , bkt .Object (obj ), "" , c ); err != nil {
2376- return fmt .Errorf ("Write for %v failed with %v" , obj , err )
2377- }
2378- }
2379- acl , err = o .ACL ().List (ctx )
2380- if err != nil {
2381- return fmt .Errorf ("ACL.List: can't retrieve ACL of %v" , name )
2382- }
2383- return nil
2384- }, func () error {
2385- if ! hasRule (acl , rule ) {
2386- return fmt .Errorf ("hasRule: object ACL missing %+v" , rule )
2356+
2357+ for _ , obj := range aclObjects {
2358+ c := randomContents ()
2359+ if err := writeObject (ctx , bkt .Object (obj ).If (Conditions {DoesNotExist : true }), "" , c ); err != nil {
2360+ t .Errorf ("Write for %v failed with %v" , obj , err )
23872361 }
2388- return nil
2389- })
2362+ }
2363+
2364+ retryAllErrors := func (err error ) bool { return err != nil }
2365+
2366+ ctxWithTimeout , cancelCtx := context .WithTimeout (ctx , time .Second * 10 )
2367+ acl , err = o .Retryer (WithErrorFunc (retryAllErrors )).ACL ().List (ctxWithTimeout )
2368+ cancelCtx ()
23902369 if err != nil {
2391- t .Fatal ( err )
2370+ t .Errorf ( "ACL.List: can't retrieve ACL of %v" , name )
23922371 }
2372+ if ! hasRule (acl , rule ) {
2373+ t .Errorf ("hasRule: object ACL missing %+v" , rule )
2374+ }
2375+
23932376 if err := o .ACL ().Delete (ctx , entity ); err != nil {
23942377 t .Errorf ("object ACL: could not delete entity %s" , entity )
23952378 }
@@ -2405,26 +2388,22 @@ func TestIntegration_ACL(t *testing.T) {
24052388 if err := bkt .ACL ().Set (ctx , entity2 , RoleReader ); err != nil {
24062389 t .Errorf ("Error while putting bucket ACL rule: %v" , err )
24072390 }
2391+
24082392 var bACL []ACLRule
2409- err = retry (ctx , func () error {
2410- bACL , err = bkt .ACL ().List (ctx )
2411- if err != nil {
2412- return fmt .Errorf ("ACL.List: error while getting the ACL of the bucket: %v" , err )
2413- }
2414- return nil
2415- }, func () error {
2416- if ! hasRule (bACL , rule2 ) {
2417- return fmt .Errorf ("hasRule: bucket ACL missing %+v" , rule2 )
2418- }
2419- return nil
2420- })
2393+ ctxWithTimeout , cancel := context .WithTimeout (ctx , time .Second * 10 )
2394+ defer cancel ()
2395+
2396+ bACL , err = bkt .Retryer (WithErrorFunc (retryAllErrors )).ACL ().List (ctxWithTimeout )
24212397 if err != nil {
2422- t .Error (err )
2398+ t .Errorf ("ACL.List: error while getting the ACL of the bucket: %v" , err )
2399+ }
2400+ if ! hasRule (bACL , rule2 ) {
2401+ t .Errorf ("hasRule: bucket ACL missing %+v" , rule2 )
24232402 }
2403+
24242404 if err := bkt .ACL ().Delete (ctx , entity2 ); err != nil {
24252405 t .Errorf ("Error while deleting bucket ACL rule: %v" , err )
24262406 }
2427-
24282407}
24292408
24302409func TestIntegration_ValidObjectNames (t * testing.T ) {
@@ -3713,24 +3692,27 @@ func TestIntegration_DeleteObjectInBucketWithRetentionPolicy(t *testing.T) {
37133692 bkt := client .Bucket (uidSpace .New ())
37143693 h .mustCreate (bkt , testutil .ProjID (), & BucketAttrs {RetentionPolicy : & RetentionPolicy {RetentionPeriod : 25 * time .Hour }})
37153694
3716- oh := bkt .Object ("some-object" )
3717- if err := writeObject (ctx , oh , "text/plain" , []byte ("hello world" )); err != nil {
3695+ o := bkt .Object ("some-object" )
3696+ if err := writeObject (ctx , o , "text/plain" , []byte ("hello world" )); err != nil {
37183697 t .Fatal (err )
37193698 }
37203699
3721- if err := oh .Delete (ctx ); err == nil {
3700+ if err := o .Delete (ctx ); err == nil {
37223701 t .Fatal ("expected to err deleting an object in a bucket with retention period, but got nil" )
37233702 }
37243703
37253704 // Remove the retention period
37263705 h .mustUpdateBucket (bkt , BucketAttrsToUpdate {RetentionPolicy : & RetentionPolicy {}}, h .mustBucketAttrs (bkt ).MetaGeneration )
3727- // Deleting with retry, as bucket metadata changes
3706+
3707+ // Delete with retry, as bucket metadata changes
37283708 // can take some time to propagate.
3729- err := retry (ctx , func () error {
3730- return oh .Delete (ctx )
3731- }, nil )
3732- if err != nil {
3733- h .t .Fatalf ("%s: object delete: %v" , loc (), err )
3709+ retry := func (err error ) bool { return err != nil }
3710+ ctx , cancel := context .WithTimeout (ctx , time .Second * 10 )
3711+ defer cancel ()
3712+
3713+ o = o .Retryer (WithErrorFunc (retry ), WithPolicy (RetryAlways ))
3714+ if err := o .Delete (ctx ); err != nil {
3715+ t .Fatalf ("object delete: %v" , err )
37343716 }
37353717 h .mustDeleteBucket (bkt )
37363718}
@@ -4087,26 +4069,19 @@ func TestIntegration_NewReaderWithContentEncodingGzip(t *testing.T) {
40874069 obj := bkt .Object ("decompressive-transcoding" )
40884070 original := bytes .Repeat ([]byte ("a" ), 4 << 10 )
40894071
4090- // Wrap the file upload in a retry.
4091- // TODO: Investigate removing retry after resolving
4092- // https://github.com/googleapis/google-api-go-client/issues/392.
4093- err := retry (ctx , func () error {
4094- // Firstly upload the gzip compressed file.
4095- w := obj .NewWriter (ctx )
4096- // Compress and upload the content.
4097- gzw := gzip .NewWriter (w )
4098- if _ , err := gzw .Write (original ); err != nil {
4099- return fmt .Errorf ("Failed to compress content: %v" , err )
4100- }
4101- if err := gzw .Close (); err != nil {
4102- return fmt .Errorf ("Failed to compress content: %v" , err )
4103- }
4104- if err := w .Close (); err != nil {
4105- return fmt .Errorf ("Failed to finish uploading the file: %v" , err )
4106- }
4107- return nil
4108- },
4109- nil )
4072+ // Firstly upload the gzip compressed file.
4073+ w := obj .If (Conditions {DoesNotExist : true }).NewWriter (ctx )
4074+ // Compress and upload the content.
4075+ gzw := gzip .NewWriter (w )
4076+ if _ , err := gzw .Write (original ); err != nil {
4077+ t .Fatalf ("Failed to compress content: %v" , err )
4078+ }
4079+ if err := gzw .Close (); err != nil {
4080+ t .Errorf ("Failed to compress content: %v" , err )
4081+ }
4082+ if err := w .Close (); err != nil {
4083+ t .Errorf ("Failed to finish uploading the file: %v" , err )
4084+ }
41104085
41114086 defer h .mustDeleteObject (obj )
41124087
@@ -4160,6 +4135,7 @@ func TestIntegration_HMACKey(t *testing.T) {
41604135 ctx := context .Background ()
41614136 client := testConfig (ctx , t )
41624137 defer client .Close ()
4138+ client .SetRetry (WithPolicy (RetryAlways ))
41634139
41644140 projectID := testutil .ProjID ()
41654141
0 commit comments