408 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			408 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
/*
 | 
						|
Copyright 2022 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 helper
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"reflect"
 | 
						|
	"testing"
 | 
						|
 | 
						|
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						|
	"k8s.io/utils/ptr"
 | 
						|
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
 | 
						|
 | 
						|
	policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
 | 
						|
	"github.com/karmada-io/karmada/pkg/util"
 | 
						|
)
 | 
						|
 | 
						|
func TestSetDefaultSpreadConstraints(t *testing.T) {
 | 
						|
	tests := []struct {
 | 
						|
		name                     string
 | 
						|
		spreadConstraint         []policyv1alpha1.SpreadConstraint
 | 
						|
		expectedSpreadConstraint []policyv1alpha1.SpreadConstraint
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name: "set spreadByField",
 | 
						|
			spreadConstraint: []policyv1alpha1.SpreadConstraint{
 | 
						|
				{
 | 
						|
					MinGroups: 1,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			expectedSpreadConstraint: []policyv1alpha1.SpreadConstraint{
 | 
						|
				{
 | 
						|
					SpreadByField: policyv1alpha1.SpreadByFieldCluster,
 | 
						|
					MinGroups:     1,
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "set minGroups",
 | 
						|
			spreadConstraint: []policyv1alpha1.SpreadConstraint{
 | 
						|
				{
 | 
						|
					SpreadByField: policyv1alpha1.SpreadByFieldCluster,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			expectedSpreadConstraint: []policyv1alpha1.SpreadConstraint{
 | 
						|
				{
 | 
						|
					SpreadByField: policyv1alpha1.SpreadByFieldCluster,
 | 
						|
					MinGroups:     1,
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tt := range tests {
 | 
						|
		t.Run(tt.name, func(t *testing.T) {
 | 
						|
			SetDefaultSpreadConstraints(tt.spreadConstraint)
 | 
						|
			if !reflect.DeepEqual(tt.spreadConstraint, tt.expectedSpreadConstraint) {
 | 
						|
				t.Errorf("expected: %v, but got %v", tt.expectedSpreadConstraint, tt.spreadConstraint)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestIsDependentOverridesPresent(t *testing.T) {
 | 
						|
	tests := []struct {
 | 
						|
		name          string
 | 
						|
		policy        *policyv1alpha1.PropagationPolicy
 | 
						|
		policyCreated bool
 | 
						|
		expectedExist bool
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name: "dependent override policy exist",
 | 
						|
			policy: &policyv1alpha1.PropagationPolicy{
 | 
						|
				ObjectMeta: metav1.ObjectMeta{
 | 
						|
					Name:      "foo",
 | 
						|
					Namespace: "bar",
 | 
						|
				},
 | 
						|
				Spec: policyv1alpha1.PropagationSpec{
 | 
						|
					DependentOverrides: []string{"foo"},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			policyCreated: true,
 | 
						|
			expectedExist: true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "dependent override policy do not exist",
 | 
						|
			policy: &policyv1alpha1.PropagationPolicy{
 | 
						|
				ObjectMeta: metav1.ObjectMeta{
 | 
						|
					Name:      "foo",
 | 
						|
					Namespace: "bar",
 | 
						|
				},
 | 
						|
				Spec: policyv1alpha1.PropagationSpec{
 | 
						|
					DependentOverrides: []string{"foo"},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			policyCreated: false,
 | 
						|
			expectedExist: false,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tt := range tests {
 | 
						|
		t.Run(tt.name, func(t *testing.T) {
 | 
						|
			fakeClient := fake.NewClientBuilder().WithScheme(Schema).Build()
 | 
						|
			if tt.policyCreated {
 | 
						|
				testOverridePolicy := &policyv1alpha1.OverridePolicy{
 | 
						|
					ObjectMeta: metav1.ObjectMeta{
 | 
						|
						Namespace: tt.policy.Namespace,
 | 
						|
						Name:      tt.policy.Name,
 | 
						|
					},
 | 
						|
				}
 | 
						|
				err := fakeClient.Create(context.TODO(), testOverridePolicy)
 | 
						|
				if err != nil {
 | 
						|
					t.Fatalf("failed to create overridePolicy, err is: %v", err)
 | 
						|
				}
 | 
						|
			}
 | 
						|
			res, err := IsDependentOverridesPresent(fakeClient, tt.policy)
 | 
						|
			if !reflect.DeepEqual(res, tt.expectedExist) || err != nil {
 | 
						|
				t.Errorf("expected %v, but got %v", tt.expectedExist, res)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestIsDependentClusterOverridesPresent(t *testing.T) {
 | 
						|
	tests := []struct {
 | 
						|
		name          string
 | 
						|
		policy        *policyv1alpha1.ClusterPropagationPolicy
 | 
						|
		policyCreated bool
 | 
						|
		expectedExist bool
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name: "dependent cluster override policy exist",
 | 
						|
			policy: &policyv1alpha1.ClusterPropagationPolicy{
 | 
						|
				ObjectMeta: metav1.ObjectMeta{
 | 
						|
					Name: "foo",
 | 
						|
				},
 | 
						|
				Spec: policyv1alpha1.PropagationSpec{
 | 
						|
					DependentOverrides: []string{"foo"},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			policyCreated: true,
 | 
						|
			expectedExist: true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "dependent cluster override policy do not exist",
 | 
						|
			policy: &policyv1alpha1.ClusterPropagationPolicy{
 | 
						|
				ObjectMeta: metav1.ObjectMeta{
 | 
						|
					Name: "foo",
 | 
						|
				},
 | 
						|
				Spec: policyv1alpha1.PropagationSpec{
 | 
						|
					DependentOverrides: []string{"foo"},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			policyCreated: false,
 | 
						|
			expectedExist: false,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tt := range tests {
 | 
						|
		t.Run(tt.name, func(t *testing.T) {
 | 
						|
			fakeClient := fake.NewClientBuilder().WithScheme(Schema).Build()
 | 
						|
			if tt.policyCreated {
 | 
						|
				testClusterOverridePolicy := &policyv1alpha1.ClusterOverridePolicy{
 | 
						|
					ObjectMeta: metav1.ObjectMeta{
 | 
						|
						Name: tt.policy.Name,
 | 
						|
					},
 | 
						|
				}
 | 
						|
				err := fakeClient.Create(context.TODO(), testClusterOverridePolicy)
 | 
						|
				if err != nil {
 | 
						|
					t.Fatalf("failed to create clusterOverridePolicy, err is: %v", err)
 | 
						|
				}
 | 
						|
			}
 | 
						|
			res, err := IsDependentClusterOverridesPresent(fakeClient, tt.policy)
 | 
						|
			if !reflect.DeepEqual(res, tt.expectedExist) || err != nil {
 | 
						|
				t.Errorf("expected %v, but got %v", tt.expectedExist, res)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestCheckMatchServiceImport(t *testing.T) {
 | 
						|
	tests := []struct {
 | 
						|
		name              string
 | 
						|
		resourceSelectors []policyv1alpha1.ResourceSelector
 | 
						|
		expected          bool
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name: " get followed resource selector",
 | 
						|
			resourceSelectors: []policyv1alpha1.ResourceSelector{
 | 
						|
				{
 | 
						|
					Name: "foo1",
 | 
						|
					Kind: util.ServiceImportKind,
 | 
						|
				},
 | 
						|
				{
 | 
						|
					Name:      "foo2",
 | 
						|
					Namespace: "bar",
 | 
						|
					Kind:      util.ServiceKind,
 | 
						|
				},
 | 
						|
				{
 | 
						|
					Name:       "foo3",
 | 
						|
					Namespace:  "bar",
 | 
						|
					Kind:       util.ServiceImportKind,
 | 
						|
					APIVersion: "multicluster.x-k8s.io/v1alpha1",
 | 
						|
				},
 | 
						|
			},
 | 
						|
			expected: true,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tt := range tests {
 | 
						|
		t.Run(tt.name, func(t *testing.T) {
 | 
						|
			res := ContainsServiceImport(tt.resourceSelectors)
 | 
						|
			if !reflect.DeepEqual(res, tt.expected) {
 | 
						|
				t.Errorf("expected %v, but got %v", tt.expected, res)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestIsReplicaDynamicDivided(t *testing.T) {
 | 
						|
	tests := []struct {
 | 
						|
		name     string
 | 
						|
		strategy *policyv1alpha1.ReplicaSchedulingStrategy
 | 
						|
		expected bool
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name:     "strategy empty",
 | 
						|
			strategy: nil,
 | 
						|
			expected: false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "strategy duplicated",
 | 
						|
			strategy: &policyv1alpha1.ReplicaSchedulingStrategy{
 | 
						|
				ReplicaSchedulingType: policyv1alpha1.ReplicaSchedulingTypeDuplicated,
 | 
						|
			},
 | 
						|
			expected: false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "strategy division preference weighted",
 | 
						|
			strategy: &policyv1alpha1.ReplicaSchedulingStrategy{
 | 
						|
				ReplicaDivisionPreference: policyv1alpha1.ReplicaDivisionPreferenceWeighted,
 | 
						|
				ReplicaSchedulingType:     policyv1alpha1.ReplicaSchedulingTypeDivided,
 | 
						|
				WeightPreference: &policyv1alpha1.ClusterPreferences{
 | 
						|
					DynamicWeight: policyv1alpha1.DynamicWeightByAvailableReplicas,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			expected: true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "strategy division preference aggregated",
 | 
						|
			strategy: &policyv1alpha1.ReplicaSchedulingStrategy{
 | 
						|
				ReplicaSchedulingType:     policyv1alpha1.ReplicaSchedulingTypeDivided,
 | 
						|
				ReplicaDivisionPreference: policyv1alpha1.ReplicaDivisionPreferenceAggregated,
 | 
						|
			},
 | 
						|
			expected: true,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tt := range tests {
 | 
						|
		t.Run(tt.name, func(t *testing.T) {
 | 
						|
			res := IsReplicaDynamicDivided(&policyv1alpha1.Placement{ReplicaScheduling: tt.strategy})
 | 
						|
			if res != tt.expected {
 | 
						|
				t.Errorf("expected %v, but got %v", tt.expected, res)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestGetAppliedPlacement(t *testing.T) {
 | 
						|
	tests := []struct {
 | 
						|
		name              string
 | 
						|
		annotations       map[string]string
 | 
						|
		expectedPlacement *policyv1alpha1.Placement
 | 
						|
		expectedErr       error
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name: "policy placement annotation exist",
 | 
						|
			annotations: map[string]string{
 | 
						|
				util.PolicyPlacementAnnotation: "{\"clusterAffinity\":{\"clusterNames\":[\"member1\",\"member2\"]}}",
 | 
						|
			},
 | 
						|
			expectedPlacement: &policyv1alpha1.Placement{
 | 
						|
				ClusterAffinity: &policyv1alpha1.ClusterAffinity{
 | 
						|
					ClusterNames: []string{"member1", "member2"},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			expectedErr: nil,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "policy placement annotation do not exist",
 | 
						|
			annotations: map[string]string{
 | 
						|
				"foo": "bar",
 | 
						|
			},
 | 
						|
			expectedPlacement: nil,
 | 
						|
			expectedErr:       nil,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tt := range tests {
 | 
						|
		t.Run(tt.name, func(t *testing.T) {
 | 
						|
			res, err := GetAppliedPlacement(tt.annotations)
 | 
						|
			if !reflect.DeepEqual(res, tt.expectedPlacement) || err != tt.expectedErr {
 | 
						|
				t.Errorf("expected %v and %v, but got %v and %v", tt.expectedPlacement, tt.expectedErr, res, err)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestSetReplicaDivisionPreferenceWeighted(t *testing.T) {
 | 
						|
	tests := []struct {
 | 
						|
		name             string
 | 
						|
		strategy         *policyv1alpha1.ReplicaSchedulingStrategy
 | 
						|
		expectedWeighted bool
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name:             "no replica scheduling strategy declared",
 | 
						|
			expectedWeighted: false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "specified aggregated division preference",
 | 
						|
			strategy: &policyv1alpha1.ReplicaSchedulingStrategy{
 | 
						|
				ReplicaSchedulingType:     policyv1alpha1.ReplicaSchedulingTypeDivided,
 | 
						|
				ReplicaDivisionPreference: policyv1alpha1.ReplicaDivisionPreferenceAggregated,
 | 
						|
			},
 | 
						|
			expectedWeighted: false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "unspecified replica division preference",
 | 
						|
			strategy: &policyv1alpha1.ReplicaSchedulingStrategy{
 | 
						|
				ReplicaSchedulingType: policyv1alpha1.ReplicaSchedulingTypeDivided,
 | 
						|
			},
 | 
						|
			expectedWeighted: true,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tt := range tests {
 | 
						|
		t.Run(tt.name, func(t *testing.T) {
 | 
						|
			p := &policyv1alpha1.Placement{ReplicaScheduling: tt.strategy}
 | 
						|
			SetReplicaDivisionPreferenceWeighted(p)
 | 
						|
			if (p.ReplicaScheduling != nil &&
 | 
						|
				p.ReplicaScheduling.ReplicaDivisionPreference == policyv1alpha1.ReplicaDivisionPreferenceWeighted) != tt.expectedWeighted {
 | 
						|
				t.Errorf("expectedWeighted %v, but got %v", tt.expectedWeighted, !tt.expectedWeighted)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestSetDefaultGracePeriodSeconds(t *testing.T) {
 | 
						|
	tests := []struct {
 | 
						|
		name           string
 | 
						|
		behavior       *policyv1alpha1.ApplicationFailoverBehavior
 | 
						|
		expectBehavior *policyv1alpha1.ApplicationFailoverBehavior
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name: "purgeMode is not graciously",
 | 
						|
			behavior: &policyv1alpha1.ApplicationFailoverBehavior{
 | 
						|
				PurgeMode: policyv1alpha1.Never,
 | 
						|
			},
 | 
						|
			expectBehavior: &policyv1alpha1.ApplicationFailoverBehavior{
 | 
						|
				PurgeMode: policyv1alpha1.Never,
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "purgeMode is graciously and gracePeriodSeconds is set",
 | 
						|
			behavior: &policyv1alpha1.ApplicationFailoverBehavior{
 | 
						|
				PurgeMode:          policyv1alpha1.Graciously,
 | 
						|
				GracePeriodSeconds: ptr.To[int32](200),
 | 
						|
			},
 | 
						|
			expectBehavior: &policyv1alpha1.ApplicationFailoverBehavior{
 | 
						|
				PurgeMode:          policyv1alpha1.Graciously,
 | 
						|
				GracePeriodSeconds: ptr.To[int32](200),
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "purgeMode is graciously and gracePeriodSeconds is not set",
 | 
						|
			behavior: &policyv1alpha1.ApplicationFailoverBehavior{
 | 
						|
				PurgeMode: policyv1alpha1.Graciously,
 | 
						|
			},
 | 
						|
			expectBehavior: &policyv1alpha1.ApplicationFailoverBehavior{
 | 
						|
				PurgeMode:          policyv1alpha1.Graciously,
 | 
						|
				GracePeriodSeconds: ptr.To[int32](600),
 | 
						|
			},
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tt := range tests {
 | 
						|
		t.Run(tt.name, func(t *testing.T) {
 | 
						|
			SetDefaultGracePeriodSeconds(tt.behavior)
 | 
						|
			if !reflect.DeepEqual(tt.behavior, tt.expectBehavior) {
 | 
						|
				t.Errorf("expectedBehavior %v, but got %v", tt.expectBehavior, tt.behavior)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 |