Skip to content

Commit

Permalink
refactor(internal): change testutil.ResetArgs to a test helper func…
Browse files Browse the repository at this point in the history
…tion (#19262)
  • Loading branch information
Halimao authored Jan 30, 2024
1 parent a86a83f commit cbc75c7
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 64 deletions.
9 changes: 5 additions & 4 deletions internal/testutil/cmd.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package testutil

import (
"fmt"
"strings"
"testing"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
Expand All @@ -18,7 +18,8 @@ import (
// 3. the custom implementations of pflag.SliceValue that are split by comma ","
//
// see https://github.com/spf13/cobra/issues/2079#issuecomment-1867991505 for more detail info
func ResetArgs(cmd *cobra.Command) {
func ResetArgs(t *testing.T, cmd *cobra.Command) {
t.Helper()
// if flags haven't been parsed yet, there is no need to reset the args
if !cmd.Flags().Parsed() {
return
Expand All @@ -37,13 +38,13 @@ func ResetArgs(cmd *cobra.Command) {
defSliceVal = strings.Split(defVal, ",")
}
if err := v.Replace(defSliceVal); err != nil {
panic(fmt.Errorf("error resetting argument <%s> with default value <%+v>: %v", pf.Name, defSliceVal, err))
t.Errorf("error resetting argument <%s> with default value <%+v>: %v", pf.Name, defSliceVal, err)
}
return
}
// handle pflag.Value
if err := pf.Value.Set(pf.DefValue); err != nil {
panic(fmt.Errorf("error resetting argument <%s> with default value <%s>: %v", pf.Name, pf.DefValue, err))
t.Errorf("error resetting argument <%s> with default value <%s>: %v", pf.Name, pf.DefValue, err)
}
})
}
160 changes: 100 additions & 60 deletions internal/testutil/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ func TestSetArgsWithOriginalMethod(t *testing.T) {

func TestSetArgsWithWrappedMethod(t *testing.T) {
var (
mockFlagWithCommaF = testutil.MockFlagsWithComma{Ary: []string{"g;m", "g;n"}}
mockFlagWithCommaG testutil.MockFlagsWithComma
mockFlagWithCommaD = testutil.MockFlagsWithComma{Ary: []string{"g;m", "g;n"}}
mockFlagWithCommaE testutil.MockFlagsWithComma
)
var (
mockFlagWithSemicolonH = testutil.MockFlagsWithSemicolon{Ary: []string{"g,m", "g,n"}}
mockFlagWithSemicolonI testutil.MockFlagsWithSemicolon
mockFlagWithSemicolonF = testutil.MockFlagsWithSemicolon{Ary: []string{"g,m", "g,n"}}
mockFlagWithSemicolonG testutil.MockFlagsWithSemicolon
)
getCMD := func() *cobra.Command {
cmd := &cobra.Command{
Expand All @@ -85,11 +85,11 @@ func TestSetArgsWithWrappedMethod(t *testing.T) {
f := cmd.Flags()
f.BoolP("a", "a", false, "check built-in pflag.Value")
f.IntSlice("b", []int{1, 2}, "check built-in pflag.SliceValue with default value")
f.IntSliceP("c", "c", nil, "check built-in pflag.SliceValue with nil default value")
f.Var(&mockFlagWithCommaF, "d", "check custom implementation of pflag.SliceValue with splitting by comma and default value")
f.VarP(&mockFlagWithCommaG, "e", "e", "check custom implementation of pflag.SliceValue with splitting by comma and nil default value")
f.Var(&mockFlagWithSemicolonH, "f", "check custom implementation of pflag.SliceValue with splitting by semicolon and default value")
f.VarP(&mockFlagWithSemicolonI, "g", "g", "check custom implementation of pflag.SliceValue with splitting by semicolon and nil default value")
f.IntSliceP("c", "c", nil, "check built pflag.SliceValue with nil default value")
f.Var(&mockFlagWithCommaD, "d", "check custom implementation of pflag.SliceValue with splitting by comma and default value")
f.VarP(&mockFlagWithCommaE, "e", "e", "check custom implementation of pflag.SliceValue with splitting by comma and nil default value")
f.Var(&mockFlagWithSemicolonF, "f", "check custom implementation of pflag.SliceValue with splitting by semicolon and default value")
f.VarP(&mockFlagWithSemicolonG, "g", "g", "check custom implementation of pflag.SliceValue with splitting by semicolon and nil default value")
return cmd
}

Expand All @@ -110,57 +110,97 @@ func TestSetArgsWithWrappedMethod(t *testing.T) {
return true
}

resetAndSetNewArgs := func(cmd *cobra.Command, args []string) {
testutil.ResetArgs(cmd)
cmd.SetArgs(args)
testCases := []struct {
name string
steps []struct {
args []string
expectNotDefaultFlags map[string]string
}
}{
{
name: "no args",
steps: []struct {
args []string
expectNotDefaultFlags map[string]string
}{
{
args: nil,
expectNotDefaultFlags: nil,
},
},
},
{
name: "built-in implementation of pflag.Value",
steps: []struct {
args []string
expectNotDefaultFlags map[string]string
}{
{
args: []string{"--a=true"},
expectNotDefaultFlags: map[string]string{"a": "true"},
},
},
},
{
name: "built-in implementation of pflag.SliceValue",
steps: []struct {
args []string
expectNotDefaultFlags map[string]string
}{
{
args: []string{"--b=3,4"},
expectNotDefaultFlags: map[string]string{"b": "[3,4]"},
},
{
args: []string{"--c=3,4"},
expectNotDefaultFlags: map[string]string{"c": "[3,4]"},
},
},
},
{
name: "custom implementation of pflag.SliceValue with comma",
steps: []struct {
args []string
expectNotDefaultFlags map[string]string
}{
{
args: []string{"--d=g;n,g;m"},
expectNotDefaultFlags: map[string]string{"d": "g;n,g;m"},
},
{
args: []string{"--e=g;n,g;m"},
expectNotDefaultFlags: map[string]string{"e": "g;n,g;m"},
},
},
},
{
// custom implementation of pflag.SliceValue with splitting by semicolon is not compatible with testutil.SetArgs.
// So `f` is changed to "g;m;g;n" (split to ["g", "m;g", "n"], and then join with ";"), not default value "g,m;g,n"
name: "custom implementation of pflag.SliceValue with semicolon",
steps: []struct {
args []string
expectNotDefaultFlags map[string]string
}{
{
args: []string{"--f=g,n;g,m"},
expectNotDefaultFlags: map[string]string{"f": "g,n;g,m"},
},
{
args: []string{"--g=g,n;g,m"},
expectNotDefaultFlags: map[string]string{"f": "g;m;g;n", "g": "g,n;g,m"},
},
},
},
}

resetAndSetNewArgs(cmd, []string{
"testcmd",
})
checkFlagsValue(cmd, nil)

resetAndSetNewArgs(cmd, []string{
"testcmd",
"--a=true",
})
checkFlagsValue(cmd, map[string]string{"a": "true"})

resetAndSetNewArgs(cmd, []string{
"testcmd",
"--b=3,4",
})
checkFlagsValue(cmd, map[string]string{"b": "[3,4]"})

resetAndSetNewArgs(cmd, []string{
"testcmd",
"--c=3,4",
})
checkFlagsValue(cmd, map[string]string{"c": "[3,4]"})

resetAndSetNewArgs(cmd, []string{
"testcmd",
"--d=g;n,g;m",
})
checkFlagsValue(cmd, map[string]string{"d": "g;n,g;m"})

resetAndSetNewArgs(cmd, []string{
"testcmd",
"--e=g;n,g;m",
})
checkFlagsValue(cmd, map[string]string{"e": "g;n,g;m"})

resetAndSetNewArgs(cmd, []string{
"testcmd",
"--f=g,n;g,m",
})
checkFlagsValue(cmd, map[string]string{"f": "g,n;g,m"})

resetAndSetNewArgs(cmd, []string{
"testcmd",
"--g=g,n;g,m",
})
// custom implementation of pflag.SliceValue with splitting by semicolon is not compatible with testutil.SetArgs.
// So `f` is changed to "g;m;g;n"(split to ["g", "m;g", "n"], and then join with ";"), not default value "g,m;g,n"
checkFlagsValue(cmd, map[string]string{"f": "g;m;g;n", "g": "g,n;g,m"})
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
for _, step := range testCase.steps {
testutil.ResetArgs(t, cmd)
args := append([]string{"testcmd"}, step.args...)
cmd.SetArgs(args)
checkFlagsValue(cmd, step.expectNotDefaultFlags)
}
})
}
}

0 comments on commit cbc75c7

Please sign in to comment.