@@ -17,6 +17,7 @@ limitations under the License.
1717package validation
1818
1919import (
20+ "strings"
2021 "testing"
2122
2223 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -29,15 +30,44 @@ func TestVerifyDependencies(t *testing.T) {
2930 dependencies []configv1alpha1.DependentObjectReference
3031 }
3132 tests := []struct {
32- name string
33- args args
34- wantErr bool
33+ name string
34+ args args
35+ wantErr bool
36+ wantErrContains string
3537 }{
3638 {
37- name : "normal case" ,
39+ name : "normal case with name only " ,
3840 args : args {dependencies : []configv1alpha1.DependentObjectReference {
3941 {APIVersion : "v1" , Kind : "Foo" , Name : "test" },
40- {APIVersion : "v2" , Kind : "Hu" , Namespace : "default" , LabelSelector : & metav1.LabelSelector {MatchLabels : map [string ]string {"bar" : "foo" }}},
42+ }},
43+ wantErr : false ,
44+ },
45+ {
46+ name : "normal case with labelSelector only" ,
47+ args : args {dependencies : []configv1alpha1.DependentObjectReference {
48+ {APIVersion : "v1" , Kind : "Foo" , LabelSelector : & metav1.LabelSelector {MatchLabels : map [string ]string {"app" : "nginx" }}},
49+ }},
50+ wantErr : false ,
51+ },
52+ {
53+ name : "normal case with both name and labelSelector" ,
54+ args : args {dependencies : []configv1alpha1.DependentObjectReference {
55+ {APIVersion : "v2" , Kind : "Hu" , Namespace : "default" , Name : "test" , LabelSelector : & metav1.LabelSelector {MatchLabels : map [string ]string {"bar" : "foo" }}},
56+ }},
57+ wantErr : false ,
58+ },
59+ {
60+ name : "normal case with matchExpressions" ,
61+ args : args {dependencies : []configv1alpha1.DependentObjectReference {
62+ {
63+ APIVersion : "v1" ,
64+ Kind : "ConfigMap" ,
65+ LabelSelector : & metav1.LabelSelector {
66+ MatchExpressions : []metav1.LabelSelectorRequirement {
67+ {Key : "env" , Operator : metav1 .LabelSelectorOpIn , Values : []string {"prod" , "staging" }},
68+ },
69+ },
70+ },
4171 }},
4272 wantErr : false ,
4373 },
@@ -46,27 +76,170 @@ func TestVerifyDependencies(t *testing.T) {
4676 args : args {dependencies : []configv1alpha1.DependentObjectReference {
4777 {Kind : "Foo" , Name : "test" },
4878 }},
49- wantErr : true ,
79+ wantErr : true ,
80+ wantErrContains : "missing required apiVersion" ,
5081 },
5182 {
5283 name : "empty kind" ,
5384 args : args {dependencies : []configv1alpha1.DependentObjectReference {
5485 {APIVersion : "v1" , Name : "test" },
5586 }},
56- wantErr : true ,
87+ wantErr : true ,
88+ wantErrContains : "missing required kind" ,
5789 },
5890 {
5991 name : "empty Name and LabelSelector at the same time" ,
6092 args : args {dependencies : []configv1alpha1.DependentObjectReference {
6193 {APIVersion : "v1" , Kind : "Foo" },
6294 }},
63- wantErr : true ,
95+ wantErr : true ,
96+ wantErrContains : "dependency can not leave name and labelSelector all empty" ,
97+ },
98+ {
99+ name : "invalid label key in matchLabels" ,
100+ args : args {dependencies : []configv1alpha1.DependentObjectReference {
101+ {
102+ APIVersion : "v1" ,
103+ Kind : "Pod" ,
104+ LabelSelector : & metav1.LabelSelector {
105+ MatchLabels : map [string ]string {
106+ "-invalid-key" : "value" ,
107+ },
108+ },
109+ },
110+ }},
111+ wantErr : true ,
112+ wantErrContains : "dependencies[0].labelSelector.matchLabels" ,
113+ },
114+ {
115+ name : "invalid label value in matchLabels" ,
116+ args : args {dependencies : []configv1alpha1.DependentObjectReference {
117+ {
118+ APIVersion : "v1" ,
119+ Kind : "Pod" ,
120+ LabelSelector : & metav1.LabelSelector {
121+ MatchLabels : map [string ]string {
122+ "app" : "invalid@value" ,
123+ },
124+ },
125+ },
126+ }},
127+ wantErr : true ,
128+ wantErrContains : "dependencies[0].labelSelector.matchLabels" ,
129+ },
130+ {
131+ name : "invalid operator in matchExpressions" ,
132+ args : args {dependencies : []configv1alpha1.DependentObjectReference {
133+ {
134+ APIVersion : "v1" ,
135+ Kind : "Pod" ,
136+ LabelSelector : & metav1.LabelSelector {
137+ MatchExpressions : []metav1.LabelSelectorRequirement {
138+ {Key : "env" , Operator : "InvalidOp" , Values : []string {"prod" }},
139+ },
140+ },
141+ },
142+ }},
143+ wantErr : true ,
144+ wantErrContains : "not a valid selector operator" ,
145+ },
146+ {
147+ name : "matchExpressions with In operator but no values" ,
148+ args : args {dependencies : []configv1alpha1.DependentObjectReference {
149+ {
150+ APIVersion : "v1" ,
151+ Kind : "Pod" ,
152+ LabelSelector : & metav1.LabelSelector {
153+ MatchExpressions : []metav1.LabelSelectorRequirement {
154+ {Key : "env" , Operator : metav1 .LabelSelectorOpIn , Values : []string {}},
155+ },
156+ },
157+ },
158+ }},
159+ wantErr : true ,
160+ wantErrContains : "must be specified when `operator` is 'In' or 'NotIn'" ,
161+ },
162+ {
163+ name : "matchExpressions with Exists operator and values" ,
164+ args : args {dependencies : []configv1alpha1.DependentObjectReference {
165+ {
166+ APIVersion : "v1" ,
167+ Kind : "Pod" ,
168+ LabelSelector : & metav1.LabelSelector {
169+ MatchExpressions : []metav1.LabelSelectorRequirement {
170+ {Key : "env" , Operator : metav1 .LabelSelectorOpExists , Values : []string {"prod" }},
171+ },
172+ },
173+ },
174+ }},
175+ wantErr : true ,
176+ wantErrContains : "may not be specified when `operator` is 'Exists' or 'DoesNotExist'" ,
177+ },
178+ {
179+ name : "invalid label key in matchExpressions" ,
180+ args : args {dependencies : []configv1alpha1.DependentObjectReference {
181+ {
182+ APIVersion : "v1" ,
183+ Kind : "Pod" ,
184+ LabelSelector : & metav1.LabelSelector {
185+ MatchExpressions : []metav1.LabelSelectorRequirement {
186+ {Key : "@invalid" , Operator : metav1 .LabelSelectorOpIn , Values : []string {"value" }},
187+ },
188+ },
189+ },
190+ }},
191+ wantErr : true ,
192+ wantErrContains : "dependencies[0].labelSelector.matchExpressions[0].key" ,
193+ },
194+ {
195+ name : "multiple dependencies with mixed errors" ,
196+ args : args {dependencies : []configv1alpha1.DependentObjectReference {
197+ {APIVersion : "v1" , Kind : "Foo" , Name : "valid" },
198+ {Kind : "Bar" , Name : "missing-apiversion" },
199+ }},
200+ wantErr : true ,
201+ wantErrContains : "dependencies[1].apiVersion" ,
202+ },
203+ {
204+ name : "multiple errors in single dependency" ,
205+ args : args {dependencies : []configv1alpha1.DependentObjectReference {
206+ {
207+ // Missing both apiVersion and kind
208+ Name : "test" ,
209+ },
210+ }},
211+ wantErr : true ,
212+ wantErrContains : "missing required" ,
213+ },
214+ {
215+ name : "label value too long" ,
216+ args : args {dependencies : []configv1alpha1.DependentObjectReference {
217+ {
218+ APIVersion : "v1" ,
219+ Kind : "Pod" ,
220+ LabelSelector : & metav1.LabelSelector {
221+ MatchLabels : map [string ]string {
222+ "app" : "this-is-a-very-long-label-value-that-exceeds-the-maximum-allowed-length-of-63-characters-for-kubernetes-labels" ,
223+ },
224+ },
225+ },
226+ }},
227+ wantErr : true ,
228+ wantErrContains : "must be no more than 63 characters" ,
64229 },
65230 }
66231 for _ , tt := range tests {
67232 t .Run (tt .name , func (t * testing.T ) {
68- if err := VerifyDependencies (tt .args .dependencies ); (err != nil ) != tt .wantErr {
233+ err := VerifyDependencies (tt .args .dependencies )
234+ if (err != nil ) != tt .wantErr {
69235 t .Errorf ("VerifyDependencies() error = %v, wantErr %v" , err , tt .wantErr )
236+ return
237+ }
238+
239+ if tt .wantErr && tt .wantErrContains != "" {
240+ if ! strings .Contains (err .Error (), tt .wantErrContains ) {
241+ t .Errorf ("VerifyDependencies() error = %v, want error containing %q" , err , tt .wantErrContains )
242+ }
70243 }
71244 })
72245 }
0 commit comments