Skip to content

Commit c220ca2

Browse files
authored
refactor(storage): replace manual retries in tests (#6510)
Fixes #5032 Also adds a retry to the HMAC key test that fixes #6544
1 parent c85704f commit c220ca2

File tree

2 files changed

+128
-153
lines changed

2 files changed

+128
-153
lines changed

storage/integration_test.go

Lines changed: 128 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -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

24302409
func 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

storage/retry_conformance_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,6 @@ var methods = map[string][]retryFunc{
224224
},
225225
},
226226
// Conditionally idempotent operations
227-
// (all conditionally idempotent operations currently fail)
228227
"storage.buckets.patch": {
229228
func(ctx context.Context, c *Client, fs *resources, preconditions bool) error {
230229
uattrs := BucketAttrsToUpdate{StorageClass: "ARCHIVE"}

0 commit comments

Comments
 (0)