open-cluster-management.io/governance-policy-propagator@v0.13.0/controllers/common/common_test.go (about)

     1  package common
     2  
     3  import (
     4  	"reflect"
     5  	"sort"
     6  	"testing"
     7  
     8  	"github.com/google/go-cmp/cmp"
     9  	"k8s.io/apimachinery/pkg/types"
    10  	clusterv1beta1 "open-cluster-management.io/api/cluster/v1beta1"
    11  	"sigs.k8s.io/controller-runtime/pkg/reconcile"
    12  
    13  	policiesv1 "open-cluster-management.io/governance-policy-propagator/api/v1"
    14  )
    15  
    16  func TestParseRootPolicyLabel(t *testing.T) {
    17  	tests := map[string]struct {
    18  		name      string
    19  		namespace string
    20  		shouldErr bool
    21  	}{
    22  		"foobar":   {"", "", true},
    23  		"foo.bar":  {"bar", "foo", false},
    24  		"fo.ob.ar": {"ob.ar", "fo", false},
    25  	}
    26  
    27  	for input, expected := range tests {
    28  		t.Run(input, func(t *testing.T) {
    29  			name, namespace, err := ParseRootPolicyLabel(input)
    30  			if (err != nil) != expected.shouldErr {
    31  				t.Fatal("expected error, got nil")
    32  			}
    33  			if name != expected.name {
    34  				t.Fatalf("expected name '%v', got '%v'", expected.name, name)
    35  			}
    36  			if namespace != expected.namespace {
    37  				t.Fatalf("expected namespace '%v', got '%v'", expected.namespace, namespace)
    38  			}
    39  		})
    40  	}
    41  }
    42  
    43  func TestGetAffectedObjsWithDecision(t *testing.T) {
    44  	newOjbs := []clusterv1beta1.ClusterDecision{
    45  		{ClusterName: "managed1", Reason: "test11"},
    46  		{ClusterName: "managed2", Reason: "test11"},
    47  	}
    48  	oldObjs := []clusterv1beta1.ClusterDecision{
    49  		{ClusterName: "managed1", Reason: "test11"},
    50  		{ClusterName: "managed3", Reason: "test11"},
    51  	}
    52  	expectedResult := []clusterv1beta1.ClusterDecision{
    53  		{ClusterName: "managed2", Reason: "test11"},
    54  		{ClusterName: "managed3", Reason: "test11"},
    55  	}
    56  
    57  	result := GetAffectedObjs(newOjbs, oldObjs)
    58  	sort.SliceStable(result, func(i, j int) bool {
    59  		return result[i].ClusterName < result[j].ClusterName
    60  	})
    61  
    62  	if !cmp.Equal(result, expectedResult) {
    63  		t.Fatalf(`GetAffectedObjs test failed expected: %+v but result is %+v`, expectedResult, result)
    64  	}
    65  }
    66  
    67  func TestGetAffectedObjsWithRequest(t *testing.T) {
    68  	newOjbs := []reconcile.Request{
    69  		{NamespacedName: types.NamespacedName{Namespace: "test1", Name: "test1"}},
    70  		{NamespacedName: types.NamespacedName{Namespace: "test2", Name: "test2"}},
    71  	}
    72  	oldOjbs := []reconcile.Request{
    73  		{NamespacedName: types.NamespacedName{Namespace: "test1", Name: "test1"}},
    74  		{NamespacedName: types.NamespacedName{Namespace: "test3", Name: "test3"}},
    75  	}
    76  	expectedResult := []reconcile.Request{
    77  		{NamespacedName: types.NamespacedName{Namespace: "test2", Name: "test2"}},
    78  		{NamespacedName: types.NamespacedName{Namespace: "test3", Name: "test3"}},
    79  	}
    80  
    81  	result := GetAffectedObjs(newOjbs, oldOjbs)
    82  	sort.SliceStable(result, func(i, j int) bool {
    83  		return result[i].NamespacedName.Namespace < result[j].NamespacedName.Namespace
    84  	})
    85  
    86  	if !cmp.Equal(result, expectedResult) {
    87  		t.Fatalf(`GetAffectedObjs test failed expected: %+v but result is %+v`, expectedResult, result)
    88  	}
    89  }
    90  
    91  func fakeCPCS(name, compliance string) *policiesv1.CompliancePerClusterStatus {
    92  	return &policiesv1.CompliancePerClusterStatus{
    93  		ComplianceState:  policiesv1.ComplianceState(compliance),
    94  		ClusterName:      name,
    95  		ClusterNamespace: name,
    96  	}
    97  }
    98  
    99  func TestCalculateRootCompliance(t *testing.T) {
   100  	allCompliantList := []*policiesv1.CompliancePerClusterStatus{
   101  		fakeCPCS("articuno", "Compliant"),
   102  		fakeCPCS("zapdos", "Compliant"),
   103  		fakeCPCS("moltres", "Compliant"),
   104  	}
   105  
   106  	tests := map[string]struct {
   107  		input []*policiesv1.CompliancePerClusterStatus
   108  		want  policiesv1.ComplianceState
   109  	}{
   110  		"all compliant": {
   111  			input: allCompliantList,
   112  			want:  policiesv1.Compliant,
   113  		},
   114  		"one noncompliant": {
   115  			input: append(allCompliantList, fakeCPCS("foo", "NonCompliant")),
   116  			want:  policiesv1.NonCompliant,
   117  		},
   118  		"one pending": {
   119  			input: append(allCompliantList, fakeCPCS("bar", "Pending")),
   120  			want:  policiesv1.Pending,
   121  		},
   122  		"one empty": {
   123  			input: append(allCompliantList, fakeCPCS("thud", "")),
   124  			want:  policiesv1.ComplianceState(""),
   125  		},
   126  		"one odd value": {
   127  			input: append(allCompliantList, fakeCPCS("wibble", "Discombobulated")),
   128  			want:  policiesv1.ComplianceState(""),
   129  		},
   130  		"noncompliant and pending": {
   131  			input: append(allCompliantList,
   132  				fakeCPCS("foo", "NonCompliant"),
   133  				fakeCPCS("bar", "Pending")),
   134  			want: policiesv1.NonCompliant,
   135  		},
   136  		"pending and unknown": {
   137  			input: append(allCompliantList,
   138  				fakeCPCS("bar", "Pending"),
   139  				fakeCPCS("thud", "")),
   140  			want: policiesv1.Pending,
   141  		},
   142  		"all states": {
   143  			input: append(allCompliantList,
   144  				fakeCPCS("foo", "NonCompliant"),
   145  				fakeCPCS("bar", "Pending"),
   146  				fakeCPCS("thud", ""),
   147  				fakeCPCS("wibble", "Discombobulated")),
   148  			want: policiesv1.NonCompliant,
   149  		},
   150  	}
   151  
   152  	for name, test := range tests {
   153  		t.Run(name, func(t *testing.T) {
   154  			got := CalculateRootCompliance(test.input)
   155  			if !reflect.DeepEqual(test.want, got) {
   156  				t.Fatalf("expected: %v, got: %v", test.want, got)
   157  			}
   158  		})
   159  	}
   160  }