Commit 47b4d8fc authored by Ed Bartosh's avatar Ed Bartosh

kubeadm: use T.Run API in app/util

Used T.Run API for kubeadm tests in app/util/
parent 74f779fb
...@@ -29,28 +29,33 @@ import ( ...@@ -29,28 +29,33 @@ import (
func TestLogDryRunAction(t *testing.T) { func TestLogDryRunAction(t *testing.T) {
var tests = []struct { var tests = []struct {
name string
action core.Action action core.Action
expectedBytes []byte expectedBytes []byte
buf *bytes.Buffer buf *bytes.Buffer
}{ }{
{ {
name: "action GET on services",
action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "default", "kubernetes"), action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "default", "kubernetes"),
expectedBytes: []byte(`[dryrun] Would perform action GET on resource "services" in API group "core/v1" expectedBytes: []byte(`[dryrun] Would perform action GET on resource "services" in API group "core/v1"
[dryrun] Resource name: "kubernetes" [dryrun] Resource name: "kubernetes"
`), `),
}, },
{ {
name: "action GET on clusterrolebindings",
action: core.NewRootGetAction(schema.GroupVersionResource{Group: rbac.GroupName, Version: rbac.SchemeGroupVersion.Version, Resource: "clusterrolebindings"}, "system:node"), action: core.NewRootGetAction(schema.GroupVersionResource{Group: rbac.GroupName, Version: rbac.SchemeGroupVersion.Version, Resource: "clusterrolebindings"}, "system:node"),
expectedBytes: []byte(`[dryrun] Would perform action GET on resource "clusterrolebindings" in API group "rbac.authorization.k8s.io/v1" expectedBytes: []byte(`[dryrun] Would perform action GET on resource "clusterrolebindings" in API group "rbac.authorization.k8s.io/v1"
[dryrun] Resource name: "system:node" [dryrun] Resource name: "system:node"
`), `),
}, },
{ {
name: "action LIST on services",
action: core.NewListAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, schema.GroupVersionKind{Version: "v1", Kind: "Service"}, "default", metav1.ListOptions{}), action: core.NewListAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, schema.GroupVersionKind{Version: "v1", Kind: "Service"}, "default", metav1.ListOptions{}),
expectedBytes: []byte(`[dryrun] Would perform action LIST on resource "services" in API group "core/v1" expectedBytes: []byte(`[dryrun] Would perform action LIST on resource "services" in API group "core/v1"
`), `),
}, },
{ {
name: "action CREATE on services",
action: core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "default", &v1.Service{ action: core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "default", &v1.Service{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "foo", Name: "foo",
...@@ -72,6 +77,7 @@ func TestLogDryRunAction(t *testing.T) { ...@@ -72,6 +77,7 @@ func TestLogDryRunAction(t *testing.T) {
`), `),
}, },
{ {
name: "action PATCH on nodes",
action: core.NewPatchAction(schema.GroupVersionResource{Version: "v1", Resource: "nodes"}, "default", "my-node", "application/strategic-merge-patch+json", []byte(`{"spec":{"taints":[{"key": "foo", "value": "bar"}]}}`)), action: core.NewPatchAction(schema.GroupVersionResource{Version: "v1", Resource: "nodes"}, "default", "my-node", "application/strategic-merge-patch+json", []byte(`{"spec":{"taints":[{"key": "foo", "value": "bar"}]}}`)),
expectedBytes: []byte(`[dryrun] Would perform action PATCH on resource "nodes" in API group "core/v1" expectedBytes: []byte(`[dryrun] Would perform action PATCH on resource "nodes" in API group "core/v1"
[dryrun] Resource name: "my-node" [dryrun] Resource name: "my-node"
...@@ -80,6 +86,7 @@ func TestLogDryRunAction(t *testing.T) { ...@@ -80,6 +86,7 @@ func TestLogDryRunAction(t *testing.T) {
`), `),
}, },
{ {
name: "action DELETE on pods",
action: core.NewDeleteAction(schema.GroupVersionResource{Version: "v1", Resource: "pods"}, "default", "my-pod"), action: core.NewDeleteAction(schema.GroupVersionResource{Version: "v1", Resource: "pods"}, "default", "my-pod"),
expectedBytes: []byte(`[dryrun] Would perform action DELETE on resource "pods" in API group "core/v1" expectedBytes: []byte(`[dryrun] Would perform action DELETE on resource "pods" in API group "core/v1"
[dryrun] Resource name: "my-pod" [dryrun] Resource name: "my-pod"
...@@ -87,16 +94,18 @@ func TestLogDryRunAction(t *testing.T) { ...@@ -87,16 +94,18 @@ func TestLogDryRunAction(t *testing.T) {
}, },
} }
for _, rt := range tests { for _, rt := range tests {
rt.buf = bytes.NewBufferString("") t.Run(rt.name, func(t *testing.T) {
logDryRunAction(rt.action, rt.buf, DefaultMarshalFunc) rt.buf = bytes.NewBufferString("")
actualBytes := rt.buf.Bytes() logDryRunAction(rt.action, rt.buf, DefaultMarshalFunc)
actualBytes := rt.buf.Bytes()
if !bytes.Equal(actualBytes, rt.expectedBytes) { if !bytes.Equal(actualBytes, rt.expectedBytes) {
t.Errorf( t.Errorf(
"failed LogDryRunAction:\n\texpected bytes: %q\n\t actual: %q", "failed LogDryRunAction:\n\texpected bytes: %q\n\t actual: %q",
rt.expectedBytes, rt.expectedBytes,
actualBytes, actualBytes,
) )
} }
})
} }
} }
...@@ -32,54 +32,63 @@ func TestHandleGetAction(t *testing.T) { ...@@ -32,54 +32,63 @@ func TestHandleGetAction(t *testing.T) {
idr := NewInitDryRunGetter(masterName, serviceSubnet) idr := NewInitDryRunGetter(masterName, serviceSubnet)
var tests = []struct { var tests = []struct {
name string
action core.GetActionImpl action core.GetActionImpl
expectedHandled bool expectedHandled bool
expectedObjectJSON []byte expectedObjectJSON []byte
expectedErr bool expectedErr bool
}{ }{
{ {
name: "get default services",
action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "default", "kubernetes"), action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "default", "kubernetes"),
expectedHandled: true, expectedHandled: true,
expectedObjectJSON: []byte(`{"metadata":{"name":"kubernetes","namespace":"default","creationTimestamp":null,"labels":{"component":"apiserver","provider":"kubernetes"}},"spec":{"ports":[{"name":"https","port":443,"targetPort":6443}],"clusterIP":"10.96.0.1"},"status":{"loadBalancer":{}}}`), expectedObjectJSON: []byte(`{"metadata":{"name":"kubernetes","namespace":"default","creationTimestamp":null,"labels":{"component":"apiserver","provider":"kubernetes"}},"spec":{"ports":[{"name":"https","port":443,"targetPort":6443}],"clusterIP":"10.96.0.1"},"status":{"loadBalancer":{}}}`),
expectedErr: false, expectedErr: false,
}, },
{ {
name: "get nodes",
action: core.NewRootGetAction(schema.GroupVersionResource{Version: "v1", Resource: "nodes"}, masterName), action: core.NewRootGetAction(schema.GroupVersionResource{Version: "v1", Resource: "nodes"}, masterName),
expectedHandled: true, expectedHandled: true,
expectedObjectJSON: []byte(`{"metadata":{"name":"master-foo","creationTimestamp":null,"labels":{"kubernetes.io/hostname":"master-foo"}},"spec":{},"status":{"daemonEndpoints":{"kubeletEndpoint":{"Port":0}},"nodeInfo":{"machineID":"","systemUUID":"","bootID":"","kernelVersion":"","osImage":"","containerRuntimeVersion":"","kubeletVersion":"","kubeProxyVersion":"","operatingSystem":"","architecture":""}}}`), expectedObjectJSON: []byte(`{"metadata":{"name":"master-foo","creationTimestamp":null,"labels":{"kubernetes.io/hostname":"master-foo"}},"spec":{},"status":{"daemonEndpoints":{"kubeletEndpoint":{"Port":0}},"nodeInfo":{"machineID":"","systemUUID":"","bootID":"","kernelVersion":"","osImage":"","containerRuntimeVersion":"","kubeletVersion":"","kubeProxyVersion":"","operatingSystem":"","architecture":""}}}`),
expectedErr: false, expectedErr: false,
}, },
{ {
name: "get clusterrolebinings",
action: core.NewRootGetAction(schema.GroupVersionResource{Group: rbac.GroupName, Version: rbac.SchemeGroupVersion.Version, Resource: "clusterrolebindings"}, "system:node"), action: core.NewRootGetAction(schema.GroupVersionResource{Group: rbac.GroupName, Version: rbac.SchemeGroupVersion.Version, Resource: "clusterrolebindings"}, "system:node"),
expectedHandled: true, expectedHandled: true,
expectedObjectJSON: []byte(``), expectedObjectJSON: []byte(``),
expectedErr: true, // we expect a NotFound error here expectedErr: true, // we expect a NotFound error here
}, },
{ {
name: "get kube-system secret bootstrap-token-abcdef",
action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, "kube-system", "bootstrap-token-abcdef"), action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, "kube-system", "bootstrap-token-abcdef"),
expectedHandled: true, expectedHandled: true,
expectedObjectJSON: []byte(``), expectedObjectJSON: []byte(``),
expectedErr: true, // we expect a NotFound error here expectedErr: true, // we expect a NotFound error here
}, },
{ // an ask for a kubernetes service in the _kube-system_ ns should not be answered { // an ask for a kubernetes service in the _kube-system_ ns should not be answered
name: "get kube-system services",
action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "kube-system", "kubernetes"), action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "kube-system", "kubernetes"),
expectedHandled: false, expectedHandled: false,
expectedObjectJSON: []byte(``), expectedObjectJSON: []byte(``),
expectedErr: false, expectedErr: false,
}, },
{ // an ask for an other service than kubernetes should not be answered { // an ask for an other service than kubernetes should not be answered
name: "get default my-other-service",
action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "default", "my-other-service"), action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "services"}, "default", "my-other-service"),
expectedHandled: false, expectedHandled: false,
expectedObjectJSON: []byte(``), expectedObjectJSON: []byte(``),
expectedErr: false, expectedErr: false,
}, },
{ // an ask for an other node than the master should not be answered { // an ask for an other node than the master should not be answered
name: "get other-node",
action: core.NewRootGetAction(schema.GroupVersionResource{Version: "v1", Resource: "nodes"}, "other-node"), action: core.NewRootGetAction(schema.GroupVersionResource{Version: "v1", Resource: "nodes"}, "other-node"),
expectedHandled: false, expectedHandled: false,
expectedObjectJSON: []byte(``), expectedObjectJSON: []byte(``),
expectedErr: false, expectedErr: false,
}, },
{ // an ask for a secret in any other ns than kube-system should not be answered { // an ask for a secret in any other ns than kube-system should not be answered
name: "get default secret bootstrap-token-abcdef",
action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, "default", "bootstrap-token-abcdef"), action: core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, "default", "bootstrap-token-abcdef"),
expectedHandled: false, expectedHandled: false,
expectedObjectJSON: []byte(``), expectedObjectJSON: []byte(``),
...@@ -87,40 +96,42 @@ func TestHandleGetAction(t *testing.T) { ...@@ -87,40 +96,42 @@ func TestHandleGetAction(t *testing.T) {
}, },
} }
for _, rt := range tests { for _, rt := range tests {
handled, obj, actualErr := idr.HandleGetAction(rt.action) t.Run(rt.name, func(t *testing.T) {
objBytes := []byte(``) handled, obj, actualErr := idr.HandleGetAction(rt.action)
if obj != nil { objBytes := []byte(``)
var err error if obj != nil {
objBytes, err = json.Marshal(obj) var err error
if err != nil { objBytes, err = json.Marshal(obj)
t.Fatalf("couldn't marshal returned object") if err != nil {
t.Fatalf("couldn't marshal returned object")
}
} }
}
if handled != rt.expectedHandled { if handled != rt.expectedHandled {
t.Errorf( t.Errorf(
"failed HandleGetAction:\n\texpected handled: %t\n\t actual: %t %v", "failed HandleGetAction:\n\texpected handled: %t\n\t actual: %t %v",
rt.expectedHandled, rt.expectedHandled,
handled, handled,
rt.action, rt.action,
) )
} }
if !bytes.Equal(objBytes, rt.expectedObjectJSON) { if !bytes.Equal(objBytes, rt.expectedObjectJSON) {
t.Errorf( t.Errorf(
"failed HandleGetAction:\n\texpected object: %q\n\t actual: %q", "failed HandleGetAction:\n\texpected object: %q\n\t actual: %q",
rt.expectedObjectJSON, rt.expectedObjectJSON,
objBytes, objBytes,
) )
} }
if (actualErr != nil) != rt.expectedErr { if (actualErr != nil) != rt.expectedErr {
t.Errorf( t.Errorf(
"failed HandleGetAction:\n\texpected error: %t\n\t actual: %t %v", "failed HandleGetAction:\n\texpected error: %t\n\t actual: %t %v",
rt.expectedErr, rt.expectedErr,
(actualErr != nil), (actualErr != nil),
rt.action, rt.action,
) )
} }
})
} }
} }
...@@ -24,11 +24,13 @@ import ( ...@@ -24,11 +24,13 @@ import (
func TestBuildArgumentListFromMap(t *testing.T) { func TestBuildArgumentListFromMap(t *testing.T) {
var tests = []struct { var tests = []struct {
name string
base map[string]string base map[string]string
overrides map[string]string overrides map[string]string
expected []string expected []string
}{ }{
{ // override an argument from the base {
name: "override an argument from the base",
base: map[string]string{ base: map[string]string{
"admission-control": "NamespaceLifecycle", "admission-control": "NamespaceLifecycle",
"insecure-bind-address": "127.0.0.1", "insecure-bind-address": "127.0.0.1",
...@@ -43,7 +45,8 @@ func TestBuildArgumentListFromMap(t *testing.T) { ...@@ -43,7 +45,8 @@ func TestBuildArgumentListFromMap(t *testing.T) {
"--insecure-bind-address=127.0.0.1", "--insecure-bind-address=127.0.0.1",
}, },
}, },
{ // add an argument that is not in base {
name: "add an argument that is not in base",
base: map[string]string{ base: map[string]string{
"insecure-bind-address": "127.0.0.1", "insecure-bind-address": "127.0.0.1",
"allow-privileged": "true", "allow-privileged": "true",
...@@ -57,7 +60,8 @@ func TestBuildArgumentListFromMap(t *testing.T) { ...@@ -57,7 +60,8 @@ func TestBuildArgumentListFromMap(t *testing.T) {
"--insecure-bind-address=127.0.0.1", "--insecure-bind-address=127.0.0.1",
}, },
}, },
{ // allow empty strings in base {
name: "allow empty strings in base",
base: map[string]string{ base: map[string]string{
"insecure-bind-address": "127.0.0.1", "insecure-bind-address": "127.0.0.1",
"allow-privileged": "true", "allow-privileged": "true",
...@@ -73,7 +77,8 @@ func TestBuildArgumentListFromMap(t *testing.T) { ...@@ -73,7 +77,8 @@ func TestBuildArgumentListFromMap(t *testing.T) {
"--something-that-allows-empty-string=", "--something-that-allows-empty-string=",
}, },
}, },
{ // allow empty strings in overrides {
name: "allow empty strings in overrides",
base: map[string]string{ base: map[string]string{
"insecure-bind-address": "127.0.0.1", "insecure-bind-address": "127.0.0.1",
"allow-privileged": "true", "allow-privileged": "true",
...@@ -93,20 +98,23 @@ func TestBuildArgumentListFromMap(t *testing.T) { ...@@ -93,20 +98,23 @@ func TestBuildArgumentListFromMap(t *testing.T) {
} }
for _, rt := range tests { for _, rt := range tests {
actual := BuildArgumentListFromMap(rt.base, rt.overrides) t.Run(rt.name, func(t *testing.T) {
if !reflect.DeepEqual(actual, rt.expected) { actual := BuildArgumentListFromMap(rt.base, rt.overrides)
t.Errorf("failed BuildArgumentListFromMap:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual) if !reflect.DeepEqual(actual, rt.expected) {
} t.Errorf("failed BuildArgumentListFromMap:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual)
}
})
} }
} }
func TestParseArgumentListToMap(t *testing.T) { func TestParseArgumentListToMap(t *testing.T) {
var tests = []struct { var tests = []struct {
name string
args []string args []string
expectedMap map[string]string expectedMap map[string]string
}{ }{
{ {
// normal case name: "normal case",
args: []string{ args: []string{
"--admission-control=NamespaceLifecycle,LimitRanger", "--admission-control=NamespaceLifecycle,LimitRanger",
"--insecure-bind-address=127.0.0.1", "--insecure-bind-address=127.0.0.1",
...@@ -119,7 +127,7 @@ func TestParseArgumentListToMap(t *testing.T) { ...@@ -119,7 +127,7 @@ func TestParseArgumentListToMap(t *testing.T) {
}, },
}, },
{ {
// test that feature-gates is working name: "test that feature-gates is working",
args: []string{ args: []string{
"--admission-control=NamespaceLifecycle,LimitRanger", "--admission-control=NamespaceLifecycle,LimitRanger",
"--insecure-bind-address=127.0.0.1", "--insecure-bind-address=127.0.0.1",
...@@ -134,7 +142,7 @@ func TestParseArgumentListToMap(t *testing.T) { ...@@ -134,7 +142,7 @@ func TestParseArgumentListToMap(t *testing.T) {
}, },
}, },
{ {
// test that a binary can be the first arg name: "test that a binary can be the first arg",
args: []string{ args: []string{
"kube-apiserver", "kube-apiserver",
"--admission-control=NamespaceLifecycle,LimitRanger", "--admission-control=NamespaceLifecycle,LimitRanger",
...@@ -152,21 +160,24 @@ func TestParseArgumentListToMap(t *testing.T) { ...@@ -152,21 +160,24 @@ func TestParseArgumentListToMap(t *testing.T) {
} }
for _, rt := range tests { for _, rt := range tests {
actualMap := ParseArgumentListToMap(rt.args) t.Run(rt.name, func(t *testing.T) {
if !reflect.DeepEqual(actualMap, rt.expectedMap) { actualMap := ParseArgumentListToMap(rt.args)
t.Errorf("failed ParseArgumentListToMap:\nexpected:\n%v\nsaw:\n%v", rt.expectedMap, actualMap) if !reflect.DeepEqual(actualMap, rt.expectedMap) {
} t.Errorf("failed ParseArgumentListToMap:\nexpected:\n%v\nsaw:\n%v", rt.expectedMap, actualMap)
}
})
} }
} }
func TestReplaceArgument(t *testing.T) { func TestReplaceArgument(t *testing.T) {
var tests = []struct { var tests = []struct {
name string
args []string args []string
mutateFunc func(map[string]string) map[string]string mutateFunc func(map[string]string) map[string]string
expectedArgs []string expectedArgs []string
}{ }{
{ {
// normal case name: "normal case",
args: []string{ args: []string{
"kube-apiserver", "kube-apiserver",
"--admission-control=NamespaceLifecycle,LimitRanger", "--admission-control=NamespaceLifecycle,LimitRanger",
...@@ -185,7 +196,7 @@ func TestReplaceArgument(t *testing.T) { ...@@ -185,7 +196,7 @@ func TestReplaceArgument(t *testing.T) {
}, },
}, },
{ {
// normal case name: "another normal case",
args: []string{ args: []string{
"kube-apiserver", "kube-apiserver",
"--admission-control=NamespaceLifecycle,LimitRanger", "--admission-control=NamespaceLifecycle,LimitRanger",
...@@ -207,21 +218,24 @@ func TestReplaceArgument(t *testing.T) { ...@@ -207,21 +218,24 @@ func TestReplaceArgument(t *testing.T) {
} }
for _, rt := range tests { for _, rt := range tests {
actualArgs := ReplaceArgument(rt.args, rt.mutateFunc) t.Run(rt.name, func(t *testing.T) {
sort.Strings(actualArgs) actualArgs := ReplaceArgument(rt.args, rt.mutateFunc)
sort.Strings(rt.expectedArgs) sort.Strings(actualArgs)
if !reflect.DeepEqual(actualArgs, rt.expectedArgs) { sort.Strings(rt.expectedArgs)
t.Errorf("failed ReplaceArgument:\nexpected:\n%v\nsaw:\n%v", rt.expectedArgs, actualArgs) if !reflect.DeepEqual(actualArgs, rt.expectedArgs) {
} t.Errorf("failed ReplaceArgument:\nexpected:\n%v\nsaw:\n%v", rt.expectedArgs, actualArgs)
}
})
} }
} }
func TestRoundtrip(t *testing.T) { func TestRoundtrip(t *testing.T) {
var tests = []struct { var tests = []struct {
name string
args []string args []string
}{ }{
{ {
// normal case name: "normal case",
args: []string{ args: []string{
"--admission-control=NamespaceLifecycle,LimitRanger", "--admission-control=NamespaceLifecycle,LimitRanger",
"--insecure-bind-address=127.0.0.1", "--insecure-bind-address=127.0.0.1",
...@@ -229,7 +243,7 @@ func TestRoundtrip(t *testing.T) { ...@@ -229,7 +243,7 @@ func TestRoundtrip(t *testing.T) {
}, },
}, },
{ {
// test that feature-gates is working name: "test that feature-gates is working",
args: []string{ args: []string{
"--admission-control=NamespaceLifecycle,LimitRanger", "--admission-control=NamespaceLifecycle,LimitRanger",
"--insecure-bind-address=127.0.0.1", "--insecure-bind-address=127.0.0.1",
...@@ -240,86 +254,89 @@ func TestRoundtrip(t *testing.T) { ...@@ -240,86 +254,89 @@ func TestRoundtrip(t *testing.T) {
} }
for _, rt := range tests { for _, rt := range tests {
// These two methods should be each other's opposite functions, test that by chaining the methods and see if you get the same result back t.Run(rt.name, func(t *testing.T) {
actual := BuildArgumentListFromMap(ParseArgumentListToMap(rt.args), map[string]string{}) // These two methods should be each other's opposite functions, test that by chaining the methods and see if you get the same result back
sort.Strings(actual) actual := BuildArgumentListFromMap(ParseArgumentListToMap(rt.args), map[string]string{})
sort.Strings(rt.args) sort.Strings(actual)
sort.Strings(rt.args)
if !reflect.DeepEqual(actual, rt.args) { if !reflect.DeepEqual(actual, rt.args) {
t.Errorf("failed TestRoundtrip:\nexpected:\n%v\nsaw:\n%v", rt.args, actual) t.Errorf("failed TestRoundtrip:\nexpected:\n%v\nsaw:\n%v", rt.args, actual)
} }
})
} }
} }
func TestParseArgument(t *testing.T) { func TestParseArgument(t *testing.T) {
var tests = []struct { var tests = []struct {
name string
arg string arg string
expectedKey string expectedKey string
expectedVal string expectedVal string
expectedErr bool expectedErr bool
}{ }{
{ {
// cannot be empty name: "arg cannot be empty",
arg: "", arg: "",
expectedErr: true, expectedErr: true,
}, },
{ {
// must contain -- and = name: "arg must contain -- and =",
arg: "a", arg: "a",
expectedErr: true, expectedErr: true,
}, },
{ {
// must contain -- and = name: "arg must contain -- and =",
arg: "a-z", arg: "a-z",
expectedErr: true, expectedErr: true,
}, },
{ {
// must contain -- name: "arg must contain --",
arg: "a=b", arg: "a=b",
expectedErr: true, expectedErr: true,
}, },
{ {
// must contain a key name: "arg must contain a key",
arg: "--=b", arg: "--=b",
expectedErr: true, expectedErr: true,
}, },
{ {
// can contain key but no value name: "arg can contain key but no value",
arg: "--a=", arg: "--a=",
expectedKey: "a", expectedKey: "a",
expectedVal: "", expectedVal: "",
expectedErr: false, expectedErr: false,
}, },
{ {
// simple case name: "simple case",
arg: "--a=b", arg: "--a=b",
expectedKey: "a", expectedKey: "a",
expectedVal: "b", expectedVal: "b",
expectedErr: false, expectedErr: false,
}, },
{ {
// keys/values with '-' should be supported name: "keys/values with '-' should be supported",
arg: "--very-long-flag-name=some-value", arg: "--very-long-flag-name=some-value",
expectedKey: "very-long-flag-name", expectedKey: "very-long-flag-name",
expectedVal: "some-value", expectedVal: "some-value",
expectedErr: false, expectedErr: false,
}, },
{ {
// numbers should be handled correctly name: "numbers should be handled correctly",
arg: "--some-number=0.2", arg: "--some-number=0.2",
expectedKey: "some-number", expectedKey: "some-number",
expectedVal: "0.2", expectedVal: "0.2",
expectedErr: false, expectedErr: false,
}, },
{ {
// lists should be handled correctly name: "lists should be handled correctly",
arg: "--admission-control=foo,bar,baz", arg: "--admission-control=foo,bar,baz",
expectedKey: "admission-control", expectedKey: "admission-control",
expectedVal: "foo,bar,baz", expectedVal: "foo,bar,baz",
expectedErr: false, expectedErr: false,
}, },
{ {
// more than one '=' should be allowed name: "more than one '=' should be allowed",
arg: "--feature-gates=EnableFoo=true,EnableBar=false", arg: "--feature-gates=EnableFoo=true,EnableBar=false",
expectedKey: "feature-gates", expectedKey: "feature-gates",
expectedVal: "EnableFoo=true,EnableBar=false", expectedVal: "EnableFoo=true,EnableBar=false",
...@@ -328,12 +345,14 @@ func TestParseArgument(t *testing.T) { ...@@ -328,12 +345,14 @@ func TestParseArgument(t *testing.T) {
} }
for _, rt := range tests { for _, rt := range tests {
key, val, actual := parseArgument(rt.arg) t.Run(rt.name, func(t *testing.T) {
if (actual != nil) != rt.expectedErr { key, val, actual := parseArgument(rt.arg)
t.Errorf("failed parseArgument:\nexpected error:\n%t\nsaw error:\n%v", rt.expectedErr, actual) if (actual != nil) != rt.expectedErr {
} t.Errorf("failed parseArgument:\nexpected error:\n%t\nsaw error:\n%v", rt.expectedErr, actual)
if (key != rt.expectedKey) || (val != rt.expectedVal) { }
t.Errorf("failed parseArgument:\nexpected key: %s\nsaw key: %s\nexpected value: %s\nsaw value: %s", rt.expectedKey, key, rt.expectedVal, val) if (key != rt.expectedKey) || (val != rt.expectedVal) {
} t.Errorf("failed parseArgument:\nexpected key: %s\nsaw key: %s\nexpected value: %s\nsaw value: %s", rt.expectedKey, key, rt.expectedVal, val)
}
})
} }
} }
...@@ -197,19 +197,21 @@ func TestGetMasterEndpoint(t *testing.T) { ...@@ -197,19 +197,21 @@ func TestGetMasterEndpoint(t *testing.T) {
} }
for _, rt := range tests { for _, rt := range tests {
actualEndpoint, actualError := GetMasterEndpoint(rt.cfg) t.Run(rt.name, func(t *testing.T) {
actualEndpoint, actualError := GetMasterEndpoint(rt.cfg)
if (actualError != nil) && !rt.expectedError { if (actualError != nil) && !rt.expectedError {
t.Errorf("%s unexpected failure: %v", rt.name, actualError) t.Errorf("%s unexpected failure: %v", rt.name, actualError)
continue return
} else if (actualError == nil) && rt.expectedError { } else if (actualError == nil) && rt.expectedError {
t.Errorf("%s passed when expected to fail", rt.name) t.Errorf("%s passed when expected to fail", rt.name)
continue return
} }
if actualEndpoint != rt.expectedEndpoint { if actualEndpoint != rt.expectedEndpoint {
t.Errorf("%s returned invalid endpoint %s, expected %s", rt.name, actualEndpoint, rt.expectedEndpoint) t.Errorf("%s returned invalid endpoint %s, expected %s", rt.name, actualEndpoint, rt.expectedEndpoint)
} }
})
} }
} }
...@@ -316,24 +318,26 @@ func TestParseHostPort(t *testing.T) { ...@@ -316,24 +318,26 @@ func TestParseHostPort(t *testing.T) {
} }
for _, rt := range tests { for _, rt := range tests {
actualHost, actualPort, actualError := ParseHostPort(rt.hostport) t.Run(rt.name, func(t *testing.T) {
actualHost, actualPort, actualError := ParseHostPort(rt.hostport)
if (actualError != nil) && !rt.expectedError { if (actualError != nil) && !rt.expectedError {
t.Errorf("%s unexpected failure: %v", rt.name, actualError) t.Errorf("%s unexpected failure: %v", rt.name, actualError)
continue return
} else if (actualError == nil) && rt.expectedError { } else if (actualError == nil) && rt.expectedError {
t.Errorf("%s passed when expected to fail", rt.name) t.Errorf("%s passed when expected to fail", rt.name)
continue return
} }
if actualHost != rt.expectedHost { if actualHost != rt.expectedHost {
t.Errorf("%s returned invalid host %s, expected %s", rt.name, actualHost, rt.expectedHost) t.Errorf("%s returned invalid host %s, expected %s", rt.name, actualHost, rt.expectedHost)
continue return
} }
if actualPort != rt.expectedPort { if actualPort != rt.expectedPort {
t.Errorf("%s returned invalid port %s, expected %s", rt.name, actualPort, rt.expectedPort) t.Errorf("%s returned invalid port %s, expected %s", rt.name, actualPort, rt.expectedPort)
} }
})
} }
} }
...@@ -368,18 +372,20 @@ func TestParsePort(t *testing.T) { ...@@ -368,18 +372,20 @@ func TestParsePort(t *testing.T) {
} }
for _, rt := range tests { for _, rt := range tests {
actualPort, actualError := ParsePort(rt.port) t.Run(rt.name, func(t *testing.T) {
actualPort, actualError := ParsePort(rt.port)
if (actualError != nil) && !rt.expectedError { if (actualError != nil) && !rt.expectedError {
t.Errorf("%s unexpected failure: %v", rt.name, actualError) t.Errorf("%s unexpected failure: %v", rt.name, actualError)
continue return
} else if (actualError == nil) && rt.expectedError { } else if (actualError == nil) && rt.expectedError {
t.Errorf("%s passed when expected to fail", rt.name) t.Errorf("%s passed when expected to fail", rt.name)
continue return
} }
if actualPort != rt.expectedPort { if actualPort != rt.expectedPort {
t.Errorf("%s returned invalid port %d, expected %d", rt.name, actualPort, rt.expectedPort) t.Errorf("%s returned invalid port %d, expected %d", rt.name, actualPort, rt.expectedPort)
} }
})
} }
} }
...@@ -31,25 +31,28 @@ func TestCheckErr(t *testing.T) { ...@@ -31,25 +31,28 @@ func TestCheckErr(t *testing.T) {
codeReturned = code codeReturned = code
} }
var tokenTest = []struct { var tests = []struct {
name string
e error e error
expected int expected int
}{ }{
{nil, 0}, {"error is nil", nil, 0},
{errors.New(""), DefaultErrorExitCode}, {"empty error", errors.New(""), DefaultErrorExitCode},
{&pferror{}, PreFlightExitCode}, {"preflight error", &pferror{}, PreFlightExitCode},
} }
for _, rt := range tokenTest { for _, rt := range tests {
codeReturned = 0 t.Run(rt.name, func(t *testing.T) {
checkErr(rt.e, errHandle) codeReturned = 0
if codeReturned != rt.expected { checkErr(rt.e, errHandle)
t.Errorf( if codeReturned != rt.expected {
"failed checkErr:\n\texpected: %d\n\t actual: %d", t.Errorf(
rt.expected, "failed checkErr:\n\texpected: %d\n\t actual: %d",
codeReturned, rt.expected,
) codeReturned,
} )
}
})
} }
} }
...@@ -58,10 +61,12 @@ func TestFormatErrMsg(t *testing.T) { ...@@ -58,10 +61,12 @@ func TestFormatErrMsg(t *testing.T) {
errMsg2 := "specified version to upgrade to v1.9.0-alpha.3 is higher than the kubeadm version v1.9.0-alpha.1.3121+84178212527295-dirty. Upgrade kubeadm first using the tool you used to install kubeadm" errMsg2 := "specified version to upgrade to v1.9.0-alpha.3 is higher than the kubeadm version v1.9.0-alpha.1.3121+84178212527295-dirty. Upgrade kubeadm first using the tool you used to install kubeadm"
testCases := []struct { testCases := []struct {
name string
errs []error errs []error
expect string expect string
}{ }{
{ {
name: "two errors",
errs: []error{ errs: []error{
errors.New(errMsg1), errors.New(errMsg1),
errors.New(errMsg2), errors.New(errMsg2),
...@@ -69,6 +74,7 @@ func TestFormatErrMsg(t *testing.T) { ...@@ -69,6 +74,7 @@ func TestFormatErrMsg(t *testing.T) {
expect: "\t- " + errMsg1 + "\n" + "\t- " + errMsg2 + "\n", expect: "\t- " + errMsg1 + "\n" + "\t- " + errMsg2 + "\n",
}, },
{ {
name: "one error",
errs: []error{ errs: []error{
errors.New(errMsg1), errors.New(errMsg1),
}, },
...@@ -77,9 +83,11 @@ func TestFormatErrMsg(t *testing.T) { ...@@ -77,9 +83,11 @@ func TestFormatErrMsg(t *testing.T) {
} }
for _, testCase := range testCases { for _, testCase := range testCases {
got := FormatErrMsg(testCase.errs) t.Run(testCase.name, func(t *testing.T) {
if got != testCase.expect { got := FormatErrMsg(testCase.errs)
t.Errorf("FormatErrMsg error, expect: %v, got: %v", testCase.expect, got) if got != testCase.expect {
} t.Errorf("FormatErrMsg error, expect: %v, got: %v", testCase.expect, got)
}
})
} }
} }
...@@ -81,56 +81,62 @@ type configClientWithToken struct { ...@@ -81,56 +81,62 @@ type configClientWithToken struct {
func TestCreateWithCerts(t *testing.T) { func TestCreateWithCerts(t *testing.T) {
var createBasicTest = []struct { var createBasicTest = []struct {
name string
cc configClient cc configClient
ccWithCerts configClientWithCerts ccWithCerts configClientWithCerts
expected string expected string
}{ }{
{configClient{}, configClientWithCerts{}, ""}, {"empty config", configClient{}, configClientWithCerts{}, ""},
{configClient{clusterName: "kubernetes"}, configClientWithCerts{}, ""}, {"clusterName kubernetes", configClient{clusterName: "kubernetes"}, configClientWithCerts{}, ""},
} }
for _, rt := range createBasicTest { for _, rt := range createBasicTest {
cwc := CreateWithCerts( t.Run(rt.name, func(t *testing.T) {
rt.cc.serverURL, cwc := CreateWithCerts(
rt.cc.clusterName, rt.cc.serverURL,
rt.cc.userName, rt.cc.clusterName,
rt.cc.caCert, rt.cc.userName,
rt.ccWithCerts.clientKey, rt.cc.caCert,
rt.ccWithCerts.clientCert, rt.ccWithCerts.clientKey,
) rt.ccWithCerts.clientCert,
if cwc.Kind != rt.expected {
t.Errorf(
"failed CreateWithCerts:\n\texpected: %s\n\t actual: %s",
rt.expected,
cwc.Kind,
) )
} if cwc.Kind != rt.expected {
t.Errorf(
"failed CreateWithCerts:\n\texpected: %s\n\t actual: %s",
rt.expected,
cwc.Kind,
)
}
})
} }
} }
func TestCreateWithToken(t *testing.T) { func TestCreateWithToken(t *testing.T) {
var createBasicTest = []struct { var createBasicTest = []struct {
name string
cc configClient cc configClient
ccWithToken configClientWithToken ccWithToken configClientWithToken
expected string expected string
}{ }{
{configClient{}, configClientWithToken{}, ""}, {"empty config", configClient{}, configClientWithToken{}, ""},
{configClient{clusterName: "kubernetes"}, configClientWithToken{}, ""}, {"clusterName kubernetes", configClient{clusterName: "kubernetes"}, configClientWithToken{}, ""},
} }
for _, rt := range createBasicTest { for _, rt := range createBasicTest {
cwc := CreateWithToken( t.Run(rt.name, func(t *testing.T) {
rt.cc.serverURL, cwc := CreateWithToken(
rt.cc.clusterName, rt.cc.serverURL,
rt.cc.userName, rt.cc.clusterName,
rt.cc.caCert, rt.cc.userName,
rt.ccWithToken.token, rt.cc.caCert,
) rt.ccWithToken.token,
if cwc.Kind != rt.expected {
t.Errorf(
"failed CreateWithToken:\n\texpected: %s\n\t actual: %s",
rt.expected,
cwc.Kind,
) )
} if cwc.Kind != rt.expected {
t.Errorf(
"failed CreateWithToken:\n\texpected: %s\n\t actual: %s",
rt.expected,
cwc.Kind,
)
}
})
} }
} }
...@@ -152,29 +158,31 @@ func TestWriteKubeconfigToDisk(t *testing.T) { ...@@ -152,29 +158,31 @@ func TestWriteKubeconfigToDisk(t *testing.T) {
{"test2", configClient{clusterName: "kubernetes", userName: "user2", serverURL: "localhost:8080"}, configClientWithToken{token: "cba"}, nil, []byte(configOut2)}, {"test2", configClient{clusterName: "kubernetes", userName: "user2", serverURL: "localhost:8080"}, configClientWithToken{token: "cba"}, nil, []byte(configOut2)},
} }
for _, rt := range writeConfig { for _, rt := range writeConfig {
c := CreateWithToken( t.Run(rt.name, func(t *testing.T) {
rt.cc.serverURL, c := CreateWithToken(
rt.cc.clusterName, rt.cc.serverURL,
rt.cc.userName, rt.cc.clusterName,
rt.cc.caCert, rt.cc.userName,
rt.ccWithToken.token, rt.cc.caCert,
) rt.ccWithToken.token,
configPath := fmt.Sprintf("%s/etc/kubernetes/%s.conf", tmpdir, rt.name)
err := WriteToDisk(configPath, c)
if err != rt.expected {
t.Errorf(
"failed WriteToDisk with an error:\n\texpected: %s\n\t actual: %s",
rt.expected,
err,
)
}
newFile, _ := ioutil.ReadFile(configPath)
if !bytes.Equal(newFile, rt.file) {
t.Errorf(
"failed WriteToDisk config write:\n\texpected: %s\n\t actual: %s",
rt.file,
newFile,
) )
} configPath := fmt.Sprintf("%s/etc/kubernetes/%s.conf", tmpdir, rt.name)
err := WriteToDisk(configPath, c)
if err != rt.expected {
t.Errorf(
"failed WriteToDisk with an error:\n\texpected: %s\n\t actual: %s",
rt.expected,
err,
)
}
newFile, _ := ioutil.ReadFile(configPath)
if !bytes.Equal(newFile, rt.file) {
t.Errorf(
"failed WriteToDisk config write:\n\texpected: %s\n\t actual: %s",
rt.file,
newFile,
)
}
})
} }
} }
...@@ -166,27 +166,29 @@ func TestComponentProbe(t *testing.T) { ...@@ -166,27 +166,29 @@ func TestComponentProbe(t *testing.T) {
}, },
} }
for _, rt := range tests { for _, rt := range tests {
actual := ComponentProbe(rt.cfg, rt.component, rt.port, rt.path, rt.scheme) t.Run(rt.name, func(t *testing.T) {
if actual.Handler.HTTPGet.Host != rt.expected { actual := ComponentProbe(rt.cfg, rt.component, rt.port, rt.path, rt.scheme)
t.Errorf("%s test case failed:\n\texpected: %s\n\t actual: %s", if actual.Handler.HTTPGet.Host != rt.expected {
rt.name, rt.expected, t.Errorf("%s test case failed:\n\texpected: %s\n\t actual: %s",
actual.Handler.HTTPGet.Host) rt.name, rt.expected,
} actual.Handler.HTTPGet.Host)
if actual.Handler.HTTPGet.Port != intstr.FromInt(rt.port) { }
t.Errorf("%s test case failed:\n\texpected: %v\n\t actual: %v", if actual.Handler.HTTPGet.Port != intstr.FromInt(rt.port) {
rt.name, rt.port, t.Errorf("%s test case failed:\n\texpected: %v\n\t actual: %v",
actual.Handler.HTTPGet.Port) rt.name, rt.port,
} actual.Handler.HTTPGet.Port)
if actual.Handler.HTTPGet.Path != rt.path { }
t.Errorf("%s test case failed:\n\texpected: %s\n\t actual: %s", if actual.Handler.HTTPGet.Path != rt.path {
rt.name, rt.path, t.Errorf("%s test case failed:\n\texpected: %s\n\t actual: %s",
actual.Handler.HTTPGet.Path) rt.name, rt.path,
} actual.Handler.HTTPGet.Path)
if actual.Handler.HTTPGet.Scheme != rt.scheme { }
t.Errorf("%s test case failed:\n\texpected: %v\n\t actual: %v", if actual.Handler.HTTPGet.Scheme != rt.scheme {
rt.name, rt.scheme, t.Errorf("%s test case failed:\n\texpected: %v\n\t actual: %v",
actual.Handler.HTTPGet.Scheme) rt.name, rt.scheme,
} actual.Handler.HTTPGet.Scheme)
}
})
} }
} }
...@@ -330,16 +332,18 @@ func TestEtcdProbe(t *testing.T) { ...@@ -330,16 +332,18 @@ func TestEtcdProbe(t *testing.T) {
}, },
} }
for _, rt := range tests { for _, rt := range tests {
// TODO: Make EtcdProbe accept a ClusterConfiguration object instead of InitConfiguration t.Run(rt.name, func(t *testing.T) {
initcfg := &kubeadmapi.InitConfiguration{ // TODO: Make EtcdProbe accept a ClusterConfiguration object instead of InitConfiguration
ClusterConfiguration: *rt.cfg, initcfg := &kubeadmapi.InitConfiguration{
} ClusterConfiguration: *rt.cfg,
actual := EtcdProbe(initcfg, rt.component, rt.port, rt.certsDir, rt.cacert, rt.cert, rt.key) }
if actual.Handler.Exec.Command[2] != rt.expected { actual := EtcdProbe(initcfg, rt.component, rt.port, rt.certsDir, rt.cacert, rt.cert, rt.key)
t.Errorf("%s test case failed:\n\texpected: %s\n\t actual: %s", if actual.Handler.Exec.Command[2] != rt.expected {
rt.name, rt.expected, t.Errorf("%s test case failed:\n\texpected: %s\n\t actual: %s",
actual.Handler.Exec.Command[2]) rt.name, rt.expected,
} actual.Handler.Exec.Command[2])
}
})
} }
} }
...@@ -376,15 +380,17 @@ func TestComponentPod(t *testing.T) { ...@@ -376,15 +380,17 @@ func TestComponentPod(t *testing.T) {
} }
for _, rt := range tests { for _, rt := range tests {
c := v1.Container{Name: rt.name} t.Run(rt.name, func(t *testing.T) {
actual := ComponentPod(c, map[string]v1.Volume{}) c := v1.Container{Name: rt.name}
if !reflect.DeepEqual(rt.expected, actual) { actual := ComponentPod(c, map[string]v1.Volume{})
t.Errorf( if !reflect.DeepEqual(rt.expected, actual) {
"failed componentPod:\n\texpected: %v\n\t actual: %v", t.Errorf(
rt.expected, "failed componentPod:\n\texpected: %v\n\t actual: %v",
actual, rt.expected,
) actual,
} )
}
})
} }
} }
...@@ -413,14 +419,16 @@ func TestNewVolume(t *testing.T) { ...@@ -413,14 +419,16 @@ func TestNewVolume(t *testing.T) {
} }
for _, rt := range tests { for _, rt := range tests {
actual := NewVolume(rt.name, rt.path, rt.pathType) t.Run(rt.name, func(t *testing.T) {
if !reflect.DeepEqual(actual, rt.expected) { actual := NewVolume(rt.name, rt.path, rt.pathType)
t.Errorf( if !reflect.DeepEqual(actual, rt.expected) {
"failed newVolume:\n\texpected: %v\n\t actual: %v", t.Errorf(
rt.expected, "failed newVolume:\n\texpected: %v\n\t actual: %v",
actual, rt.expected,
) actual,
} )
}
})
} }
} }
...@@ -454,14 +462,16 @@ func TestNewVolumeMount(t *testing.T) { ...@@ -454,14 +462,16 @@ func TestNewVolumeMount(t *testing.T) {
} }
for _, rt := range tests { for _, rt := range tests {
actual := NewVolumeMount(rt.name, rt.path, rt.ro) t.Run(rt.name, func(t *testing.T) {
if !reflect.DeepEqual(actual, rt.expected) { actual := NewVolumeMount(rt.name, rt.path, rt.ro)
t.Errorf( if !reflect.DeepEqual(actual, rt.expected) {
"failed newVolumeMount:\n\texpected: %v\n\t actual: %v", t.Errorf(
rt.expected, "failed newVolumeMount:\n\texpected: %v\n\t actual: %v",
actual, rt.expected,
) actual,
} )
}
})
} }
} }
func TestVolumeMapToSlice(t *testing.T) { func TestVolumeMapToSlice(t *testing.T) {
...@@ -508,11 +518,13 @@ func TestVolumeMountMapToSlice(t *testing.T) { ...@@ -508,11 +518,13 @@ func TestVolumeMountMapToSlice(t *testing.T) {
func TestGetExtraParameters(t *testing.T) { func TestGetExtraParameters(t *testing.T) {
var tests = []struct { var tests = []struct {
name string
overrides map[string]string overrides map[string]string
defaults map[string]string defaults map[string]string
expected []string expected []string
}{ }{
{ {
name: "with admission-control default NamespaceLifecycle",
overrides: map[string]string{ overrides: map[string]string{
"admission-control": "NamespaceLifecycle,LimitRanger", "admission-control": "NamespaceLifecycle,LimitRanger",
}, },
...@@ -528,6 +540,7 @@ func TestGetExtraParameters(t *testing.T) { ...@@ -528,6 +540,7 @@ func TestGetExtraParameters(t *testing.T) {
}, },
}, },
{ {
name: "without admission-control default",
overrides: map[string]string{ overrides: map[string]string{
"admission-control": "NamespaceLifecycle,LimitRanger", "admission-control": "NamespaceLifecycle,LimitRanger",
}, },
...@@ -544,12 +557,14 @@ func TestGetExtraParameters(t *testing.T) { ...@@ -544,12 +557,14 @@ func TestGetExtraParameters(t *testing.T) {
} }
for _, rt := range tests { for _, rt := range tests {
actual := GetExtraParameters(rt.overrides, rt.defaults) t.Run(rt.name, func(t *testing.T) {
sort.Strings(actual) actual := GetExtraParameters(rt.overrides, rt.defaults)
sort.Strings(rt.expected) sort.Strings(actual)
if !reflect.DeepEqual(actual, rt.expected) { sort.Strings(rt.expected)
t.Errorf("failed getExtraParameters:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual) if !reflect.DeepEqual(actual, rt.expected) {
} t.Errorf("failed getExtraParameters:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual)
}
})
} }
} }
...@@ -599,27 +614,29 @@ func TestReadStaticPodFromDisk(t *testing.T) { ...@@ -599,27 +614,29 @@ func TestReadStaticPodFromDisk(t *testing.T) {
} }
for _, rt := range tests { for _, rt := range tests {
tmpdir := testutil.SetupTempDir(t) t.Run(rt.description, func(t *testing.T) {
defer os.RemoveAll(tmpdir) tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
manifestPath := filepath.Join(tmpdir, "pod.yaml") manifestPath := filepath.Join(tmpdir, "pod.yaml")
if rt.writeManifest { if rt.writeManifest {
err := ioutil.WriteFile(manifestPath, []byte(rt.podYaml), 0644) err := ioutil.WriteFile(manifestPath, []byte(rt.podYaml), 0644)
if err != nil { if err != nil {
t.Fatalf("Failed to write pod manifest\n%s\n\tfatal error: %v", rt.description, err) t.Fatalf("Failed to write pod manifest\n%s\n\tfatal error: %v", rt.description, err)
}
} }
}
_, actualErr := ReadStaticPodFromDisk(manifestPath) _, actualErr := ReadStaticPodFromDisk(manifestPath)
if (actualErr != nil) != rt.expectErr { if (actualErr != nil) != rt.expectErr {
t.Errorf( t.Errorf(
"ReadStaticPodFromDisk failed\n%s\n\texpected error: %t\n\tgot: %t\n\tactual error: %v", "ReadStaticPodFromDisk failed\n%s\n\texpected error: %t\n\tgot: %t\n\tactual error: %v",
rt.description, rt.description,
rt.expectErr, rt.expectErr,
(actualErr != nil), (actualErr != nil),
actualErr, actualErr,
) )
} }
})
} }
} }
...@@ -657,38 +674,40 @@ func TestManifestFilesAreEqual(t *testing.T) { ...@@ -657,38 +674,40 @@ func TestManifestFilesAreEqual(t *testing.T) {
} }
for _, rt := range tests { for _, rt := range tests {
tmpdir := testutil.SetupTempDir(t) t.Run(rt.description, func(t *testing.T) {
defer os.RemoveAll(tmpdir) tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
// write 2 manifests // write 2 manifests
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
if rt.podYamls[i] != "" { if rt.podYamls[i] != "" {
manifestPath := filepath.Join(tmpdir, strconv.Itoa(i)+".yaml") manifestPath := filepath.Join(tmpdir, strconv.Itoa(i)+".yaml")
err := ioutil.WriteFile(manifestPath, []byte(rt.podYamls[i]), 0644) err := ioutil.WriteFile(manifestPath, []byte(rt.podYamls[i]), 0644)
if err != nil { if err != nil {
t.Fatalf("Failed to write manifest file\n%s\n\tfatal error: %v", rt.description, err) t.Fatalf("Failed to write manifest file\n%s\n\tfatal error: %v", rt.description, err)
}
} }
} }
}
// compare them // compare them
result, actualErr := ManifestFilesAreEqual(filepath.Join(tmpdir, "0.yaml"), filepath.Join(tmpdir, "1.yaml")) result, actualErr := ManifestFilesAreEqual(filepath.Join(tmpdir, "0.yaml"), filepath.Join(tmpdir, "1.yaml"))
if result != rt.expectedResult { if result != rt.expectedResult {
t.Errorf( t.Errorf(
"ManifestFilesAreEqual failed\n%s\nexpected result: %t\nactual result: %t", "ManifestFilesAreEqual failed\n%s\nexpected result: %t\nactual result: %t",
rt.description, rt.description,
rt.expectedResult, rt.expectedResult,
result, result,
) )
} }
if (actualErr != nil) != rt.expectErr { if (actualErr != nil) != rt.expectErr {
t.Errorf( t.Errorf(
"ManifestFilesAreEqual failed\n%s\n\texpected error: %t\n\tgot: %t\n\tactual error: %v", "ManifestFilesAreEqual failed\n%s\n\texpected error: %t\n\tgot: %t\n\tactual error: %v",
rt.description, rt.description,
rt.expectErr, rt.expectErr,
(actualErr != nil), (actualErr != nil),
actualErr, actualErr,
) )
} }
})
} }
} }
...@@ -30,13 +30,14 @@ const ( ...@@ -30,13 +30,14 @@ const (
func TestParseTemplate(t *testing.T) { func TestParseTemplate(t *testing.T) {
var tmplTests = []struct { var tmplTests = []struct {
name string
template string template string
data interface{} data interface{}
output string output string
errExpected bool errExpected bool
}{ }{
// should parse a valid template and set the right values
{ {
name: "should parse a valid template and set the right values",
template: validTmpl, template: validTmpl,
data: struct{ ImageRepository, Arch string }{ data: struct{ ImageRepository, Arch string }{
ImageRepository: "k8s.gcr.io", ImageRepository: "k8s.gcr.io",
...@@ -45,8 +46,8 @@ func TestParseTemplate(t *testing.T) { ...@@ -45,8 +46,8 @@ func TestParseTemplate(t *testing.T) {
output: validTmplOut, output: validTmplOut,
errExpected: false, errExpected: false,
}, },
// should noop if there aren't any {{ .foo }} present
{ {
name: "should noop if there aren't any {{ .foo }} present",
template: doNothing, template: doNothing,
data: struct{ ImageRepository, Arch string }{ data: struct{ ImageRepository, Arch string }{
ImageRepository: "k8s.gcr.io", ImageRepository: "k8s.gcr.io",
...@@ -55,15 +56,15 @@ func TestParseTemplate(t *testing.T) { ...@@ -55,15 +56,15 @@ func TestParseTemplate(t *testing.T) {
output: doNothing, output: doNothing,
errExpected: false, errExpected: false,
}, },
// invalid syntax, passing nil
{ {
name: "invalid syntax, passing nil",
template: invalidTmpl1, template: invalidTmpl1,
data: nil, data: nil,
output: "", output: "",
errExpected: true, errExpected: true,
}, },
// invalid syntax
{ {
name: "invalid syntax",
template: invalidTmpl2, template: invalidTmpl2,
data: struct{}{}, data: struct{}{},
output: "", output: "",
...@@ -71,20 +72,22 @@ func TestParseTemplate(t *testing.T) { ...@@ -71,20 +72,22 @@ func TestParseTemplate(t *testing.T) {
}, },
} }
for _, tt := range tmplTests { for _, tt := range tmplTests {
outbytes, err := ParseTemplate(tt.template, tt.data) t.Run(tt.name, func(t *testing.T) {
if tt.errExpected != (err != nil) { outbytes, err := ParseTemplate(tt.template, tt.data)
t.Errorf( if tt.errExpected != (err != nil) {
"failed TestParseTemplate:\n\texpected err: %t\n\t actual: %s", t.Errorf(
tt.errExpected, "failed TestParseTemplate:\n\texpected err: %t\n\t actual: %s",
err, tt.errExpected,
) err,
} )
if tt.output != string(outbytes) { }
t.Errorf( if tt.output != string(outbytes) {
"failed TestParseTemplate:\n\texpected bytes: %s\n\t actual: %s", t.Errorf(
tt.output, "failed TestParseTemplate:\n\texpected bytes: %s\n\t actual: %s",
outbytes, tt.output,
) outbytes,
} )
}
})
} }
} }
...@@ -17,6 +17,7 @@ limitations under the License. ...@@ -17,6 +17,7 @@ limitations under the License.
package util package util
import ( import (
"fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"path" "path"
...@@ -48,14 +49,16 @@ func TestValidVersion(t *testing.T) { ...@@ -48,14 +49,16 @@ func TestValidVersion(t *testing.T) {
"v1.6.1+coreos.0", "v1.6.1+coreos.0",
} }
for _, s := range validVersions { for _, s := range validVersions {
ver, err := KubernetesReleaseVersion(s) t.Run(s, func(t *testing.T) {
t.Log("Valid: ", s, ver, err) ver, err := KubernetesReleaseVersion(s)
if err != nil { t.Log("Valid: ", s, ver, err)
t.Errorf("KubernetesReleaseVersion unexpected error for version %q: %v", s, err) if err != nil {
} t.Errorf("KubernetesReleaseVersion unexpected error for version %q: %v", s, err)
if ver != s { }
t.Errorf("KubernetesReleaseVersion should return same valid version string. %q != %q", s, ver) if ver != s {
} t.Errorf("KubernetesReleaseVersion should return same valid version string. %q != %q", s, ver)
}
})
} }
} }
...@@ -68,14 +71,16 @@ func TestInvalidVersion(t *testing.T) { ...@@ -68,14 +71,16 @@ func TestInvalidVersion(t *testing.T) {
"something1.2", "something1.2",
} }
for _, s := range invalidVersions { for _, s := range invalidVersions {
ver, err := KubernetesReleaseVersion(s) t.Run(s, func(t *testing.T) {
t.Log("Invalid: ", s, ver, err) ver, err := KubernetesReleaseVersion(s)
if err == nil { t.Log("Invalid: ", s, ver, err)
t.Errorf("KubernetesReleaseVersion error expected for version %q, but returned successfully", s) if err == nil {
} t.Errorf("KubernetesReleaseVersion error expected for version %q, but returned successfully", s)
if ver != "" { }
t.Errorf("KubernetesReleaseVersion should return empty string in case of error. Returned %q for version %q", ver, s) if ver != "" {
} t.Errorf("KubernetesReleaseVersion should return empty string in case of error. Returned %q for version %q", ver, s)
}
})
} }
} }
...@@ -86,14 +91,16 @@ func TestValidConvenientForUserVersion(t *testing.T) { ...@@ -86,14 +91,16 @@ func TestValidConvenientForUserVersion(t *testing.T) {
"1.6.1_coreos.0", "1.6.1_coreos.0",
} }
for _, s := range validVersions { for _, s := range validVersions {
ver, err := KubernetesReleaseVersion(s) t.Run(s, func(t *testing.T) {
t.Log("Valid: ", s, ver, err) ver, err := KubernetesReleaseVersion(s)
if err != nil { t.Log("Valid: ", s, ver, err)
t.Errorf("KubernetesReleaseVersion unexpected error for version %q: %v", s, err) if err != nil {
} t.Errorf("KubernetesReleaseVersion unexpected error for version %q: %v", s, err)
if ver != "v"+s { }
t.Errorf("KubernetesReleaseVersion should return semantic version string. %q vs. %q", s, ver) if ver != "v"+s {
} t.Errorf("KubernetesReleaseVersion should return semantic version string. %q vs. %q", s, ver)
}
})
} }
} }
...@@ -128,16 +135,18 @@ func TestVersionFromNetwork(t *testing.T) { ...@@ -128,16 +135,18 @@ func TestVersionFromNetwork(t *testing.T) {
kubeReleaseBucketURL = server.URL kubeReleaseBucketURL = server.URL
for k, v := range cases { for k, v := range cases {
ver, err := KubernetesReleaseVersion(k) t.Run(k, func(t *testing.T) {
t.Logf("Key: %q. Result: %q, Error: %v", k, ver, err) ver, err := KubernetesReleaseVersion(k)
switch { t.Logf("Key: %q. Result: %q, Error: %v", k, ver, err)
case err != nil && !v.ErrorExpected: switch {
t.Errorf("KubernetesReleaseVersion: unexpected error for %q. Error: %+v", k, err) case err != nil && !v.ErrorExpected:
case err == nil && v.ErrorExpected: t.Errorf("KubernetesReleaseVersion: unexpected error for %q. Error: %+v", k, err)
t.Errorf("KubernetesReleaseVersion: error expected for key %q, but result is %q", k, ver) case err == nil && v.ErrorExpected:
case ver != v.Expected: t.Errorf("KubernetesReleaseVersion: error expected for key %q, but result is %q", k, ver)
t.Errorf("KubernetesReleaseVersion: unexpected result for key %q. Expected: %q Actual: %q", k, v.Expected, ver) case ver != v.Expected:
} t.Errorf("KubernetesReleaseVersion: unexpected result for key %q. Expected: %q Actual: %q", k, v.Expected, ver)
}
})
} }
} }
...@@ -158,11 +167,13 @@ func TestVersionToTag(t *testing.T) { ...@@ -158,11 +167,13 @@ func TestVersionToTag(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
tag := KubernetesVersionToImageTag(tc.input) t.Run(fmt.Sprintf("input:%s/expected:%s", tc.input, tc.expected), func(t *testing.T) {
t.Logf("KubernetesVersionToImageTag: Input: %q. Result: %q. Expected: %q", tc.input, tag, tc.expected) tag := KubernetesVersionToImageTag(tc.input)
if tag != tc.expected { t.Logf("KubernetesVersionToImageTag: Input: %q. Result: %q. Expected: %q", tc.input, tag, tc.expected)
t.Errorf("failed KubernetesVersionToImageTag: Input: %q. Result: %q. Expected: %q", tc.input, tag, tc.expected) if tag != tc.expected {
} t.Errorf("failed KubernetesVersionToImageTag: Input: %q. Result: %q. Expected: %q", tc.input, tag, tc.expected)
}
})
} }
} }
...@@ -194,18 +205,19 @@ func TestSplitVersion(t *testing.T) { ...@@ -194,18 +205,19 @@ func TestSplitVersion(t *testing.T) {
kubeReleaseBucketURL = "https://dl.k8s.io" kubeReleaseBucketURL = "https://dl.k8s.io"
for _, tc := range cases { for _, tc := range cases {
bucket, label, err := splitVersion(tc.input) t.Run(fmt.Sprintf("input:%s/label:%s", tc.input, tc.label), func(t *testing.T) {
switch { bucket, label, err := splitVersion(tc.input)
case err != nil && tc.valid: switch {
t.Errorf("splitVersion: unexpected error for %q. Error: %v", tc.input, err) case err != nil && tc.valid:
case err == nil && !tc.valid: t.Errorf("splitVersion: unexpected error for %q. Error: %v", tc.input, err)
t.Errorf("splitVersion: error expected for key %q, but result is %q, %q", tc.input, bucket, label) case err == nil && !tc.valid:
case bucket != tc.bucket: t.Errorf("splitVersion: error expected for key %q, but result is %q, %q", tc.input, bucket, label)
t.Errorf("splitVersion: unexpected bucket result for key %q. Expected: %q Actual: %q", tc.input, tc.bucket, bucket) case bucket != tc.bucket:
case label != tc.label: t.Errorf("splitVersion: unexpected bucket result for key %q. Expected: %q Actual: %q", tc.input, tc.bucket, bucket)
t.Errorf("splitVersion: unexpected label result for key %q. Expected: %q Actual: %q", tc.input, tc.label, label) case label != tc.label:
} t.Errorf("splitVersion: unexpected label result for key %q. Expected: %q Actual: %q", tc.input, tc.label, label)
}
})
} }
} }
...@@ -227,13 +239,14 @@ func TestKubernetesIsCIVersion(t *testing.T) { ...@@ -227,13 +239,14 @@ func TestKubernetesIsCIVersion(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
result := KubernetesIsCIVersion(tc.input) t.Run(fmt.Sprintf("input:%s/expected:%t", tc.input, tc.expected), func(t *testing.T) {
t.Logf("KubernetesIsCIVersion: Input: %q. Result: %v. Expected: %v", tc.input, result, tc.expected) result := KubernetesIsCIVersion(tc.input)
if result != tc.expected { t.Logf("KubernetesIsCIVersion: Input: %q. Result: %v. Expected: %v", tc.input, result, tc.expected)
t.Errorf("failed KubernetesIsCIVersion: Input: %q. Result: %v. Expected: %v", tc.input, result, tc.expected) if result != tc.expected {
} t.Errorf("failed KubernetesIsCIVersion: Input: %q. Result: %v. Expected: %v", tc.input, result, tc.expected)
}
})
} }
} }
// Validate KubernetesReleaseVersion but with bucket prefixes // Validate KubernetesReleaseVersion but with bucket prefixes
...@@ -258,16 +271,18 @@ func TestCIBuildVersion(t *testing.T) { ...@@ -258,16 +271,18 @@ func TestCIBuildVersion(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
ver, err := KubernetesReleaseVersion(tc.input) t.Run(fmt.Sprintf("input:%s/expected:%s", tc.input, tc.expected), func(t *testing.T) {
t.Logf("Input: %q. Result: %q, Error: %v", tc.input, ver, err) ver, err := KubernetesReleaseVersion(tc.input)
switch { t.Logf("Input: %q. Result: %q, Error: %v", tc.input, ver, err)
case err != nil && tc.valid: switch {
t.Errorf("KubernetesReleaseVersion: unexpected error for input %q. Error: %v", tc.input, err) case err != nil && tc.valid:
case err == nil && !tc.valid: t.Errorf("KubernetesReleaseVersion: unexpected error for input %q. Error: %v", tc.input, err)
t.Errorf("KubernetesReleaseVersion: error expected for input %q, but result is %q", tc.input, ver) case err == nil && !tc.valid:
case ver != tc.expected: t.Errorf("KubernetesReleaseVersion: error expected for input %q, but result is %q", tc.input, ver)
t.Errorf("KubernetesReleaseVersion: unexpected result for input %q. Expected: %q Actual: %q", tc.input, tc.expected, ver) case ver != tc.expected:
} t.Errorf("KubernetesReleaseVersion: unexpected result for input %q. Expected: %q Actual: %q", tc.input, tc.expected, ver)
}
})
} }
} }
...@@ -284,10 +299,12 @@ func TestNormalizedBuildVersionVersion(t *testing.T) { ...@@ -284,10 +299,12 @@ func TestNormalizedBuildVersionVersion(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
output := normalizedBuildVersion(tc.input) t.Run(fmt.Sprintf("input:%s/expected:%s", tc.input, tc.expected), func(t *testing.T) {
if output != tc.expected { output := normalizedBuildVersion(tc.input)
t.Errorf("normalizedBuildVersion: unexpected output %q for input %q. Expected: %q", output, tc.input, tc.expected) if output != tc.expected {
} t.Errorf("normalizedBuildVersion: unexpected output %q for input %q. Expected: %q", output, tc.input, tc.expected)
}
})
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment