k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340/pkg/validation/validate/values_test.go (about) 1 // Copyright 2015 go-swagger maintainers 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package validate 16 17 import ( 18 "math" 19 "testing" 20 21 "github.com/stretchr/testify/assert" 22 "k8s.io/kube-openapi/pkg/validation/errors" 23 "k8s.io/kube-openapi/pkg/validation/strfmt" 24 ) 25 26 func TestValues_ValidateIntEnum(t *testing.T) { 27 enumValues := []interface{}{1, 2, 3} 28 29 err := Enum("test", "body", int64(5), enumValues) 30 assert.NotNil(t, err) 31 err2 := Enum("test", "body", int64(1), enumValues) 32 assert.Nil(t, err2) 33 } 34 35 func TestValues_ValidateEnum(t *testing.T) { 36 enumValues := []string{"aa", "bb", "cc"} 37 38 err := Enum("test", "body", "a", enumValues) 39 assert.Error(t, err) 40 err = Enum("test", "body", "bb", enumValues) 41 assert.Nil(t, err) 42 } 43 44 // Check edge cases in Enum 45 func TestValues_Enum_EdgeCases(t *testing.T) { 46 enumValues := "aa, bb, cc" 47 48 err := Enum("test", "body", int64(1), enumValues) 49 // No validation occurs: enumValues is not a slice 50 assert.Nil(t, err) 51 52 // TODO(TEST): edge case: value is not a concrete type 53 // It's really a go internals challenge 54 // to figure a test case to demonstrate 55 // this case must be checked (!!) 56 } 57 58 func TestValues_ValidateUniqueItems(t *testing.T) { 59 var err error 60 61 itemsNonUnique := []interface{}{ 62 []int32{1, 2, 3, 4, 4, 5}, 63 []string{"aa", "bb", "cc", "cc", "dd"}, 64 } 65 for _, v := range itemsNonUnique { 66 err = UniqueItems("test", "body", v) 67 assert.Error(t, err) 68 } 69 70 itemsUnique := []interface{}{ 71 []int32{1, 2, 3}, 72 "I'm a string", 73 map[string]int{ 74 "aaa": 1111, 75 "b": 2, 76 "ccc": 333, 77 }, 78 nil, 79 } 80 for _, v := range itemsUnique { 81 err = UniqueItems("test", "body", v) 82 assert.Nil(t, err) 83 } 84 } 85 86 func TestValues_ValidateMinLength(t *testing.T) { 87 var minLength int64 = 5 88 err := MinLength("test", "body", "aa", minLength) 89 assert.Error(t, err) 90 err = MinLength("test", "body", "aaaaa", minLength) 91 assert.Nil(t, err) 92 } 93 94 func TestValues_ValidateMaxLength(t *testing.T) { 95 var maxLength int64 = 5 96 err := MaxLength("test", "body", "bbbbbb", maxLength) 97 assert.Error(t, err) 98 err = MaxLength("test", "body", "aa", maxLength) 99 assert.Nil(t, err) 100 } 101 102 func TestValues_ValidateRequired(t *testing.T) { 103 var err error 104 path := "test" 105 in := "body" 106 107 RequiredFail := []interface{}{ 108 "", 109 0, 110 nil, 111 } 112 113 for _, v := range RequiredFail { 114 err = Required(path, in, v) 115 assert.Error(t, err) 116 } 117 118 RequiredSuccess := []interface{}{ 119 " ", 120 "bla-bla-bla", 121 2, 122 []interface{}{21, []int{}, "testString"}, 123 } 124 125 for _, v := range RequiredSuccess { 126 err = Required(path, in, v) 127 assert.Nil(t, err) 128 } 129 130 } 131 132 func TestValuMultipleOf(t *testing.T) { 133 134 // positive 135 136 err := MultipleOf("test", "body", 9, 3) 137 assert.Nil(t, err) 138 139 err = MultipleOf("test", "body", 9.3, 3.1) 140 assert.Nil(t, err) 141 142 err = MultipleOf("test", "body", 9.1, 0.1) 143 assert.Nil(t, err) 144 145 err = MultipleOf("test", "body", 3, 0.3) 146 assert.Nil(t, err) 147 148 err = MultipleOf("test", "body", 6, 0.3) 149 assert.Nil(t, err) 150 151 err = MultipleOf("test", "body", 1, 0.25) 152 assert.Nil(t, err) 153 154 err = MultipleOf("test", "body", 8, 0.2) 155 assert.Nil(t, err) 156 157 // zero 158 err = MultipleOf("test", "body", 9, 0) 159 assert.Error(t, err) 160 161 err = MultipleOf("test", "body", 9.1, 0) 162 assert.Error(t, err) 163 164 // negative 165 166 err = MultipleOf("test", "body", 3, 0.4) 167 assert.Error(t, err) 168 169 err = MultipleOf("test", "body", 9.1, 0.2) 170 assert.Error(t, err) 171 172 err = MultipleOf("test", "body", 9.34, 0.1) 173 assert.Error(t, err) 174 175 // error on negative factor 176 err = MultipleOf("test", "body", 9.34, -0.1) 177 assert.Error(t, err) 178 } 179 180 // Test edge case for Pattern (in regular spec, no invalid regexp should reach there) 181 func TestValues_Pattern_Edgecases(t *testing.T) { 182 var err *errors.Validation 183 err = Pattern("path", "in", "pick-a-boo", `.*-[a-z]-.*`) 184 assert.Nil(t, err) 185 186 // Invalid regexp 187 err = Pattern("path", "in", "pick-a-boo", `.*-[a(-z]-^).*`) 188 if assert.NotNil(t, err) { 189 assert.Equal(t, int(err.Code()), int(errors.PatternFailCode)) 190 assert.Contains(t, err.Error(), "pattern is invalid") 191 } 192 193 // Valid regexp, invalid pattern 194 err = Pattern("path", "in", "pick-8-boo", `.*-[a-z]-.*`) 195 if assert.NotNil(t, err) { 196 assert.Equal(t, int(err.Code()), int(errors.PatternFailCode)) 197 assert.NotContains(t, err.Error(), "pattern is invalid") 198 assert.Contains(t, err.Error(), "should match") 199 } 200 } 201 202 // Test edge cases in FormatOf 203 // not easily tested with full specs 204 func TestValues_FormatOf_EdgeCases(t *testing.T) { 205 var err *errors.Validation 206 207 err = FormatOf("path", "in", "bugz", "", nil) 208 if assert.NotNil(t, err) { 209 assert.Equal(t, int(err.Code()), int(errors.InvalidTypeCode)) 210 assert.Contains(t, err.Error(), "bugz is an invalid type name") 211 } 212 213 err = FormatOf("path", "in", "bugz", "", strfmt.Default) 214 if assert.NotNil(t, err) { 215 assert.Equal(t, int(err.Code()), int(errors.InvalidTypeCode)) 216 assert.Contains(t, err.Error(), "bugz is an invalid type name") 217 } 218 } 219 220 // Test edge cases in MaximumNativeType 221 // not easily exercised with full specs 222 func TestValues_MaximumNative(t *testing.T) { 223 assert.Nil(t, MaximumNativeType("path", "in", int(5), 10, false)) 224 assert.Nil(t, MaximumNativeType("path", "in", uint(5), 10, true)) 225 assert.Nil(t, MaximumNativeType("path", "in", int8(5), 10, true)) 226 assert.Nil(t, MaximumNativeType("path", "in", uint8(5), 10, true)) 227 assert.Nil(t, MaximumNativeType("path", "in", int16(5), 10, true)) 228 assert.Nil(t, MaximumNativeType("path", "in", uint16(5), 10, true)) 229 assert.Nil(t, MaximumNativeType("path", "in", int32(5), 10, true)) 230 assert.Nil(t, MaximumNativeType("path", "in", uint32(5), 10, true)) 231 assert.Nil(t, MaximumNativeType("path", "in", int64(5), 10, true)) 232 assert.Nil(t, MaximumNativeType("path", "in", uint64(5), 10, true)) 233 assert.Nil(t, MaximumNativeType("path", "in", float32(5.5), 10, true)) 234 assert.Nil(t, MaximumNativeType("path", "in", float64(5.5), 10, true)) 235 236 var err *errors.Validation 237 238 err = MaximumNativeType("path", "in", int32(10), 10, true) 239 if assert.NotNil(t, err) { 240 code := int(err.Code()) 241 assert.Equal(t, code, errors.MaxFailCode) 242 } 243 244 err = MaximumNativeType("path", "in", uint(10), 10, true) 245 if assert.NotNil(t, err) { 246 code := int(err.Code()) 247 assert.Equal(t, code, errors.MaxFailCode) 248 } 249 250 err = MaximumNativeType("path", "in", int64(12), 10, false) 251 if assert.NotNil(t, err) { 252 code := int(err.Code()) 253 assert.Equal(t, code, errors.MaxFailCode) 254 } 255 256 err = MaximumNativeType("path", "in", float32(12.6), 10, false) 257 if assert.NotNil(t, err) { 258 code := int(err.Code()) 259 assert.Equal(t, code, int(errors.MaxFailCode)) 260 } 261 262 err = MaximumNativeType("path", "in", float64(12.6), 10, false) 263 if assert.NotNil(t, err) { 264 code := int(err.Code()) 265 assert.Equal(t, code, int(errors.MaxFailCode)) 266 } 267 268 err = MaximumNativeType("path", "in", uint(5), -10, true) 269 if assert.NotNil(t, err) { 270 code := int(err.Code()) 271 assert.Equal(t, code, int(errors.MaxFailCode)) 272 } 273 } 274 275 // Test edge cases in MinimumNativeType 276 // not easily exercised with full specs 277 func TestValues_MinimumNative(t *testing.T) { 278 assert.Nil(t, MinimumNativeType("path", "in", int(5), 0, false)) 279 assert.Nil(t, MinimumNativeType("path", "in", uint(5), 0, true)) 280 assert.Nil(t, MinimumNativeType("path", "in", int8(5), 0, true)) 281 assert.Nil(t, MinimumNativeType("path", "in", uint8(5), 0, true)) 282 assert.Nil(t, MinimumNativeType("path", "in", int16(5), 0, true)) 283 assert.Nil(t, MinimumNativeType("path", "in", uint16(5), 0, true)) 284 assert.Nil(t, MinimumNativeType("path", "in", int32(5), 0, true)) 285 assert.Nil(t, MinimumNativeType("path", "in", uint32(5), 0, true)) 286 assert.Nil(t, MinimumNativeType("path", "in", int64(5), 0, true)) 287 assert.Nil(t, MinimumNativeType("path", "in", uint64(5), 0, true)) 288 assert.Nil(t, MinimumNativeType("path", "in", float32(5.5), 0, true)) 289 assert.Nil(t, MinimumNativeType("path", "in", float64(5.5), 0, true)) 290 291 var err *errors.Validation 292 293 err = MinimumNativeType("path", "in", uint(10), 10, true) 294 if assert.NotNil(t, err) { 295 code := int(err.Code()) 296 assert.Equal(t, code, int(errors.MinFailCode)) 297 } 298 299 err = MinimumNativeType("path", "in", uint(10), 10, true) 300 if assert.NotNil(t, err) { 301 code := int(err.Code()) 302 assert.Equal(t, code, int(errors.MinFailCode)) 303 } 304 305 err = MinimumNativeType("path", "in", int64(8), 10, false) 306 if assert.NotNil(t, err) { 307 code := int(err.Code()) 308 assert.Equal(t, code, int(errors.MinFailCode)) 309 } 310 311 err = MinimumNativeType("path", "in", float32(12.6), 20, false) 312 if assert.NotNil(t, err) { 313 code := int(err.Code()) 314 assert.Equal(t, code, int(errors.MinFailCode)) 315 } 316 317 err = MinimumNativeType("path", "in", float64(12.6), 20, false) 318 if assert.NotNil(t, err) { 319 code := int(err.Code()) 320 assert.Equal(t, code, int(errors.MinFailCode)) 321 } 322 323 err = MinimumNativeType("path", "in", uint(5), -10, true) 324 assert.Nil(t, err) 325 } 326 327 // Test edge cases in MaximumNativeType 328 // not easily exercised with full specs 329 func TestValues_MultipleOfNative(t *testing.T) { 330 assert.Nil(t, MultipleOfNativeType("path", "in", int(5), 1)) 331 assert.Nil(t, MultipleOfNativeType("path", "in", uint(5), 1)) 332 assert.Nil(t, MultipleOfNativeType("path", "in", int8(5), 1)) 333 assert.Nil(t, MultipleOfNativeType("path", "in", uint8(5), 1)) 334 assert.Nil(t, MultipleOfNativeType("path", "in", int16(5), 1)) 335 assert.Nil(t, MultipleOfNativeType("path", "in", uint16(5), 1)) 336 assert.Nil(t, MultipleOfNativeType("path", "in", int32(5), 1)) 337 assert.Nil(t, MultipleOfNativeType("path", "in", uint32(5), 1)) 338 assert.Nil(t, MultipleOfNativeType("path", "in", int64(5), 1)) 339 assert.Nil(t, MultipleOfNativeType("path", "in", uint64(5), 1)) 340 341 var err *errors.Validation 342 343 err = MultipleOfNativeType("path", "in", int64(5), 0) 344 if assert.NotNil(t, err) { 345 code := int(err.Code()) 346 assert.Equal(t, code, int(errors.MultipleOfMustBePositiveCode)) 347 } 348 349 err = MultipleOfNativeType("path", "in", uint64(5), 0) 350 if assert.NotNil(t, err) { 351 code := int(err.Code()) 352 assert.Equal(t, code, int(errors.MultipleOfMustBePositiveCode)) 353 } 354 355 err = MultipleOfNativeType("path", "in", int64(5), -1) 356 if assert.NotNil(t, err) { 357 code := int(err.Code()) 358 assert.Equal(t, code, int(errors.MultipleOfMustBePositiveCode)) 359 } 360 361 err = MultipleOfNativeType("path", "in", int64(11), 5) 362 if assert.NotNil(t, err) { 363 code := int(err.Code()) 364 assert.Equal(t, code, int(errors.MultipleOfFailCode)) 365 } 366 367 err = MultipleOfNativeType("path", "in", uint64(11), 5) 368 if assert.NotNil(t, err) { 369 code := int(err.Code()) 370 assert.Equal(t, code, int(errors.MultipleOfFailCode)) 371 } 372 } 373 374 // Test edge cases in IsValueValidAgainstRange 375 // not easily exercised with full specs 376 func TestValues_IsValueValidAgainstRange(t *testing.T) { 377 var err error 378 379 // We did not simulate these formats in full specs 380 err = IsValueValidAgainstRange(float32(123.45), "number", "float32", "prefix", "path") 381 assert.NoError(t, err) 382 383 err = IsValueValidAgainstRange(float64(123.45), "number", "float32", "prefix", "path") 384 assert.NoError(t, err) 385 386 err = IsValueValidAgainstRange(int64(123), "number", "float", "prefix", "path") 387 assert.NoError(t, err) 388 389 err = IsValueValidAgainstRange(int64(123), "integer", "", "prefix", "path") 390 assert.NoError(t, err) 391 392 err = IsValueValidAgainstRange(int64(123), "integer", "int64", "prefix", "path") 393 assert.NoError(t, err) 394 395 err = IsValueValidAgainstRange(int64(123), "integer", "uint64", "prefix", "path") 396 assert.NoError(t, err) 397 398 // Error case (do not occur in normal course of a validation) 399 err = IsValueValidAgainstRange(float64(math.MaxFloat64), "integer", "", "prefix", "path") 400 if assert.Error(t, err) { 401 assert.Contains(t, err.Error(), "must be of type integer (default format)") 402 } 403 404 // Checking a few limits 405 err = IsValueValidAgainstRange("123", "number", "", "prefix", "path") 406 if assert.Error(t, err) { 407 assert.Contains(t, err.Error(), "called with invalid (non numeric) val type") 408 } 409 410 err = IsValueValidAgainstRange(int64(2147483647), "integer", "int32", "prefix", "path") 411 assert.NoError(t, err) 412 413 err = IsValueValidAgainstRange(int64(2147483647), "integer", "uint32", "prefix", "path") 414 assert.NoError(t, err) 415 }