Improve test coverage for /pkg/controllers/binding

Signed-off-by: xovoxy <xilovele@gmail.com>
This commit is contained in:
xovoxy 2024-08-09 21:51:39 +08:00
parent 37488bd109
commit effcc6c899
2 changed files with 593 additions and 17 deletions

View File

@ -34,10 +34,12 @@ import (
controllerruntime "sigs.k8s.io/controller-runtime" controllerruntime "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1" policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2" workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
testing2 "github.com/karmada-io/karmada/pkg/search/proxy/testing" testing2 "github.com/karmada-io/karmada/pkg/search/proxy/testing"
"github.com/karmada-io/karmada/pkg/util"
"github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager" "github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager"
"github.com/karmada-io/karmada/pkg/util/gclient" "github.com/karmada-io/karmada/pkg/util/gclient"
testing3 "github.com/karmada-io/karmada/pkg/util/testing" testing3 "github.com/karmada-io/karmada/pkg/util/testing"
@ -258,18 +260,14 @@ func TestResourceBindingController_newOverridePolicyFunc(t *testing.T) {
} }
tests := []struct { tests := []struct {
name string name string
want bool want []reconcile.Request
obIsNil bool req client.Object
rb *workv1alpha2.ResourceBinding
}{ }{
{ {
name: "newOverridePolicyFunc success test", name: "newOverridePolicyFunc success test",
want: false, want: []reconcile.Request{{NamespacedName: types.NamespacedName{Namespace: "default", Name: "test-rb"}}},
obIsNil: false, req: &policyv1alpha1.OverridePolicy{
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tempOP := &policyv1alpha1.OverridePolicy{
ObjectMeta: metav1.ObjectMeta{Namespace: rs.Namespace}, ObjectMeta: metav1.ObjectMeta{Namespace: rs.Namespace},
Spec: policyv1alpha1.OverrideSpec{ResourceSelectors: []policyv1alpha1.ResourceSelector{ Spec: policyv1alpha1.OverrideSpec{ResourceSelectors: []policyv1alpha1.ResourceSelector{
{ {
@ -279,18 +277,162 @@ func TestResourceBindingController_newOverridePolicyFunc(t *testing.T) {
Name: rs.Name, Name: rs.Name,
}, },
}}, }},
},
rb: &workv1alpha2.ResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test-rb",
Namespace: "default",
},
Spec: workv1alpha2.ResourceBindingSpec{
Resource: rs,
},
},
},
{
name: "namespace not match",
want: nil,
req: &policyv1alpha1.OverridePolicy{
ObjectMeta: metav1.ObjectMeta{Namespace: rs.Namespace},
Spec: policyv1alpha1.OverrideSpec{ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: rs.APIVersion,
Kind: rs.Kind,
Namespace: rs.Namespace,
Name: rs.Name,
},
}},
},
rb: &workv1alpha2.ResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test-rb",
Namespace: "test",
},
Spec: workv1alpha2.ResourceBindingSpec{
Resource: rs,
},
},
},
{
name: "ResourceSelector is empty",
want: []reconcile.Request{{NamespacedName: types.NamespacedName{Namespace: "default", Name: "test-rb"}}},
req: &policyv1alpha1.OverridePolicy{
ObjectMeta: metav1.ObjectMeta{Namespace: rs.Namespace},
Spec: policyv1alpha1.OverrideSpec{ResourceSelectors: []policyv1alpha1.ResourceSelector{}},
},
rb: &workv1alpha2.ResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test-rb",
Namespace: "default",
},
Spec: workv1alpha2.ResourceBindingSpec{
Resource: rs,
},
},
},
{
name: "client is nil",
want: nil,
req: nil,
rb: &workv1alpha2.ResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test-rb",
Namespace: "default",
},
Spec: workv1alpha2.ResourceBindingSpec{
Resource: rs,
},
},
},
} }
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c, makeErr := makeFakeRBCByResource(&rs) c, makeErr := makeFakeRBCByResource(&rs)
if makeErr != nil { if makeErr != nil {
t.Errorf("makeFakeRBCByResource %v", makeErr) t.Errorf("makeFakeRBCByResource %v", makeErr)
return return
} }
got := c.newOverridePolicyFunc()
if (got == nil) != tt.want { if tt.rb != nil {
t.Errorf("newOverridePolicyFunc() is not same as want:%v", tt.want) if err := c.Client.Create(context.Background(), tt.rb); err != nil {
t.Errorf("create rb %v", err)
return
} }
if (got(context.TODO(), client.Object(tempOP)) == nil) == tt.obIsNil { }
t.Errorf("newOverridePolicyFunc() got() result is not same as want: %v", tt.obIsNil)
got := c.newOverridePolicyFunc()
result := got(context.Background(), tt.req)
if !reflect.DeepEqual(result, tt.want) {
t.Errorf("newOverridePolicyFunc() got() result is %v not same as want: %v", result, tt.want)
}
})
}
}
func TestResourceBindingController_removeFinalizer(t *testing.T) {
tests := []struct {
name string
want controllerruntime.Result
wantErr bool
rb *workv1alpha2.ResourceBinding
create bool
}{
{
name: "Remove finalizer succeed",
want: controllerruntime.Result{},
wantErr: false,
rb: &workv1alpha2.ResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Finalizers: []string{util.BindingControllerFinalizer},
},
},
create: true,
},
{
name: "finalizers not exist",
want: controllerruntime.Result{},
wantErr: false,
rb: &workv1alpha2.ResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
},
create: true,
},
{
name: "rb not found",
want: controllerruntime.Result{},
wantErr: true,
rb: &workv1alpha2.ResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Finalizers: []string{util.BindingControllerFinalizer},
},
},
create: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c, err := makeFakeRBCByResource(nil)
if err != nil {
t.Fatalf("Failed to create ClusterResourceBindingController: %v", err)
}
if tt.create && tt.rb != nil {
if err := c.Client.Create(context.Background(), tt.rb); err != nil {
t.Fatalf("Failed to create ClusterResourceBinding: %v", err)
}
}
result, err := c.removeFinalizer(context.Background(), tt.rb)
if (err != nil) != tt.wantErr {
t.Errorf("ClusterResourceBindingController.removeFinalizer() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(result, tt.want) {
t.Errorf("ClusterResourceBindingController.removeFinalizer() = %v, want %v", result, tt.want)
} }
}) })
} }

View File

@ -0,0 +1,434 @@
/*
Copyright 2024 The Karmada Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package binding
import (
"context"
"fmt"
"reflect"
"testing"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
fakedynamic "k8s.io/client-go/dynamic/fake"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/tools/record"
controllerruntime "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
testing2 "github.com/karmada-io/karmada/pkg/search/proxy/testing"
"github.com/karmada-io/karmada/pkg/util"
"github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager"
"github.com/karmada-io/karmada/pkg/util/gclient"
testing3 "github.com/karmada-io/karmada/pkg/util/testing"
"github.com/karmada-io/karmada/test/helper"
)
func makeFakeCRBCByResource(rs *workv1alpha2.ObjectReference) (*ClusterResourceBindingController, error) {
tempDyClient := fakedynamic.NewSimpleDynamicClient(scheme.Scheme)
if rs == nil {
return &ClusterResourceBindingController{
Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(),
RESTMapper: testing2.RestMapper,
InformerManager: genericmanager.NewSingleClusterInformerManager(tempDyClient, 0, nil),
DynamicClient: tempDyClient,
}, nil
}
var obj runtime.Object
var src string
switch rs.Kind {
case "Namespace":
obj = &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Namespace: "", Name: rs.Name}}
src = "namespaces"
default:
return nil, fmt.Errorf("%s not support yet, pls add for it", rs.Kind)
}
tempDyClient.Resources = []*metav1.APIResourceList{
{
GroupVersion: appsv1.SchemeGroupVersion.String(),
APIResources: []metav1.APIResource{
{Name: rs.Name, Namespaced: true, Kind: rs.Kind, Version: rs.APIVersion},
},
},
}
return &ClusterResourceBindingController{
Client: fake.NewClientBuilder().WithScheme(gclient.NewSchema()).Build(),
RESTMapper: helper.NewGroupRESTMapper(rs.Kind, meta.RESTScopeNamespace),
InformerManager: testing3.NewSingleClusterInformerManagerByRS(src, obj),
DynamicClient: tempDyClient,
EventRecorder: record.NewFakeRecorder(1024),
}, nil
}
func TestClusterResourceBindingController_Reconcile(t *testing.T) {
rs := workv1alpha2.ObjectReference{
APIVersion: "v1",
Kind: "Namespace",
Name: "test",
}
req := controllerruntime.Request{NamespacedName: client.ObjectKey{Namespace: "", Name: "test"}}
tests := []struct {
name string
want controllerruntime.Result
wantErr bool
crb *workv1alpha2.ClusterResourceBinding
del bool
req controllerruntime.Request
}{
{
name: "Reconcile create crb",
want: controllerruntime.Result{},
wantErr: false,
crb: &workv1alpha2.ClusterResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Labels: map[string]string{"clusterresourcebinding.karmada.io/permanent-id": "f2603cdb-f3f3-4a4b-b289-3186a4fef979"},
Finalizers: []string{util.ClusterResourceBindingControllerFinalizer},
},
Spec: workv1alpha2.ResourceBindingSpec{
Resource: rs,
},
},
req: req,
},
{
name: "Reconcile crb deleted",
want: controllerruntime.Result{},
wantErr: false,
crb: &workv1alpha2.ClusterResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Labels: map[string]string{"clusterresourcebinding.karmada.io/permanent-id": "f2603cdb-f3f3-4a4b-b289-3186a4fef979"},
Finalizers: []string{util.ClusterResourceBindingControllerFinalizer},
},
Spec: workv1alpha2.ResourceBindingSpec{
Resource: rs,
},
},
del: true,
req: req,
},
{
name: "Req not found",
want: controllerruntime.Result{},
wantErr: false,
crb: &workv1alpha2.ClusterResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test-noexist",
},
},
req: req,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c, err := makeFakeCRBCByResource(&rs)
if err != nil {
t.Fatalf("%s", err)
}
if tt.crb != nil {
if err := c.Client.Create(context.Background(), tt.crb); err != nil {
t.Fatalf("Failed to create ClusterResourceBinding: %v", err)
}
}
if tt.del {
if err := c.Client.Delete(context.Background(), tt.crb); err != nil {
t.Fatalf("Failed to delete ClusterResourceBinding: %v", err)
}
}
result, err := c.Reconcile(context.Background(), req)
if (err != nil) != tt.wantErr {
t.Errorf("ClusterResourceBindingController.Reconcile() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(result, tt.want) {
t.Errorf("ClusterResourceBindingController.Reconcile() = %v, want %v", result, tt.want)
}
})
}
}
func TestClusterResourceBindingController_removeFinalizer(t *testing.T) {
tests := []struct {
name string
want controllerruntime.Result
wantErr bool
crb *workv1alpha2.ClusterResourceBinding
create bool
}{
{
name: "Remove finalizer succeed",
want: controllerruntime.Result{},
wantErr: false,
crb: &workv1alpha2.ClusterResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Finalizers: []string{util.ClusterResourceBindingControllerFinalizer},
},
},
create: true,
},
{
name: "finalizers not exist",
want: controllerruntime.Result{},
wantErr: false,
crb: &workv1alpha2.ClusterResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
},
create: true,
},
{
name: "crb not found",
want: controllerruntime.Result{},
wantErr: true,
crb: &workv1alpha2.ClusterResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Finalizers: []string{util.ClusterResourceBindingControllerFinalizer},
},
},
create: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c, err := makeFakeCRBCByResource(nil)
if err != nil {
t.Fatalf("Failed to create ClusterResourceBindingController: %v", err)
}
if tt.create && tt.crb != nil {
if err := c.Client.Create(context.Background(), tt.crb); err != nil {
t.Fatalf("Failed to create ClusterResourceBinding: %v", err)
}
}
result, err := c.removeFinalizer(context.Background(), tt.crb)
if (err != nil) != tt.wantErr {
t.Errorf("ClusterResourceBindingController.removeFinalizer() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(result, tt.want) {
t.Errorf("ClusterResourceBindingController.removeFinalizer() = %v, want %v", result, tt.want)
}
})
}
}
func TestClusterResourceBindingController_syncBinding(t *testing.T) {
rs := workv1alpha2.ObjectReference{
APIVersion: "v1",
Kind: "Namespace",
Name: "test",
}
tests := []struct {
name string
want controllerruntime.Result
wantErr bool
crb *workv1alpha2.ClusterResourceBinding
}{
{
name: "sync binding",
want: controllerruntime.Result{},
wantErr: false,
crb: &workv1alpha2.ClusterResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Labels: map[string]string{"clusterresourcebinding.karmada.io/permanent-id": "f2603cdb-f3f3-4a4b-b289-3186a4fef979"},
Finalizers: []string{util.ClusterResourceBindingControllerFinalizer},
},
Spec: workv1alpha2.ResourceBindingSpec{
Resource: rs,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c, err := makeFakeCRBCByResource(&rs)
if err != nil {
t.Fatalf("failed to create fake ClusterResourceBindingController: %v", err)
}
result, err := c.syncBinding(context.Background(), tt.crb)
if (err != nil) != tt.wantErr {
t.Errorf("ClusterResourceBindingController.syncBinding() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(result, tt.want) {
t.Errorf("ClusterResourceBindingController.syncBinding() = %v, want %v", result, tt.want)
}
})
}
}
func TestClusterResourceBindingController_removeOrphanWorks(t *testing.T) {
rs := workv1alpha2.ObjectReference{
APIVersion: "v1",
Kind: "Namespace",
Name: "test",
}
tests := []struct {
name string
wantErr bool
crb *workv1alpha2.ClusterResourceBinding
}{
{
name: "removeOrphanWorks test",
wantErr: false,
crb: &workv1alpha2.ClusterResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Labels: map[string]string{"clusterresourcebinding.karmada.io/permanent-id": "f2603cdb-f3f3-4a4b-b289-3186a4fef979"},
Finalizers: []string{util.ClusterResourceBindingControllerFinalizer},
},
Spec: workv1alpha2.ResourceBindingSpec{
Resource: rs,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c, err := makeFakeCRBCByResource(&rs)
if err != nil {
t.Fatalf("failed to create fake ClusterResourceBindingController: %v", err)
}
err = c.removeOrphanWorks(context.Background(), tt.crb)
if (err != nil) != tt.wantErr {
t.Errorf("ClusterResourceBindingController.syncBinding() error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}
func TestClusterResourceBindingController_newOverridePolicyFunc(t *testing.T) {
rs := workv1alpha2.ObjectReference{
APIVersion: "v1",
Kind: "Namespace",
Name: "test",
}
tests := []struct {
name string
want []reconcile.Request
req client.Object
crb *workv1alpha2.ClusterResourceBinding
}{
{
name: "not clusteroverridepolicy",
want: nil,
req: &policyv1alpha1.OverridePolicy{},
crb: &workv1alpha2.ClusterResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Labels: map[string]string{"clusterresourcebinding.karmada.io/permanent-id": "f2603cdb-f3f3-4a4b-b289-3186a4fef979"},
Finalizers: []string{util.ClusterResourceBindingControllerFinalizer},
},
Spec: workv1alpha2.ResourceBindingSpec{
Resource: rs,
},
},
},
{
name: "newOverridePolicyFunc test succeed",
want: []reconcile.Request{{NamespacedName: types.NamespacedName{Name: rs.Name}}},
req: &policyv1alpha1.ClusterOverridePolicy{
Spec: policyv1alpha1.OverrideSpec{
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: rs.APIVersion,
Kind: rs.Kind,
Name: rs.Name,
},
},
},
},
crb: &workv1alpha2.ClusterResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Labels: map[string]string{"clusterresourcebinding.karmada.io/permanent-id": "f2603cdb-f3f3-4a4b-b289-3186a4fef979"},
Finalizers: []string{util.ClusterResourceBindingControllerFinalizer},
},
Spec: workv1alpha2.ResourceBindingSpec{
Resource: rs,
},
},
},
{
name: "ResourceSelector is empty",
want: []reconcile.Request{{NamespacedName: types.NamespacedName{Name: rs.Name}}},
req: &policyv1alpha1.ClusterOverridePolicy{
Spec: policyv1alpha1.OverrideSpec{
ResourceSelectors: []policyv1alpha1.ResourceSelector{},
},
},
crb: &workv1alpha2.ClusterResourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Labels: map[string]string{"clusterresourcebinding.karmada.io/permanent-id": "f2603cdb-f3f3-4a4b-b289-3186a4fef979"},
Finalizers: []string{util.ClusterResourceBindingControllerFinalizer},
},
Spec: workv1alpha2.ResourceBindingSpec{
Resource: rs,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c, err := makeFakeCRBCByResource(&rs)
if err != nil {
t.Fatalf("failed to create fake ClusterResourceBindingController: %v", err)
}
if tt.crb != nil {
if err := c.Client.Create(context.Background(), tt.crb); err != nil {
t.Fatalf("Failed to create ClusterResourceBinding: %v", err)
}
}
got := c.newOverridePolicyFunc()
result := got(context.Background(), tt.req)
if !reflect.DeepEqual(result, tt.want) {
t.Errorf("ClusterResourceBindingController.newOverridePolicyFunc() get = %v, want %v", result, tt.want)
return
}
})
}
}