github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/params/validator_test.go (about) 1 // Copyright 2022-2023 The Inspektor Gadget authors 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 params 16 17 import ( 18 "errors" 19 "fmt" 20 "strconv" 21 "testing" 22 23 "github.com/stretchr/testify/require" 24 ) 25 26 func TestValidateIntUint(t *testing.T) { 27 type test struct { 28 name string 29 bitSize int 30 value string 31 expectedError bool 32 validateFn func(bitsize int) func(string) error 33 } 34 35 tests := []test{} 36 37 bitSizes := []int{8, 16, 32, 64} 38 39 // ValidateInt 40 for _, bitSize := range bitSizes { 41 // test max and min numbers allowed 42 tests = append(tests, test{ 43 name: fmt.Sprintf("int%d_max", bitSize), 44 bitSize: bitSize, 45 value: strconv.FormatInt(1<<(bitSize-1)-1, 10), 46 expectedError: false, 47 validateFn: ValidateInt, 48 }) 49 50 tests = append(tests, test{ 51 name: fmt.Sprintf("int%d_min", bitSize), 52 bitSize: bitSize, 53 value: strconv.FormatInt(-(1 << (bitSize - 1)), 10), 54 expectedError: false, 55 validateFn: ValidateInt, 56 }) 57 58 // test offset by one numbers 59 if bitSize == 64 { 60 tests = append(tests, test{ 61 name: fmt.Sprintf("int%d_max+1", bitSize), 62 bitSize: bitSize, 63 value: "9223372036854775808", // 2^63 64 expectedError: true, 65 validateFn: ValidateInt, 66 }) 67 68 tests = append(tests, test{ 69 name: fmt.Sprintf("int%d_min-1", bitSize), 70 bitSize: bitSize, 71 value: "-9223372036854775809", // -2^63 - 1 72 expectedError: true, 73 validateFn: ValidateInt, 74 }) 75 break 76 } 77 78 tests = append(tests, test{ 79 name: fmt.Sprintf("int%d_max+1", bitSize), 80 bitSize: bitSize, 81 value: strconv.FormatInt(1<<(bitSize-1), 10), 82 expectedError: true, 83 validateFn: ValidateInt, 84 }) 85 86 tests = append(tests, test{ 87 name: fmt.Sprintf("int%d_min-1", bitSize), 88 bitSize: bitSize, 89 value: strconv.FormatInt(-(1<<(bitSize-1))-1, 10), 90 expectedError: true, 91 validateFn: ValidateInt, 92 }) 93 } 94 95 // ValidateUint 96 for _, bitSize := range bitSizes { 97 // test max numbers allowed 98 tests = append(tests, test{ 99 name: fmt.Sprintf("uint%d_max", bitSize), 100 bitSize: bitSize, 101 value: strconv.FormatUint(1<<(bitSize)-1, 10), 102 expectedError: false, 103 validateFn: ValidateUint, 104 }) 105 106 // test offset by one numbers 107 if bitSize == 64 { 108 // we need to hardcode this one, otherwise it'll overflow 109 tests = append(tests, test{ 110 name: fmt.Sprintf("uint%d_max+1", bitSize), 111 bitSize: bitSize, 112 value: "18446744073709551616", // 2^64 + 1 113 expectedError: true, 114 validateFn: ValidateUint, 115 }) 116 break 117 } 118 119 tests = append(tests, test{ 120 name: fmt.Sprintf("uint%d_max+1", bitSize), 121 bitSize: bitSize, 122 value: strconv.FormatUint(1<<(bitSize), 10), 123 expectedError: true, 124 validateFn: ValidateUint, 125 }) 126 } 127 128 for _, test := range tests { 129 test := test 130 t.Run(test.name, func(t *testing.T) { 131 fmt.Printf("set value: %s\n", test.value) 132 133 err := test.validateFn(test.bitSize)(test.value) 134 if test.expectedError { 135 require.Error(t, err) 136 } else { 137 require.Nil(t, err) 138 } 139 }) 140 } 141 } 142 143 func TestValidateFloat(t *testing.T) { 144 type test struct { 145 name string 146 bitSize int 147 value string 148 expectedError bool 149 } 150 151 tests := []test{ 152 { 153 name: "no_float", 154 bitSize: 32, 155 value: "no_a_float", 156 expectedError: true, 157 }, 158 { 159 name: "float32", 160 bitSize: 32, 161 value: "1.23456789", 162 expectedError: false, 163 }, 164 { 165 name: "float64", 166 bitSize: 64, 167 value: "1.234567890123456789", 168 expectedError: false, 169 }, 170 { 171 name: "float32_overflow", 172 bitSize: 32, 173 value: "3.4E+39", // math.MaxFloat32 * 10 174 expectedError: true, 175 }, 176 { 177 name: "float64_overflow", 178 bitSize: 64, 179 value: "1.8E+309", // math.MaxFloat64 * 10 180 expectedError: true, 181 }, 182 } 183 184 for _, test := range tests { 185 test := test 186 t.Run(test.name, func(t *testing.T) { 187 err := ValidateFloat(test.bitSize)(test.value) 188 if test.expectedError { 189 require.Error(t, err) 190 } else { 191 require.Nil(t, err) 192 } 193 }) 194 } 195 } 196 197 func TestValidateBool(t *testing.T) { 198 type test struct { 199 name string 200 value string 201 expectedError bool 202 } 203 204 tests := []test{ 205 { 206 name: "true_no_error", 207 value: "true", 208 expectedError: false, 209 }, 210 { 211 name: "false_no_error", 212 value: "false", 213 expectedError: false, 214 }, 215 { 216 name: "bad_input_foo", 217 value: "foo", 218 expectedError: true, 219 }, 220 { 221 name: "bad_input_0", 222 value: "0", 223 expectedError: true, 224 }, 225 { 226 name: "bad_input_1", 227 value: "1", 228 expectedError: true, 229 }, 230 { 231 name: "bad_input_empty", 232 value: "", 233 expectedError: true, 234 }, 235 } 236 237 for _, test := range tests { 238 test := test 239 t.Run(test.name, func(t *testing.T) { 240 err := ValidateBool(test.value) 241 if test.expectedError { 242 require.Error(t, err) 243 } else { 244 require.Nil(t, err) 245 } 246 }) 247 } 248 } 249 250 func TestValidateIntRange(t *testing.T) { 251 type test struct { 252 min int64 253 max int64 254 value string 255 expectedError bool 256 } 257 258 tests := []test{ 259 { 260 min: -10, 261 max: 10, 262 value: "10", 263 expectedError: false, 264 }, 265 { 266 min: -10, 267 max: 10, 268 value: "11", 269 expectedError: true, 270 }, 271 { 272 min: -10, 273 max: 10, 274 value: "-10", 275 expectedError: false, 276 }, 277 { 278 min: -10, 279 max: 10, 280 value: "-11", 281 expectedError: true, 282 }, 283 { 284 min: -10, 285 max: 10, 286 value: "foo", 287 expectedError: true, 288 }, 289 { 290 min: int64(-9223372036854775808), 291 max: int64(9223372036854775808 - 1), 292 value: "9223372036854775808", // 2^63 293 expectedError: true, 294 }, 295 } 296 297 for _, test := range tests { 298 test := test 299 t.Run(fmt.Sprintf("min%d_max%d_error_%t", test.min, test.max, test.expectedError), func(t *testing.T) { 300 err := ValidateIntRange(test.min, test.max)(test.value) 301 if test.expectedError { 302 require.Error(t, err) 303 } else { 304 require.Nil(t, err) 305 } 306 }) 307 } 308 } 309 310 func TestValidateUintRange(t *testing.T) { 311 type test struct { 312 min uint64 313 max uint64 314 value string 315 expectedError bool 316 } 317 318 tests := []test{ 319 { 320 min: 10, 321 max: 20, 322 value: "20", 323 expectedError: false, 324 }, 325 { 326 min: 10, 327 max: 20, 328 value: "21", 329 expectedError: true, 330 }, 331 { 332 min: 10, 333 max: 20, 334 value: "10", 335 expectedError: false, 336 }, 337 { 338 min: 10, 339 max: 20, 340 value: "9", 341 expectedError: true, 342 }, 343 { 344 min: 10, 345 max: 20, 346 value: "foo", 347 expectedError: true, 348 }, 349 { 350 min: 0, 351 max: uint64(18446744073709551616 - 1), 352 value: "18446744073709551616", // 2^64 353 expectedError: true, 354 }, 355 } 356 357 for _, test := range tests { 358 test := test 359 name := fmt.Sprintf("min%d_max%d_error_%t", test.min, test.max, test.expectedError) 360 t.Run(name, func(t *testing.T) { 361 err := ValidateUintRange(test.min, test.max)(test.value) 362 if test.expectedError { 363 require.Error(t, err) 364 } else { 365 require.Nil(t, err) 366 } 367 }) 368 } 369 } 370 371 func TestValidateSlice(t *testing.T) { 372 type test struct { 373 name string 374 value string 375 validator func(string) error 376 expectedError bool 377 } 378 379 noErrFn := func(string) error { return nil } 380 errFn := func(string) error { return errors.New("error") } 381 382 tests := []test{ 383 { 384 name: "empty_slice_no_error", 385 value: "", 386 validator: noErrFn, 387 expectedError: false, 388 }, 389 { 390 name: "slice_with_2_elements_no_error", 391 value: "foo,bar", 392 validator: noErrFn, 393 expectedError: false, 394 }, 395 { 396 name: "slice_with_2_elements_no_error", 397 value: "foo,bar", 398 validator: errFn, 399 expectedError: true, 400 }, 401 { 402 name: "slice_with_2_elements_custom_err_func", 403 value: "foo,bar", 404 validator: func(s string) error { 405 if s == "bar" { 406 return errors.New("error") 407 } 408 409 return nil 410 }, 411 expectedError: true, 412 }, 413 { 414 name: "empty_slice_with_ValidateUintRange_no_error", 415 value: "", 416 validator: ValidateUintRange(1, 10), 417 expectedError: false, 418 }, 419 { 420 name: "slice_with_1_element_with_ValidateUintRange_no_error", 421 value: "4", 422 validator: ValidateUintRange(1, 10), 423 expectedError: false, 424 }, 425 { 426 name: "slice_with_2_elements_with_ValidateUintRange_no_error", 427 value: "5,2", 428 validator: ValidateUintRange(1, 10), 429 expectedError: false, 430 }, 431 { 432 name: "slice_with_3_elements_with_ValidateUintRange_error", 433 value: "5,2,11", 434 validator: ValidateUintRange(1, 10), 435 expectedError: true, 436 }, 437 } 438 439 for _, test := range tests { 440 test := test 441 t.Run(test.name, func(t *testing.T) { 442 err := ValidateSlice(test.validator)(test.value) 443 if test.expectedError { 444 require.Error(t, err) 445 } else { 446 require.Nil(t, err) 447 } 448 }) 449 } 450 } 451 452 type validateTest struct { 453 name string 454 value string 455 expectedError bool 456 } 457 458 func testValidate(t *testing.T, tests []validateTest, validate func(str string) error) { 459 for _, test := range tests { 460 test := test 461 t.Run(test.name, func(t *testing.T) { 462 err := validate(test.value) 463 if test.expectedError { 464 require.Error(t, err) 465 } else { 466 require.Nil(t, err) 467 } 468 }) 469 } 470 } 471 472 func TestValidateDuration(t *testing.T) { 473 testValidate(t, 474 []validateTest{ 475 { 476 name: "1s_no_error", 477 value: "1s", 478 expectedError: false, 479 }, 480 { 481 name: "1m_no_error", 482 value: "1m", 483 expectedError: false, 484 }, 485 { 486 name: "empty_error", 487 value: "", 488 expectedError: true, 489 }, 490 { 491 name: "bad_input_0", 492 value: "-", 493 expectedError: true, 494 }, 495 { 496 name: "bad_input_1", 497 value: "asdafaf", 498 expectedError: true, 499 }, 500 { 501 name: "bad_unit", 502 value: "1sad", 503 expectedError: true, 504 }, 505 }, 506 ValidateDuration, 507 ) 508 } 509 510 func TestValidateIP(t *testing.T) { 511 testValidate(t, 512 []validateTest{ 513 { 514 name: "IPv4_no_error", 515 value: "127.0.0.1", 516 expectedError: false, 517 }, 518 { 519 name: "IPv6_no_error", 520 value: "::1", 521 expectedError: false, 522 }, 523 { 524 name: "empty_no_error", 525 value: "", 526 expectedError: false, 527 }, 528 { 529 name: "bad_input_0", 530 value: "-", 531 expectedError: true, 532 }, 533 { 534 name: "bad_input_1", 535 value: "foo", 536 expectedError: true, 537 }, 538 }, 539 ValidateIP, 540 ) 541 }