@@ -38,7 +38,7 @@ func newMockPreflight(crd *apiextensionsv1.CustomResourceDefinition, err error)
3838 }, preflightOpts ... )
3939}
4040
41- const crdFolder string = "../../../../../ testdata/manifests"
41+ const crdFolder string = "testdata/manifests"
4242
4343func getCrdFromManifestFile (t * testing.T , oldCrdFile string ) * apiextensionsv1.CustomResourceDefinition {
4444 if oldCrdFile == "" {
@@ -66,14 +66,22 @@ func getManifestString(t *testing.T, crdFile string) string {
6666 return string (buff )
6767}
6868
69+ func wantErrorMsgs (wantMsgs []string ) require.ErrorAssertionFunc {
70+ return func (t require.TestingT , haveErr error , _ ... interface {}) {
71+ for _ , wantMsg := range wantMsgs {
72+ require .ErrorContains (t , haveErr , wantMsg )
73+ }
74+ }
75+ }
76+
6977// TestInstall exists only for completeness as Install() is currently a no-op. It can be used as
7078// a template for real tests in the future if the func is implemented.
7179func TestInstall (t * testing.T ) {
7280 tests := []struct {
7381 name string
7482 oldCrdPath string
7583 release * release.Release
76- wantErrMsgs [] string
84+ requireErr require. ErrorAssertionFunc
7785 wantCrdGetErr error
7886 }{
7987 {
@@ -91,7 +99,7 @@ func TestInstall(t *testing.T) {
9199 Name : "test-release" ,
92100 Manifest : "abcd" ,
93101 },
94- wantErrMsgs : []string {"json: cannot unmarshal string into Go value of type unstructured.detector" },
102+ requireErr : wantErrorMsgs ( []string {"json: cannot unmarshal string into Go value of type unstructured.detector" }) ,
95103 },
96104 {
97105 name : "release with no CRD objects" ,
@@ -107,7 +115,7 @@ func TestInstall(t *testing.T) {
107115 Manifest : getManifestString (t , "crd-valid-upgrade.json" ),
108116 },
109117 wantCrdGetErr : fmt .Errorf ("error!" ),
110- wantErrMsgs : []string {"error!" },
118+ requireErr : wantErrorMsgs ( []string {"error!" }) ,
111119 },
112120 {
113121 name : "fail to get old crd, not found error" ,
@@ -123,7 +131,7 @@ func TestInstall(t *testing.T) {
123131 Name : "test-release" ,
124132 Manifest : getManifestString (t , "crd-invalid" ),
125133 },
126- wantErrMsgs : []string {"json: cannot unmarshal" },
134+ requireErr : wantErrorMsgs ( []string {"json: cannot unmarshal" }) ,
127135 },
128136 {
129137 name : "valid upgrade" ,
@@ -142,7 +150,7 @@ func TestInstall(t *testing.T) {
142150 Name : "test-release" ,
143151 Manifest : getManifestString (t , "crd-invalid-upgrade.json" ),
144152 },
145- wantErrMsgs : []string {
153+ requireErr : wantErrorMsgs ( []string {
146154 `scope:` ,
147155 `storedVersionRemoval:` ,
148156 `enum:` ,
@@ -156,7 +164,7 @@ func TestInstall(t *testing.T) {
156164 `minLength:` ,
157165 `minProperties:` ,
158166 `default:` ,
159- },
167+ }) ,
160168 },
161169 {
162170 name : "new crd validation failure for existing field removal" ,
@@ -167,9 +175,9 @@ func TestInstall(t *testing.T) {
167175 Name : "test-release" ,
168176 Manifest : getManifestString (t , "crd-field-removed.json" ),
169177 },
170- wantErrMsgs : []string {
178+ requireErr : wantErrorMsgs ( []string {
171179 `existingFieldRemoval:` ,
172- },
180+ }) ,
173181 },
174182 {
175183 name : "new crd validation should not fail on description changes" ,
@@ -187,10 +195,8 @@ func TestInstall(t *testing.T) {
187195 t .Run (tc .name , func (t * testing.T ) {
188196 preflight := newMockPreflight (getCrdFromManifestFile (t , tc .oldCrdPath ), tc .wantCrdGetErr )
189197 err := preflight .Install (context .Background (), tc .release )
190- if len (tc .wantErrMsgs ) != 0 {
191- for _ , expectedErrMsg := range tc .wantErrMsgs {
192- require .ErrorContains (t , err , expectedErrMsg )
193- }
198+ if tc .requireErr != nil {
199+ tc .requireErr (t , err )
194200 } else {
195201 require .NoError (t , err )
196202 }
@@ -203,7 +209,7 @@ func TestUpgrade(t *testing.T) {
203209 name string
204210 oldCrdPath string
205211 release * release.Release
206- wantErrMsgs [] string
212+ requireErr require. ErrorAssertionFunc
207213 wantCrdGetErr error
208214 }{
209215 {
@@ -221,7 +227,7 @@ func TestUpgrade(t *testing.T) {
221227 Name : "test-release" ,
222228 Manifest : "abcd" ,
223229 },
224- wantErrMsgs : []string {"json: cannot unmarshal string into Go value of type unstructured.detector" },
230+ requireErr : wantErrorMsgs ( []string {"json: cannot unmarshal string into Go value of type unstructured.detector" }) ,
225231 },
226232 {
227233 name : "release with no CRD objects" ,
@@ -237,7 +243,7 @@ func TestUpgrade(t *testing.T) {
237243 Manifest : getManifestString (t , "crd-valid-upgrade.json" ),
238244 },
239245 wantCrdGetErr : fmt .Errorf ("error!" ),
240- wantErrMsgs : []string {"error!" },
246+ requireErr : wantErrorMsgs ( []string {"error!" }) ,
241247 },
242248 {
243249 name : "fail to get old crd, not found error" ,
@@ -253,7 +259,7 @@ func TestUpgrade(t *testing.T) {
253259 Name : "test-release" ,
254260 Manifest : getManifestString (t , "crd-invalid" ),
255261 },
256- wantErrMsgs : []string {"json: cannot unmarshal" },
262+ requireErr : wantErrorMsgs ( []string {"json: cannot unmarshal" }) ,
257263 },
258264 {
259265 name : "valid upgrade" ,
@@ -272,7 +278,7 @@ func TestUpgrade(t *testing.T) {
272278 Name : "test-release" ,
273279 Manifest : getManifestString (t , "crd-invalid-upgrade.json" ),
274280 },
275- wantErrMsgs : []string {
281+ requireErr : wantErrorMsgs ( []string {
276282 `scope:` ,
277283 `storedVersionRemoval:` ,
278284 `enum:` ,
@@ -286,7 +292,7 @@ func TestUpgrade(t *testing.T) {
286292 `minLength:` ,
287293 `minProperties:` ,
288294 `default:` ,
289- },
295+ }) ,
290296 },
291297 {
292298 name : "new crd validation failure for existing field removal" ,
@@ -297,9 +303,9 @@ func TestUpgrade(t *testing.T) {
297303 Name : "test-release" ,
298304 Manifest : getManifestString (t , "crd-field-removed.json" ),
299305 },
300- wantErrMsgs : []string {
306+ requireErr : wantErrorMsgs ( []string {
301307 `existingFieldRemoval:` ,
302- },
308+ }) ,
303309 },
304310 {
305311 name : "webhook conversion strategy exists" ,
@@ -316,9 +322,9 @@ func TestUpgrade(t *testing.T) {
316322 Name : "test-release" ,
317323 Manifest : getManifestString (t , "crd-conversion-no-webhook.json" ),
318324 },
319- wantErrMsgs : []string {
320- `validating upgrade for CRD "crontabs.stable.example.com": v1 < -> v2: ^.spec.foobarbaz: enum: allowed enum values removed` ,
321- },
325+ requireErr : wantErrorMsgs ( []string {
326+ `validating upgrade for CRD "crontabs.stable.example.com": v1 -> v2: ^.spec.foobarbaz: enum: allowed enum values removed` ,
327+ }) ,
322328 },
323329 {
324330 name : "new crd validation should not fail on description changes" ,
@@ -330,16 +336,43 @@ func TestUpgrade(t *testing.T) {
330336 Manifest : getManifestString (t , "crd-description-changed.json" ),
331337 },
332338 },
339+ {
340+ name : "success when old crd and new crd contain the exact same validation issues" ,
341+ oldCrdPath : "crd-conversion-no-webhook.json" ,
342+ release : & release.Release {
343+ Name : "test-release" ,
344+ Manifest : getManifestString (t , "crd-conversion-no-webhook.json" ),
345+ },
346+ },
347+ {
348+ name : "failure when old crd and new crd contain the exact same validation issues, but new crd introduces another validation issue" ,
349+ oldCrdPath : "crd-conversion-no-webhook.json" ,
350+ release : & release.Release {
351+ Name : "test-release" ,
352+ Manifest : getManifestString (t , "crd-conversion-no-webhook-extra-issue.json" ),
353+ },
354+ requireErr : func (t require.TestingT , err error , _ ... interface {}) {
355+ require .ErrorContains (t , err ,
356+ `validating upgrade for CRD "crontabs.stable.example.com":` ,
357+ )
358+ // The newly introduced issue is reported
359+ require .Contains (t , err .Error (),
360+ `v1 -> v2: ^.spec.extraField: type: type changed : "boolean" -> "string"` ,
361+ )
362+ // The existing issue is not reported
363+ require .NotContains (t , err .Error (),
364+ `v1 -> v2: ^.spec.foobarbaz: enum: allowed enum values removed` ,
365+ )
366+ },
367+ },
333368 }
334369
335370 for _ , tc := range tests {
336371 t .Run (tc .name , func (t * testing.T ) {
337372 preflight := newMockPreflight (getCrdFromManifestFile (t , tc .oldCrdPath ), tc .wantCrdGetErr )
338373 err := preflight .Upgrade (context .Background (), tc .release )
339- if len (tc .wantErrMsgs ) != 0 {
340- for _ , expectedErrMsg := range tc .wantErrMsgs {
341- require .ErrorContains (t , err , expectedErrMsg )
342- }
374+ if tc .requireErr != nil {
375+ tc .requireErr (t , err )
343376 } else {
344377 require .NoError (t , err )
345378 }
0 commit comments