Merge pull request #5742 from anujagrawal699/addedTests-pkg/util/helper/work.go

Added tests for pkg/util/helper/work.go
This commit is contained in:
karmada-bot 2024-12-31 09:53:31 +08:00 committed by GitHub
commit 492e24dd8c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 494 additions and 7 deletions

View File

@ -17,13 +17,360 @@ limitations under the License.
package helper
import (
"reflect"
"context"
"testing"
"time"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
"github.com/karmada-io/karmada/pkg/util"
)
func TestCreateOrUpdateWork(t *testing.T) {
scheme := runtime.NewScheme()
assert.NoError(t, workv1alpha1.Install(scheme))
assert.NoError(t, workv1alpha2.Install(scheme))
tests := []struct {
name string
existingWork *workv1alpha1.Work
workMeta metav1.ObjectMeta
resource *unstructured.Unstructured
wantErr bool
verify func(*testing.T, client.Client)
}{
{
name: "create new work",
workMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "test-work",
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "test-deployment",
"uid": "test-uid",
},
},
},
verify: func(t *testing.T, c client.Client) {
work := &workv1alpha1.Work{}
err := c.Get(context.TODO(), client.ObjectKey{Namespace: "default", Name: "test-work"}, work)
assert.NoError(t, err)
assert.Equal(t, "test-work", work.Name)
assert.Equal(t, 1, len(work.Spec.Workload.Manifests))
},
},
{
name: "create work with PropagationInstruction",
workMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "test-work",
Labels: map[string]string{
util.PropagationInstruction: "some-value",
},
Annotations: map[string]string{
workv1alpha2.ResourceConflictResolutionAnnotation: "overwrite",
},
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "test-deployment",
"uid": "test-uid",
},
},
},
verify: func(t *testing.T, c client.Client) {
work := &workv1alpha1.Work{}
err := c.Get(context.TODO(), client.ObjectKey{Namespace: "default", Name: "test-work"}, work)
assert.NoError(t, err)
// Get the resource from manifests
manifest := &unstructured.Unstructured{}
err = manifest.UnmarshalJSON(work.Spec.Workload.Manifests[0].Raw)
assert.NoError(t, err)
// Verify labels and annotations were set
labels := manifest.GetLabels()
assert.Equal(t, util.ManagedByKarmadaLabelValue, labels[util.ManagedByKarmadaLabel])
annotations := manifest.GetAnnotations()
assert.Equal(t, "test-uid", annotations[workv1alpha2.ResourceTemplateUIDAnnotation])
assert.Equal(t, "test-work", annotations[workv1alpha2.WorkNameAnnotation])
assert.Equal(t, "default", annotations[workv1alpha2.WorkNamespaceAnnotation])
assert.Equal(t, "overwrite", annotations[workv1alpha2.ResourceConflictResolutionAnnotation])
},
},
{
name: "create work with PropagationInstructionSuppressed",
workMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "test-work",
Labels: map[string]string{
util.PropagationInstruction: util.PropagationInstructionSuppressed,
},
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "test-deployment",
"uid": "test-uid",
},
},
},
verify: func(t *testing.T, c client.Client) {
work := &workv1alpha1.Work{}
err := c.Get(context.TODO(), client.ObjectKey{Namespace: "default", Name: "test-work"}, work)
assert.NoError(t, err)
// Get the resource from manifests
manifest := &unstructured.Unstructured{}
err = manifest.UnmarshalJSON(work.Spec.Workload.Manifests[0].Raw)
assert.NoError(t, err)
// Verify labels and annotations were NOT set
labels := manifest.GetLabels()
assert.Empty(t, labels[util.ManagedByKarmadaLabel])
annotations := manifest.GetAnnotations()
assert.Empty(t, annotations[workv1alpha2.ResourceTemplateUIDAnnotation])
},
},
{
name: "update existing work",
existingWork: &workv1alpha1.Work{
ObjectMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "test-work",
},
},
workMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "test-work",
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "test-deployment",
"uid": "test-uid",
},
},
},
verify: func(t *testing.T, c client.Client) {
work := &workv1alpha1.Work{}
err := c.Get(context.TODO(), client.ObjectKey{Namespace: "default", Name: "test-work"}, work)
assert.NoError(t, err)
assert.Equal(t, 1, len(work.Spec.Workload.Manifests))
},
},
{
name: "error when work is being deleted",
existingWork: &workv1alpha1.Work{
ObjectMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "test-work",
DeletionTimestamp: &metav1.Time{Time: time.Now()},
Finalizers: []string{"test.finalizer.io"}, // Finalizer to satisfy fake client requirement
},
Spec: workv1alpha1.WorkSpec{
Workload: workv1alpha1.WorkloadTemplate{
Manifests: []workv1alpha1.Manifest{
{
RawExtension: runtime.RawExtension{
Raw: []byte(`{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"name":"test-deployment"}}`),
},
},
},
},
},
},
workMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "test-work",
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "test-deployment",
},
},
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := fake.NewClientBuilder().WithScheme(scheme)
if tt.existingWork != nil {
c = c.WithObjects(tt.existingWork)
}
client := c.Build()
err := CreateOrUpdateWork(context.TODO(), client, tt.workMeta, tt.resource)
if tt.wantErr {
assert.Error(t, err)
return
}
assert.NoError(t, err)
if tt.verify != nil {
tt.verify(t, client)
}
})
}
}
func TestGetWorksByLabelsSet(t *testing.T) {
scheme := runtime.NewScheme()
assert.NoError(t, workv1alpha1.Install(scheme))
work1 := &workv1alpha1.Work{
ObjectMeta: metav1.ObjectMeta{
Name: "work1",
Labels: map[string]string{
"app": "test",
},
},
}
work2 := &workv1alpha1.Work{
ObjectMeta: metav1.ObjectMeta{
Name: "work2",
Labels: map[string]string{
"app": "other",
},
},
}
tests := []struct {
name string
works []client.Object
labels labels.Set
wantCount int
}{
{
name: "no works exist",
works: []client.Object{},
labels: labels.Set{"app": "test"},
wantCount: 0,
},
{
name: "find work by label",
works: []client.Object{work1, work2},
labels: labels.Set{"app": "test"},
wantCount: 1,
},
{
name: "find multiple works",
works: []client.Object{work1, work2},
labels: labels.Set{},
wantCount: 2,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client := fake.NewClientBuilder().
WithScheme(scheme).
WithObjects(tt.works...).
Build()
workList, err := GetWorksByLabelsSet(context.TODO(), client, tt.labels)
assert.NoError(t, err)
assert.Equal(t, tt.wantCount, len(workList.Items))
})
}
}
func TestGetWorksByBindingID(t *testing.T) {
scheme := runtime.NewScheme()
assert.NoError(t, workv1alpha1.Install(scheme))
bindingID := "test-binding-id"
work1 := &workv1alpha1.Work{
ObjectMeta: metav1.ObjectMeta{
Name: "work1",
Labels: map[string]string{
workv1alpha2.ResourceBindingPermanentIDLabel: bindingID,
},
},
}
work2 := &workv1alpha1.Work{
ObjectMeta: metav1.ObjectMeta{
Name: "work2",
Labels: map[string]string{
workv1alpha2.ClusterResourceBindingPermanentIDLabel: bindingID,
},
},
}
tests := []struct {
name string
works []client.Object
bindingID string
namespaced bool
wantWorks []string
}{
{
name: "find namespaced binding works",
works: []client.Object{work1, work2},
bindingID: bindingID,
namespaced: true,
wantWorks: []string{"work1"},
},
{
name: "find cluster binding works",
works: []client.Object{work1, work2},
bindingID: bindingID,
namespaced: false,
wantWorks: []string{"work2"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client := fake.NewClientBuilder().
WithScheme(scheme).
WithObjects(tt.works...).
Build()
workList, err := GetWorksByBindingID(context.TODO(), client, tt.bindingID, tt.namespaced)
assert.NoError(t, err)
assert.Equal(t, len(tt.wantWorks), len(workList.Items))
// Verify the correct works were returned
foundWorkNames := make([]string, len(workList.Items))
for i, work := range workList.Items {
foundWorkNames[i] = work.Name
}
assert.ElementsMatch(t, tt.wantWorks, foundWorkNames)
})
}
}
func TestGenEventRef(t *testing.T) {
tests := []struct {
name string
@ -93,17 +440,157 @@ func TestGenEventRef(t *testing.T) {
},
wantErr: true,
},
{
name: "empty kind",
obj: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"metadata": map[string]interface{}{
"name": "test-obj",
"uid": "test-uid",
},
},
},
wantErr: true,
},
{
name: "empty name",
obj: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "Pod",
"metadata": map[string]interface{}{
"uid": "test-uid",
},
},
},
wantErr: true,
},
{
name: "missing uid but has annotation",
obj: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "Pod",
"metadata": map[string]interface{}{
"name": "test-pod",
"annotations": map[string]interface{}{
workv1alpha2.ResourceTemplateUIDAnnotation: "annotation-uid",
},
},
},
},
want: &corev1.ObjectReference{
APIVersion: "v1",
Kind: "Pod",
Name: "test-pod",
UID: "annotation-uid",
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
actual, err := GenEventRef(tt.obj)
if (err != nil) != tt.wantErr {
t.Errorf("GenEventRef() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(actual, tt.want) {
t.Errorf("GenEventRef() = %v, want %v", actual, tt.want)
if tt.wantErr {
assert.Error(t, err)
assert.Nil(t, actual)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want, actual)
}
})
}
}
func TestIsWorkContains(t *testing.T) {
deployment := unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
},
}
deploymentData, _ := deployment.MarshalJSON()
service := unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
},
}
serviceData, _ := service.MarshalJSON()
tests := []struct {
name string
manifests []workv1alpha1.Manifest
targetResource schema.GroupVersionKind
want bool
}{
{
name: "resource exists in manifests",
manifests: []workv1alpha1.Manifest{
{RawExtension: runtime.RawExtension{Raw: deploymentData}},
{RawExtension: runtime.RawExtension{Raw: serviceData}},
},
targetResource: schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"},
want: true,
},
{
name: "resource does not exist in manifests",
manifests: []workv1alpha1.Manifest{
{RawExtension: runtime.RawExtension{Raw: serviceData}},
},
targetResource: schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := IsWorkContains(tt.manifests, tt.targetResource)
assert.Equal(t, tt.want, got)
})
}
}
func TestIsWorkSuspendDispatching(t *testing.T) {
tests := []struct {
name string
work *workv1alpha1.Work
want bool
}{
{
name: "dispatching is suspended",
work: &workv1alpha1.Work{
Spec: workv1alpha1.WorkSpec{
SuspendDispatching: ptr.To(true),
},
},
want: true,
},
{
name: "dispatching is not suspended",
work: &workv1alpha1.Work{
Spec: workv1alpha1.WorkSpec{
SuspendDispatching: ptr.To(false),
},
},
want: false,
},
{
name: "suspend dispatching is nil",
work: &workv1alpha1.Work{
Spec: workv1alpha1.WorkSpec{},
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := IsWorkSuspendDispatching(tt.work)
assert.Equal(t, tt.want, got)
})
}
}