github.com/argoproj/argo-cd/v2@v2.10.9/notification_controller/controller/controller_test.go (about) 1 package controller 2 3 import ( 4 "context" 5 "testing" 6 "time" 7 8 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" 9 "github.com/sirupsen/logrus/hooks/test" 10 "github.com/stretchr/testify/assert" 11 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 12 "k8s.io/apimachinery/pkg/runtime" 13 "k8s.io/client-go/dynamic/fake" 14 k8sfake "k8s.io/client-go/kubernetes/fake" 15 "k8s.io/client-go/tools/cache" 16 ) 17 18 func TestIsAppSyncStatusRefreshed(t *testing.T) { 19 logger, _ := test.NewNullLogger() 20 logEntry := logger.WithField("", "") 21 22 tests := []struct { 23 name string 24 app *unstructured.Unstructured 25 expectedValue bool 26 }{ 27 { 28 name: "No OperationState", 29 app: &unstructured.Unstructured{ 30 Object: map[string]interface{}{ 31 "status": map[string]interface{}{}, 32 }, 33 }, 34 expectedValue: true, 35 }, 36 { 37 name: "No FinishedAt, Completed Phase", 38 app: &unstructured.Unstructured{ 39 Object: map[string]interface{}{ 40 "status": map[string]interface{}{ 41 "operationState": map[string]interface{}{ 42 "phase": "Succeeded", 43 }, 44 }, 45 }, 46 }, 47 expectedValue: false, 48 }, 49 { 50 name: "FinishedAt After ReconciledAt & ObservedAt", 51 app: &unstructured.Unstructured{ 52 Object: map[string]interface{}{ 53 "status": map[string]interface{}{ 54 "operationState": map[string]interface{}{ 55 "finishedAt": "2021-01-01T01:05:00Z", 56 "phase": "Succeeded", 57 }, 58 "reconciledAt": "2021-01-01T01:02:00Z", 59 "observedAt": "2021-01-01T01:04:00Z", 60 }, 61 }, 62 }, 63 expectedValue: false, 64 }, 65 { 66 name: "FinishedAt Before ReconciledAt & ObservedAt", 67 app: &unstructured.Unstructured{ 68 Object: map[string]interface{}{ 69 "status": map[string]interface{}{ 70 "operationState": map[string]interface{}{ 71 "finishedAt": "2021-01-01T01:02:00Z", 72 "phase": "Succeeded", 73 }, 74 "reconciledAt": "2021-01-01T01:04:00Z", 75 "observedAt": "2021-01-01T01:06:00Z", 76 }, 77 }, 78 }, 79 expectedValue: true, 80 }, 81 } 82 83 for _, test := range tests { 84 t.Run(test.name, func(t *testing.T) { 85 actualValue := isAppSyncStatusRefreshed(test.app, logEntry) 86 assert.Equal(t, test.expectedValue, actualValue) 87 }) 88 } 89 } 90 91 func TestGetAppProj_invalidProjectNestedString(t *testing.T) { 92 app := &unstructured.Unstructured{ 93 Object: map[string]interface{}{ 94 "spec": map[string]interface{}{}, 95 }, 96 } 97 informer := cache.NewSharedIndexInformer(nil, nil, 0, nil) 98 proj := getAppProj(app, informer) 99 100 assert.Nil(t, proj) 101 } 102 103 func TestInit(t *testing.T) { 104 scheme := runtime.NewScheme() 105 err := v1alpha1.SchemeBuilder.AddToScheme(scheme) 106 if err != nil { 107 t.Fatalf("Error registering the resource: %v", err) 108 } 109 dynamicClient := fake.NewSimpleDynamicClient(scheme) 110 k8sClient := k8sfake.NewSimpleClientset() 111 appLabelSelector := "app=test" 112 113 selfServiceNotificationEnabledFlags := []bool{false, true} 114 for _, selfServiceNotificationEnabled := range selfServiceNotificationEnabledFlags { 115 nc := NewController( 116 k8sClient, 117 dynamicClient, 118 nil, 119 "default", 120 []string{}, 121 appLabelSelector, 122 nil, 123 "my-secret", 124 "my-configmap", 125 selfServiceNotificationEnabled, 126 ) 127 128 assert.NotNil(t, nc) 129 130 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 131 defer cancel() 132 133 err = nc.Init(ctx) 134 135 assert.NoError(t, err) 136 } 137 } 138 139 func TestInitTimeout(t *testing.T) { 140 scheme := runtime.NewScheme() 141 err := v1alpha1.SchemeBuilder.AddToScheme(scheme) 142 if err != nil { 143 t.Fatalf("Error registering the resource: %v", err) 144 } 145 dynamicClient := fake.NewSimpleDynamicClient(scheme) 146 k8sClient := k8sfake.NewSimpleClientset() 147 appLabelSelector := "app=test" 148 149 nc := NewController( 150 k8sClient, 151 dynamicClient, 152 nil, 153 "default", 154 []string{}, 155 appLabelSelector, 156 nil, 157 "my-secret", 158 "my-configmap", 159 false, 160 ) 161 162 assert.NotNil(t, nc) 163 164 // Use a short timeout to simulate a timeout during cache synchronization 165 ctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond) 166 defer cancel() 167 168 err = nc.Init(ctx) 169 170 // Expect an error & add assertion for the error message 171 assert.Error(t, err) 172 assert.Equal(t, "Timed out waiting for caches to sync", err.Error()) 173 } 174 175 func TestCheckAppNotInAdditionalNamespaces(t *testing.T) { 176 app := &unstructured.Unstructured{ 177 Object: map[string]interface{}{ 178 "spec": map[string]interface{}{}, 179 }, 180 } 181 namespace := "argocd" 182 var applicationNamespaces []string 183 applicationNamespaces = append(applicationNamespaces, "namespace1") 184 applicationNamespaces = append(applicationNamespaces, "namespace2") 185 186 // app is in same namespace as controller's namespace 187 app.SetNamespace(namespace) 188 assert.False(t, checkAppNotInAdditionalNamespaces(app, namespace, applicationNamespaces)) 189 190 // app is not in the namespace as controller's namespace, but it is in one of the applicationNamespaces 191 app.SetNamespace("namespace2") 192 assert.False(t, checkAppNotInAdditionalNamespaces(app, "", applicationNamespaces)) 193 194 // app is not in the namespace as controller's namespace, and it is not in any of the applicationNamespaces 195 app.SetNamespace("namespace3") 196 assert.True(t, checkAppNotInAdditionalNamespaces(app, "", applicationNamespaces)) 197 }