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