mirror of
https://github.com/openshift/installer.git
synced 2026-02-07 03:47:13 +01:00
304 lines
8.2 KiB
Go
304 lines
8.2 KiB
Go
package validate
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestLastIP(t *testing.T) {
|
|
cases := []struct {
|
|
in net.IPNet
|
|
out net.IP
|
|
}{
|
|
{
|
|
in: net.IPNet{
|
|
IP: net.ParseIP("192.168.0.0").To4(),
|
|
Mask: net.CIDRMask(24, 32),
|
|
},
|
|
out: net.ParseIP("192.168.0.255"),
|
|
},
|
|
{
|
|
in: net.IPNet{
|
|
IP: net.ParseIP("192.168.0.0").To4(),
|
|
Mask: net.CIDRMask(22, 32),
|
|
},
|
|
out: net.ParseIP("192.168.3.255"),
|
|
},
|
|
{
|
|
in: net.IPNet{
|
|
IP: net.ParseIP("192.168.0.0").To4(),
|
|
Mask: net.CIDRMask(32, 32),
|
|
},
|
|
out: net.ParseIP("192.168.0.0"),
|
|
},
|
|
{
|
|
in: net.IPNet{
|
|
IP: net.ParseIP("0.0.0.0").To4(),
|
|
Mask: net.CIDRMask(0, 32),
|
|
},
|
|
out: net.ParseIP("255.255.255.255"),
|
|
},
|
|
}
|
|
|
|
var out net.IP
|
|
for i, c := range cases {
|
|
if out = lastIP(&c.in); out.String() != c.out.String() {
|
|
t.Errorf("test case %d: expected %s but got %s", i, c.out, out)
|
|
}
|
|
}
|
|
}
|
|
|
|
const caseMsg = "must be lower case"
|
|
const emptyMsg = "cannot be empty"
|
|
const invalidDomainMsg = "invalid domain name"
|
|
const invalidHostMsg = "invalid host (must be a domain name or IP address)"
|
|
const invalidIPMsg = "invalid IPv4 address"
|
|
const invalidIntMsg = "invalid integer"
|
|
const invalidPortMsg = "invalid port number"
|
|
const noCIDRNetmaskMsg = "must provide a CIDR netmask (eg, /24)"
|
|
|
|
type test struct {
|
|
in string
|
|
expected string
|
|
}
|
|
|
|
type validator func(string) error
|
|
|
|
func runTests(t *testing.T, funcName string, fn validator, tests []test) {
|
|
for _, test := range tests {
|
|
err := fn(test.in)
|
|
if (err == nil && test.expected != "") || (err != nil && err.Error() != test.expected) {
|
|
t.Errorf("For %s(%q), expected %q, got %q", funcName, test.in, test.expected, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNonEmpty(t *testing.T) {
|
|
tests := []test{
|
|
{"", emptyMsg},
|
|
{" ", emptyMsg},
|
|
{"a", ""},
|
|
{".", ""},
|
|
{"日本語", ""},
|
|
}
|
|
runTests(t, "NonEmpty", nonEmpty, tests)
|
|
}
|
|
|
|
func TestClusterName(t *testing.T) {
|
|
const charsMsg = "only lower case alphanumeric [a-z0-9], dashes and dots are allowed"
|
|
const lengthMsg = "must be between 1 and 253 characters"
|
|
const segmentLengthMsg = "no segment between dots can be more than 63 characters"
|
|
const startEndCharMsg = "must start and end with a lower case alphanumeric character [a-z0-9]"
|
|
const segmentStartEndCharMsg = "segments between dots must start and end with a lower case alphanumeric character [a-z0-9]"
|
|
|
|
maxSizeName := strings.Repeat("123456789.", 25) + "123"
|
|
maxSizeSegment := strings.Repeat("1234567890", 6) + "123"
|
|
|
|
tests := []test{
|
|
{"", emptyMsg},
|
|
{" ", emptyMsg},
|
|
{"a", ""},
|
|
{"A", caseMsg},
|
|
{"abc D", caseMsg},
|
|
{"1", ""},
|
|
{".", startEndCharMsg},
|
|
{"a.", startEndCharMsg},
|
|
{".a", startEndCharMsg},
|
|
{"a.a", ""},
|
|
{"-a", startEndCharMsg},
|
|
{"a-", startEndCharMsg},
|
|
{"a.-a", segmentStartEndCharMsg},
|
|
{"a-.a", segmentStartEndCharMsg},
|
|
{"a%a", charsMsg},
|
|
{"日本語", charsMsg},
|
|
{"a日本語a", charsMsg},
|
|
{maxSizeName, ""},
|
|
{maxSizeName + "a", lengthMsg},
|
|
{maxSizeSegment + ".abc", ""},
|
|
{maxSizeSegment + "a.abc", segmentLengthMsg},
|
|
}
|
|
runTests(t, "ClusterName", ClusterName, tests)
|
|
}
|
|
|
|
func TestIPv4(t *testing.T) {
|
|
tests := []test{
|
|
{"", emptyMsg},
|
|
{" ", emptyMsg},
|
|
{"0.0.0.0", ""},
|
|
{"1.2.3.4", ""},
|
|
{"1.2.3.", invalidIPMsg},
|
|
{"1.2.3.4.", invalidIPMsg},
|
|
{"1.2.3.a", invalidIPMsg},
|
|
{"255.255.255.255", ""},
|
|
}
|
|
runTests(t, "IPv4", IPv4, tests)
|
|
}
|
|
|
|
func TestSubnetCIDR(t *testing.T) {
|
|
const netmaskSizeMsg = "invalid netmask size (must be between 0 and 32)"
|
|
|
|
tests := []test{
|
|
{"", emptyMsg},
|
|
{" ", emptyMsg},
|
|
{"/16", invalidIPMsg},
|
|
{"0.0.0.0/0", ""},
|
|
{"0.0.0.0/32", ""},
|
|
{"1.2.3.4", noCIDRNetmaskMsg},
|
|
{"1.2.3.", noCIDRNetmaskMsg},
|
|
{"1.2.3.4.", noCIDRNetmaskMsg},
|
|
{"1.2.3.4/0", ""},
|
|
{"1.2.3.4/1", ""},
|
|
{"1.2.3.4/31", ""},
|
|
{"1.2.3.4/32", ""},
|
|
{"1.2.3./16", invalidIPMsg},
|
|
{"1.2.3.4./16", invalidIPMsg},
|
|
{"1.2.3.4/33", netmaskSizeMsg},
|
|
{"1.2.3.4/-1", netmaskSizeMsg},
|
|
{"1.2.3.4/abc", netmaskSizeMsg},
|
|
{"172.17.1.2", noCIDRNetmaskMsg},
|
|
{"172.17.1.2/", netmaskSizeMsg},
|
|
{"172.17.1.2/33", netmaskSizeMsg},
|
|
{"172.17.1.2/20", "overlaps with default Docker Bridge subnet (172.17.0.0/16)"},
|
|
{"255.255.255.255/1", ""},
|
|
{"255.255.255.255/32", ""},
|
|
}
|
|
runTests(t, "SubnetCIDR", SubnetCIDR, tests)
|
|
}
|
|
|
|
func TestDomainName(t *testing.T) {
|
|
tests := []test{
|
|
{"", emptyMsg},
|
|
{" ", emptyMsg},
|
|
{"a", ""},
|
|
{".", invalidDomainMsg},
|
|
{"日本語", invalidDomainMsg},
|
|
{"日本語.com", invalidDomainMsg},
|
|
{"abc.日本語.com", invalidDomainMsg},
|
|
{"a日本語a.com", invalidDomainMsg},
|
|
{"abc", ""},
|
|
{"ABC", ""},
|
|
{"ABC123", ""},
|
|
{"ABC123.COM123", ""},
|
|
{"1", ""},
|
|
{"0.0", ""},
|
|
{"1.2.3.4", ""},
|
|
{"1.2.3.4.", ""},
|
|
{"abc.", ""},
|
|
{"abc.com", ""},
|
|
{"abc.com.", ""},
|
|
{"a.b.c.d.e.f", ""},
|
|
{".abc", invalidDomainMsg},
|
|
{".abc.com", invalidDomainMsg},
|
|
{".abc.com", invalidDomainMsg},
|
|
}
|
|
runTests(t, "DomainName", DomainName, tests)
|
|
}
|
|
|
|
func TestEmail(t *testing.T) {
|
|
const invalidMsg = "invalid email address"
|
|
tests := []test{
|
|
{"", emptyMsg},
|
|
{" ", emptyMsg},
|
|
{"a", invalidMsg},
|
|
{".", invalidMsg},
|
|
{"日本語", invalidMsg},
|
|
{"a@abc.com", ""},
|
|
{"A@abc.com", ""},
|
|
{"1@abc.com", ""},
|
|
{"a.B.1.あ@abc.com", ""},
|
|
{"ア@abc.com", ""},
|
|
{"中文@abc.com", ""},
|
|
{"a@abc.com", ""},
|
|
{"a@ABC.com", ""},
|
|
{"a@123.com", ""},
|
|
{"a@日本語.com", invalidDomainMsg},
|
|
{"a@.com", invalidDomainMsg},
|
|
{"@abc.com", invalidMsg},
|
|
}
|
|
runTests(t, "Email", Email, tests)
|
|
}
|
|
|
|
func TestCIDRsDontOverlap(t *testing.T) {
|
|
cases := []struct {
|
|
a string
|
|
b string
|
|
err *regexp.Regexp
|
|
}{
|
|
{
|
|
a: "192.168.0.0/24",
|
|
b: "192.168.0.0/24",
|
|
err: regexp.MustCompile("^\"192.168.0.0/24\" and \"192.168.0.0/24\" overlap$"),
|
|
},
|
|
{
|
|
a: "192.168.0.0/24",
|
|
b: "192.168.0.3/24",
|
|
err: regexp.MustCompile("^\"192.168.0.0/24\" and \"192.168.0.3/24\" overlap$"),
|
|
},
|
|
{
|
|
a: "192.168.0.0/30",
|
|
b: "192.168.0.3/30",
|
|
err: regexp.MustCompile("^\"192.168.0.0/30\" and \"192.168.0.3/30\" overlap$"),
|
|
},
|
|
{
|
|
a: "192.168.0.0/30",
|
|
b: "192.168.0.4/30",
|
|
},
|
|
{
|
|
a: "0.0.0.0/0",
|
|
b: "192.168.0.0/24",
|
|
err: regexp.MustCompile("^\"0.0.0.0/0\" and \"192.168.0.0/24\" overlap$"),
|
|
},
|
|
}
|
|
|
|
for _, testCase := range cases {
|
|
t.Run(fmt.Sprintf("%s %s", testCase.a, testCase.b), func(t *testing.T) {
|
|
err := CIDRsDontOverlap(testCase.a, testCase.b)
|
|
if testCase.err == nil {
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
} else {
|
|
assert.Regexp(t, testCase.err, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOpenSSHPublicKey(t *testing.T) {
|
|
const invalidMsg = "invalid SSH public key"
|
|
const multiLineMsg = "invalid SSH public key (should not contain any newline characters)"
|
|
const privateKeyMsg = "invalid SSH public key (appears to be a private key)"
|
|
tests := []struct {
|
|
in string
|
|
expected string
|
|
}{
|
|
{"a", invalidMsg},
|
|
{".", invalidMsg},
|
|
{"日本語", invalidMsg},
|
|
{"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDxL", ""},
|
|
{"ssh-rsa \t AAAAB3NzaC1yc2EAAAADAQABAAACAQDxL", ""},
|
|
{"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDxL you@example.com", ""},
|
|
{"\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDxL you@example.com", ""},
|
|
{"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDxL you@example.com\n", ""},
|
|
{"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDxL\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDxL", multiLineMsg},
|
|
{"ssh-rsa\nAAAAB3NzaC1yc2EAAAADAQABAAACAQDxL you@example.com", multiLineMsg},
|
|
{"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDxL\nyou@example.com", multiLineMsg},
|
|
{"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDxL", ""},
|
|
{"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCt3BebCHqnSsgpLjo4kVvyfY/z2BS8t27r/7du+O2pb4xYkr7n+KFpbOz523vMTpQ+o1jY4u4TgexglyT9nqasWgLOvo1qjD1agHme8LlTPQSk07rXqOB85Uq5p7ig2zoOejF6qXhcc3n1c7+HkxHrgpBENjLVHOBpzPBIAHkAGaZcl07OCqbsG5yxqEmSGiAlh/IiUVOZgdDMaGjCRFy0wk0mQaGD66DmnFc1H5CzcPjsxr0qO65e7lTGsE930KkO1Vc+RHCVwvhdXs+c2NhJ2/3740Kpes9n1/YullaWZUzlCPDXtRuy6JRbFbvy39JUgHWGWzB3d+3f8oJ/N4qZ cardno:000603633110", ""},
|
|
{"-----BEGIN CERTIFICATE-----abcd-----END CERTIFICATE-----", invalidMsg},
|
|
{"-----BEGIN RSA PRIVATE KEY-----\nabc\n-----END RSA PRIVATE KEY-----", privateKeyMsg},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
err := SSHPublicKey(test.in)
|
|
if (err == nil && test.expected != "") || (err != nil && err.Error() != test.expected) {
|
|
t.Errorf("For %q, expected %q, got %q", test.in, test.expected, err)
|
|
}
|
|
}
|
|
}
|