diff --git a/cloud/scope/machine_test.go b/cloud/scope/machine_test.go index fa100581f..12e390208 100644 --- a/cloud/scope/machine_test.go +++ b/cloud/scope/machine_test.go @@ -110,25 +110,27 @@ func TestValidateMachineScopeParams(t *testing.T) { } func TestMachineScopeAddFinalizer(t *testing.T) { - NewTestSuite(mock.MockK8sClient{}).Run(t, Paths( - Mock("scheme 1", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Scheme().DoAndReturn(func() *runtime.Scheme { + t.Parallel() + + NewTestSuite(mock.MockK8sClient{}).Run(context.Background(), t, Paths( + Call("scheme 1", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Scheme().DoAndReturn(func() *runtime.Scheme { s := runtime.NewScheme() infrav1alpha1.AddToScheme(s) return s }) }), Either( - Mock("scheme 2", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Scheme().DoAndReturn(func() *runtime.Scheme { + Call("scheme 2", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Scheme().DoAndReturn(func() *runtime.Scheme { s := runtime.NewScheme() infrav1alpha1.AddToScheme(s) return s }) }), - Result("has finalizer", func(ctx MockContext) { + Result("has finalizer", func(ctx context.Context, m Mock) { mScope, err := NewMachineScope(ctx, "token", MachineScopeParams{ - Client: ctx.K8sClient, + Client: m.K8sClient, Cluster: &clusterv1.Cluster{}, Machine: &clusterv1.Machine{}, LinodeCluster: &infrav1alpha1.LinodeCluster{}, @@ -146,12 +148,12 @@ func TestMachineScopeAddFinalizer(t *testing.T) { ), Either( Case( - Mock("able to patch", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Patch(ctx, gomock.Any(), gomock.Any()).Return(nil) + Call("able to patch", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Patch(ctx, gomock.Any(), gomock.Any()).Return(nil) }), - Result("finalizer added", func(ctx MockContext) { + Result("finalizer added", func(ctx context.Context, m Mock) { mScope, err := NewMachineScope(ctx, "token", MachineScopeParams{ - Client: ctx.K8sClient, + Client: m.K8sClient, Cluster: &clusterv1.Cluster{}, Machine: &clusterv1.Machine{}, LinodeCluster: &infrav1alpha1.LinodeCluster{}, @@ -164,12 +166,12 @@ func TestMachineScopeAddFinalizer(t *testing.T) { }), ), Case( - Mock("unable to patch", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Patch(ctx, gomock.Any(), gomock.Any()).Return(errors.New("fail")) + Call("unable to patch", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Patch(ctx, gomock.Any(), gomock.Any()).Return(errors.New("fail")) }), - Result("error", func(ctx MockContext) { + Result("error", func(ctx context.Context, m Mock) { mScope, err := NewMachineScope(ctx, "token", MachineScopeParams{ - Client: ctx.K8sClient, + Client: m.K8sClient, Cluster: &clusterv1.Cluster{}, Machine: &clusterv1.Machine{}, LinodeCluster: &infrav1alpha1.LinodeCluster{}, @@ -185,16 +187,18 @@ func TestMachineScopeAddFinalizer(t *testing.T) { } func TestNewMachineScope(t *testing.T) { - NewTestSuite(mock.MockK8sClient{}).Run(t, Paths( + t.Parallel() + + NewTestSuite(mock.MockK8sClient{}).Run(context.Background(), t, Paths( Either( - Result("invalid params", func(ctx MockContext) { + Result("invalid params", func(ctx context.Context, m Mock) { mScope, err := NewMachineScope(ctx, "token", MachineScopeParams{}) require.ErrorContains(t, err, "is required") assert.Nil(t, mScope) }), - Result("no token", func(ctx MockContext) { + Result("no token", func(ctx context.Context, m Mock) { mScope, err := NewMachineScope(ctx, "", MachineScopeParams{ - Client: ctx.K8sClient, + Client: m.K8sClient, Cluster: &clusterv1.Cluster{}, Machine: &clusterv1.Machine{}, LinodeCluster: &infrav1alpha1.LinodeCluster{}, @@ -204,12 +208,12 @@ func TestNewMachineScope(t *testing.T) { assert.Nil(t, mScope) }), Case( - Mock("no secret", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Get(ctx, gomock.Any(), gomock.Any()).Return(apierrors.NewNotFound(schema.GroupResource{}, "example")) + Call("no secret", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Get(ctx, gomock.Any(), gomock.Any()).Return(apierrors.NewNotFound(schema.GroupResource{}, "example")) }), - Result("error", func(ctx MockContext) { + Result("error", func(ctx context.Context, m Mock) { mScope, err := NewMachineScope(ctx, "", MachineScopeParams{ - Client: ctx.K8sClient, + Client: m.K8sClient, Cluster: &clusterv1.Cluster{}, Machine: &clusterv1.Machine{}, LinodeCluster: &infrav1alpha1.LinodeCluster{}, @@ -228,20 +232,20 @@ func TestNewMachineScope(t *testing.T) { ), ), Either( - Mock("valid scheme", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Scheme().DoAndReturn(func() *runtime.Scheme { + Call("valid scheme", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Scheme().DoAndReturn(func() *runtime.Scheme { s := runtime.NewScheme() infrav1alpha1.AddToScheme(s) return s }) }), Case( - Mock("invalid scheme", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Scheme().Return(runtime.NewScheme()) + Call("invalid scheme", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Scheme().Return(runtime.NewScheme()) }), - Result("cannot init patch helper", func(ctx MockContext) { + Result("cannot init patch helper", func(ctx context.Context, m Mock) { mScope, err := NewMachineScope(ctx, "token", MachineScopeParams{ - Client: ctx.K8sClient, + Client: m.K8sClient, Cluster: &clusterv1.Cluster{}, Machine: &clusterv1.Machine{}, LinodeCluster: &infrav1alpha1.LinodeCluster{}, @@ -253,8 +257,8 @@ func TestNewMachineScope(t *testing.T) { ), ), Either( - Mock("credentials in secret", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Get(ctx, gomock.Any(), gomock.Any()). + Call("credentials in secret", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Get(ctx, gomock.Any(), gomock.Any()). DoAndReturn(func(ctx context.Context, key client.ObjectKey, obj *corev1.Secret, opts ...client.GetOption) error { *obj = corev1.Secret{ Data: map[string][]byte{ @@ -264,9 +268,9 @@ func TestNewMachineScope(t *testing.T) { return nil }) }), - Result("default credentials", func(ctx MockContext) { + Result("default credentials", func(ctx context.Context, m Mock) { mScope, err := NewMachineScope(ctx, "token", MachineScopeParams{ - Client: ctx.K8sClient, + Client: m.K8sClient, Cluster: &clusterv1.Cluster{}, Machine: &clusterv1.Machine{}, LinodeCluster: &infrav1alpha1.LinodeCluster{}, @@ -277,9 +281,9 @@ func TestNewMachineScope(t *testing.T) { }), ), Either( - Result("credentials from LinodeMachine credentialsRef", func(ctx MockContext) { + Result("credentials from LinodeMachine credentialsRef", func(ctx context.Context, m Mock) { mScope, err := NewMachineScope(ctx, "", MachineScopeParams{ - Client: ctx.K8sClient, + Client: m.K8sClient, Cluster: &clusterv1.Cluster{}, Machine: &clusterv1.Machine{}, LinodeCluster: &infrav1alpha1.LinodeCluster{}, @@ -295,9 +299,9 @@ func TestNewMachineScope(t *testing.T) { require.NoError(t, err) assert.NotNil(t, mScope) }), - Result("credentials from LinodeCluster credentialsRef", func(ctx MockContext) { + Result("credentials from LinodeCluster credentialsRef", func(ctx context.Context, m Mock) { mScope, err := NewMachineScope(ctx, "token", MachineScopeParams{ - Client: ctx.K8sClient, + Client: m.K8sClient, Cluster: &clusterv1.Cluster{}, Machine: &clusterv1.Machine{}, LinodeCluster: &infrav1alpha1.LinodeCluster{ @@ -318,18 +322,20 @@ func TestNewMachineScope(t *testing.T) { } func TestMachineScopeGetBootstrapData(t *testing.T) { - NewTestSuite(mock.MockK8sClient{}).Run(t, Paths( - Mock("able to get secret", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Get(ctx, gomock.Any(), gomock.Any()). + t.Parallel() + + NewTestSuite(mock.MockK8sClient{}).Run(context.Background(), t, Paths( + Call("able to get secret", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Get(ctx, gomock.Any(), gomock.Any()). DoAndReturn(func(ctx context.Context, key client.ObjectKey, obj *corev1.Secret, opts ...client.GetOption) error { secret := corev1.Secret{Data: map[string][]byte{"value": []byte("test-data")}} *obj = secret return nil }) }), - Result("success", func(ctx MockContext) { + Result("success", func(ctx context.Context, m Mock) { mScope := MachineScope{ - Client: ctx.K8sClient, + Client: m.K8sClient, Machine: &clusterv1.Machine{ Spec: clusterv1.MachineSpec{ Bootstrap: clusterv1.Bootstrap{ @@ -345,32 +351,32 @@ func TestMachineScopeGetBootstrapData(t *testing.T) { assert.Equal(t, data, []byte("test-data")) }), Either( - Mock("unable to get secret", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Get(ctx, gomock.Any(), gomock.Any()). + Call("unable to get secret", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Get(ctx, gomock.Any(), gomock.Any()). Return(apierrors.NewNotFound(schema.GroupResource{}, "test-data")) }), - Mock("secret is missing data", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Get(ctx, gomock.Any(), gomock.Any()). + Call("secret is missing data", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Get(ctx, gomock.Any(), gomock.Any()). DoAndReturn(func(ctx context.Context, key client.ObjectKey, obj *corev1.Secret, opts ...client.GetOption) error { *obj = corev1.Secret{} return nil }) }), - Result("secret ref missing", func(ctx MockContext) { + Result("secret ref missing", func(ctx context.Context, m Mock) { mScope := MachineScope{ - Client: ctx.K8sClient, + Client: m.K8sClient, Machine: &clusterv1.Machine{}, LinodeMachine: &infrav1alpha1.LinodeMachine{}, } data, err := mScope.GetBootstrapData(ctx) require.ErrorContains(t, err, "bootstrap data secret is nil") - assert.Len(t, data, 0) + assert.Empty(t, data) }), ), - Result("error", func(ctx MockContext) { + Result("error", func(ctx context.Context, m Mock) { mScope := MachineScope{ - Client: ctx.K8sClient, + Client: m.K8sClient, Machine: &clusterv1.Machine{ Spec: clusterv1.MachineSpec{ Bootstrap: clusterv1.Bootstrap{ @@ -383,7 +389,7 @@ func TestMachineScopeGetBootstrapData(t *testing.T) { data, err := mScope.GetBootstrapData(ctx) require.Error(t, err) - assert.Len(t, data, 0) + assert.Empty(t, data) }), )) } diff --git a/controller/linodeobjectstoragebucket_controller_test.go b/controller/linodeobjectstoragebucket_controller_test.go index ef23feaec..32718dda2 100644 --- a/controller/linodeobjectstoragebucket_controller_test.go +++ b/controller/linodeobjectstoragebucket_controller_test.go @@ -103,9 +103,9 @@ var _ = Describe("lifecycle", Ordered, Label("bucket", "lifecycle"), func() { ctlrSuite.Run(Paths( Either( - Mock("bucket is created", func(ctx MockContext) { - getBucket := ctx.ObjectStorageClient.EXPECT().GetObjectStorageBucket(gomock.Any(), obj.Spec.Cluster, gomock.Any()).Return(nil, nil) - ctx.ObjectStorageClient.EXPECT().CreateObjectStorageBucket(gomock.Any(), gomock.Any()). + Call("bucket is created", func(ctx context.Context, m Mock) { + getBucket := m.ObjectStorageClient.EXPECT().GetObjectStorageBucket(gomock.Any(), obj.Spec.Cluster, gomock.Any()).Return(nil, nil) + m.ObjectStorageClient.EXPECT().CreateObjectStorageBucket(gomock.Any(), gomock.Any()). After(getBucket). Return(&linodego.ObjectStorageBucket{ Label: obj.Name, @@ -115,21 +115,21 @@ var _ = Describe("lifecycle", Ordered, Label("bucket", "lifecycle"), func() { }, nil) }), Case( - Mock("bucket is not created", func(ctx MockContext) { - getBucket := ctx.ObjectStorageClient.EXPECT().GetObjectStorageBucket(gomock.Any(), obj.Spec.Cluster, gomock.Any()).Return(nil, nil) - ctx.ObjectStorageClient.EXPECT().CreateObjectStorageBucket(gomock.Any(), gomock.Any()).After(getBucket).Return(nil, errors.New("create bucket error")) + Call("bucket is not created", func(ctx context.Context, m Mock) { + getBucket := m.ObjectStorageClient.EXPECT().GetObjectStorageBucket(gomock.Any(), obj.Spec.Cluster, gomock.Any()).Return(nil, nil) + m.ObjectStorageClient.EXPECT().CreateObjectStorageBucket(gomock.Any(), gomock.Any()).After(getBucket).Return(nil, errors.New("create bucket error")) }), - Result("error", func(ctx MockContext) { - bScope.LinodeClient = ctx.ObjectStorageClient + Result("error", func(ctx context.Context, m Mock) { + bScope.LinodeClient = m.ObjectStorageClient _, err := reconciler.reconcile(ctx, &bScope) Expect(err.Error()).To(ContainSubstring("create bucket error")) }), ), ), Either( - Mock("keys are created", func(ctx MockContext) { + Call("keys are created", func(ctx context.Context, m Mock) { for idx := range 2 { - ctx.ObjectStorageClient.EXPECT().CreateObjectStorageKey(gomock.Any(), gomock.Any()). + m.ObjectStorageClient.EXPECT().CreateObjectStorageKey(gomock.Any(), gomock.Any()). Return(&linodego.ObjectStorageKey{ ID: idx, AccessKey: fmt.Sprintf("access-key-%d", idx), @@ -138,19 +138,19 @@ var _ = Describe("lifecycle", Ordered, Label("bucket", "lifecycle"), func() { } }), Case( - Mock("keys are not created", func(ctx MockContext) { - ctx.ObjectStorageClient.EXPECT().CreateObjectStorageKey(gomock.Any(), gomock.Any()).Return(nil, errors.New("create key error")) + Call("keys are not created", func(ctx context.Context, m Mock) { + m.ObjectStorageClient.EXPECT().CreateObjectStorageKey(gomock.Any(), gomock.Any()).Return(nil, errors.New("create key error")) }), - Result("error", func(ctx MockContext) { - bScope.LinodeClient = ctx.ObjectStorageClient + Result("error", func(ctx context.Context, m Mock) { + bScope.LinodeClient = m.ObjectStorageClient _, err := reconciler.reconcile(ctx, &bScope) Expect(err.Error()).To(ContainSubstring("create key error")) }), ), ), - Result("resource status is updated and key secret is created", func(ctx MockContext) { + Result("resource status is updated and key secret is created", func(ctx context.Context, m Mock) { objectKey := client.ObjectKeyFromObject(&obj) - bScope.LinodeClient = ctx.ObjectStorageClient + bScope.LinodeClient = m.ObjectStorageClient _, err := reconciler.reconcile(ctx, &bScope) Expect(err).NotTo(HaveOccurred()) @@ -182,17 +182,17 @@ var _ = Describe("lifecycle", Ordered, Label("bucket", "lifecycle"), func() { Expect(key.StringData.AccessKeyRO).To(Equal("access-key-1")) Expect(key.StringData.SecretKeyRO).To(Equal("secret-key-1")) - Expect(<-ctx.Events()).To(ContainSubstring("Object storage keys assigned")) - Expect(<-ctx.Events()).To(ContainSubstring("Object storage keys stored in secret")) - Expect(<-ctx.Events()).To(ContainSubstring("Object storage bucket synced")) + Expect(<-m.Events()).To(ContainSubstring("Object storage keys assigned")) + Expect(<-m.Events()).To(ContainSubstring("Object storage keys stored in secret")) + Expect(<-m.Events()).To(ContainSubstring("Object storage bucket synced")) - logOutput := ctx.Logs() + logOutput := m.Logs() Expect(logOutput).To(ContainSubstring("Reconciling apply")) Expect(logOutput).To(ContainSubstring("Secret lifecycle-bucket-details was applied with new access keys")) }), Either( - Mock("bucket is retrieved on update", func(ctx MockContext) { - ctx.ObjectStorageClient.EXPECT().GetObjectStorageBucket(gomock.Any(), obj.Spec.Cluster, gomock.Any()). + Call("bucket is retrieved on update", func(ctx context.Context, m Mock) { + m.ObjectStorageClient.EXPECT().GetObjectStorageBucket(gomock.Any(), obj.Spec.Cluster, gomock.Any()). Return(&linodego.ObjectStorageBucket{ Label: obj.Name, Cluster: obj.Spec.Cluster, @@ -201,11 +201,11 @@ var _ = Describe("lifecycle", Ordered, Label("bucket", "lifecycle"), func() { }, nil) }), Case( - Mock("bucket is not retrieved on update", func(ctx MockContext) { - ctx.ObjectStorageClient.EXPECT().GetObjectStorageBucket(gomock.Any(), obj.Spec.Cluster, gomock.Any()).Return(nil, errors.New("get bucket error")) + Call("bucket is not retrieved on update", func(ctx context.Context, m Mock) { + m.ObjectStorageClient.EXPECT().GetObjectStorageBucket(gomock.Any(), obj.Spec.Cluster, gomock.Any()).Return(nil, errors.New("get bucket error")) }), - Result("error", func(ctx MockContext) { - bScope.LinodeClient = ctx.ObjectStorageClient + Result("error", func(ctx context.Context, m Mock) { + bScope.LinodeClient = m.ObjectStorageClient _, err := reconciler.reconcile(ctx, &bScope) Expect(err.Error()).To(ContainSubstring("get bucket error")) }), @@ -221,38 +221,38 @@ var _ = Describe("lifecycle", Ordered, Label("bucket", "lifecycle"), func() { // nb: Order matters for paths of the same length. The leftmost path is evaluated first. // If we evaluate the happy path first, the bucket resource is mutated so the error path won't occur. Case( - Mock("keys are not rotated", func(ctx MockContext) { - ctx.ObjectStorageClient.EXPECT().CreateObjectStorageKey(gomock.Any(), gomock.Any()).Return(nil, errors.New("create key error")) + Call("keys are not rotated", func(ctx context.Context, m Mock) { + m.ObjectStorageClient.EXPECT().CreateObjectStorageKey(gomock.Any(), gomock.Any()).Return(nil, errors.New("create key error")) }), - Result("error", func(ctx MockContext) { - bScope.LinodeClient = ctx.ObjectStorageClient + Result("error", func(ctx context.Context, m Mock) { + bScope.LinodeClient = m.ObjectStorageClient _, err := reconciler.reconcile(ctx, &bScope) Expect(err.Error()).To(ContainSubstring("create key error")) }), ), Case( - Mock("keys are rotated", func(ctx MockContext) { + Call("keys are rotated", func(ctx context.Context, m Mock) { for idx := range 2 { - createCall := ctx.ObjectStorageClient.EXPECT().CreateObjectStorageKey(gomock.Any(), gomock.Any()). + createCall := m.ObjectStorageClient.EXPECT().CreateObjectStorageKey(gomock.Any(), gomock.Any()). Return(&linodego.ObjectStorageKey{ ID: idx + 2, AccessKey: fmt.Sprintf("access-key-%d", idx+2), SecretKey: fmt.Sprintf("secret-key-%d", idx+2), }, nil) - ctx.ObjectStorageClient.EXPECT().DeleteObjectStorageKey(gomock.Any(), idx).After(createCall).Return(nil) + m.ObjectStorageClient.EXPECT().DeleteObjectStorageKey(gomock.Any(), idx).After(createCall).Return(nil) } }), - Result("resource lastKeyGeneration is updated", func(ctx MockContext) { + Result("resource lastKeyGeneration is updated", func(ctx context.Context, m Mock) { objectKey := client.ObjectKeyFromObject(&obj) - bScope.LinodeClient = ctx.ObjectStorageClient + bScope.LinodeClient = m.ObjectStorageClient _, err := reconciler.reconcile(ctx, &bScope) Expect(err).NotTo(HaveOccurred()) Expect(k8sClient.Get(ctx, objectKey, &obj)).To(Succeed()) Expect(*obj.Status.LastKeyGeneration).To(Equal(1)) - Expect(<-ctx.Events()).To(ContainSubstring("Object storage keys assigned")) + Expect(<-m.Events()).To(ContainSubstring("Object storage keys assigned")) - logOutput := ctx.Logs() + logOutput := m.Logs() Expect(logOutput).To(ContainSubstring("Reconciling apply")) Expect(logOutput).To(ContainSubstring("Secret lifecycle-bucket-details was applied with new access keys")) }), @@ -266,19 +266,19 @@ var _ = Describe("lifecycle", Ordered, Label("bucket", "lifecycle"), func() { ), Either( Case( - Mock("keys are not retrieved", func(ctx MockContext) { - ctx.ObjectStorageClient.EXPECT().GetObjectStorageKey(gomock.Any(), gomock.Any()).Times(2).Return(nil, errors.New("get key error")) + Call("keys are not retrieved", func(ctx context.Context, m Mock) { + m.ObjectStorageClient.EXPECT().GetObjectStorageKey(gomock.Any(), gomock.Any()).Times(2).Return(nil, errors.New("get key error")) }), - Result("error", func(ctx MockContext) { - bScope.LinodeClient = ctx.ObjectStorageClient + Result("error", func(ctx context.Context, m Mock) { + bScope.LinodeClient = m.ObjectStorageClient _, err := reconciler.reconcile(ctx, &bScope) Expect(err.Error()).To(ContainSubstring("get key error")) }), ), Case( - Mock("keys are retrieved", func(ctx MockContext) { + Call("keys are retrieved", func(ctx context.Context, m Mock) { for idx := range 2 { - ctx.ObjectStorageClient.EXPECT().GetObjectStorageKey(gomock.Any(), idx+2). + m.ObjectStorageClient.EXPECT().GetObjectStorageKey(gomock.Any(), idx+2). Return(&linodego.ObjectStorageKey{ ID: idx + 2, AccessKey: fmt.Sprintf("access-key-%d", idx+2), @@ -286,8 +286,8 @@ var _ = Describe("lifecycle", Ordered, Label("bucket", "lifecycle"), func() { }, nil) } }), - Result("secret is restored", func(ctx MockContext) { - bScope.LinodeClient = ctx.ObjectStorageClient + Result("secret is restored", func(ctx context.Context, m Mock) { + bScope.LinodeClient = m.ObjectStorageClient _, err := reconciler.reconcile(ctx, &bScope) Expect(err).NotTo(HaveOccurred()) @@ -306,11 +306,11 @@ var _ = Describe("lifecycle", Ordered, Label("bucket", "lifecycle"), func() { Expect(key.StringData.AccessKeyRO).To(Equal("access-key-3")) Expect(key.StringData.SecretKeyRO).To(Equal("secret-key-3")) - Expect(<-ctx.Events()).To(ContainSubstring("Object storage keys retrieved")) - Expect(<-ctx.Events()).To(ContainSubstring("Object storage keys stored in secret")) - Expect(<-ctx.Events()).To(ContainSubstring("Object storage bucket synced")) + Expect(<-m.Events()).To(ContainSubstring("Object storage keys retrieved")) + Expect(<-m.Events()).To(ContainSubstring("Object storage keys stored in secret")) + Expect(<-m.Events()).To(ContainSubstring("Object storage bucket synced")) - logOutput := ctx.Logs() + logOutput := m.Logs() Expect(logOutput).To(ContainSubstring("Reconciling apply")) Expect(logOutput).To(ContainSubstring("Secret lifecycle-bucket-details was applied with new access keys")) }), @@ -324,31 +324,31 @@ var _ = Describe("lifecycle", Ordered, Label("bucket", "lifecycle"), func() { }), Either( Case( - Mock("keys are not revoked", func(ctx MockContext) { - ctx.ObjectStorageClient.EXPECT().DeleteObjectStorageKey(gomock.Any(), gomock.Any()).Times(2).Return(errors.New("revoke error")) + Call("keys are not revoked", func(ctx context.Context, m Mock) { + m.ObjectStorageClient.EXPECT().DeleteObjectStorageKey(gomock.Any(), gomock.Any()).Times(2).Return(errors.New("revoke error")) }), - Result("error", func(ctx MockContext) { - bScope.LinodeClient = ctx.ObjectStorageClient + Result("error", func(ctx context.Context, m Mock) { + bScope.LinodeClient = m.ObjectStorageClient _, err := reconciler.reconcile(ctx, &bScope) Expect(err.Error()).To(ContainSubstring("revoke error")) }), ), Case( - Mock("keys are revoked", func(ctx MockContext) { - ctx.ObjectStorageClient.EXPECT().DeleteObjectStorageKey(gomock.Any(), 2).Return(nil) - ctx.ObjectStorageClient.EXPECT().DeleteObjectStorageKey(gomock.Any(), 3).Return(nil) + Call("keys are revoked", func(ctx context.Context, m Mock) { + m.ObjectStorageClient.EXPECT().DeleteObjectStorageKey(gomock.Any(), 2).Return(nil) + m.ObjectStorageClient.EXPECT().DeleteObjectStorageKey(gomock.Any(), 3).Return(nil) }), - Result("finalizer is removed", func(ctx MockContext) { + Result("finalizer is removed", func(ctx context.Context, m Mock) { objectKey := client.ObjectKeyFromObject(&obj) k8sClient.Get(ctx, objectKey, &obj) - bScope.LinodeClient = ctx.ObjectStorageClient + bScope.LinodeClient = m.ObjectStorageClient _, err := reconciler.reconcile(ctx, &bScope) Expect(err).NotTo(HaveOccurred()) Expect(apierrors.IsNotFound(k8sClient.Get(ctx, objectKey, &obj))).To(BeTrue()) - Expect(<-ctx.Events()).To(ContainSubstring("Object storage keys revoked")) + Expect(<-m.Events()).To(ContainSubstring("Object storage keys revoked")) - logOutput := ctx.Logs() + logOutput := m.Logs() Expect(logOutput).To(ContainSubstring("Reconciling delete")) }), ), @@ -382,15 +382,15 @@ var _ = Describe("errors", Label("bucket", "errors"), func() { ctlrSuite.Run(Paths( Either( - Mock("resource can be fetched", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + Call("resource can be fetched", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) }), Case( - Mock("resource is not found", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(apierrors.NewNotFound(schema.GroupResource{}, "mock")) + Call("resource is not found", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(apierrors.NewNotFound(schema.GroupResource{}, "mock")) }), - Result("no error", func(ctx MockContext) { - reconciler.Client = ctx.K8sClient + Result("no error", func(ctx context.Context, m Mock) { + reconciler.Client = m.K8sClient _, err := reconciler.Reconcile(ctx, reconcile.Request{ NamespacedName: client.ObjectKeyFromObject(bScope.Bucket), }) @@ -398,112 +398,112 @@ var _ = Describe("errors", Label("bucket", "errors"), func() { }), ), Case( - Mock("resource can't be fetched", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("non-404 error")) + Call("resource can't be fetched", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("non-404 error")) }), - Result("error", func(ctx MockContext) { - reconciler.Client = ctx.K8sClient + Result("error", func(ctx context.Context, m Mock) { + reconciler.Client = m.K8sClient reconciler.Logger = bScope.Logger _, err := reconciler.Reconcile(ctx, reconcile.Request{ NamespacedName: client.ObjectKeyFromObject(bScope.Bucket), }) Expect(err.Error()).To(ContainSubstring("non-404 error")) - Expect(ctx.Logs()).To(ContainSubstring("Failed to fetch LinodeObjectStorageBucket")) + Expect(m.Logs()).To(ContainSubstring("Failed to fetch LinodeObjectStorageBucket")) }), ), ), - Result("scope params is missing args", func(ctx MockContext) { - reconciler.Client = ctx.K8sClient + Result("scope params is missing args", func(ctx context.Context, m Mock) { + reconciler.Client = m.K8sClient reconciler.Logger = bScope.Logger _, err := reconciler.Reconcile(ctx, reconcile.Request{ NamespacedName: client.ObjectKeyFromObject(bScope.Bucket), }) Expect(err.Error()).To(ContainSubstring("failed to create object storage bucket scope")) - Expect(ctx.Logs()).To(ContainSubstring("Failed to create object storage bucket scope")) + Expect(m.Logs()).To(ContainSubstring("Failed to create object storage bucket scope")) }), - Mock("scheme with no infrav1alpha1", func(ctx MockContext) { - prev := ctx.K8sClient.EXPECT().Scheme().Return(scheme.Scheme) - ctx.K8sClient.EXPECT().Scheme().After(prev).Return(runtime.NewScheme()).Times(2) + Call("scheme with no infrav1alpha1", func(ctx context.Context, m Mock) { + prev := m.K8sClient.EXPECT().Scheme().Return(scheme.Scheme) + m.K8sClient.EXPECT().Scheme().After(prev).Return(runtime.NewScheme()).Times(2) }), - Result("error", func(ctx MockContext) { - bScope.Client = ctx.K8sClient + Result("error", func(ctx context.Context, m Mock) { + bScope.Client = m.K8sClient - patchHelper, err := patch.NewHelper(bScope.Bucket, ctx.K8sClient) + patchHelper, err := patch.NewHelper(bScope.Bucket, m.K8sClient) Expect(err).NotTo(HaveOccurred()) bScope.PatchHelper = patchHelper _, err = reconciler.reconcile(ctx, &bScope) Expect(err.Error()).To(ContainSubstring("no kind is registered")) }), - Mock("get bucket", func(ctx MockContext) { - ctx.ObjectStorageClient.EXPECT().GetObjectStorageBucket(gomock.Any(), gomock.Any(), gomock.Any()).Return(&linodego.ObjectStorageBucket{Created: ptr.To(time.Now())}, nil) + Call("get bucket", func(ctx context.Context, m Mock) { + m.ObjectStorageClient.EXPECT().GetObjectStorageBucket(gomock.Any(), gomock.Any(), gomock.Any()).Return(&linodego.ObjectStorageBucket{Created: ptr.To(time.Now())}, nil) }), Either( Case( - Mock("failed check for deleted secret", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("api error")) + Call("failed check for deleted secret", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("api error")) }), - Result("error", func(ctx MockContext) { + Result("error", func(ctx context.Context, m Mock) { bScope.Bucket.Spec.KeyGeneration = ptr.To(1) bScope.Bucket.Status.LastKeyGeneration = bScope.Bucket.Spec.KeyGeneration bScope.Bucket.Status.KeySecretName = ptr.To("mock-bucket-details") bScope.Bucket.Status.AccessKeyRefs = []int{0, 1} - bScope.LinodeClient = ctx.ObjectStorageClient - bScope.Client = ctx.K8sClient + bScope.LinodeClient = m.ObjectStorageClient + bScope.Client = m.K8sClient err := reconciler.reconcileApply(ctx, &bScope) Expect(err.Error()).To(ContainSubstring("api error")) - Expect(<-ctx.Events()).To(ContainSubstring("api error")) - Expect(ctx.Logs()).To(ContainSubstring("Failed to ensure access key secret exists")) + Expect(<-m.Events()).To(ContainSubstring("api error")) + Expect(m.Logs()).To(ContainSubstring("Failed to ensure access key secret exists")) }), ), - Mock("secret deleted", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(apierrors.NewNotFound(schema.GroupResource{Resource: "Secret"}, "mock-bucket-details")) + Call("secret deleted", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(apierrors.NewNotFound(schema.GroupResource{Resource: "Secret"}, "mock-bucket-details")) }), ), - Mock("get keys", func(ctx MockContext) { + Call("get keys", func(ctx context.Context, m Mock) { for idx := range 2 { - ctx.ObjectStorageClient.EXPECT().GetObjectStorageKey(gomock.Any(), idx).Return(&linodego.ObjectStorageKey{ID: idx}, nil) + m.ObjectStorageClient.EXPECT().GetObjectStorageKey(gomock.Any(), idx).Return(&linodego.ObjectStorageKey{ID: idx}, nil) } }), Either( Case( - Mock("secret resource creation fails", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Scheme().Return(scheme.Scheme).AnyTimes() - ctx.K8sClient.EXPECT().Create(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("secret creation error")) + Call("secret resource creation fails", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Scheme().Return(scheme.Scheme).AnyTimes() + m.K8sClient.EXPECT().Create(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("secret creation error")) }), - Result("creation error", func(ctx MockContext) { + Result("creation error", func(ctx context.Context, m Mock) { bScope.Bucket.Spec.KeyGeneration = ptr.To(1) bScope.Bucket.Status.LastKeyGeneration = bScope.Bucket.Spec.KeyGeneration bScope.Bucket.Status.KeySecretName = ptr.To("mock-bucket-details") bScope.Bucket.Status.AccessKeyRefs = []int{0, 1} - bScope.LinodeClient = ctx.ObjectStorageClient - bScope.Client = ctx.K8sClient + bScope.LinodeClient = m.ObjectStorageClient + bScope.Client = m.K8sClient err := reconciler.reconcileApply(ctx, &bScope) Expect(err.Error()).To(ContainSubstring("secret creation error")) - Expect(<-ctx.Events()).To(ContainSubstring("keys retrieved")) - Expect(<-ctx.Events()).To(ContainSubstring("secret creation error")) - Expect(ctx.Logs()).To(ContainSubstring("Failed to apply key secret")) + Expect(<-m.Events()).To(ContainSubstring("keys retrieved")) + Expect(<-m.Events()).To(ContainSubstring("secret creation error")) + Expect(m.Logs()).To(ContainSubstring("Failed to apply key secret")) }), ), Case( - Mock("secret generation fails", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Scheme().Return(runtime.NewScheme()) + Call("secret generation fails", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Scheme().Return(runtime.NewScheme()) }), - Result("error", func(ctx MockContext) { + Result("error", func(ctx context.Context, m Mock) { bScope.Bucket.Spec.KeyGeneration = ptr.To(1) bScope.Bucket.Status.LastKeyGeneration = bScope.Bucket.Spec.KeyGeneration bScope.Bucket.Status.KeySecretName = ptr.To("mock-bucket-details") bScope.Bucket.Status.AccessKeyRefs = []int{0, 1} - bScope.LinodeClient = ctx.ObjectStorageClient - bScope.Client = ctx.K8sClient + bScope.LinodeClient = m.ObjectStorageClient + bScope.Client = m.K8sClient err := reconciler.reconcileApply(ctx, &bScope) Expect(err.Error()).To(ContainSubstring("no kind is registered")) - Expect(<-ctx.Events()).To(ContainSubstring("keys retrieved")) - Expect(<-ctx.Events()).To(ContainSubstring("no kind is registered")) - Expect(ctx.Logs()).To(ContainSubstring("Failed to generate key secret")) + Expect(<-m.Events()).To(ContainSubstring("keys retrieved")) + Expect(<-m.Events()).To(ContainSubstring("no kind is registered")) + Expect(m.Logs()).To(ContainSubstring("Failed to generate key secret")) }), ), ), @@ -511,15 +511,15 @@ var _ = Describe("errors", Label("bucket", "errors"), func() { bScope.Bucket.Status.AccessKeyRefs = []int{0, 1} bScope.Bucket.ObjectMeta.Finalizers = []string{} }), - Mock("revoke keys", func(ctx MockContext) { - ctx.ObjectStorageClient.EXPECT().DeleteObjectStorageKey(gomock.Any(), gomock.Any()).Times(2).Return(nil) + Call("revoke keys", func(ctx context.Context, m Mock) { + m.ObjectStorageClient.EXPECT().DeleteObjectStorageKey(gomock.Any(), gomock.Any()).Times(2).Return(nil) }), - Result("error", func(ctx MockContext) { - bScope.LinodeClient = ctx.ObjectStorageClient - bScope.Client = ctx.K8sClient + Result("error", func(ctx context.Context, m Mock) { + bScope.LinodeClient = m.ObjectStorageClient + bScope.Client = m.K8sClient err := reconciler.reconcileDelete(ctx, &bScope) Expect(err.Error()).To(ContainSubstring("failed to remove finalizer from bucket")) - Expect(<-ctx.Events()).To(ContainSubstring("failed to remove finalizer from bucket")) + Expect(<-m.Events()).To(ContainSubstring("failed to remove finalizer from bucket")) }), )) }) diff --git a/mock/mocktest/controller_suite.go b/mock/mocktest/controller_suite.go index 2b64239ca..330dd55c6 100644 --- a/mock/mocktest/controller_suite.go +++ b/mock/mocktest/controller_suite.go @@ -5,13 +5,16 @@ import ( "errors" "github.com/go-logr/logr" - "github.com/linode/cluster-api-provider-linode/mock" "github.com/onsi/ginkgo/v2" "go.uber.org/mock/gomock" "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/log/zap" + + "github.com/linode/cluster-api-provider-linode/mock" ) +const recorderBufferSize = 20 + type ctlrSuite struct { clients []mock.MockClient recorder *record.FakeRecorder @@ -26,17 +29,16 @@ func NewControllerTestSuite(clients ...mock.MockClient) *ctlrSuite { panic(errors.New("unable to run tests without clients")) } - c := ctlrSuite{ + logs := bytes.Buffer{} + + return &ctlrSuite{ clients: clients, // Create a recorder with a buffered channel for consuming event strings. - recorder: record.NewFakeRecorder(50), - logs: &bytes.Buffer{}, + recorder: record.NewFakeRecorder(recorderBufferSize), + // Create a logger that writes to both GinkgoWriter and the local logs buffer + logger: zap.New(zap.WriteTo(ginkgo.GinkgoWriter), zap.WriteTo(&logs)), + logs: &logs, } - - // Create a logger that writes to both GinkgoWriter and the local logs buffer - c.logger = zap.New(zap.WriteTo(ginkgo.GinkgoWriter), zap.WriteTo(c.logs)) - - return &c } // Recorder returns a *FakeRecorder for recording events published in a reconcile loop. @@ -59,18 +61,17 @@ func (c *ctlrSuite) Run(paths []path) { mockCtrl := gomock.NewController(ginkgo.GinkgoT()) defer mockCtrl.Finish() - mockCtx := MockContext{ - Context: ctx, + m := Mock{ TestReporter: mockCtrl.T, recorder: c.recorder, logs: c.logs, } for _, client := range c.clients { - mockCtx.MockClients.Build(client, mockCtrl) + m.MockClients.Build(client, mockCtrl) } - path.Run(mockCtx) + path.Run(ctx, m) // Flush the channel if any events were not consumed. for len(c.recorder.Events) > 0 { diff --git a/mock/mocktest/node.go b/mock/mocktest/node.go index 17bc22947..77015a639 100644 --- a/mock/mocktest/node.go +++ b/mock/mocktest/node.go @@ -5,14 +5,14 @@ import ( "context" "fmt" - "github.com/linode/cluster-api-provider-linode/mock" "go.uber.org/mock/gomock" "k8s.io/client-go/tools/record" + + "github.com/linode/cluster-api-provider-linode/mock" ) -// MockContext is the context for a single test path. -type MockContext struct { - context.Context +// Mock holds configuration for a single test path. +type Mock struct { gomock.TestReporter mock.MockClients @@ -21,37 +21,37 @@ type MockContext struct { } // Events returns a channel for receiving event strings for a single test path. -func (ctx MockContext) Events() <-chan string { - return ctx.recorder.Events +func (m Mock) Events() <-chan string { + return m.recorder.Events } // Logs returns a string of all log output written during a single test path. -func (ctx MockContext) Logs() string { - return ctx.logs.String() +func (m Mock) Logs() string { + return m.logs.String() } -// Mock declares a function for mocking method calls on a single mock client. -func Mock(text string, do func(MockContext)) call { +// Call declares a function for mocking method calls on a single mock client. +func Call(text string, does func(context.Context, Mock)) call { return call{ - text: fmt.Sprintf("Mock(%s)", text), - do: do, + text: fmt.Sprintf("Call(%s)", text), + does: does, } } // Result terminates a test path with a function that tests the effects of mocked method calls. -func Result(text string, do func(MockContext)) result { +func Result(text string, does func(context.Context, Mock)) result { return result{ text: fmt.Sprintf("Result(%s)", text), - do: do, + does: does, } } // Once declares a function that runs one time when executing all test paths. // It is triggered at the beginning of the leftmost test path where it is inserted. -func Once(text string, do func(context.Context)) once { +func Once(text string, does func(context.Context)) once { return once{ text: fmt.Sprintf("Once(%s)", text), - do: do, + does: does, } } @@ -73,7 +73,7 @@ type node interface { // A container for describing and holding a function. type fn struct { text string - do func(MockContext) + does func(context.Context, Mock) } // Contains a function for mocking method calls on a single mock client. @@ -85,7 +85,7 @@ type result fn // Contains a function for an event trigger that runs once. type once struct { text string - do func(context.Context) + does func(context.Context) described bool ran bool } diff --git a/mock/mocktest/path.go b/mock/mocktest/path.go index 52e825a23..c6312f763 100644 --- a/mock/mocktest/path.go +++ b/mock/mocktest/path.go @@ -15,7 +15,7 @@ type path struct { // Describe generates a string of all nodes belonging to a test path. func (p path) Describe() string { - var text []string + text := make([]string, 0, len(p.once)+len(p.calls)+1) for _, o := range p.once { if !o.described { text = append(text, o.text) @@ -43,14 +43,13 @@ func Paths(nodes ...node) []path { tmp := []path{} final := []path{} - for i, n := range nodes { + for idx, n := range nodes { // If all paths are closed, make a new path if len(tmp) == 0 { tmp = append(tmp, path{}) } switch impl := n.(type) { - // A once node should only be added to the first path. // It will only invoked once in the first path evaluated. case once: @@ -59,13 +58,13 @@ func Paths(nodes ...node) []path { // A call node should be appended to all open paths. case call: // Add new entry to each open path - for j, pth := range tmp { - tmp[j].calls = append(pth.calls, impl) + for j := range tmp { + tmp[j].calls = append(tmp[j].calls, impl) } // Panic if any paths are open at the end - if i == len(nodes)-1 { - panic(fmt.Errorf("unresolved path at index %d", i)) + if idx == len(nodes)-1 { + panic(fmt.Errorf("unresolved path at index %d", idx)) } // A result node should terminate all open paths. @@ -83,8 +82,8 @@ func Paths(nodes ...node) []path { // The call is appended to all open paths, and then immediately closed with the result. case leaf: // Add new entry to each open path and close it - for j, pth := range tmp { - tmp[j].calls = append(pth.calls, impl.call) + for j := range tmp { + tmp[j].calls = append(tmp[j].calls, impl.call) tmp[j].result = impl.result } @@ -141,8 +140,8 @@ func Paths(nodes ...node) []path { tmp = newTmp // Panic if any paths are open at the end - if open && i == len(nodes)-1 { - panic(fmt.Errorf("unresolved path at index %d", i)) + if open && idx == len(nodes)-1 { + panic(fmt.Errorf("unresolved path at index %d", idx)) } } } diff --git a/mock/mocktest/path_run.go b/mock/mocktest/path_run.go index 91833c27c..25e64e3fa 100644 --- a/mock/mocktest/path_run.go +++ b/mock/mocktest/path_run.go @@ -1,57 +1,50 @@ package mocktest import ( - "fmt" + "context" "testing" "github.com/onsi/ginkgo/v2" ) // Run evaluates all declared mock client methods and assertions for the given test path. -func (p path) Run(ctx MockContext) { - if ctx.Context == nil { - panic("MockContext requires Context") - } - if ctx.TestReporter == nil { - panic("MockContext requires TestReporter, i.e. *testing.T, GinkgoT()") +func (p path) Run(ctx context.Context, m Mock) { + if m.TestReporter == nil { + panic("Mock requires TestReporter, i.e. *testing.T, GinkgoT()") } for _, o := range p.once { - evalOnce(ctx, o) + evalOnce(ctx, m, o) } for _, c := range p.calls { - evalFn(ctx, fn(c)) + evalFn(ctx, m, fn(c)) } - evalFn(ctx, fn(p.result)) + evalFn(ctx, m, fn(p.result)) } -func evalFn(ctx MockContext, f fn) { - switch tt := ctx.TestReporter.(type) { +func evalFn(ctx context.Context, m Mock, fun fn) { + switch tt := m.TestReporter.(type) { case *testing.T: - tt.Log(f.text) + tt.Log(fun.text) case ginkgo.GinkgoTInterface: - ginkgo.By(f.text) - default: - fmt.Println(f.text) + ginkgo.By(fun.text) } - f.do(ctx) + fun.does(ctx, m) } -func evalOnce(ctx MockContext, f *once) { - if f.ran { +func evalOnce(ctx context.Context, m Mock, fun *once) { + if fun.ran { return } - switch tt := ctx.TestReporter.(type) { + switch tt := m.TestReporter.(type) { case *testing.T: - tt.Log(f.text) + tt.Log(fun.text) case ginkgo.GinkgoTInterface: - ginkgo.By(f.text) - default: - fmt.Println(f.text) + ginkgo.By(fun.text) } - f.do(ctx) - f.ran = true + fun.does(ctx) + fun.ran = true } diff --git a/mock/mocktest/path_test.go b/mock/mocktest/path_test.go index 68d430d22..17a53a40a 100644 --- a/mock/mocktest/path_test.go +++ b/mock/mocktest/path_test.go @@ -1,14 +1,14 @@ package mocktest import ( + "context" "errors" "testing" - "go.uber.org/mock/gomock" - "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/linode/linodego" "github.com/stretchr/testify/assert" + "go.uber.org/mock/gomock" + "sigs.k8s.io/controller-runtime/pkg/client" infrav1alpha1 "github.com/linode/cluster-api-provider-linode/api/v1alpha1" "github.com/linode/cluster-api-provider-linode/mock" @@ -36,16 +36,15 @@ var _ = Describe("k8s client", Label("k8sclient"), func() { }) for _, path := range Paths( - Mock("fetch object", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + Call("fetch object", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) }), - Result("no error", func(ctx MockContext) { - Expect(contrivedCalls(ctx)).To(Succeed()) + Result("no error", func(ctx context.Context, m Mock) { + Expect(contrivedCalls(ctx, m)).To(Succeed()) }), ) { It(path.Describe(), func(ctx SpecContext) { - path.Run(MockContext{ - Context: ctx, + path.Run(ctx, Mock{ TestReporter: GinkgoT(), MockClients: mock.MockClients{ K8sClient: mock.NewMockK8sClient(mockCtrl), @@ -67,31 +66,30 @@ var _ = Describe("multiple clients", Label("multiple"), func() { }) for _, path := range Paths( - Mock("read object", func(ctx MockContext) { - ctx.K8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + Call("read object", func(ctx context.Context, m Mock) { + m.K8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) }), Either( Case( - Mock("underlying exists", func(ctx MockContext) { - ctx.MachineClient.EXPECT().CreateInstance(gomock.Any(), gomock.Any()).Return(&linodego.Instance{ID: 1}, nil) + Call("underlying exists", func(ctx context.Context, m Mock) { + m.MachineClient.EXPECT().CreateInstance(gomock.Any(), gomock.Any()).Return(&linodego.Instance{ID: 1}, nil) }), - Result("no error", func(ctx MockContext) { - Expect(contrivedCalls(ctx)).To(Succeed()) + Result("no error", func(ctx context.Context, m Mock) { + Expect(contrivedCalls(ctx, m)).To(Succeed()) }), ), Case( - Mock("underlying does not exist", func(ctx MockContext) { - ctx.MachineClient.EXPECT().CreateInstance(gomock.Any(), gomock.Any()).Return(nil, errors.New("404")) + Call("underlying does not exist", func(ctx context.Context, m Mock) { + m.MachineClient.EXPECT().CreateInstance(gomock.Any(), gomock.Any()).Return(nil, errors.New("404")) }), - Result("error", func(ctx MockContext) { - Expect(contrivedCalls(ctx)).NotTo(Succeed()) + Result("error", func(ctx context.Context, m Mock) { + Expect(contrivedCalls(ctx, m)).NotTo(Succeed()) }), ), ), ) { It(path.Describe(), func(ctx SpecContext) { - path.Run(MockContext{ - Context: ctx, + path.Run(ctx, Mock{ TestReporter: GinkgoT(), MockClients: mock.MockClients{ MachineClient: mock.NewMockLinodeMachineClient(mockCtrl), @@ -102,16 +100,16 @@ var _ = Describe("multiple clients", Label("multiple"), func() { } }) -func contrivedCalls(ctx MockContext) error { +func contrivedCalls(ctx context.Context, m Mock) error { GinkgoHelper() - err := ctx.K8sClient.Get(ctx, client.ObjectKey{}, &infrav1alpha1.LinodeMachine{}) + err := m.K8sClient.Get(ctx, client.ObjectKey{}, &infrav1alpha1.LinodeMachine{}) if err != nil { return err } - if ctx.MachineClient != nil { - _, err = ctx.MachineClient.CreateInstance(ctx, linodego.InstanceCreateOptions{}) + if m.MachineClient != nil { + _, err = m.MachineClient.CreateInstance(ctx, linodego.InstanceCreateOptions{}) if err != nil { return err } @@ -121,6 +119,8 @@ func contrivedCalls(ctx MockContext) error { } func TestPaths(t *testing.T) { + t.Parallel() + for _, tc := range []struct { name string input []node @@ -356,6 +356,8 @@ func TestPaths(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { + t.Parallel() + if tc.panicErr != nil { assert.PanicsWithError(t, tc.panicErr.Error(), func() { Paths(tc.input...) diff --git a/mock/mocktest/suite.go b/mock/mocktest/suite.go index 2e530f08b..dcbef0570 100644 --- a/mock/mocktest/suite.go +++ b/mock/mocktest/suite.go @@ -5,8 +5,9 @@ import ( "errors" "testing" - "github.com/linode/cluster-api-provider-linode/mock" "go.uber.org/mock/gomock" + + "github.com/linode/cluster-api-provider-linode/mock" ) type suite struct { @@ -21,9 +22,7 @@ func NewTestSuite(clients ...mock.MockClient) *suite { return &suite{clients: clients} } -func (s *suite) Run(t *testing.T, paths []path) { - t.Parallel() - +func (s *suite) Run(ctx context.Context, t *testing.T, paths []path) { for _, path := range paths { t.Run(path.Describe(), func(t *testing.T) { t.Parallel() @@ -31,16 +30,15 @@ func (s *suite) Run(t *testing.T, paths []path) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() - mockCtx := MockContext{ - Context: context.Background(), + m := Mock{ TestReporter: mockCtrl.T, } for _, client := range s.clients { - mockCtx.MockClients.Build(client, mockCtrl) + m.MockClients.Build(client, mockCtrl) } - path.Run(mockCtx) + path.Run(ctx, m) }) } }