package command import ( "context" "fmt" "testing" "github.com/stretchr/testify/assert" "edge-infra.dev/pkg/lib/cli/rags" ) var testCases = []struct { cmd *Command expectedLongName string expectedName string expectedErr error }{ { // root command, no extensions, 3 subcommands cmd: &Command{ ShortUsage: "lift", Commands: []*Command{ {ShortUsage: "subcmd1"}, {ShortUsage: "subcmd2"}, {ShortUsage: "subcmd3"}, }, }, expectedLongName: "", expectedName: "", }, { // 1 subcommand, 1 extension cmd: &Command{ ShortUsage: "lift pack [flags] ", ShortHelp: "packs stuff up", LongHelp: "packs stuff up --but longer", Extensions: []Extension{&testExtension{name: "ext1"}}, Exec: func(_ context.Context, _ []string) error { return nil }, }, expectedLongName: "pack", expectedName: "pack", }, { // 2 subcommand, 2 extensions cmd: &Command{ ShortUsage: "edge clustersecret view [flags] ", ShortHelp: "clustersecret view sees all", LongHelp: "it really does see everything", Extensions: []Extension{&testExtension{name: "ext1"}, &testExtension{name: "ext2"}}, }, expectedLongName: "clustersecret view", expectedName: "view", }, { // 3 subcommand, 2 valid extensions, 1 faulty extension in the middle cmd: &Command{ ShortUsage: "root subcmd1 subcmd2 subcmd3 [flags] ", ShortHelp: "definitely does something", LongHelp: "does something described in more detail", Extensions: []Extension{&testExtension{name: "ext1"}, &faultyExtension{}, &testExtension{name: "ext2"}}, Exec: func(_ context.Context, _ []string) error { return nil }, }, expectedLongName: "subcmd1 subcmd2 subcmd3", expectedName: "subcmd3", expectedErr: fmt.Errorf("Faulty extension AfterParse"), }, } type testExtension struct { name string finishedAfterParse bool stringFlag string boolFlag bool } type faultyExtension struct{} func (ext *testExtension) RegisterFlags(rs *rags.RagSet) { rs.StringVar(&ext.stringFlag, ext.name+"-string-flag", "default string value", "string usage message") rs.BoolVar(&ext.boolFlag, ext.name+"-bool-flag", false, "bool usage message") } func (ext *testExtension) AfterParse() error { ext.finishedAfterParse = true return nil } func (ext *faultyExtension) RegisterFlags(_ *rags.RagSet) {} func (ext *faultyExtension) AfterParse() error { return fmt.Errorf("Faulty extension AfterParse") } // test name related functionality func TestLongName(t *testing.T) { for _, tc := range testCases { assert.Equal(t, tc.expectedLongName, tc.cmd.LongName()) } } func TestName(t *testing.T) { for _, tc := range testCases { assert.Equal(t, tc.expectedName, tc.cmd.Name()) } } // testing afterParse() and wExec() func TestAfterParse(t *testing.T) { for _, tc := range testCases { _, err := tc.cmd.afterParse(context.TODO()) for _, e := range tc.cmd.Extensions { // checks to see that every extension either successfully finished AfterParse // or if an error was encountered, that execution of afterParse immediately halts seenFaultyExt := false if ext, ok := e.(*testExtension); ok { assert.Equal(t, !seenFaultyExt, ext.finishedAfterParse) } else if _, ok := e.(*faultyExtension); ok { assert.Equal(t, err, fmt.Errorf("Faulty extension AfterParse")) break } } } } func TestWExec(t *testing.T) { for _, tc := range testCases { // only test commands with execs since nil values aren't // filled in until Command() is called if tc.cmd.Exec != nil { wrappedExec := tc.cmd.wExec() assert.Equal(t, tc.expectedErr, wrappedExec(nil, nil)) } } } // testing Command() func TestCommand(t *testing.T) { for _, tc := range testCases { cmd := tc.cmd.Command() assert.NotNil(t, cmd) // checking flagset was properly initialized assert.Equal(t, tc.cmd.ShortUsage, cmd.FlagSet.Name()) fs := tc.cmd.Rags.FlagSet() for _, e := range tc.cmd.Extensions { if ext, ok := e.(*testExtension); ok { assert.NotNil(t, fs.Lookup(ext.name+"-string-flag")) assert.NotNil(t, fs.Lookup(ext.name+"-bool-flag")) } } // checking basic command fields are populated assert.Equal(t, tc.cmd.Name(), cmd.Name) assert.Equal(t, tc.cmd.ShortUsage, cmd.ShortUsage) assert.Equal(t, tc.cmd.ShortHelp, cmd.ShortHelp) assert.Equal(t, tc.cmd.LongHelp, cmd.LongHelp) assert.NotNil(t, cmd.Options) assert.NotNil(t, cmd.UsageFunc) assert.NotNil(t, cmd.Exec) // checking all subcommands were added assert.Equal(t, len(tc.cmd.Commands), len(cmd.Subcommands)) } }