Merge pull request #72457 from bart0sh/PR0053-kubeadm-app-cmd-use-T.Run

kubeadm: use T.Run API in app/cmd
This commit is contained in:
Kubernetes Prow Robot 2019-01-01 04:00:36 -08:00 committed by GitHub
commit b502b99d25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 263 additions and 215 deletions

View File

@ -52,16 +52,19 @@ func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) {
} }
var tests = []struct { var tests = []struct {
name string
command string command string
withClientCert bool withClientCert bool
withToken bool withToken bool
additionalFlags []string additionalFlags []string
}{ }{
{ // Test user subCommand withClientCert {
name: "user subCommand withClientCert",
command: "user", command: "user",
withClientCert: true, withClientCert: true,
}, },
{ // Test user subCommand withToken {
name: "user subCommand withToken",
withToken: true, withToken: true,
command: "user", command: "user",
additionalFlags: []string{"--token=123456"}, additionalFlags: []string{"--token=123456"},
@ -69,36 +72,38 @@ func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
buf := new(bytes.Buffer) t.Run(test.name, func(t *testing.T) {
buf := new(bytes.Buffer)
// Get subcommands working in the temporary directory // Get subcommands working in the temporary directory
cmd := newCmdUserKubeConfig(buf) cmd := newCmdUserKubeConfig(buf)
// Execute the subcommand // Execute the subcommand
allFlags := append(commonFlags, test.additionalFlags...) allFlags := append(commonFlags, test.additionalFlags...)
cmd.SetArgs(allFlags) cmd.SetArgs(allFlags)
if err := cmd.Execute(); err != nil { if err := cmd.Execute(); err != nil {
t.Fatal("Could not execute subcommand") t.Fatal("Could not execute subcommand")
} }
// reads kubeconfig written to stdout // reads kubeconfig written to stdout
config, err := clientcmd.Load(buf.Bytes()) config, err := clientcmd.Load(buf.Bytes())
if err != nil { if err != nil {
t.Errorf("couldn't read kubeconfig file from buffer: %v", err) t.Errorf("couldn't read kubeconfig file from buffer: %v", err)
continue return
} }
// checks that CLI flags are properly propagated // checks that CLI flags are properly propagated
kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert) kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert)
if test.withClientCert { if test.withClientCert {
// checks that kubeconfig files have expected client cert // checks that kubeconfig files have expected client cert
kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithClientCert(t, config, caCert, "myUser") kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithClientCert(t, config, caCert, "myUser")
} }
if test.withToken { if test.withToken {
// checks that kubeconfig files have expected token // checks that kubeconfig files have expected token
kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithToken(t, config, "myUser", "123456") kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithToken(t, config, "myUser", "123456")
} }
})
} }
} }

View File

@ -88,8 +88,10 @@ func TestRunCompletion(t *testing.T) {
parentCmd.AddCommand(cmd) parentCmd.AddCommand(cmd)
for _, tc := range testCases { for _, tc := range testCases {
if err := RunCompletion(&out, "", cmd, tc.args); (err != nil) != tc.expectedError { t.Run(tc.name, func(t *testing.T) {
t.Errorf("Test case %q: TestRunCompletion expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil)) if err := RunCompletion(&out, "", cmd, tc.args); (err != nil) != tc.expectedError {
} t.Errorf("Test case %q: TestRunCompletion expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil))
}
})
} }
} }

View File

@ -195,51 +195,53 @@ func TestConfigDirCleaner(t *testing.T) {
} }
for name, test := range tests { for name, test := range tests {
t.Logf("Running test: %s", name) t.Run(name, func(t *testing.T) {
t.Logf("Running test: %s", name)
// Create a temporary directory for our fake config dir: // Create a temporary directory for our fake config dir:
tmpDir, err := ioutil.TempDir("", "kubeadm-reset-test") tmpDir, err := ioutil.TempDir("", "kubeadm-reset-test")
if err != nil {
t.Errorf("Unable to create temporary directory: %s", err)
}
for _, createDir := range test.setupDirs {
err := os.Mkdir(filepath.Join(tmpDir, createDir), 0700)
if err != nil { if err != nil {
t.Errorf("Unable to setup test config directory: %s", err) t.Errorf("Unable to create temporary directory: %s", err)
} }
}
for _, createFile := range test.setupFiles { for _, createDir := range test.setupDirs {
fullPath := filepath.Join(tmpDir, createFile) err := os.Mkdir(filepath.Join(tmpDir, createDir), 0700)
f, err := os.Create(fullPath) if err != nil {
if err != nil { t.Errorf("Unable to setup test config directory: %s", err)
t.Errorf("Unable to create test file: %s", err) }
} }
f.Close()
}
if test.resetDir == "" { for _, createFile := range test.setupFiles {
test.resetDir = "pki" fullPath := filepath.Join(tmpDir, createFile)
} f, err := os.Create(fullPath)
resetConfigDir(tmpDir, filepath.Join(tmpDir, test.resetDir)) if err != nil {
t.Errorf("Unable to create test file: %s", err)
}
f.Close()
}
// Verify the files we cleanup implicitly in every test: if test.resetDir == "" {
assertExists(t, tmpDir) test.resetDir = "pki"
assertNotExists(t, filepath.Join(tmpDir, kubeadmconstants.AdminKubeConfigFileName)) }
assertNotExists(t, filepath.Join(tmpDir, kubeadmconstants.KubeletKubeConfigFileName)) resetConfigDir(tmpDir, filepath.Join(tmpDir, test.resetDir))
assertDirEmpty(t, filepath.Join(tmpDir, "manifests"))
assertDirEmpty(t, filepath.Join(tmpDir, "pki"))
// Verify the files as requested by the test: // Verify the files we cleanup implicitly in every test:
for _, path := range test.verifyExists { assertExists(t, tmpDir)
assertExists(t, filepath.Join(tmpDir, path)) assertNotExists(t, filepath.Join(tmpDir, kubeadmconstants.AdminKubeConfigFileName))
} assertNotExists(t, filepath.Join(tmpDir, kubeadmconstants.KubeletKubeConfigFileName))
for _, path := range test.verifyNotExists { assertDirEmpty(t, filepath.Join(tmpDir, "manifests"))
assertNotExists(t, filepath.Join(tmpDir, path)) assertDirEmpty(t, filepath.Join(tmpDir, "pki"))
}
os.RemoveAll(tmpDir) // Verify the files as requested by the test:
for _, path := range test.verifyExists {
assertExists(t, filepath.Join(tmpDir, path))
}
for _, path := range test.verifyNotExists {
assertNotExists(t, filepath.Join(tmpDir, path))
}
os.RemoveAll(tmpDir)
})
} }
} }
@ -309,38 +311,40 @@ func TestGetEtcdDataDir(t *testing.T) {
} }
for name, test := range tests { for name, test := range tests {
tmpdir := testutil.SetupTempDir(t) t.Run(name, func(t *testing.T) {
defer os.RemoveAll(tmpdir) tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
manifestPath := filepath.Join(tmpdir, "etcd.yaml") manifestPath := filepath.Join(tmpdir, "etcd.yaml")
if test.writeManifest { if test.writeManifest {
err := ioutil.WriteFile(manifestPath, []byte(test.podYaml), 0644) err := ioutil.WriteFile(manifestPath, []byte(test.podYaml), 0644)
if err != nil { if err != nil {
t.Fatalf(dedent.Dedent("failed to write pod manifest\n%s\n\tfatal error: %v"), name, err) t.Fatalf(dedent.Dedent("failed to write pod manifest\n%s\n\tfatal error: %v"), name, err)
}
} }
}
var dataDir string var dataDir string
var err error var err error
if test.validClient { if test.validClient {
client := clientsetfake.NewSimpleClientset() client := clientsetfake.NewSimpleClientset()
dataDir, err = getEtcdDataDir(manifestPath, client) dataDir, err = getEtcdDataDir(manifestPath, client)
} else { } else {
dataDir, err = getEtcdDataDir(manifestPath, nil) dataDir, err = getEtcdDataDir(manifestPath, nil)
} }
if (err != nil) != test.expectErr { if (err != nil) != test.expectErr {
t.Fatalf(dedent.Dedent( t.Fatalf(dedent.Dedent(
"getEtcdDataDir failed\n%s\nexpected error: %t\n\tgot: %t\nerror: %v"), "getEtcdDataDir failed\n%s\nexpected error: %t\n\tgot: %t\nerror: %v"),
name, name,
test.expectErr, test.expectErr,
(err != nil), (err != nil),
err, err,
) )
} }
if dataDir != test.dataDir { if dataDir != test.dataDir {
t.Fatalf(dedent.Dedent("getEtcdDataDir failed\n%s\n\texpected: %s\ngot: %s"), name, test.dataDir, dataDir) t.Fatalf(dedent.Dedent("getEtcdDataDir failed\n%s\n\texpected: %s\ngot: %s"), name, test.dataDir, dataDir)
} }
})
} }
} }

View File

@ -167,31 +167,33 @@ func TestRunCreateToken(t *testing.T) {
}, },
} }
for _, tc := range testCases { for _, tc := range testCases {
bts, err := kubeadmapiv1beta1.NewBootstrapTokenString(tc.token) t.Run(tc.name, func(t *testing.T) {
if err != nil && len(tc.token) != 0 { // if tc.token is "" it's okay as it will be generated later at runtime bts, err := kubeadmapiv1beta1.NewBootstrapTokenString(tc.token)
t.Fatalf("token couldn't be parsed for testing: %v", err) if err != nil && len(tc.token) != 0 { // if tc.token is "" it's okay as it will be generated later at runtime
} t.Fatalf("token couldn't be parsed for testing: %v", err)
}
cfg := &kubeadmapiv1beta1.InitConfiguration{ cfg := &kubeadmapiv1beta1.InitConfiguration{
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{ ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
// KubernetesVersion is not used, but we set this explicitly to avoid // KubernetesVersion is not used, but we set this explicitly to avoid
// the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig // the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
KubernetesVersion: constants.MinimumControlPlaneVersion.String(), KubernetesVersion: constants.MinimumControlPlaneVersion.String(),
},
BootstrapTokens: []kubeadmapiv1beta1.BootstrapToken{
{
Token: bts,
TTL: &metav1.Duration{Duration: 0},
Usages: tc.usages,
Groups: tc.extraGroups,
}, },
}, BootstrapTokens: []kubeadmapiv1beta1.BootstrapToken{
} {
Token: bts,
TTL: &metav1.Duration{Duration: 0},
Usages: tc.usages,
Groups: tc.extraGroups,
},
},
}
err = RunCreateToken(&buf, fakeClient, "", cfg, tc.printJoin, "") err = RunCreateToken(&buf, fakeClient, "", cfg, tc.printJoin, "")
if (err != nil) != tc.expectedError { if (err != nil) != tc.expectedError {
t.Errorf("Test case %s: RunCreateToken expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil)) t.Errorf("Test case %s: RunCreateToken expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil))
} }
})
} }
} }
@ -253,24 +255,26 @@ func TestNewCmdToken(t *testing.T) {
} }
for _, tc := range testCases { for _, tc := range testCases {
// the command is created for each test so that the kubeConfigFile t.Run(tc.name, func(t *testing.T) {
// variable in NewCmdToken() is reset. // the command is created for each test so that the kubeConfigFile
cmd := NewCmdToken(&buf, &bufErr) // variable in NewCmdToken() is reset.
if _, err = f.WriteString(tc.configToWrite); err != nil { cmd := NewCmdToken(&buf, &bufErr)
t.Errorf("Unable to write test file %q: %v", fullPath, err) if _, err = f.WriteString(tc.configToWrite); err != nil {
} t.Errorf("Unable to write test file %q: %v", fullPath, err)
// store the current value of the environment variable. }
storedEnv := os.Getenv(clientcmd.RecommendedConfigPathEnvVar) // store the current value of the environment variable.
if tc.kubeConfigEnv != "" { storedEnv := os.Getenv(clientcmd.RecommendedConfigPathEnvVar)
os.Setenv(clientcmd.RecommendedConfigPathEnvVar, tc.kubeConfigEnv) if tc.kubeConfigEnv != "" {
} os.Setenv(clientcmd.RecommendedConfigPathEnvVar, tc.kubeConfigEnv)
cmd.SetArgs(tc.args) }
err := cmd.Execute() cmd.SetArgs(tc.args)
if (err != nil) != tc.expectedError { err := cmd.Execute()
t.Errorf("Test case %q: NewCmdToken expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil)) if (err != nil) != tc.expectedError {
} t.Errorf("Test case %q: NewCmdToken expected error: %v, saw: %v", tc.name, tc.expectedError, (err != nil))
// restore the environment variable. }
os.Setenv(clientcmd.RecommendedConfigPathEnvVar, storedEnv) // restore the environment variable.
os.Setenv(clientcmd.RecommendedConfigPathEnvVar, storedEnv)
})
} }
} }

View File

@ -28,11 +28,13 @@ import (
func TestSetImplicitFlags(t *testing.T) { func TestSetImplicitFlags(t *testing.T) {
var tests = []struct { var tests = []struct {
name string
flags *applyFlags flags *applyFlags
expectedFlags applyFlags expectedFlags applyFlags
errExpected bool errExpected bool
}{ }{
{ // if not dryRun or force is set; the nonInteractiveMode field should not be touched {
name: "if not dryRun or force is set; the nonInteractiveMode field should not be touched",
flags: &applyFlags{ flags: &applyFlags{
newK8sVersionStr: "v1.8.0", newK8sVersionStr: "v1.8.0",
dryRun: false, dryRun: false,
@ -46,7 +48,8 @@ func TestSetImplicitFlags(t *testing.T) {
nonInteractiveMode: false, nonInteractiveMode: false,
}, },
}, },
{ // if not dryRun or force is set; the nonInteractiveMode field should not be touched {
name: "if not dryRun or force is set; the nonInteractiveMode field should not be touched",
flags: &applyFlags{ flags: &applyFlags{
newK8sVersionStr: "v1.8.0", newK8sVersionStr: "v1.8.0",
dryRun: false, dryRun: false,
@ -60,7 +63,8 @@ func TestSetImplicitFlags(t *testing.T) {
nonInteractiveMode: true, nonInteractiveMode: true,
}, },
}, },
{ // if dryRun or force is set; the nonInteractiveMode field should be set to true {
name: "if dryRun or force is set; the nonInteractiveMode field should be set to true",
flags: &applyFlags{ flags: &applyFlags{
newK8sVersionStr: "v1.8.0", newK8sVersionStr: "v1.8.0",
dryRun: true, dryRun: true,
@ -74,7 +78,8 @@ func TestSetImplicitFlags(t *testing.T) {
nonInteractiveMode: true, nonInteractiveMode: true,
}, },
}, },
{ // if dryRun or force is set; the nonInteractiveMode field should be set to true {
name: "if dryRun or force is set; the nonInteractiveMode field should be set to true",
flags: &applyFlags{ flags: &applyFlags{
newK8sVersionStr: "v1.8.0", newK8sVersionStr: "v1.8.0",
dryRun: false, dryRun: false,
@ -88,7 +93,8 @@ func TestSetImplicitFlags(t *testing.T) {
nonInteractiveMode: true, nonInteractiveMode: true,
}, },
}, },
{ // if dryRun or force is set; the nonInteractiveMode field should be set to true {
name: "if dryRun or force is set; the nonInteractiveMode field should be set to true",
flags: &applyFlags{ flags: &applyFlags{
newK8sVersionStr: "v1.8.0", newK8sVersionStr: "v1.8.0",
dryRun: true, dryRun: true,
@ -102,7 +108,8 @@ func TestSetImplicitFlags(t *testing.T) {
nonInteractiveMode: true, nonInteractiveMode: true,
}, },
}, },
{ // if dryRun or force is set; the nonInteractiveMode field should be set to true {
name: "if dryRun or force is set; the nonInteractiveMode field should be set to true",
flags: &applyFlags{ flags: &applyFlags{
newK8sVersionStr: "v1.8.0", newK8sVersionStr: "v1.8.0",
dryRun: true, dryRun: true,
@ -116,7 +123,8 @@ func TestSetImplicitFlags(t *testing.T) {
nonInteractiveMode: true, nonInteractiveMode: true,
}, },
}, },
{ // if the new version is empty; it should error out {
name: "if the new version is empty; it should error out",
flags: &applyFlags{ flags: &applyFlags{
newK8sVersionStr: "", newK8sVersionStr: "",
}, },
@ -127,27 +135,29 @@ func TestSetImplicitFlags(t *testing.T) {
}, },
} }
for _, rt := range tests { for _, rt := range tests {
actualErr := SetImplicitFlags(rt.flags) t.Run(rt.name, func(t *testing.T) {
actualErr := SetImplicitFlags(rt.flags)
// If an error was returned; make newK8sVersion nil so it's easy to match using reflect.DeepEqual later (instead of a random pointer) // If an error was returned; make newK8sVersion nil so it's easy to match using reflect.DeepEqual later (instead of a random pointer)
if actualErr != nil { if actualErr != nil {
rt.flags.newK8sVersion = nil rt.flags.newK8sVersion = nil
} }
if !reflect.DeepEqual(*rt.flags, rt.expectedFlags) { if !reflect.DeepEqual(*rt.flags, rt.expectedFlags) {
t.Errorf( t.Errorf(
"failed SetImplicitFlags:\n\texpected flags: %v\n\t actual: %v", "failed SetImplicitFlags:\n\texpected flags: %v\n\t actual: %v",
rt.expectedFlags, rt.expectedFlags,
*rt.flags, *rt.flags,
) )
} }
if (actualErr != nil) != rt.errExpected { if (actualErr != nil) != rt.errExpected {
t.Errorf( t.Errorf(
"failed SetImplicitFlags:\n\texpected error: %t\n\t actual: %t", "failed SetImplicitFlags:\n\texpected error: %t\n\t actual: %t",
rt.errExpected, rt.errExpected,
(actualErr != nil), (actualErr != nil),
) )
} }
})
} }
} }

View File

@ -25,15 +25,18 @@ import (
func TestPrintConfiguration(t *testing.T) { func TestPrintConfiguration(t *testing.T) {
var tests = []struct { var tests = []struct {
name string
cfg *kubeadmapi.ClusterConfiguration cfg *kubeadmapi.ClusterConfiguration
buf *bytes.Buffer buf *bytes.Buffer
expectedBytes []byte expectedBytes []byte
}{ }{
{ {
name: "config is nil",
cfg: nil, cfg: nil,
expectedBytes: []byte(""), expectedBytes: []byte(""),
}, },
{ {
name: "cluster config with local Etcd",
cfg: &kubeadmapi.ClusterConfiguration{ cfg: &kubeadmapi.ClusterConfiguration{
KubernetesVersion: "v1.7.1", KubernetesVersion: "v1.7.1",
Etcd: kubeadmapi.Etcd{ Etcd: kubeadmapi.Etcd{
@ -67,6 +70,7 @@ func TestPrintConfiguration(t *testing.T) {
`), `),
}, },
{ {
name: "cluster config with ServiceSubnet and external Etcd",
cfg: &kubeadmapi.ClusterConfiguration{ cfg: &kubeadmapi.ClusterConfiguration{
KubernetesVersion: "v1.7.1", KubernetesVersion: "v1.7.1",
Networking: kubeadmapi.Networking{ Networking: kubeadmapi.Networking{
@ -108,15 +112,17 @@ func TestPrintConfiguration(t *testing.T) {
}, },
} }
for _, rt := range tests { for _, rt := range tests {
rt.buf = bytes.NewBufferString("") t.Run(rt.name, func(t *testing.T) {
printConfiguration(rt.cfg, rt.buf) rt.buf = bytes.NewBufferString("")
actualBytes := rt.buf.Bytes() printConfiguration(rt.cfg, rt.buf)
if !bytes.Equal(actualBytes, rt.expectedBytes) { actualBytes := rt.buf.Bytes()
t.Errorf( if !bytes.Equal(actualBytes, rt.expectedBytes) {
"failed PrintConfiguration:\n\texpected: %q\n\t actual: %q", t.Errorf(
string(rt.expectedBytes), "failed PrintConfiguration:\n\texpected: %q\n\t actual: %q",
string(actualBytes), string(rt.expectedBytes),
) string(actualBytes),
} )
}
})
} }
} }

View File

@ -27,35 +27,42 @@ import (
func TestSortedSliceFromStringIntMap(t *testing.T) { func TestSortedSliceFromStringIntMap(t *testing.T) {
var tests = []struct { var tests = []struct {
name string
strMap map[string]uint16 strMap map[string]uint16
expectedSlice []string expectedSlice []string
}{ // The returned slice should be alphabetically sorted based on the string keys in the map }{
{ {
name: "the returned slice should be alphabetically sorted based on the string keys in the map",
strMap: map[string]uint16{"foo": 1, "bar": 2}, strMap: map[string]uint16{"foo": 1, "bar": 2},
expectedSlice: []string{"bar", "foo"}, expectedSlice: []string{"bar", "foo"},
}, },
{ // The int value should not affect this func {
name: "the int value should not affect this func",
strMap: map[string]uint16{"foo": 2, "bar": 1}, strMap: map[string]uint16{"foo": 2, "bar": 1},
expectedSlice: []string{"bar", "foo"}, expectedSlice: []string{"bar", "foo"},
}, },
{ {
name: "slice with 4 keys and different values",
strMap: map[string]uint16{"b": 2, "a": 1, "cb": 0, "ca": 1000}, strMap: map[string]uint16{"b": 2, "a": 1, "cb": 0, "ca": 1000},
expectedSlice: []string{"a", "b", "ca", "cb"}, expectedSlice: []string{"a", "b", "ca", "cb"},
}, },
{ // This should work for version numbers as well; and the lowest version should come first {
name: "this should work for version numbers as well; and the lowest version should come first",
strMap: map[string]uint16{"v1.7.0": 1, "v1.6.1": 1, "v1.6.2": 1, "v1.8.0": 1, "v1.8.0-alpha.1": 1}, strMap: map[string]uint16{"v1.7.0": 1, "v1.6.1": 1, "v1.6.2": 1, "v1.8.0": 1, "v1.8.0-alpha.1": 1},
expectedSlice: []string{"v1.6.1", "v1.6.2", "v1.7.0", "v1.8.0", "v1.8.0-alpha.1"}, expectedSlice: []string{"v1.6.1", "v1.6.2", "v1.7.0", "v1.8.0", "v1.8.0-alpha.1"},
}, },
} }
for _, rt := range tests { for _, rt := range tests {
actualSlice := sortedSliceFromStringIntMap(rt.strMap) t.Run(rt.name, func(t *testing.T) {
if !reflect.DeepEqual(actualSlice, rt.expectedSlice) { actualSlice := sortedSliceFromStringIntMap(rt.strMap)
t.Errorf( if !reflect.DeepEqual(actualSlice, rt.expectedSlice) {
"failed SortedSliceFromStringIntMap:\n\texpected: %v\n\t actual: %v", t.Errorf(
rt.expectedSlice, "failed SortedSliceFromStringIntMap:\n\texpected: %v\n\t actual: %v",
actualSlice, rt.expectedSlice,
) actualSlice,
} )
}
})
} }
} }

View File

@ -22,43 +22,51 @@ import (
func TestValidateExactArgNumber(t *testing.T) { func TestValidateExactArgNumber(t *testing.T) {
var tests = []struct { var tests = []struct {
name string
args, supportedArgs []string args, supportedArgs []string
expectedErr bool expectedErr bool
}{ }{
{ // one arg given and one arg expected {
name: "one arg given and one arg expected",
args: []string{"my-node-1234"}, args: []string{"my-node-1234"},
supportedArgs: []string{"node-name"}, supportedArgs: []string{"node-name"},
expectedErr: false, expectedErr: false,
}, },
{ // two args given and two args expected {
name: "two args given and two args expected",
args: []string{"my-node-1234", "foo"}, args: []string{"my-node-1234", "foo"},
supportedArgs: []string{"node-name", "second-toplevel-arg"}, supportedArgs: []string{"node-name", "second-toplevel-arg"},
expectedErr: false, expectedErr: false,
}, },
{ // too few supplied args {
name: "too few supplied args",
args: []string{}, args: []string{},
supportedArgs: []string{"node-name"}, supportedArgs: []string{"node-name"},
expectedErr: true, expectedErr: true,
}, },
{ // too few non-empty args {
name: "too few non-empty args",
args: []string{""}, args: []string{""},
supportedArgs: []string{"node-name"}, supportedArgs: []string{"node-name"},
expectedErr: true, expectedErr: true,
}, },
{ // too many args {
name: "too many args",
args: []string{"my-node-1234", "foo"}, args: []string{"my-node-1234", "foo"},
supportedArgs: []string{"node-name"}, supportedArgs: []string{"node-name"},
expectedErr: true, expectedErr: true,
}, },
} }
for _, rt := range tests { for _, rt := range tests {
actual := ValidateExactArgNumber(rt.args, rt.supportedArgs) t.Run(rt.name, func(t *testing.T) {
if (actual != nil) != rt.expectedErr { actual := ValidateExactArgNumber(rt.args, rt.supportedArgs)
t.Errorf( if (actual != nil) != rt.expectedErr {
"failed ValidateExactArgNumber:\n\texpected error: %t\n\t actual error: %t", t.Errorf(
rt.expectedErr, "failed ValidateExactArgNumber:\n\texpected error: %t\n\t actual error: %t",
(actual != nil), rt.expectedErr,
) (actual != nil),
} )
}
})
} }
} }

View File

@ -69,28 +69,30 @@ func TestRunVersion(t *testing.T) {
}, },
} }
for _, tc := range testCases { for _, tc := range testCases {
var err error t.Run(tc.name, func(t *testing.T) {
if len(tc.flag) > 0 { var err error
if err = cmd.Flags().Set(flagNameOutput, tc.flag); err != nil { if len(tc.flag) > 0 {
if err = cmd.Flags().Set(flagNameOutput, tc.flag); err != nil {
goto error
}
}
buf.Reset()
if err = RunVersion(&buf, cmd); err != nil {
goto error goto error
} }
} if buf.String() == "" {
buf.Reset() err = errors.New("empty output")
if err = RunVersion(&buf, cmd); err != nil { goto error
goto error }
} if tc.shouldBeValidYAML {
if buf.String() == "" { err = yaml.Unmarshal(buf.Bytes(), &iface)
err = errors.New("empty output") } else if tc.shouldBeValidJSON {
goto error err = json.Unmarshal(buf.Bytes(), &iface)
} }
if tc.shouldBeValidYAML { error:
err = yaml.Unmarshal(buf.Bytes(), &iface) if (err != nil) != tc.expectedError {
} else if tc.shouldBeValidJSON { t.Errorf("Test case %q: RunVersion expected error: %v, saw: %v; %v", tc.name, tc.expectedError, err != nil, err)
err = json.Unmarshal(buf.Bytes(), &iface) }
} })
error:
if (err != nil) != tc.expectedError {
t.Errorf("Test case %q: RunVersion expected error: %v, saw: %v; %v", tc.name, tc.expectedError, err != nil, err)
}
} }
} }