347 lines
7.1 KiB
Go
347 lines
7.1 KiB
Go
package kong
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func mustNew(t *testing.T, cli interface{}) *Kong {
|
|
t.Helper()
|
|
parser, err := New(cli, ExitFunction(func(int) {
|
|
t.Fatalf("unexpected exit()")
|
|
}))
|
|
require.NoError(t, err)
|
|
return parser
|
|
}
|
|
|
|
func TestPositionalArguments(t *testing.T) {
|
|
var cli struct {
|
|
User struct {
|
|
Create struct {
|
|
ID int `kong:"arg"`
|
|
First string `kong:"arg"`
|
|
Last string `kong:"arg"`
|
|
} `kong:"cmd"`
|
|
} `kong:"cmd"`
|
|
}
|
|
p := mustNew(t, &cli)
|
|
cmd, err := p.Parse([]string{"user", "create", "10", "Alec", "Thomas"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "user create <id> <first> <last>", cmd)
|
|
t.Run("Missing", func(t *testing.T) {
|
|
_, err := p.Parse([]string{"user", "create", "10"})
|
|
require.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestBranchingArgument(t *testing.T) {
|
|
/*
|
|
app user create <id> <first> <last>
|
|
app user <id> delete
|
|
app user <id> rename <to>
|
|
|
|
*/
|
|
var cli struct {
|
|
User struct {
|
|
Create struct {
|
|
ID string `kong:"arg"`
|
|
First string `kong:"arg"`
|
|
Last string `kong:"arg"`
|
|
} `kong:"cmd"`
|
|
|
|
// Branching argument.
|
|
ID struct {
|
|
ID int `kong:"arg"`
|
|
Flag int
|
|
Delete struct{} `kong:"cmd"`
|
|
Rename struct {
|
|
To string
|
|
} `kong:"cmd"`
|
|
} `kong:"arg"`
|
|
} `kong:"cmd,help='User management.'"`
|
|
}
|
|
p := mustNew(t, &cli)
|
|
cmd, err := p.Parse([]string{"user", "10", "delete"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, 10, cli.User.ID.ID)
|
|
require.Equal(t, "user <id> delete", cmd)
|
|
t.Run("Missing", func(t *testing.T) {
|
|
_, err = p.Parse([]string{"user"})
|
|
require.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestResetWithDefaults(t *testing.T) {
|
|
var cli struct {
|
|
Flag string
|
|
FlagWithDefault string `kong:"default='default'"`
|
|
}
|
|
cli.Flag = "BLAH"
|
|
cli.FlagWithDefault = "BLAH"
|
|
parser := mustNew(t, &cli)
|
|
_, err := parser.Parse([]string{})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "", cli.Flag)
|
|
require.Equal(t, "default", cli.FlagWithDefault)
|
|
}
|
|
|
|
func TestFlagSlice(t *testing.T) {
|
|
var cli struct {
|
|
Slice []int
|
|
}
|
|
parser := mustNew(t, &cli)
|
|
_, err := parser.Parse([]string{"--slice=1,2,3"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, []int{1, 2, 3}, cli.Slice)
|
|
}
|
|
|
|
func TestArgSlice(t *testing.T) {
|
|
var cli struct {
|
|
Slice []int `kong:"arg"`
|
|
Flag bool
|
|
}
|
|
parser := mustNew(t, &cli)
|
|
_, err := parser.Parse([]string{"1", "2", "3", "--flag"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, []int{1, 2, 3}, cli.Slice)
|
|
require.Equal(t, true, cli.Flag)
|
|
}
|
|
|
|
func TestUnsupportedFieldErrors(t *testing.T) {
|
|
var cli struct {
|
|
Keys map[string]string
|
|
}
|
|
_, err := New(&cli)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestMatchingArgField(t *testing.T) {
|
|
var cli struct {
|
|
ID struct {
|
|
NotID int `kong:"arg"`
|
|
} `kong:"arg"`
|
|
}
|
|
|
|
_, err := New(&cli)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestCantMixPositionalAndBranches(t *testing.T) {
|
|
var cli struct {
|
|
Arg string `kong:"arg"`
|
|
Command struct {
|
|
} `kong:"cmd"`
|
|
}
|
|
_, err := New(&cli)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestPropagatedFlags(t *testing.T) {
|
|
var cli struct {
|
|
Flag1 string
|
|
Command1 struct {
|
|
Flag2 bool
|
|
Command2 struct{} `kong:"cmd"`
|
|
} `kong:"cmd"`
|
|
}
|
|
|
|
parser := mustNew(t, &cli)
|
|
_, err := parser.Parse([]string{"command-1", "command-2", "--flag-2", "--flag-1=moo"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "moo", cli.Flag1)
|
|
require.Equal(t, true, cli.Command1.Flag2)
|
|
}
|
|
|
|
func TestRequiredFlag(t *testing.T) {
|
|
var cli struct {
|
|
Flag string `kong:"required"`
|
|
}
|
|
|
|
parser := mustNew(t, &cli)
|
|
_, err := parser.Parse([]string{})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestOptionalArg(t *testing.T) {
|
|
var cli struct {
|
|
Arg string `kong:"arg,optional"`
|
|
}
|
|
|
|
parser := mustNew(t, &cli)
|
|
_, err := parser.Parse([]string{})
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestRequiredArg(t *testing.T) {
|
|
var cli struct {
|
|
Arg string `kong:"arg"`
|
|
}
|
|
|
|
parser := mustNew(t, &cli)
|
|
_, err := parser.Parse([]string{})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestInvalidRequiredAfterOptional(t *testing.T) {
|
|
var cli struct {
|
|
ID int `kong:"arg,optional"`
|
|
Name string `kong:"arg"`
|
|
}
|
|
|
|
_, err := New(&cli)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestOptionalStructArg(t *testing.T) {
|
|
var cli struct {
|
|
Name struct {
|
|
Name string `kong:"arg,optional"`
|
|
Enabled bool
|
|
} `kong:"arg,optional"`
|
|
}
|
|
|
|
parser := mustNew(t, &cli)
|
|
|
|
t.Run("WithFlag", func(t *testing.T) {
|
|
_, err := parser.Parse([]string{"gak", "--enabled"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "gak", cli.Name.Name)
|
|
require.Equal(t, true, cli.Name.Enabled)
|
|
})
|
|
|
|
t.Run("WithoutFlag", func(t *testing.T) {
|
|
_, err := parser.Parse([]string{"gak"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "gak", cli.Name.Name)
|
|
})
|
|
|
|
t.Run("WithNothing", func(t *testing.T) {
|
|
_, err := parser.Parse([]string{})
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
|
|
func TestMixedRequiredArgs(t *testing.T) {
|
|
var cli struct {
|
|
Name string `kong:"arg"`
|
|
ID int `kong:"arg,optional"`
|
|
}
|
|
|
|
parser := mustNew(t, &cli)
|
|
|
|
t.Run("SingleRequired", func(t *testing.T) {
|
|
_, err := parser.Parse([]string{"gak", "5"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "gak", cli.Name)
|
|
require.Equal(t, 5, cli.ID)
|
|
})
|
|
|
|
t.Run("ExtraOptional", func(t *testing.T) {
|
|
_, err := parser.Parse([]string{"gak"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "gak", cli.Name)
|
|
})
|
|
}
|
|
|
|
func TestDefaultValueForOptionalArg(t *testing.T) {
|
|
var cli struct {
|
|
Arg string `kong:"arg,optional,default='👌'"`
|
|
}
|
|
p := mustNew(t, &cli)
|
|
_, err := p.Parse(nil)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "👌", cli.Arg)
|
|
}
|
|
|
|
func TestNoValueInTag(t *testing.T) {
|
|
var cli struct {
|
|
Empty1 string `kong:"default"`
|
|
Empty2 string `kong:"default="`
|
|
}
|
|
p := mustNew(t, &cli)
|
|
_, err := p.Parse(nil)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "", cli.Empty1)
|
|
require.Equal(t, "", cli.Empty2)
|
|
}
|
|
|
|
func TestCommaInQuotes(t *testing.T) {
|
|
var cli struct {
|
|
Numbers string `kong:"default='1,2'"`
|
|
}
|
|
p := mustNew(t, &cli)
|
|
_, err := p.Parse(nil)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "1,2", cli.Numbers)
|
|
}
|
|
|
|
func TestBadString(t *testing.T) {
|
|
var cli struct {
|
|
Numbers string `kong:"default='yay'n"`
|
|
}
|
|
_, err := New(&cli)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestNoQuoteEnd(t *testing.T) {
|
|
var cli struct {
|
|
Numbers string `kong:"default='yay"`
|
|
}
|
|
_, err := New(&cli)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestEscapedQuote(t *testing.T) {
|
|
var cli struct {
|
|
DoYouKnow string `kong:"default='i don\\'t know'"`
|
|
}
|
|
p := mustNew(t, &cli)
|
|
_, err := p.Parse(nil)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "i don't know", cli.DoYouKnow)
|
|
}
|
|
|
|
func TestInvalidDefaultErrors(t *testing.T) {
|
|
var cli struct {
|
|
Flag int `kong:"default='foo'"`
|
|
}
|
|
p := mustNew(t, &cli)
|
|
_, err := p.Parse(nil)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestHelp(t *testing.T) {
|
|
var cli struct {
|
|
Flag string
|
|
}
|
|
p := mustNew(t, &cli)
|
|
_, err := p.Parse([]string{"--flag=hello", "--help"})
|
|
require.NoError(t, err)
|
|
require.NotEqual(t, "hello", cli.Flag)
|
|
}
|
|
|
|
func TestDuplicateFlag(t *testing.T) {
|
|
var cli struct {
|
|
Flag bool
|
|
Cmd struct {
|
|
Flag bool
|
|
}
|
|
}
|
|
_, err := New(&cli)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestDuplicateFlagOnPeerCommandIsOkay(t *testing.T) {
|
|
var cli struct {
|
|
Cmd1 struct {
|
|
Flag bool
|
|
}
|
|
Cmd2 struct {
|
|
Flag bool
|
|
}
|
|
}
|
|
_, err := New(&cli)
|
|
require.NoError(t, err)
|
|
}
|