github.com/openshift/installer@v1.4.17/pkg/validate/validate_test.go (about) 1 package validate 2 3 import ( 4 "fmt" 5 "net" 6 "strings" 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10 ) 11 12 func TestClusterName(t *testing.T) { 13 maxSizeName := strings.Repeat("123456789.", 5) + "1234" 14 15 cases := []struct { 16 name string 17 clusterName string 18 valid bool 19 }{ 20 {"empty", "", false}, 21 {"only whitespace", " ", false}, 22 {"single lowercase", "a", true}, 23 {"single uppercase", "A", false}, 24 {"contains whitespace", "abc D", false}, 25 {"single number", "1", true}, 26 {"single dot", ".", false}, 27 {"ends with dot", "a.", false}, 28 {"starts with dot", ".a", false}, 29 {"multiple labels", "a.a", true}, 30 {"starts with dash", "-a", false}, 31 {"ends with dash", "a-", false}, 32 {"label starts with dash", "a.-a", false}, 33 {"label ends with dash", "a-.a", false}, 34 {"invalid percent", "a%a", false}, 35 {"only non-ascii", "日本語", false}, 36 {"contains non-ascii", "a日本語a", false}, 37 {"max size", maxSizeName, true}, 38 {"too long", maxSizeName + "a", false}, 39 } 40 for _, tc := range cases { 41 t.Run(tc.name, func(t *testing.T) { 42 err := ClusterName(tc.clusterName) 43 if tc.valid { 44 assert.NoError(t, err) 45 } else { 46 assert.Error(t, err) 47 } 48 }) 49 } 50 } 51 52 func TestOnPremClusterName(t *testing.T) { 53 cases := []struct { 54 name string 55 clusterName string 56 valid bool 57 }{ 58 {"single lowercase", "a", true}, 59 {"has a dot", "a.a", false}, 60 {"valid name", "abcde", true}, 61 } 62 for _, tc := range cases { 63 t.Run(tc.name, func(t *testing.T) { 64 err := OnPremClusterName(tc.clusterName) 65 if tc.valid { 66 assert.NoError(t, err) 67 } else { 68 assert.Error(t, err) 69 } 70 }) 71 } 72 } 73 74 func TestClusterName1035(t *testing.T) { 75 maxSizeName := "a" + strings.Repeat("123456789.", 5) + "123" 76 77 cases := []struct { 78 name string 79 clusterName string 80 valid bool 81 }{ 82 {"empty", "", false}, 83 {"only whitespace", " ", false}, 84 {"single lowercase", "a", true}, 85 {"single uppercase", "A", false}, 86 {"contains whitespace", "abc D", false}, 87 {"single number", "1", false}, 88 {"single dot", ".", false}, 89 {"ends with dot", "a.", false}, 90 {"starts with dot", ".a", false}, 91 {"multiple labels", "a.a", true}, 92 {"starts with dash", "-a", false}, 93 {"ends with dash", "a-", false}, 94 {"label starts with dash", "a.-a", false}, 95 {"label ends with dash", "a-.a", false}, 96 {"invalid percent", "a%a", false}, 97 {"only non-ascii", "日本語", false}, 98 {"contains non-ascii", "a日本語a", false}, 99 {"max size", maxSizeName, true}, 100 {"too long", maxSizeName + "a", false}, 101 {"URLs", "https://hello.openshift.org", false}, 102 } 103 for _, tc := range cases { 104 t.Run(tc.name, func(t *testing.T) { 105 err := ClusterName1035(tc.clusterName) 106 if tc.valid { 107 assert.NoError(t, err) 108 } else { 109 assert.Error(t, err) 110 } 111 }) 112 } 113 } 114 115 func TestVCenter(t *testing.T) { 116 cases := []struct { 117 name string 118 clusterName string 119 valid bool 120 }{ 121 {"empty", "", false}, 122 {"only whitespace", " ", false}, 123 {"single lowercase", "a", true}, 124 {"single uppercase", "A", false}, 125 {"contains whitespace", "abc D", false}, 126 {"single number", "1", true}, 127 {"single dot", ".", false}, 128 {"ends with dot", "a.", false}, 129 {"starts with dot", ".a", false}, 130 {"multiple labels", "a.a", true}, 131 {"starts with dash", "-a", false}, 132 {"ends with dash", "a-", false}, 133 {"label starts with dash", "a.-a", false}, 134 {"label ends with dash", "a-.a", false}, 135 {"invalid percent", "a%a", false}, 136 {"only non-ascii", "日本語", false}, 137 {"contains non-ascii", "a日本語a", false}, 138 {"URLs", "https://hello.openshift.org", false}, 139 {"IP", "192.168.1.1", true}, 140 } 141 for _, tc := range cases { 142 t.Run(tc.name, func(t *testing.T) { 143 err := Host(tc.clusterName) 144 if tc.valid { 145 assert.NoError(t, err) 146 } else { 147 assert.Error(t, err) 148 } 149 }) 150 } 151 } 152 153 func TestSubnetCIDR(t *testing.T) { 154 cases := []struct { 155 cidr string 156 expErr string 157 }{ 158 {"0.0.0.0/32", "address must be specified"}, 159 {"1.2.3.4/0", "invalid network address. got 1.2.3.4/0, expecting 0.0.0.0/0"}, 160 {"1.2.3.4/1", "invalid network address. got 1.2.3.4/1, expecting 0.0.0.0/1"}, 161 {"1.2.3.4/31", ""}, 162 {"1.2.3.4/32", ""}, 163 {"0:0:0:0:0:1:102:304/116", "invalid network address. got ::1:102:304/116, expecting ::1:102:0/116"}, 164 {"0:0:0:0:0:ffff:102:304/116", "invalid network address. got 1.2.3.4/20, expecting 1.2.0.0/20"}, 165 {"255.255.255.255/1", "invalid network address. got 255.255.255.255/1, expecting 128.0.0.0/1"}, 166 {"255.255.255.255/32", ""}, 167 } 168 for _, tc := range cases { 169 t.Run(tc.cidr, func(t *testing.T) { 170 ip, cidr, err := net.ParseCIDR(tc.cidr) 171 if err != nil { 172 t.Fatalf("could not parse cidr: %v", err) 173 } 174 err = SubnetCIDR(&net.IPNet{IP: ip, Mask: cidr.Mask}) 175 if tc.expErr != "" { 176 assert.EqualError(t, err, tc.expErr) 177 } else { 178 assert.NoError(t, err) 179 } 180 }) 181 } 182 } 183 184 func TestDomainName_AcceptingTrailingDot(t *testing.T) { 185 cases := []struct { 186 domain string 187 valid bool 188 }{ 189 {"", false}, 190 {" ", false}, 191 {"a", true}, 192 {".", false}, 193 {"日本語", false}, 194 {"日本語.com", false}, 195 {"abc.日本語.com", false}, 196 {"a日本語a.com", false}, 197 {"abc", true}, 198 {"ABC", false}, 199 {"ABC123", false}, 200 {"ABC123.COM123", false}, 201 {"1", true}, 202 {"0.0", true}, 203 {"1.2.3.4", true}, 204 {"1.2.3.4.", true}, 205 {"abc.", true}, 206 {"abc.com", true}, 207 {"abc.com.", true}, 208 {"a.b.c.d.e.f", true}, 209 {".abc", false}, 210 {".abc.com", false}, 211 {".abc.com", false}, 212 } 213 for _, tc := range cases { 214 t.Run(tc.domain, func(t *testing.T) { 215 err := DomainName(tc.domain, true) 216 if tc.valid { 217 assert.NoError(t, err) 218 } else { 219 assert.Error(t, err) 220 } 221 }) 222 } 223 } 224 225 func TestDomainName_RejectingTrailingDot(t *testing.T) { 226 cases := []struct { 227 domain string 228 valid bool 229 }{ 230 {"", false}, 231 {" ", false}, 232 {"a", true}, 233 {".", false}, 234 {"日本語", false}, 235 {"日本語.com", false}, 236 {"abc.日本語.com", false}, 237 {"a日本語a.com", false}, 238 {"abc", true}, 239 {"ABC", false}, 240 {"ABC123", false}, 241 {"ABC123.COM123", false}, 242 {"1", true}, 243 {"0.0", true}, 244 {"1.2.3.4", true}, 245 {"1.2.3.4.", false}, 246 {"abc.", false}, 247 {"abc.com", true}, 248 {"abc.com.", false}, 249 {"a.b.c.d.e.f", true}, 250 {".abc", false}, 251 {".abc.com", false}, 252 {".abc.com", false}, 253 } 254 for _, tc := range cases { 255 t.Run(tc.domain, func(t *testing.T) { 256 err := DomainName(tc.domain, false) 257 if tc.valid { 258 assert.NoError(t, err) 259 } else { 260 assert.Error(t, err) 261 } 262 }) 263 } 264 } 265 266 func TestNoProxyDomainName(t *testing.T) { 267 cases := []struct { 268 domain string 269 valid bool 270 }{ 271 {"", false}, 272 {" ", false}, 273 {"a", true}, 274 {".", false}, 275 {"日本語", false}, 276 {"日本語.com", false}, 277 {"abc.日本語.com", false}, 278 {"a日本語a.com", false}, 279 {"abc", true}, 280 {"ABC", false}, 281 {"ABC123", false}, 282 {"ABC123.COM123", false}, 283 {"1", true}, 284 {"0.0", true}, 285 {"1.2.3.4", true}, 286 {"1.2.3.4.", true}, 287 {"abc.", true}, 288 {"abc.com", true}, 289 {"abc.com.", true}, 290 {"a.b.c.d.e.f", true}, 291 {".abc", true}, 292 {".abc.com", true}, 293 } 294 for _, tc := range cases { 295 t.Run(tc.domain, func(t *testing.T) { 296 err := NoProxyDomainName(tc.domain) 297 if tc.valid { 298 assert.NoError(t, err) 299 } else { 300 assert.Error(t, err) 301 } 302 }) 303 } 304 } 305 306 func TestDoCIDRsOverlap(t *testing.T) { 307 cases := []struct { 308 a string 309 b string 310 overlap bool 311 }{ 312 { 313 a: "192.168.0.0/30", 314 b: "192.168.0.3/30", 315 overlap: true, 316 }, 317 { 318 a: "192.168.0.0/30", 319 b: "192.168.0.4/30", 320 overlap: false, 321 }, 322 { 323 a: "192.168.0.0/29", 324 b: "192.168.0.4/30", 325 overlap: true, 326 }, 327 { 328 a: "0.0.0.0/0", 329 b: "192.168.0.0/24", 330 overlap: true, 331 }, 332 } 333 for _, tc := range cases { 334 t.Run(fmt.Sprintf("%s %s", tc.a, tc.b), func(t *testing.T) { 335 _, a, err := net.ParseCIDR(tc.a) 336 if err != nil { 337 t.Fatalf("could not parse cidr %q: %v", tc.a, err) 338 } 339 _, b, err := net.ParseCIDR(tc.b) 340 if err != nil { 341 t.Fatalf("could not parse cidr %q: %v", tc.b, err) 342 } 343 actual := DoCIDRsOverlap(a, b) 344 assert.Equal(t, tc.overlap, actual) 345 }) 346 } 347 } 348 349 func TestImagePullSecret(t *testing.T) { 350 cases := []struct { 351 name string 352 secret string 353 valid bool 354 }{ 355 { 356 name: "single entry with auth", 357 secret: `{"auths":{"example.com":{"auth":"authorization value"}}}`, 358 valid: true, 359 }, 360 { 361 name: "single entry with credsStore", 362 secret: `{"auths":{"example.com":{"credsStore":"creds store value"}}}`, 363 valid: true, 364 }, 365 { 366 name: "empty", 367 secret: `{}`, 368 valid: false, 369 }, 370 { 371 name: "no auths", 372 secret: `{"not-auths":{"example.com":{"auth":"authorization value"}}}`, 373 valid: false, 374 }, 375 { 376 name: "no auth or credsStore", 377 secret: `{"auths":{"example.com":{"unrequired-field":"value"}}}`, 378 valid: false, 379 }, 380 { 381 name: "additional fields", 382 secret: `{"auths":{"example.com":{"auth":"authorization value","other-field":"other field value"}}}`, 383 valid: true, 384 }, 385 { 386 name: "no entries", 387 secret: `{"auths":{}}`, 388 valid: false, 389 }, 390 { 391 name: "multiple valid entries", 392 secret: `{"auths":{"example.com":{"auth":"authorization value"},"other-example.com":{"auth":"other auth value"}}}`, 393 valid: true, 394 }, 395 { 396 name: "mix of valid and invalid entries", 397 secret: `{"auths":{"example.com":{"auth":"authorization value"},"other-example.com":{"unrequired-field":"value"}}}`, 398 valid: false, 399 }, 400 } 401 for _, tc := range cases { 402 t.Run(tc.name, func(t *testing.T) { 403 err := ImagePullSecret(tc.secret) 404 if tc.valid { 405 assert.NoError(t, err) 406 } else { 407 assert.Error(t, err) 408 } 409 }) 410 } 411 } 412 413 const invalidFormatCertificate = `-----INVALID FORMAT----- 414 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 445 rLWYdt40z0pjcR3FDVzh 446 -----INVALID FORMAT----- 447 ` 448 const validCACertificate = `-----BEGIN CERTIFICATE----- 449 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 480 rLWYdt40z0pjcR3FDVzh 481 -----END CERTIFICATE----- 482 ` 483 484 const validCertificate = `-----BEGIN CERTIFICATE----- 485 MIIF0TCCA7mgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwdzELMAkGA1UEBhMCVVMx 486 FzAVBgNVBAgMDk5vcnRoIENhcm9saW5hMRQwEgYDVQQKDAtSZWQgSGF0IEluYzEf 487 MB0GA1UECwwWT3BlblNoaWZ0IEluc3RhbGwgVGVzdDEYMBYGA1UEAwwPSW50ZXJt 488 ZWRpYXRlIENBMB4XDTE5MDcyMjIwMTMwMloXDTIwMDczMTIwMTMwMlowgY4xCzAJ 489 BgNVBAYTAlVTMRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTEQMA4GA1UEBwwHUmFs 490 ZWlnaDEUMBIGA1UECgwLUmVkIEhhdCBJbmMxHzAdBgNVBAsMFk9wZW5TaGlmdCBJ 491 bnN0YWxsIFRlc3QxHTAbBgNVBAMMFHJlZ2lzdHJ5LmV4YW1wbGUuY29tMIIBIjAN 492 BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyCT3n3zYL7PkLtnzBU9WUyZBz1Q+ 493 SXUP739DjT+xmRunE1ViD2wfkVIhTHowlw6B7+23tSRQngEu5i4+lglzqouYY5jE 494 sqWUXaPMa5FeeDstI6LIUxqk9/2yWRBrrdJlVWor57F310aTzkYtkmkCJTDy3k9R 495 Le8jma8fnchaVpttbHgN/F+CiS+OV8u9PtALGuJ4DfHy2hM4pxhiKMxFpYOaxBuq 496 41Y0ts8CXyEiVWwZB7+fFrAjog8uJuhAdya1rAWvSDo+GQr2CDY2/PJcAVHO1n9F 497 h1LkjqIOd4OOqOy9gIYDc5bvZvWGuzeCN8icrdH8KM53witq5yhZHRL4EQIDAQAB 498 o4IBTTCCAUkwCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4 499 QgENBCYWJE9wZW5TU0wgR2VuZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNV 500 HQ4EFgQUxzJ/lMs83RIoGheipNbag+SZr4wwga8GA1UdIwSBpzCBpIAUPUqJPYDZ 501 eUXbBlR0xXA/F+DYYaihgYekgYQwgYExCzAJBgNVBAYTAlVTMRcwFQYDVQQIDA5O 502 b3J0aCBDYXJvbGluYTEQMA4GA1UEBwwHUmFsZWlnaDEUMBIGA1UECgwLUmVkIEhh 503 dCBJbmMxHzAdBgNVBAsMFk9wZW5TaGlmdCBJbnN0YWxsIFRlc3QxEDAOBgNVBAMM 504 B1Jvb3QgQ0GCAhAAMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD 505 ATANBgkqhkiG9w0BAQsFAAOCAgEALXbZyIAXZPBBe+uWBscUFpmXvfQR9CQRbnYi 506 X4453dLKZqEsWNVcUQihrfaNyHCrkG7dSgT64JWWJcyXLXe9TfVR9FLGjzt4p0P2 507 V9T+PFjp3JN+Elh6XDeNisZ7fHzYs2yYnugZELdWkLOcUwkvUHhSQ5aSWYFrngn7 508 J3mT3GS3WSpLUvVQDn3RBDbS0ossnF1tq9n6Nhs4Xvhdso6gEZU9SeztbnSK9N/k 509 zWLV5PjgwpevJ17jzpxm7ZIAlcp31i4SIircJtGwgUS3cJZXPPWMdK72qnLQjFMF 510 BNEc11EBilMK8tn/K4Dn06BBJMRtOCkq0KhopeZX0HmtQE29z6hy9fcTBklCwLXQ 511 NMSOKemXsOiGTwghosa0xw0H2e9R8z9KTX5xBGgHbHbWu7e/oDVY9+XTnfQ0ZqFi 512 aBa/U/WWLMQQDNvQQGsllxBHC+pOpDD8YhycPmbpsFfhNo58U9VQ6mqtX3o7j5nP 513 imNTY4B5RmZUILe+C0XhON6VL5RCa+s6YngIUcfeylTSB8BTeVBxIAInubKzrgZM 514 4ThJWLbaiTkRqaT/viDfxsmgzJsrDm3ZWzYXwF/a5o6NHK4lqCYf/1nvbjgE5PAm 515 69R88P32rKeiRJ8AoC4N/5YR++NkB11gsW9ooU2nV90owi6eMhQ6+qGLTrq0mTtv 516 CNA1OOo= 517 -----END CERTIFICATE----- 518 ` 519 const invalidStringWithCertificate = `-----BEGIN CERTIFICATE----- 520 MIIF0TCCA7mgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwdzELMAkGA1UEBhMCVVMx 521 FzAVBgNVBAgMDk5vcnRoIENhcm9saW5hMRQwEgYDVQQKDAtSZWQgSGF0IEluYzEf 522 MB0GA1UECwwWT3BlblNoaWZ0IEluc3RhbGwgVGVzdDEYMBYGA1UEAwwPSW50ZXJt 523 ZWRpYXRlIENBMB4XDTE5MDcyMjIwMTMwMloXDTIwMDczMTIwMTMwMlowgY4xCzAJ 524 BgNVBAYTAlVTMRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTEQMA4GA1UEBwwHUmFs 525 ZWlnaDEUMBIGA1UECgwLUmVkIEhhdCBJbmMxHzAdBgNVBAsMFk9wZW5TaGlmdCBJ 526 bnN0YWxsIFRlc3QxHTAbBgNVBAMMFHJlZ2lzdHJ5LmV4YW1wbGUuY29tMIIBIjAN 527 BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyCT3n3zYL7PkLtnzBU9WUyZBz1Q+ 528 SXUP739DjT+xmRunE1ViD2wfkVIhTHowlw6B7+23tSRQngEu5i4+lglzqouYY5jE 529 sqWUXaPMa5FeeDstI6LIUxqk9/2yWRBrrdJlVWor57F310aTzkYtkmkCJTDy3k9R 530 Le8jma8fnchaVpttbHgN/F+CiS+OV8u9PtALGuJ4DfHy2hM4pxhiKMxFpYOaxBuq 531 41Y0ts8CXyEiVWwZB7+fFrAjog8uJuhAdya1rAWvSDo+GQr2CDY2/PJcAVHO1n9F 532 h1LkjqIOd4OOqOy9gIYDc5bvZvWGuzeCN8icrdH8KM53witq5yhZHRL4EQIDAQAB 533 o4IBTTCCAUkwCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4 534 QgENBCYWJE9wZW5TU0wgR2VuZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNV 535 HQ4EFgQUxzJ/lMs83RIoGheipNbag+SZr4wwga8GA1UdIwSBpzCBpIAUPUqJPYDZ 536 eUXbBlR0xXA/F+DYYaihgYekgYQwgYExCzAJBgNVBAYTAlVTMRcwFQYDVQQIDA5O 537 b3J0aCBDYXJvbGluYTEQMA4GA1UEBwwHUmFsZWlnaDEUMBIGA1UECgwLUmVkIEhh 538 dCBJbmMxHzAdBgNVBAsMFk9wZW5TaGlmdCBJbnN0YWxsIFRlc3QxEDAOBgNVBAMM 539 B1Jvb3QgQ0GCAhAAMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD 540 ATANBgkqhkiG9w0BAQsFAAOCAgEALXbZyIAXZPBBe+uWBscUFpmXvfQR9CQRbnYi 541 X4453dLKZqEsWNVcUQihrfaNyHCrkG7dSgT64JWWJcyXLXe9TfVR9FLGjzt4p0P2 542 V9T+PFjp3JN+Elh6XDeNisZ7fHzYs2yYnugZELdWkLOcUwkvUHhSQ5aSWYFrngn7 543 J3mT3GS3WSpLUvVQDn3RBDbS0ossnF1tq9n6Nhs4Xvhdso6gEZU9SeztbnSK9N/k 544 zWLV5PjgwpevJ17jzpxm7ZIAlcp31i4SIircJtGwgUS3cJZXPPWMdK72qnLQjFMF 545 BNEc11EBilMK8tn/K4Dn06BBJMRtOCkq0KhopeZX0HmtQE29z6hy9fcTBklCwLXQ 546 NMSOKemXsOiGTwghosa0xw0H2e9R8z9KTX5xBGgHbHbWu7e/oDVY9+XTnfQ0ZqFi 547 aBa/U/WWLMQQDNvQQGsllxBHC+pOpDD8YhycPmbpsFfhNo58U9VQ6mqtX3o7j5nP 548 imNTY4B5RmZUILe+C0XhON6VL5RCa+s6YngIUcfeylTSB8BTeVBxIAInubKzrgZM 549 4ThJWLbaiTkRqaT/viDfxsmgzJsrDm3ZWzYXwF/a5o6NHK4lqCYf/1nvbjgE5PAm 550 69R88P32rKeiRJ8AoC4N/5YR++NkB11gsW9ooU2nV90owi6eMhQ6+qGLTrq0mTtv 551 CNA1OOo= 552 -----END CERTIFICATE----- 553 Invalid data here 554 ` 555 556 func TestAdditionalTrustBundle(t *testing.T) { 557 cases := []struct { 558 name string 559 certificate string 560 valid bool 561 }{ 562 { 563 name: "valid ca certificate", 564 certificate: validCACertificate, 565 valid: true, 566 }, 567 { 568 name: "valid certificate", 569 certificate: validCertificate, 570 valid: true, 571 }, 572 { 573 name: "invalid format", 574 certificate: invalidFormatCertificate, 575 valid: false, 576 }, 577 { 578 name: "invalid certificate", 579 certificate: invalidFormatCertificate, 580 valid: false, 581 }, 582 { 583 name: "valid certificate with extra invalid string", 584 certificate: invalidStringWithCertificate, 585 valid: false, 586 }, 587 } 588 for _, tc := range cases { 589 t.Run(tc.name, func(t *testing.T) { 590 err := CABundle(tc.certificate) 591 if tc.valid { 592 assert.NoError(t, err) 593 } else { 594 assert.Error(t, err) 595 } 596 }) 597 } 598 } 599 600 func TestSSHPublicKey(t *testing.T) { 601 cases := []struct { 602 name string 603 key string 604 valid bool 605 }{ 606 { 607 name: "valid", 608 key: "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSUGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XAt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/EnmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbxNrRFi9wrf+M7Q==", 609 valid: true, 610 }, 611 { 612 name: "valid with email", 613 key: "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSUGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XAt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/EnmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbxNrRFi9wrf+M7Q== name@example.com", 614 valid: true, 615 }, 616 { 617 name: "invalid format", 618 key: "bad-format AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSUGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XAt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/EnmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbxNrRFi9wrf+M7Q==", 619 valid: true, 620 }, 621 { 622 name: "invalid key", 623 key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDxL", 624 valid: false, 625 }, 626 } 627 for _, tc := range cases { 628 t.Run(tc.name, func(t *testing.T) { 629 err := SSHPublicKey(tc.key) 630 if tc.valid { 631 assert.NoError(t, err) 632 } else { 633 assert.Error(t, err) 634 } 635 }) 636 } 637 } 638 639 func TestURI(t *testing.T) { 640 cases := []struct { 641 name string 642 uri string 643 valid bool 644 }{ 645 { 646 name: "valid", 647 uri: "https://example.com", 648 valid: true, 649 }, 650 { 651 name: "missing scheme", 652 uri: "example.com", 653 valid: false, 654 }, 655 } 656 for _, tc := range cases { 657 t.Run(tc.name, func(t *testing.T) { 658 err := URI(tc.uri) 659 if tc.valid { 660 assert.NoError(t, err) 661 } else { 662 assert.Error(t, err) 663 } 664 }) 665 } 666 } 667 668 func TestMAC(t *testing.T) { 669 cases := []struct { 670 name string 671 addr string 672 expected string 673 }{ 674 { 675 name: "valid_mac", 676 addr: "7A:CE:E3:29:35:6F", 677 }, 678 { 679 name: "invalid_multicast", 680 addr: "7D:CE:E3:29:35:6F", 681 expected: "expected unicast mac address", 682 }, 683 { 684 name: "invalid_infiniband", 685 addr: "00-00-00-00-fe-80-00-00-00-00-00-00-02-00-5e-10-00-00-00-01", 686 expected: "invalid MAC address", 687 }, 688 { 689 name: "invalid_mac", 690 addr: "this is a bad mac", 691 expected: "invalid MAC address", 692 }, 693 } 694 for _, tc := range cases { 695 t.Run(tc.name, func(t *testing.T) { 696 err := MAC(tc.addr) 697 if tc.expected == "" { 698 assert.NoError(t, err) 699 } else { 700 assert.Regexp(t, tc.expected, err) 701 } 702 }) 703 } 704 }