From bc49211e902f9f39840096876a063960b9b2badf Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Fri, 29 Nov 2024 08:00:35 +0100 Subject: [PATCH] tests: fix async propagation and cleanup --- features/etag-propagation.feature | 7 ++++++ helpers/retry.go | 17 +++++++++++++++ steps/resources/cleanup.go | 36 ++++++++++++++++++++----------- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/features/etag-propagation.feature b/features/etag-propagation.feature index 965f386..9f38401 100644 --- a/features/etag-propagation.feature +++ b/features/etag-propagation.feature @@ -33,8 +33,15 @@ Feature: Etag and Treesize propagation Scenario: Change etag of personal home and move subtree Given user "admin" has created a folder "a-folder/a-sub-folder-B" in the home directory with the alias "a-sub-folder-B" And user "admin" has created a folder "a-folder/a-sub-folder/testFolder" in the home directory with the alias "testFolder" + And user "admin" remembers the fileinfo of the resource with the alias "Admin Home" And user "admin" has created a folder "a-folder/a-sub-folder/testFolder/test2" in the home directory with the alias "test2" + # This is needed to make sure that the propagation has happened to the testing file tree before we move the folder + And for user "admin" the etag of the resource with the alias "Admin Home" should have changed + And user "admin" remembers the fileinfo of the resource with the alias "Admin Home" And user "admin" has uploaded a file "a-folder/a-sub-folder/testfile.txt" with content "text" in the home directory with the alias "testfile.txt" + # This is needed to make sure that the propagation has happened to the testing file tree before we move the folder + And for user "admin" the etag of the resource with the alias "Admin Home" should have changed + # Now we have a clean state and can start the actual test And user "admin" remembers the fileinfo of the resource with the alias "Admin Home" And user "admin" remembers the fileinfo of the resource with the alias "a-folder" And user "admin" remembers the fileinfo of the resource with the alias "a-sub-folder" diff --git a/helpers/retry.go b/helpers/retry.go index 65a754c..ac1ca34 100644 --- a/helpers/retry.go +++ b/helpers/retry.go @@ -1,7 +1,10 @@ package helpers import ( + "context" "time" + + providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" ) // Retry retries a function f max times with a delay between each attempt @@ -17,3 +20,17 @@ func Retry(f func() error, max int, delay time.Duration) error { time.Sleep(delay) return f() } + +// RetryResource retries a function f max times with a delay between each attempt +func RetryResource(f func(*providerv1beta1.Reference, context.Context) error, ref *providerv1beta1.Reference, ctx context.Context, max int, delay time.Duration) error { + // retry the function f max-1 times with a delay between each attempt + for i := 0; i < max-1; i++ { + time.Sleep(delay) + if f(ref, ctx) == nil { + return nil + } + } + // last attempt + time.Sleep(delay) + return f(ref, ctx) +} diff --git a/steps/resources/cleanup.go b/steps/resources/cleanup.go index a798d84..e9ea6f4 100644 --- a/steps/resources/cleanup.go +++ b/steps/resources/cleanup.go @@ -2,10 +2,12 @@ package resources import ( "context" + "errors" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cucumber/godog" + "github.com/owncloud/cs3api-validator/helpers" ) // deleteResourcesAfterScenario deletes resources which have been created after running the scenario @@ -15,7 +17,6 @@ func (f *ResourcesFeatureContext) DeleteResourcesAfterScenario(ctx context.Conte // we don't now which user has access to which reference, // therefore we just try to delete each reference with all users - for u := range f.Users { reqctx, err := f.GetAuthContext(u) if err != nil { @@ -25,18 +26,9 @@ func (f *ResourcesFeatureContext) DeleteResourcesAfterScenario(ctx context.Conte notYetDeleted := []*providerv1beta1.Reference{} for _, ref := range resourcesToDelete { - resp, err := f.Client.Delete( - reqctx, - &providerv1beta1.DeleteRequest{ - Ref: ref, - }, - ) - if err != nil { - continue - } - - // non-existing resources are not errors - if resp.Status.Code != rpc.Code_CODE_OK && resp.Status.Code != rpc.Code_CODE_NOT_FOUND { + // we need to retry the deletion because the resource might be in postprocessing + e := helpers.RetryResource(f.deleteResource, ref, reqctx, 3, f.Config.AsyncPropagationDelay) + if e != nil { notYetDeleted = append(notYetDeleted, ref) } } @@ -47,6 +39,24 @@ func (f *ResourcesFeatureContext) DeleteResourcesAfterScenario(ctx context.Conte return ctx, nil } +func (f *ResourcesFeatureContext) deleteResource(ref *providerv1beta1.Reference, reqctx context.Context) error { + resp, err := f.Client.Delete( + reqctx, + &providerv1beta1.DeleteRequest{ + Ref: ref, + }, + ) + if err != nil { + return err + } + + // non-existing resources are not errors + if resp.Status.Code != rpc.Code_CODE_OK && resp.Status.Code != rpc.Code_CODE_NOT_FOUND { + return errors.New(resp.GetStatus().GetMessage()) + } + return nil +} + // emptyTrashAfterScenario empties the trash for all users after running the scenario func (f *ResourcesFeatureContext) EmptyTrashAfterScenario(ctx context.Context, sc *godog.Scenario, errsctx error) (context.Context, error) { for u := range f.Users {