diff --git a/pkg/apiserver/rest/dualwriter_mode1_test.go b/pkg/apiserver/rest/dualwriter_mode1_test.go index fdae37d76ca..e5504e4df4e 100644 --- a/pkg/apiserver/rest/dualwriter_mode1_test.go +++ b/pkg/apiserver/rest/dualwriter_mode1_test.go @@ -7,8 +7,8 @@ import ( "time" "github.com/prometheus/client_golang/prometheus" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/api/meta" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -62,16 +62,15 @@ func TestMode1_Create(t *testing.T) { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, tt.input) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m) + tt.setupStorageFn(us.Mock) } dw := NewDualWriter(Mode1, ls, us, p, kind) @@ -79,14 +78,14 @@ func TestMode1_Create(t *testing.T) { obj, err := dw.Create(context.Background(), tt.input, func(context.Context, runtime.Object) error { return nil }, &metav1.CreateOptions{}) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } acc, err := meta.Accessor(obj) - assert.NoError(t, err) - assert.Equal(t, acc.GetResourceVersion(), "1") - assert.NotEqual(t, obj, anotherObj) + require.NoError(t, err) + require.Equal(t, acc.GetResourceVersion(), "1") + require.NotEqual(t, obj, anotherObj) }) } } @@ -125,16 +124,15 @@ func TestMode1_CreateOnUnifiedStorage(t *testing.T) { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m) + tt.setupLegacyFn(ls.Mock) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m) + tt.setupStorageFn(us.Mock) } ctx := context.TODO() @@ -144,7 +142,7 @@ func TestMode1_CreateOnUnifiedStorage(t *testing.T) { dw := NewDualWriter(Mode1, ls, us, p, kind) err := dw.(*DualWriterMode1).createOnUnifiedStorage(ctx, func(context.Context, runtime.Object) error { return nil }, tt.input, &metav1.CreateOptions{}) - assert.NoError(t, err) + require.NoError(t, err) }) } } @@ -154,14 +152,12 @@ func TestMode1_Get(t *testing.T) { setupLegacyFn func(m *mock.Mock, name string) setupStorageFn func(m *mock.Mock, name string) name string - input string wantErr bool } tests := []testCase{ { - name: "get an object only in the legacy store", - input: "foo", + name: "should succeed when getting an object from LegacyStorage", setupLegacyFn: func(m *mock.Mock, name string) { m.On("Get", mock.Anything, name, mock.Anything).Return(exampleObj, nil) }, @@ -170,44 +166,56 @@ func TestMode1_Get(t *testing.T) { }, }, { - name: "error when getting an object in the legacy store fails", - input: "object-fail", + name: "should error when getting an object from LegacyStorage fails", setupLegacyFn: func(m *mock.Mock, name string) { m.On("Get", mock.Anything, name, mock.Anything).Return(nil, errors.New("error")) }, + setupStorageFn: func(m *mock.Mock, name string) { + m.On("Get", mock.Anything, name, mock.Anything).Return(exampleObj, nil) + }, wantErr: true, }, + { + name: "should not error when getting an object from UnifiedStorage fails", + setupLegacyFn: func(m *mock.Mock, name string) { + m.On("Get", mock.Anything, name, mock.Anything).Return(exampleObj, nil) + }, + setupStorageFn: func(m *mock.Mock, name string) { + m.On("Get", mock.Anything, name, mock.Anything).Return(nil, errors.New("error")) + }, + }, } + name := "foo" + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, name) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) + tt.setupStorageFn(us.Mock, name) } dw := NewDualWriter(Mode1, ls, us, p, kind) - obj, err := dw.Get(context.Background(), tt.input, &metav1.GetOptions{}) + obj, err := dw.Get(context.Background(), name, &metav1.GetOptions{}) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } us.AssertNotCalled(t, "Get", context.Background(), tt.name, &metav1.GetOptions{}) - assert.Equal(t, obj, exampleObj) - assert.NotEqual(t, obj, anotherObj) + require.Equal(t, obj, exampleObj) + require.NotEqual(t, obj, anotherObj) }) } } @@ -221,41 +229,39 @@ func TestMode1_GetFromUnifiedStorage(t *testing.T) { setupStorageFn func(m *mock.Mock, name string) ctx *context.Context name string - input string } tests := []testCase{ { - name: "Get from unified storage", - input: "foo", + name: "should succeed when getting an object from UnifiedStorage", setupStorageFn: func(m *mock.Mock, name string) { m.On("Get", mock.Anything, name, mock.Anything).Return(exampleObj, nil) }, }, { - name: "Get from unified storage works even if parent context is canceled", - input: "foo", - ctx: &ctxCanceled, + name: "should succeed when getting an object from UnifiedStorage even if parent context is canceled", + ctx: &ctxCanceled, setupStorageFn: func(m *mock.Mock, name string) { m.On("Get", mock.Anything, name, mock.Anything).Return(exampleObj, nil) }, }, } + name := "foo" + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, name) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) + tt.setupStorageFn(us.Mock, name) } ctx := context.TODO() @@ -264,8 +270,8 @@ func TestMode1_GetFromUnifiedStorage(t *testing.T) { } dw := NewDualWriter(Mode1, ls, us, p, kind) - err := dw.(*DualWriterMode1).getFromUnifiedStorage(ctx, exampleObj, tt.input, &metav1.GetOptions{}) - assert.NoError(t, err) + err := dw.(*DualWriterMode1).getFromUnifiedStorage(ctx, exampleObj, name, &metav1.GetOptions{}) + require.NoError(t, err) }) } } @@ -280,28 +286,39 @@ func TestMode1_List(t *testing.T) { tests := []testCase{ { - name: "error when listing an object in the legacy store is not implemented", + name: "should error when listing from LegacyStorage fails", setupLegacyFn: func(m *mock.Mock) { - m.On("List", mock.Anything, mock.Anything).Return(&example.PodList{}, errors.New("error")) + m.On("List", mock.Anything, mock.Anything).Return(nil, errors.New("error")) + }, + setupStorageFn: func(m *mock.Mock) { + m.On("List", mock.Anything, mock.Anything).Return(&example.PodList{}, nil) + }, + wantErr: true, + }, + { + name: "should not error when listing from UnifiedStorage fails", + setupLegacyFn: func(m *mock.Mock) { + m.On("List", mock.Anything, mock.Anything).Return(&example.PodList{}, nil) + }, + setupStorageFn: func(m *mock.Mock) { + m.On("List", mock.Anything, mock.Anything).Return(nil, errors.New("error")) }, }, - // TODO: legacy list is missing } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m) + tt.setupLegacyFn(ls.Mock) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m) + tt.setupStorageFn(us.Mock) } dw := NewDualWriter(Mode1, ls, us, p, kind) @@ -309,7 +326,7 @@ func TestMode1_List(t *testing.T) { _, err := dw.List(context.Background(), &metainternalversion.ListOptions{}) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } }) @@ -329,13 +346,16 @@ func TestMode1_ListFromUnifiedStorage(t *testing.T) { tests := []testCase{ { - name: "list from unified storage", + name: "should succeed when listing from UnifiedStorage", setupStorageFn: func(m *mock.Mock) { m.On("List", mock.Anything, mock.Anything).Return(anotherList, nil) }, + setupLegacyFn: func(m *mock.Mock) { + m.On("List", mock.Anything, mock.Anything).Return(anotherList, nil) + }, }, { - name: "list from unified storage works even if parent context is canceled", + name: "should succeed when listing from UnifiedStorage even if parent context is canceled", ctx: &ctxCanceled, setupStorageFn: func(m *mock.Mock) { m.On("List", mock.Anything, mock.Anything).Return(anotherList, nil) @@ -347,16 +367,15 @@ func TestMode1_ListFromUnifiedStorage(t *testing.T) { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m) + tt.setupLegacyFn(ls.Mock) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m) + tt.setupStorageFn(us.Mock) } ctx := context.TODO() @@ -367,7 +386,7 @@ func TestMode1_ListFromUnifiedStorage(t *testing.T) { dw := NewDualWriter(Mode1, ls, us, p, kind) err := dw.(*DualWriterMode1).listFromUnifiedStorage(ctx, &metainternalversion.ListOptions{}, anotherList) - assert.NoError(t, err) + require.NoError(t, err) }) } } @@ -377,56 +396,69 @@ func TestMode1_Delete(t *testing.T) { setupLegacyFn func(m *mock.Mock, name string) setupStorageFn func(m *mock.Mock, name string) name string - input string wantErr bool } tests := []testCase{ { - name: "deleting an object in the legacy store", - input: "foo", + name: "should succeed when deleting an object from LegacyStorage", setupLegacyFn: func(m *mock.Mock, name string) { m.On("Delete", mock.Anything, name, mock.Anything, mock.Anything).Return(exampleObj, false, nil) }, + setupStorageFn: func(m *mock.Mock, name string) { + m.On("Delete", mock.Anything, name, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + }, }, { - name: "error when deleting an object in the legacy store", - input: "object-fail", + name: "should error when deleting an object from LegacyStorage fails", setupLegacyFn: func(m *mock.Mock, name string) { m.On("Delete", mock.Anything, name, mock.Anything, mock.Anything).Return(nil, false, errors.New("error")) }, + setupStorageFn: func(m *mock.Mock, name string) { + m.On("Delete", mock.Anything, name, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + }, wantErr: true, }, + { + name: "should not error when deleting an object from UnifiedStorage fails", + setupLegacyFn: func(m *mock.Mock, name string) { + m.On("Delete", mock.Anything, name, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + }, + setupStorageFn: func(m *mock.Mock, name string) { + m.On("Delete", mock.Anything, name, mock.Anything, mock.Anything).Return(nil, false, errors.New("error")) + }, + }, } + name := "foo" + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, name) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) + tt.setupStorageFn(us.Mock, name) } dw := NewDualWriter(Mode1, ls, us, p, kind) - obj, _, err := dw.Delete(context.Background(), tt.input, func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{}) + obj, _, err := dw.Delete(context.Background(), name, func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{}) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } - us.AssertNotCalled(t, "Delete", context.Background(), tt.input, func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{}) - assert.Equal(t, obj, exampleObj) - assert.NotEqual(t, obj, anotherObj) + us.AssertNotCalled(t, "Delete", context.Background(), name, func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{}) + require.Equal(t, obj, exampleObj) + require.NotEqual(t, obj, anotherObj) }) } } @@ -440,39 +472,39 @@ func TestMode1_DeleteFromUnifiedStorage(t *testing.T) { setupLegacyFn func(m *mock.Mock, name string) setupStorageFn func(m *mock.Mock, name string) name string - input string } tests := []testCase{ { - name: "Delete from unified storage", - setupStorageFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + name: "should succeed when deleting an object from UnifiedStorage", + setupStorageFn: func(m *mock.Mock, name string) { + m.On("Delete", mock.Anything, name, mock.Anything, mock.Anything).Return(exampleObj, false, nil) }, }, { - name: "Delete from unified storage works even if parent context is canceled", + name: "should succeed when deleting an object from UnifiedStorage even if parent context is canceled", ctx: &ctxCanceled, - setupStorageFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + setupStorageFn: func(m *mock.Mock, name string) { + m.On("Delete", mock.Anything, name, mock.Anything, mock.Anything).Return(exampleObj, false, nil) }, }, } + name := "foo" + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, name) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) + tt.setupStorageFn(us.Mock, name) } ctx := context.TODO() @@ -482,8 +514,8 @@ func TestMode1_DeleteFromUnifiedStorage(t *testing.T) { dw := NewDualWriter(Mode1, ls, us, p, kind) - err := dw.(*DualWriterMode1).deleteFromUnifiedStorage(ctx, exampleObj, tt.input, func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{}) - assert.NoError(t, err) + err := dw.(*DualWriterMode1).deleteFromUnifiedStorage(ctx, exampleObj, name, func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{}) + require.NoError(t, err) }) } } @@ -499,36 +531,51 @@ func TestMode1_DeleteCollection(t *testing.T) { tests := []testCase{ { - name: "deleting a collection in the legacy store", + name: "should succeed when deleting a collection from LegacyStorage", input: &metav1.DeleteOptions{TypeMeta: metav1.TypeMeta{Kind: "foo"}}, setupLegacyFn: func(m *mock.Mock, input *metav1.DeleteOptions) { m.On("DeleteCollection", mock.Anything, mock.Anything, input, mock.Anything).Return(exampleObj, nil) }, + setupStorageFn: func(m *mock.Mock, input *metav1.DeleteOptions) { + m.On("DeleteCollection", mock.Anything, mock.Anything, input, mock.Anything).Return(exampleObj, nil) + }, }, { - name: "error deleting a collection in the legacy store", + name: "should error when deleting a collection from LegacyStorage fails", input: &metav1.DeleteOptions{TypeMeta: metav1.TypeMeta{Kind: "fail"}}, setupLegacyFn: func(m *mock.Mock, input *metav1.DeleteOptions) { m.On("DeleteCollection", mock.Anything, mock.Anything, input, mock.Anything).Return(nil, errors.New("error")) }, + setupStorageFn: func(m *mock.Mock, input *metav1.DeleteOptions) { + m.On("DeleteCollection", mock.Anything, mock.Anything, input, mock.Anything).Return(exampleObj, nil) + }, wantErr: true, }, + { + name: "should not error when deleting a collection from UnifiedStorage fails", + input: &metav1.DeleteOptions{TypeMeta: metav1.TypeMeta{Kind: "foo"}}, + setupLegacyFn: func(m *mock.Mock, input *metav1.DeleteOptions) { + m.On("DeleteCollection", mock.Anything, mock.Anything, input, mock.Anything).Return(exampleObj, nil) + }, + setupStorageFn: func(m *mock.Mock, input *metav1.DeleteOptions) { + m.On("DeleteCollection", mock.Anything, mock.Anything, input, mock.Anything).Return(nil, errors.New("error")) + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, tt.input) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) + tt.setupStorageFn(us.Mock, tt.input) } dw := NewDualWriter(Mode1, ls, us, p, kind) @@ -536,13 +583,13 @@ func TestMode1_DeleteCollection(t *testing.T) { obj, err := dw.DeleteCollection(context.Background(), func(ctx context.Context, obj runtime.Object) error { return nil }, tt.input, &metainternalversion.ListOptions{}) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } us.AssertNotCalled(t, "DeleteCollection", context.Background(), tt.input, func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{}) - assert.Equal(t, obj, exampleObj) - assert.NotEqual(t, obj, anotherObj) + require.Equal(t, obj, exampleObj) + require.NotEqual(t, obj, anotherObj) }) } } @@ -561,14 +608,14 @@ func TestMode1_DeleteCollectionFromUnifiedStorage(t *testing.T) { tests := []testCase{ { - name: "Delete Collection from unified storage", + name: "should succeed when deleting a collection from UnifiedStorage", input: &metav1.DeleteOptions{TypeMeta: metav1.TypeMeta{Kind: "foo"}}, setupStorageFn: func(m *mock.Mock) { m.On("DeleteCollection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleObj, nil) }, }, { - name: "Delete Collection from unified storage works even if parent context is canceled", + name: "should succeed when deleting a collection from UnifiedStorage even if parent context is canceled", input: &metav1.DeleteOptions{TypeMeta: metav1.TypeMeta{Kind: "foo"}}, ctx: &ctxCanceled, setupStorageFn: func(m *mock.Mock) { @@ -581,16 +628,15 @@ func TestMode1_DeleteCollectionFromUnifiedStorage(t *testing.T) { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m) + tt.setupLegacyFn(ls.Mock) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m) + tt.setupStorageFn(us.Mock) } ctx := context.TODO() @@ -601,7 +647,7 @@ func TestMode1_DeleteCollectionFromUnifiedStorage(t *testing.T) { dw := NewDualWriter(Mode1, ls, us, p, kind) err := dw.(*DualWriterMode1).deleteCollectionFromUnifiedStorage(ctx, exampleObj, func(ctx context.Context, obj runtime.Object) error { return nil }, tt.input, &metainternalversion.ListOptions{}) - assert.NoError(t, err) + require.NoError(t, err) }) } } @@ -611,14 +657,12 @@ func TestMode1_Update(t *testing.T) { setupLegacyFn func(m *mock.Mock, input string) setupStorageFn func(m *mock.Mock, input string) name string - input string wantErr bool } tests := []testCase{ { - name: "update an object in legacy", - input: "foo", + name: "should succeed when updating an object in LegacyStorage", setupLegacyFn: func(m *mock.Mock, input string) { m.On("Update", mock.Anything, input, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleObj, false, nil) }, @@ -627,8 +671,7 @@ func TestMode1_Update(t *testing.T) { }, }, { - name: "error updating an object in legacy", - input: "object-fail", + name: "should error when updating an object in LegacyStorage fails", setupLegacyFn: func(m *mock.Mock, input string) { m.On("Update", mock.Anything, input, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, false, errors.New("error")) }, @@ -637,35 +680,45 @@ func TestMode1_Update(t *testing.T) { }, wantErr: true, }, + { + name: "should not error when updating an object in UnifiedStorage fails", + setupLegacyFn: func(m *mock.Mock, input string) { + m.On("Update", mock.Anything, input, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + }, + setupStorageFn: func(m *mock.Mock, input string) { + m.On("Update", mock.Anything, input, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, false, errors.New("error")) + }, + }, } + name := "foo" + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, name) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) + tt.setupStorageFn(us.Mock, name) } dw := NewDualWriter(Mode1, ls, us, p, kind) - obj, _, err := dw.Update(context.Background(), tt.input, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{}) + obj, _, err := dw.Update(context.Background(), name, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{}) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } - assert.Equal(t, obj, exampleObj) - assert.NotEqual(t, obj, anotherObj) + require.Equal(t, obj, exampleObj) + require.NotEqual(t, obj, anotherObj) }) } } @@ -680,13 +733,11 @@ func TestMode1_UpdateOnUnifiedStorage(t *testing.T) { setupStorageFn func(m *mock.Mock, input string) setupGetFn func(m *mock.Mock, input string) name string - input string } tests := []testCase{ { - name: "Update on unified storage", - input: "foo", + name: "should succeed when updating an object on UnifiedStorage", setupStorageFn: func(m *mock.Mock, input string) { m.On("Update", mock.Anything, input, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(anotherObj, false, nil) }, @@ -695,9 +746,8 @@ func TestMode1_UpdateOnUnifiedStorage(t *testing.T) { }, }, { - name: "Update on unified storage works even if parent context is canceled", - ctx: &ctxCanceled, - input: "foo", + name: "should succeed when updating an object on UnifiedStorage even if parent context is canceled", + ctx: &ctxCanceled, setupStorageFn: func(m *mock.Mock, input string) { m.On("Update", mock.Anything, input, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(anotherObj, false, nil) }, @@ -707,24 +757,26 @@ func TestMode1_UpdateOnUnifiedStorage(t *testing.T) { }, } + name := "foo" + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, name) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) + tt.setupStorageFn(us.Mock, name) } if tt.setupGetFn != nil { - tt.setupGetFn(m, tt.input) + tt.setupGetFn(ls.Mock, name) + tt.setupGetFn(us.Mock, name) } ctx := context.TODO() @@ -734,8 +786,8 @@ func TestMode1_UpdateOnUnifiedStorage(t *testing.T) { dw := NewDualWriter(Mode1, ls, us, p, kind) - err := dw.(*DualWriterMode1).updateOnUnifiedStorageMode1(ctx, exampleObj, tt.input, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{}) - assert.NoError(t, err) + err := dw.(*DualWriterMode1).updateOnUnifiedStorageMode1(ctx, exampleObj, name, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{}) + require.NoError(t, err) }) } } diff --git a/pkg/apiserver/rest/dualwriter_mode2_test.go b/pkg/apiserver/rest/dualwriter_mode2_test.go index 4d150ac2ad7..6e67ac0fe59 100644 --- a/pkg/apiserver/rest/dualwriter_mode2_test.go +++ b/pkg/apiserver/rest/dualwriter_mode2_test.go @@ -29,21 +29,25 @@ func TestMode2_Create(t *testing.T) { tests := []testCase{ { - name: "creating an object in both the LegacyStorage and Storage", + name: "should create an object in both the LegacyStorage and Storage", input: exampleObj, setupLegacyFn: func(m *mock.Mock, input runtime.Object) { - m.On("Create", mock.Anything, exampleObjNoRV, mock.Anything, mock.Anything).Return(exampleObj, nil) + m.On("Create", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, nil) }, - setupStorageFn: func(m *mock.Mock, input runtime.Object) { - m.On("Create", mock.Anything, exampleObj, mock.Anything, mock.Anything).Return(exampleObj, nil) + setupStorageFn: func(m *mock.Mock, _ runtime.Object) { + // We don't use the input here, as the input is transformed before being passed to unified storage. + m.On("Create", mock.Anything, exampleObjNoRV, mock.Anything, mock.Anything).Return(exampleObj, nil) }, }, { - name: "error when creating object in the legacy store fails", + name: "should return an error when creating an object in the LegacyStorage fails", input: failingObj, setupLegacyFn: func(m *mock.Mock, input runtime.Object) { m.On("Create", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, errors.New("error")) }, + setupStorageFn: func(m *mock.Mock, input runtime.Object) { + m.On("Create", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, nil) + }, wantErr: true, }, } @@ -52,16 +56,15 @@ func TestMode2_Create(t *testing.T) { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, tt.input) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) + tt.setupStorageFn(us.Mock, tt.input) } dw := NewDualWriter(Mode2, ls, us, p, kind) @@ -89,7 +92,7 @@ func TestMode2_Get(t *testing.T) { tests := []testCase{ { - name: "getting an object from storage", + name: "should get an object from both the LegacyStorage and Storage", input: "foo", setupLegacyFn: func(m *mock.Mock, input string) { m.On("Get", mock.Anything, input, mock.Anything).Return(exampleObj, nil) @@ -99,7 +102,7 @@ func TestMode2_Get(t *testing.T) { }, }, { - name: "object not present in storage but present in legacy store", + name: "should return an error when getting an object from the Storage fails", input: "foo", setupLegacyFn: func(m *mock.Mock, input string) { m.On("Get", mock.Anything, input, mock.Anything).Return(exampleObj, nil) @@ -107,9 +110,22 @@ func TestMode2_Get(t *testing.T) { setupStorageFn: func(m *mock.Mock, input string) { m.On("Get", mock.Anything, input, mock.Anything).Return(nil, errors.New("error")) }, + wantErr: true, }, { - name: "error when getting object in both stores fails", + name: "should not error when object is not found in the Storage but found in the LegacyStorage", + input: "foo", + setupLegacyFn: func(m *mock.Mock, input string) { + m.On("Get", mock.Anything, input, mock.Anything).Return(exampleObj, nil) + }, + setupStorageFn: func(m *mock.Mock, input string) { + m.On("Get", mock.Anything, input, mock.Anything).Return(nil, apierrors.NewNotFound( + schema.GroupResource{Group: "", Resource: "pods"}, "not-found")) + }, + wantErr: true, + }, + { + name: "should return an error when getting an object from both the LegacyStorage and Storage fails", input: "object-fail", setupLegacyFn: func(m *mock.Mock, input string) { m.On("Get", mock.Anything, input, mock.Anything).Return(nil, errors.New("error")) @@ -125,16 +141,15 @@ func TestMode2_Get(t *testing.T) { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, tt.input) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) + tt.setupStorageFn(us.Mock, tt.input) } dw := NewDualWriter(Mode2, ls, us, p, kind) @@ -163,7 +178,7 @@ func TestMode2_List(t *testing.T) { tests := []testCase{ { - name: "object present in both Storage and LegacyStorage", + name: "should return a list of objects from both the LegacyStorage and Storage", inputLegacy: exampleOption, setupLegacyFn: func(m *mock.Mock) { m.On("List", mock.Anything, mock.Anything).Return(exampleList, nil) @@ -172,168 +187,25 @@ func TestMode2_List(t *testing.T) { m.On("List", mock.Anything, mock.Anything).Return(anotherList, nil) }, }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - l := (LegacyStorage)(nil) - s := (Storage)(nil) - m := &mock.Mock{} - - ls := legacyStoreMock{m, l} - us := storageMock{m, s} - - if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m) - } - if tt.setupStorageFn != nil { - tt.setupStorageFn(m) - } - - dw := NewDualWriter(Mode2, ls, us, p, kind) - - obj, err := dw.List(context.Background(), &metainternalversion.ListOptions{}) - - if tt.wantErr { - require.Error(t, err) - return - } - require.Equal(t, exampleList, obj) - }) - } -} - -func TestMode2_Delete(t *testing.T) { - type testCase struct { - setupLegacyFn func(m *mock.Mock, input string) - setupStorageFn func(m *mock.Mock, input string) - name string - input string - wantErr bool - } - tests := - []testCase{ { - name: "delete in legacy and storage", - input: "foo", - setupLegacyFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) - }, - setupStorageFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) - }, - }, - { - name: "object delete in legacy not found, but found in storage", - input: "foo", - setupLegacyFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, "not-found-legacy", mock.Anything, mock.Anything).Return(nil, false, apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "pods"}, "not-found")) - }, - setupStorageFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) - }, - }, - { - name: " object delete in storage not found, but found in legacy", - input: "foo", - setupLegacyFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) - }, - setupStorageFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, "not-found-storage", mock.Anything, mock.Anything).Return(nil, false, apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "pods"}, "not-found")) - }, - }, - { - name: " object not found in both", - input: "object-fail", - setupLegacyFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "pods"}, "not-found")) - }, - setupStorageFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "pods"}, "not-found")) - }, - wantErr: true, - }, - { - name: " object delete error", - input: "object-fail", - setupLegacyFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, errors.New("error")) - }, - setupStorageFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, errors.New("error")) - }, - wantErr: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - l := (LegacyStorage)(nil) - s := (Storage)(nil) - m := &mock.Mock{} - - ls := legacyStoreMock{m, l} - us := storageMock{m, s} - - if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) - } - if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) - } - - dw := NewDualWriter(Mode2, ls, us, p, kind) - - obj, _, err := dw.Delete(context.Background(), tt.input, func(context.Context, runtime.Object) error { return nil }, &metav1.DeleteOptions{}) - - if tt.wantErr { - require.Error(t, err) - return - } - - require.Equal(t, obj, exampleObj) - require.NotEqual(t, obj, anotherObj) - }) - } -} - -func TestMode2_DeleteCollection(t *testing.T) { - type testCase struct { - setupLegacyFn func(m *mock.Mock) - setupStorageFn func(m *mock.Mock) - name string - input string - wantErr bool - } - tests := - []testCase{ - { - name: "deleting a collection in both stores", - input: "foo", + name: "should return an error when listing objects from the LegacyStorage fails", + inputLegacy: exampleOption, setupLegacyFn: func(m *mock.Mock) { - m.On("DeleteCollection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleList, nil) + m.On("List", mock.Anything, mock.Anything).Return(nil, errors.New("error")) }, setupStorageFn: func(m *mock.Mock) { - m.On("DeleteCollection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleList, nil) - }, - }, - { - name: "error deleting a collection in the storage when legacy store is successful", - input: "fail", - setupLegacyFn: func(m *mock.Mock) { - m.On("DeleteCollection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleObj, nil) - }, - setupStorageFn: func(m *mock.Mock) { - m.On("DeleteCollection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("error")) + m.On("List", mock.Anything, mock.Anything).Return(anotherList, nil) }, wantErr: true, }, { - name: "deleting a collection when error in legacy store", - input: "fail", + name: "should return an error when listing objects from the Storage fails", + inputLegacy: exampleOption, setupLegacyFn: func(m *mock.Mock) { - m.On("DeleteCollection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("error")) + m.On("List", mock.Anything, mock.Anything).Return(exampleList, nil) + }, + setupStorageFn: func(m *mock.Mock) { + m.On("List", mock.Anything, mock.Anything).Return(nil, errors.New("error")) }, wantErr: true, }, @@ -356,7 +228,177 @@ func TestMode2_DeleteCollection(t *testing.T) { dw := NewDualWriter(Mode2, ls, us, p, kind) - obj, err := dw.DeleteCollection(context.Background(), func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{TypeMeta: metav1.TypeMeta{Kind: tt.input}}, &metainternalversion.ListOptions{}) + obj, err := dw.List(context.Background(), &metainternalversion.ListOptions{}) + + if tt.wantErr { + require.Error(t, err) + return + } + require.Equal(t, exampleList, obj) + }) + } +} + +func TestMode2_Delete(t *testing.T) { + type testCase struct { + setupLegacyFn func(m *mock.Mock, input string) + setupStorageFn func(m *mock.Mock, input string) + name string + wantErr bool + } + tests := + []testCase{ + { + name: "should delete an object from both the LegacyStorage and Storage", + setupLegacyFn: func(m *mock.Mock, input string) { + m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + }, + setupStorageFn: func(m *mock.Mock, input string) { + m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + }, + }, + { + name: "should return an error when deleting an object from the LegacyStorage fails", + setupLegacyFn: func(m *mock.Mock, input string) { + m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, errors.New("error")) + }, + setupStorageFn: func(m *mock.Mock, input string) { + m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + }, + wantErr: true, + }, + { + name: "should return an error when deleting an object from the Storage fails", + setupLegacyFn: func(m *mock.Mock, input string) { + m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + }, + setupStorageFn: func(m *mock.Mock, input string) { + m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, errors.New("error")) + }, + wantErr: true, + }, + { + name: "should return an error when the object is not found in LegacyStorage", + setupLegacyFn: func(m *mock.Mock, input string) { + m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, + apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "pods"}, input)) + }, + setupStorageFn: func(m *mock.Mock, input string) { + m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + }, + wantErr: true, + }, + { + name: "should not return an error when the object is not found in Storage", + setupLegacyFn: func(m *mock.Mock, input string) { + m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + }, + setupStorageFn: func(m *mock.Mock, input string) { + m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, + apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "pods"}, input)) + }, + }, + { + name: "should return an error when deleting an object from both the LegacyStorage and Storage fails", + setupLegacyFn: func(m *mock.Mock, input string) { + m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, errors.New("error")) + }, + setupStorageFn: func(m *mock.Mock, input string) { + m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, errors.New("error")) + }, + wantErr: true, + }, + } + + name := "foo" + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + l := (LegacyStorage)(nil) + s := (Storage)(nil) + + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} + + if tt.setupLegacyFn != nil { + tt.setupLegacyFn(ls.Mock, name) + } + if tt.setupStorageFn != nil { + tt.setupStorageFn(us.Mock, name) + } + + dw := NewDualWriter(Mode2, ls, us, p, kind) + + obj, _, err := dw.Delete(context.Background(), name, func(context.Context, runtime.Object) error { return nil }, &metav1.DeleteOptions{}) + + if tt.wantErr { + require.Error(t, err) + return + } + + require.Equal(t, obj, exampleObj) + require.NotEqual(t, obj, anotherObj) + }) + } +} + +func TestMode2_DeleteCollection(t *testing.T) { + type testCase struct { + setupLegacyFn func(m *mock.Mock) + setupStorageFn func(m *mock.Mock) + name string + wantErr bool + } + tests := + []testCase{ + { + name: "should delete a collection from both the LegacyStorage and Storage", + setupLegacyFn: func(m *mock.Mock) { + m.On("DeleteCollection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleList, nil) + }, + setupStorageFn: func(m *mock.Mock) { + m.On("DeleteCollection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleList, nil) + }, + }, + { + name: "should return an error when deleting a collection from the Storage fails", + setupLegacyFn: func(m *mock.Mock) { + m.On("DeleteCollection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleList, nil) + }, + setupStorageFn: func(m *mock.Mock) { + m.On("DeleteCollection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("error")) + }, + wantErr: true, + }, + { + name: "should return an error when deleting a collection from the LegacyStorage fails", + setupLegacyFn: func(m *mock.Mock) { + m.On("DeleteCollection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("error")) + }, + wantErr: true, + }, + } + + name := "foo" + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + l := (LegacyStorage)(nil) + s := (Storage)(nil) + + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} + + if tt.setupLegacyFn != nil { + tt.setupLegacyFn(ls.Mock) + } + if tt.setupStorageFn != nil { + tt.setupStorageFn(us.Mock) + } + + dw := NewDualWriter(Mode2, ls, us, p, kind) + + obj, err := dw.DeleteCollection(context.Background(), func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{TypeMeta: metav1.TypeMeta{Kind: name}}, &metainternalversion.ListOptions{}) if tt.wantErr { require.Error(t, err) @@ -373,14 +415,12 @@ func TestMode2_Update(t *testing.T) { setupLegacyFn func(m *mock.Mock, input string) setupStorageFn func(m *mock.Mock, input string) name string - input string wantErr bool } tests := []testCase{ { - name: "update an object in both stores", - input: "foo", + name: "should succeed when updating an object in both the LegacyStorage and Storage is successful", setupLegacyFn: func(m *mock.Mock, input string) { m.On("Update", mock.Anything, input, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleObj, false, nil) }, @@ -390,34 +430,44 @@ func TestMode2_Update(t *testing.T) { expectedObj: exampleObj, }, { - name: "error updating legacy store", - input: "object-fail", + name: "should return an error when updating the LegacyStorage fails", setupLegacyFn: func(m *mock.Mock, input string) { m.On("Update", mock.Anything, input, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, false, errors.New("error")) }, wantErr: true, }, + { + name: "should return an error when updating the Storage fails", + setupLegacyFn: func(m *mock.Mock, input string) { + m.On("Update", mock.Anything, input, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + }, + setupStorageFn: func(m *mock.Mock, input string) { + m.On("Update", mock.Anything, input, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, false, errors.New("error")) + }, + wantErr: true, + }, } + name := "foo" + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, name) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) + tt.setupStorageFn(us.Mock, name) } dw := NewDualWriter(Mode2, ls, us, p, kind) - obj, _, err := dw.Update(context.Background(), tt.input, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{}) + obj, _, err := dw.Update(context.Background(), name, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{}) if tt.wantErr { require.Error(t, err) diff --git a/pkg/apiserver/rest/dualwriter_mode3_test.go b/pkg/apiserver/rest/dualwriter_mode3_test.go index d5ddbe04a88..bc8635b2fd7 100644 --- a/pkg/apiserver/rest/dualwriter_mode3_test.go +++ b/pkg/apiserver/rest/dualwriter_mode3_test.go @@ -6,8 +6,8 @@ import ( "testing" "github.com/prometheus/client_golang/prometheus" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" apierrors "k8s.io/apimachinery/pkg/api/errors" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -26,17 +26,18 @@ func TestMode3_Create(t *testing.T) { tests := []testCase{ { - name: "creating an object in both the LegacyStorage and Storage", + name: "should succeed when creating an object in both the LegacyStorage and Storage", input: exampleObj, setupLegacyFn: func(m *mock.Mock, input runtime.Object) { - m.On("Create", mock.Anything, exampleObjNoRV, mock.Anything, mock.Anything).Return(exampleObj, nil).Once() + m.On("Create", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, nil).Once() }, - setupStorageFn: func(m *mock.Mock, input runtime.Object) { - m.On("Create", mock.Anything, exampleObj, mock.Anything, mock.Anything).Return(exampleObj, nil).Once() + setupStorageFn: func(m *mock.Mock, _ runtime.Object) { + // We don't use the input here, as the input is transformed before being passed to unified storage. + m.On("Create", mock.Anything, exampleObjNoRV, mock.Anything, mock.Anything).Return(exampleObj, nil).Once() }, }, { - name: "error when creating object in the legacy store fails", + name: "should return an error when creating an object in the legacy store fails", input: failingObj, setupLegacyFn: func(m *mock.Mock, input runtime.Object) { m.On("Create", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, errors.New("error")).Once() @@ -44,14 +45,15 @@ func TestMode3_Create(t *testing.T) { wantErr: true, }, { - name: "error when creating object in the unistore fails - legacy delete should be called", + name: "should return an error when creating an object in the unified store fails and delete from LegacyStorage", input: exampleObj, setupLegacyFn: func(m *mock.Mock, input runtime.Object) { m.On("Delete", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleObj, true, nil).Once() - m.On("Create", mock.Anything, exampleObjNoRV, mock.Anything, mock.Anything).Return(exampleObj, nil).Once() + m.On("Create", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, nil).Once() }, - setupStorageFn: func(m *mock.Mock, input runtime.Object) { - m.On("Create", mock.Anything, exampleObj, mock.Anything, mock.Anything).Return(exampleObj, errors.New("error")).Once() + setupStorageFn: func(m *mock.Mock, _ runtime.Object) { + // We don't use the input here, as the input is transformed before being passed to unified storage. + m.On("Create", mock.Anything, exampleObjNoRV, mock.Anything, mock.Anything).Return(nil, errors.New("error")).Once() }, wantErr: true, }, @@ -61,16 +63,15 @@ func TestMode3_Create(t *testing.T) { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, tt.input) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) + tt.setupStorageFn(us.Mock, tt.input) } dw := NewDualWriter(Mode3, ls, us, p, kind) @@ -78,66 +79,83 @@ func TestMode3_Create(t *testing.T) { obj, err := dw.Create(context.Background(), tt.input, createFn, &metav1.CreateOptions{}) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } - assert.Equal(t, exampleObj, obj) + require.Equal(t, exampleObj, obj) }) } } func TestMode3_Get(t *testing.T) { type testCase struct { + setupLegacyFn func(m *mock.Mock, name string) setupStorageFn func(m *mock.Mock, name string) name string - input string wantErr bool } tests := []testCase{ { - name: "get an object only in unified store", - input: "foo", + name: "should succeed when getting an object from both stores", + setupLegacyFn: func(m *mock.Mock, name string) { + m.On("Get", mock.Anything, name, mock.Anything).Return(exampleObj, nil) + }, setupStorageFn: func(m *mock.Mock, name string) { m.On("Get", mock.Anything, name, mock.Anything).Return(exampleObj, nil) }, }, { - name: "error when getting an object in the unified store fails", - input: "object-fail", + name: "should return an error when getting an object in the unified store fails", + setupLegacyFn: func(m *mock.Mock, name string) { + m.On("Get", mock.Anything, name, mock.Anything).Return(exampleObj, nil) + }, setupStorageFn: func(m *mock.Mock, name string) { m.On("Get", mock.Anything, name, mock.Anything).Return(nil, errors.New("error")) }, wantErr: true, }, + { + name: "should succeed when getting an object in the LegacyStorage fails", + setupLegacyFn: func(m *mock.Mock, name string) { + m.On("Get", mock.Anything, name, mock.Anything).Return(nil, errors.New("error")) + }, + setupStorageFn: func(m *mock.Mock, name string) { + m.On("Get", mock.Anything, name, mock.Anything).Return(exampleObj, nil) + }, + }, } + name := "foo" + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} + if tt.setupLegacyFn != nil { + tt.setupLegacyFn(ls.Mock, name) + } if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) + tt.setupStorageFn(us.Mock, name) } p := prometheus.NewRegistry() dw := NewDualWriter(Mode3, ls, us, p, kind) - obj, err := dw.Get(context.Background(), tt.input, &metav1.GetOptions{}) + obj, err := dw.Get(context.Background(), name, &metav1.GetOptions{}) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } - assert.Equal(t, obj, exampleObj) - assert.NotEqual(t, obj, anotherObj) + require.Equal(t, obj, exampleObj) + require.NotEqual(t, obj, anotherObj) }) } } @@ -150,38 +168,36 @@ func TestMode1_GetFromLegacyStorage(t *testing.T) { setupLegacyFn func(m *mock.Mock, name string) ctx *context.Context name string - input string } tests := []testCase{ { - name: "Get from legacy storage", - input: "foo", + name: "should succeed when getting an object from the LegacyStorage", setupLegacyFn: func(m *mock.Mock, name string) { m.On("Get", mock.Anything, name, mock.Anything).Return(exampleObj, nil) }, }, { - name: "Get from legacy storage works even if parent context is canceled", - input: "foo", - ctx: &ctxCanceled, + name: "should succeed when getting an object from the LegacyStorage even if parent context is canceled", + ctx: &ctxCanceled, setupLegacyFn: func(m *mock.Mock, name string) { m.On("Get", mock.Anything, name, mock.Anything).Return(exampleObj, nil) }, }, } + name := "foo" + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, name) } ctx := context.TODO() @@ -190,8 +206,8 @@ func TestMode1_GetFromLegacyStorage(t *testing.T) { } dw := NewDualWriter(Mode3, ls, us, p, kind) - err := dw.(*DualWriterMode3).getFromLegacyStorage(ctx, exampleObj, tt.input, &metav1.GetOptions{}) - assert.NoError(t, err) + err := dw.(*DualWriterMode3).getFromLegacyStorage(ctx, exampleObj, name, &metav1.GetOptions{}) + require.NoError(t, err) }) } } @@ -200,22 +216,19 @@ func TestMode3_List(t *testing.T) { type testCase struct { setupStorageFn func(m *mock.Mock, options *metainternalversion.ListOptions) name string - options *metainternalversion.ListOptions wantErr bool } tests := []testCase{ { - name: "error when listing an object in the unified store is not implemented", - options: &metainternalversion.ListOptions{TypeMeta: metav1.TypeMeta{Kind: "fail"}}, + name: "should return an error when listing an object in the UnifiedStorage is failing", setupStorageFn: func(m *mock.Mock, options *metainternalversion.ListOptions) { m.On("List", mock.Anything, options).Return(nil, errors.New("error")) }, wantErr: true, }, { - name: "list objects in the unified store", - options: &metainternalversion.ListOptions{TypeMeta: metav1.TypeMeta{Kind: "foo"}}, + name: "should succeed when listing objects in the UnifiedStorage is successful", setupStorageFn: func(m *mock.Mock, options *metainternalversion.ListOptions) { m.On("List", mock.Anything, options).Return(exampleList, nil) }, @@ -226,26 +239,25 @@ func TestMode3_List(t *testing.T) { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.options) + tt.setupStorageFn(us.Mock, &metainternalversion.ListOptions{TypeMeta: metav1.TypeMeta{Kind: "foo"}}) } dw := NewDualWriter(Mode3, ls, us, p, kind) - res, err := dw.List(context.Background(), tt.options) + res, err := dw.List(context.Background(), &metainternalversion.ListOptions{TypeMeta: metav1.TypeMeta{Kind: "foo"}}) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } - assert.Equal(t, exampleList, res) - assert.NotEqual(t, anotherList, res) + require.Equal(t, exampleList, res) + require.NotEqual(t, anotherList, res) }) } } @@ -255,14 +267,12 @@ func TestMode3_Delete(t *testing.T) { setupLegacyFn func(m *mock.Mock, input string) setupStorageFn func(m *mock.Mock, input string) name string - input string wantErr bool } tests := []testCase{ { - name: "delete in legacy and storage", - input: "foo", + name: "should succeed when deleting an object in both stores", setupLegacyFn: func(m *mock.Mock, input string) { m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) }, @@ -271,39 +281,25 @@ func TestMode3_Delete(t *testing.T) { }, }, { - name: "object delete in legacy not found, but found in storage", - input: "foo", + name: "should succeed when deleting an object in the LegacyStorage is not found, but found in the UnifiedStorage", setupLegacyFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, "not-found-legacy", mock.Anything, mock.Anything).Return(nil, false, apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "pods"}, "not-found")) + m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "pods"}, input)) }, setupStorageFn: func(m *mock.Mock, input string) { m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) }, }, { - name: " object delete in storage not found, but found in legacy", - input: "foo", + name: "should succeed when deleting an object in the UnifiedStorage is not found in the LegacyStorage", setupLegacyFn: func(m *mock.Mock, input string) { + m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "pods"}, input)) + }, + setupStorageFn: func(m *mock.Mock, input string) { m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(exampleObj, false, nil) }, - setupStorageFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, "not-found-storage", mock.Anything, mock.Anything).Return(nil, false, apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "pods"}, "not-found")) - }, }, { - name: " object not found in both", - input: "object-fail", - setupLegacyFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "pods"}, "not-found")) - }, - setupStorageFn: func(m *mock.Mock, input string) { - m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "pods"}, "not-found")) - }, - wantErr: true, - }, - { - name: " object delete error", - input: "object-fail", + name: "should return an error when deleting an object in the LegacyStorage and UnifiedStorage is failing", setupLegacyFn: func(m *mock.Mock, input string) { m.On("Delete", mock.Anything, input, mock.Anything, mock.Anything).Return(nil, false, errors.New("error")) }, @@ -314,33 +310,34 @@ func TestMode3_Delete(t *testing.T) { }, } + name := "foo" + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, name) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) + tt.setupStorageFn(us.Mock, name) } dw := NewDualWriter(Mode3, ls, us, p, kind) - obj, _, err := dw.Delete(context.Background(), tt.input, func(context.Context, runtime.Object) error { return nil }, &metav1.DeleteOptions{}) + obj, _, err := dw.Delete(context.Background(), name, func(context.Context, runtime.Object) error { return nil }, &metav1.DeleteOptions{}) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } - assert.Equal(t, obj, exampleObj) - assert.NotEqual(t, obj, anotherObj) + require.Equal(t, obj, exampleObj) + require.NotEqual(t, obj, anotherObj) }) } } @@ -350,14 +347,12 @@ func TestMode3_DeleteCollection(t *testing.T) { setupLegacyFn func(m *mock.Mock) setupStorageFn func(m *mock.Mock) name string - input string wantErr bool } tests := []testCase{ { - name: "deleting a collection in both stores", - input: "foo", + name: "should succeed when deleting a collection in both stores", setupLegacyFn: func(m *mock.Mock) { m.On("DeleteCollection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleList, nil) }, @@ -366,8 +361,7 @@ func TestMode3_DeleteCollection(t *testing.T) { }, }, { - name: "error deleting a collection in the storage when legacy store is successful", - input: "foo", + name: "should return an error when deleting a collection in the storage fails and LegacyStorage is successful", setupLegacyFn: func(m *mock.Mock) { m.On("DeleteCollection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleObj, nil) }, @@ -377,40 +371,40 @@ func TestMode3_DeleteCollection(t *testing.T) { wantErr: true, }, { - name: "error deleting a collection legacy store", - input: "fail", + name: "should return an error when deleting a collection in the LegacyStorage fails", setupLegacyFn: func(m *mock.Mock) { - m.On("DeleteCollection", mock.Anything, mock.Anything, &metav1.DeleteOptions{TypeMeta: metav1.TypeMeta{Kind: "fail"}}, mock.Anything).Return(nil, errors.New("error")) + m.On("DeleteCollection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("error")) }, wantErr: true, }, } + name := "foo" + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m) + tt.setupLegacyFn(ls.Mock) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m) + tt.setupStorageFn(us.Mock) } dw := NewDualWriter(Mode3, ls, us, p, kind) - obj, err := dw.DeleteCollection(context.Background(), func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{TypeMeta: metav1.TypeMeta{Kind: tt.input}}, &metainternalversion.ListOptions{}) + obj, err := dw.DeleteCollection(context.Background(), func(ctx context.Context, obj runtime.Object) error { return nil }, &metav1.DeleteOptions{TypeMeta: metav1.TypeMeta{Kind: name}}, &metainternalversion.ListOptions{}) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } - assert.Equal(t, exampleList, obj) + require.Equal(t, exampleList, obj) }) } } @@ -421,14 +415,12 @@ func TestMode3_Update(t *testing.T) { setupLegacyFn func(m *mock.Mock, input string) setupStorageFn func(m *mock.Mock, input string) name string - input string wantErr bool } tests := []testCase{ { - name: "update an object in both stores", - input: "foo", + name: "should succeed when updating an object in both stores", setupLegacyFn: func(m *mock.Mock, input string) { m.On("Update", mock.Anything, input, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleObj, false, nil).Once() }, @@ -438,16 +430,14 @@ func TestMode3_Update(t *testing.T) { expectedObj: exampleObj, }, { - name: "error updating legacy store", - input: "object-fail", + name: "should return an error when updating an object in the LegacyStorage fails", setupLegacyFn: func(m *mock.Mock, input string) { m.On("Update", mock.Anything, input, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, false, errors.New("error")).Once() }, wantErr: true, }, { - name: "error updating unistore", - input: "object-fail", + name: "should return an error when updating an object in the UnifiedStorage fails", setupLegacyFn: func(m *mock.Mock, input string) { m.On("Update", mock.Anything, input, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleObj, false, nil).Once() }, @@ -458,33 +448,34 @@ func TestMode3_Update(t *testing.T) { }, } + name := "foo" + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + ls := legacyStoreMock{&mock.Mock{}, l} + us := storageMock{&mock.Mock{}, s} if tt.setupLegacyFn != nil { - tt.setupLegacyFn(m, tt.input) + tt.setupLegacyFn(ls.Mock, name) } if tt.setupStorageFn != nil { - tt.setupStorageFn(m, tt.input) + tt.setupStorageFn(us.Mock, name) } dw := NewDualWriter(Mode3, ls, us, p, kind) - obj, _, err := dw.Update(context.Background(), tt.input, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{}) + obj, _, err := dw.Update(context.Background(), name, updatedObjInfoObj{}, func(ctx context.Context, obj runtime.Object) error { return nil }, func(ctx context.Context, obj, old runtime.Object) error { return nil }, false, &metav1.UpdateOptions{}) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } - assert.Equal(t, tt.expectedObj, obj) - assert.NotEqual(t, anotherObj, obj) + require.Equal(t, tt.expectedObj, obj) + require.NotEqual(t, anotherObj, obj) }) } } diff --git a/pkg/apiserver/rest/dualwriter_test.go b/pkg/apiserver/rest/dualwriter_test.go index e299ae91e3f..44f969351c1 100644 --- a/pkg/apiserver/rest/dualwriter_test.go +++ b/pkg/apiserver/rest/dualwriter_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/apis/example" @@ -57,13 +57,16 @@ func TestSetDualWritingMode(t *testing.T) { for _, tt := range tests { l := (LegacyStorage)(nil) s := (Storage)(nil) - m := &mock.Mock{} - m.On("List", mock.Anything, mock.Anything).Return(exampleList, nil) - m.On("List", mock.Anything, mock.Anything).Return(anotherList, nil) + sm := &mock.Mock{} + sm.On("List", mock.Anything, mock.Anything).Return(anotherList, nil) + sm.On("Update", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + sm.On("Delete", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(exampleObj, false, nil) + us := storageMock{sm, s} - ls := legacyStoreMock{m, l} - us := storageMock{m, s} + lm := &mock.Mock{} + lm.On("List", mock.Anything, mock.Anything).Return(exampleList, nil) + ls := legacyStoreMock{lm, l} dwMode, err := SetDualWritingMode(context.Background(), tt.kvStore, &SyncerConfig{ LegacyStorage: ls, @@ -77,8 +80,8 @@ func TestSetDualWritingMode(t *testing.T) { DataSyncerRecordsLimit: 1000, DataSyncerInterval: time.Hour, }) - assert.NoError(t, err) - assert.Equal(t, tt.expectedMode, dwMode) + require.NoError(t, err) + require.Equal(t, tt.expectedMode, dwMode) } } @@ -121,7 +124,7 @@ func TestCompare(t *testing.T) { } for _, tt := range testCase { t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.expected, Compare(tt.input1, tt.input2)) + require.Equal(t, tt.expected, Compare(tt.input1, tt.input2)) }) } } diff --git a/pkg/apiserver/rest/storage_mocks_test.go b/pkg/apiserver/rest/storage_mocks_test.go index 5e818b99560..582bcdc067c 100644 --- a/pkg/apiserver/rest/storage_mocks_test.go +++ b/pkg/apiserver/rest/storage_mocks_test.go @@ -5,7 +5,6 @@ import ( "errors" "github.com/stretchr/testify/mock" - "k8s.io/apimachinery/pkg/api/meta" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -30,8 +29,8 @@ func (m legacyStoreMock) Get(ctx context.Context, name string, options *metav1.G } args := m.Called(ctx, name, options) - if name == "object-fail" { - return nil, args.Error(1) + if err := args.Get(1); err != nil { + return nil, err.(error) } return args.Get(0).(runtime.Object), args.Error(1) } @@ -44,13 +43,8 @@ func (m legacyStoreMock) Create(ctx context.Context, obj runtime.Object, createV } args := m.Called(ctx, obj, createValidation, options) - acc, err := meta.Accessor(obj) - if err != nil { - return nil, args.Error(1) - } - name := acc.GetName() - if name == "object-fail" { - return nil, args.Error(1) + if err := args.Get(1); err != nil { + return nil, err.(error) } return args.Get(0).(runtime.Object), args.Error(1) } @@ -63,8 +57,8 @@ func (m legacyStoreMock) List(ctx context.Context, options *metainternalversion. } args := m.Called(ctx, options) - if options.Kind == "fail" { - return nil, args.Error(1) + if err := args.Get(1); err != nil { + return nil, err.(error) } return args.Get(0).(runtime.Object), args.Error(1) } @@ -80,8 +74,8 @@ func (m legacyStoreMock) Update(ctx context.Context, name string, objInfo rest.U default: } args := m.Called(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options) - if name == "object-fail" { - return nil, false, args.Error(2) + if err := args.Get(2); err != nil { + return nil, false, err.(error) } return args.Get(0).(runtime.Object), args.Bool(1), args.Error(2) } @@ -94,11 +88,8 @@ func (m legacyStoreMock) Delete(ctx context.Context, name string, deleteValidati } args := m.Called(ctx, name, deleteValidation, options) - if name == "object-fail" { - return nil, false, args.Error(2) - } - if name == "not-found-legacy" { - return nil, false, args.Error(2) + if err := args.Get(2); err != nil { + return nil, false, err.(error) } return args.Get(0).(runtime.Object), args.Bool(1), args.Error(2) } @@ -110,8 +101,8 @@ func (m legacyStoreMock) DeleteCollection(ctx context.Context, deleteValidation default: } args := m.Called(ctx, deleteValidation, options, listOptions) - if options.Kind == "fail" { - return nil, args.Error(1) + if err := args.Get(1); err != nil { + return nil, err.(error) } return args.Get(0).(runtime.Object), args.Error(1) } @@ -125,11 +116,8 @@ func (m storageMock) Get(ctx context.Context, name string, options *metav1.GetOp } args := m.Called(ctx, name, options) - if name == "object-fail" { - return nil, args.Error(1) - } - if name == "not-found" { - return nil, args.Error(1) + if err := args.Get(1); err != nil { + return nil, err.(error) } return args.Get(0).(runtime.Object), args.Error(1) } @@ -142,13 +130,8 @@ func (m storageMock) Create(ctx context.Context, obj runtime.Object, createValid } args := m.Called(ctx, obj, createValidation, options) - acc, err := meta.Accessor(obj) - if err != nil { - return nil, args.Error(1) - } - name := acc.GetName() - if name == "object-fail" { - return nil, args.Error(1) + if err := args.Get(1); err != nil { + return nil, err.(error) } return args.Get(0).(runtime.Object), args.Error(1) } @@ -161,8 +144,8 @@ func (m storageMock) List(ctx context.Context, options *metainternalversion.List } args := m.Called(ctx, options) - if options.Kind == "fail" { - return nil, args.Error(1) + if err := args.Get(1); err != nil { + return nil, err.(error) } return args.Get(0).(runtime.Object), args.Error(1) } @@ -179,8 +162,8 @@ func (m storageMock) Update(ctx context.Context, name string, objInfo rest.Updat } args := m.Called(ctx, name, objInfo, createValidation, updateValidation, forceAllowCreate, options) - if name == "object-fail" { - return nil, false, args.Error(2) + if err := args.Get(2); err != nil { + return nil, false, err.(error) } return args.Get(0).(runtime.Object), args.Bool(1), args.Error(2) } @@ -193,8 +176,8 @@ func (m storageMock) Delete(ctx context.Context, name string, deleteValidation r } args := m.Called(ctx, name, deleteValidation, options) - if name == "object-fail" { - return nil, false, args.Error(2) + if err := args.Get(2); err != nil { + return nil, false, err.(error) } return args.Get(0).(runtime.Object), args.Bool(1), args.Error(2) } @@ -207,8 +190,8 @@ func (m storageMock) DeleteCollection(ctx context.Context, deleteValidation rest } args := m.Called(ctx, deleteValidation, options, listOptions) - if options.Kind == "fail" { - return nil, args.Error(1) + if err := args.Get(1); err != nil { + return nil, err.(error) } return args.Get(0).(runtime.Object), args.Error(1) }