Something went wrong. Try again.
Simple, intuitive CLI framework for Go pkg.go.dev/go.followtheprocess.codes/cli
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538package arg_test
import ( "bytes" "errors" "net" "net/url" "testing" "time"
"go.followtheprocess.codes/cli/internal/arg" "go.followtheprocess.codes/cli/internal/format" "go.followtheprocess.codes/cli/internal/parse" "go.followtheprocess.codes/test")
func TestArgableTypes(t *testing.T) { // We can't do table testing here because Arg[T] is a different type for each test // so we can't do a []Arg[T] which is needed to define the test cases // so strap in for a bunch of copy pasta t.Run("int valid", func(t *testing.T) { var i int
intArg, err := arg.New(&i, "int", "Set an int value", arg.Config[int]{}) test.Ok(t, err)
err = intArg.Set("42") test.Ok(t, err) test.Equal(t, i, 42) test.Equal(t, intArg.Type(), format.TypeInt) test.Equal(t, intArg.String(), "42") test.Equal(t, intArg.Usage(), "Set an int value") test.Equal(t, intArg.Default(), "") })
t.Run("int invalid", func(t *testing.T) { var i int
intArg, err := arg.New(&i, "int", "Set an int value", arg.Config[int]{}) test.Ok(t, err)
err = intArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("int8 valid", func(t *testing.T) { var i int8
intArg, err := arg.New(&i, "int", "Set an int8 value", arg.Config[int8]{}) test.Ok(t, err)
err = intArg.Set("42") test.Ok(t, err) test.Equal(t, i, int8(42)) test.Equal(t, intArg.Type(), format.TypeInt8) test.Equal(t, intArg.Usage(), "Set an int8 value") test.Equal(t, intArg.String(), "42") })
t.Run("int8 invalid", func(t *testing.T) { var i int8
intArg, err := arg.New(&i, "int", "Set an int8 value", arg.Config[int8]{}) test.Ok(t, err)
err = intArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("int16 valid", func(t *testing.T) { var i int16
intArg, err := arg.New(&i, "int", "Set an int16 value", arg.Config[int16]{}) test.Ok(t, err)
err = intArg.Set("42") test.Ok(t, err) test.Equal(t, i, int16(42)) test.Equal(t, intArg.Type(), format.TypeInt16) test.Equal(t, intArg.Usage(), "Set an int16 value") test.Equal(t, intArg.String(), "42") })
t.Run("int16 invalid", func(t *testing.T) { var i int16
intArg, err := arg.New(&i, "int", "Set an int16 value", arg.Config[int16]{}) test.Ok(t, err)
err = intArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("int32 valid", func(t *testing.T) { var i int32
intArg, err := arg.New(&i, "int", "Set an int32 value", arg.Config[int32]{}) test.Ok(t, err)
err = intArg.Set("42") test.Ok(t, err) test.Equal(t, i, int32(42)) test.Equal(t, intArg.Type(), format.TypeInt32) test.Equal(t, intArg.Usage(), "Set an int32 value") test.Equal(t, intArg.String(), "42") })
t.Run("int32 invalid", func(t *testing.T) { var i int32
intArg, err := arg.New(&i, "int", "Set an int32 value", arg.Config[int32]{}) test.Ok(t, err)
err = intArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("int64 valid", func(t *testing.T) { var i int64
intArg, err := arg.New(&i, "int", "Set an int64 value", arg.Config[int64]{}) test.Ok(t, err)
err = intArg.Set("42") test.Ok(t, err) test.Equal(t, i, int64(42)) test.Equal(t, intArg.Type(), format.TypeInt64) test.Equal(t, intArg.Usage(), "Set an int64 value") test.Equal(t, intArg.String(), "42") })
t.Run("int64 invalid", func(t *testing.T) { var i int64
intArg, err := arg.New(&i, "int", "Set an int64 value", arg.Config[int64]{}) test.Ok(t, err)
err = intArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("uint valid", func(t *testing.T) { var i uint
intArg, err := arg.New(&i, "uint", "Set a uint value", arg.Config[uint]{}) test.Ok(t, err)
err = intArg.Set("42") test.Ok(t, err) test.Equal(t, i, 42) test.Equal(t, intArg.Type(), format.TypeUint) test.Equal(t, intArg.Usage(), "Set a uint value") test.Equal(t, intArg.String(), "42") })
t.Run("uint invalid", func(t *testing.T) { var i uint
intArg, err := arg.New(&i, "uint", "Set a uint value", arg.Config[uint]{}) test.Ok(t, err)
err = intArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("uint8 valid", func(t *testing.T) { var i uint8
intArg, err := arg.New(&i, "uint", "Set a uint8 value", arg.Config[uint8]{}) test.Ok(t, err)
err = intArg.Set("42") test.Ok(t, err) test.Equal(t, i, uint8(42)) test.Equal(t, intArg.Type(), "uint8") test.Equal(t, intArg.Usage(), "Set a uint8 value") test.Equal(t, intArg.String(), "42") })
t.Run("uint8 invalid", func(t *testing.T) { var i uint8
intArg, err := arg.New(&i, "uint", "Set a uint8 value", arg.Config[uint8]{}) test.Ok(t, err)
err = intArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("uint16 valid", func(t *testing.T) { var i uint16
intArg, err := arg.New(&i, "uint", "Set a uint16 value", arg.Config[uint16]{}) test.Ok(t, err)
err = intArg.Set("42") test.Ok(t, err) test.Equal(t, i, uint16(42)) test.Equal(t, intArg.Type(), format.TypeUint16) test.Equal(t, intArg.Usage(), "Set a uint16 value") test.Equal(t, intArg.String(), "42") })
t.Run("uint16 invalid", func(t *testing.T) { var i uint16
intArg, err := arg.New(&i, "uint", "Set a uint16 value", arg.Config[uint16]{}) test.Ok(t, err)
err = intArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("uint32 valid", func(t *testing.T) { var i uint32
intArg, err := arg.New(&i, "uint", "Set a uint32 value", arg.Config[uint32]{}) test.Ok(t, err)
err = intArg.Set("42") test.Ok(t, err) test.Equal(t, i, uint32(42)) test.Equal(t, intArg.Type(), format.TypeUint32) test.Equal(t, intArg.Usage(), "Set a uint32 value") test.Equal(t, intArg.String(), "42") })
t.Run("uint32 invalid", func(t *testing.T) { var i uint32
intArg, err := arg.New(&i, "uint", "Set a uint32 value", arg.Config[uint32]{}) test.Ok(t, err)
err = intArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("uint64 valid", func(t *testing.T) { var i uint64
intArg, err := arg.New(&i, "uint", "Set a uint64 value", arg.Config[uint64]{}) test.Ok(t, err)
err = intArg.Set("42") test.Ok(t, err) test.Equal(t, i, uint64(42)) test.Equal(t, intArg.Type(), format.TypeUint64) test.Equal(t, intArg.Usage(), "Set a uint64 value") test.Equal(t, intArg.String(), "42") })
t.Run("uint64 invalid", func(t *testing.T) { var i uint64
intArg, err := arg.New(&i, "uint", "Set a uint64 value", arg.Config[uint64]{}) test.Ok(t, err)
err = intArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("uintptr valid", func(t *testing.T) { var i uintptr
intArg, err := arg.New(&i, "uintptr", "Set a uintptr value", arg.Config[uintptr]{}) test.Ok(t, err)
err = intArg.Set("42") test.Ok(t, err) test.Equal(t, i, uintptr(42)) test.Equal(t, intArg.Type(), format.TypeUintptr) test.Equal(t, intArg.Usage(), "Set a uintptr value") test.Equal(t, intArg.String(), "42") })
t.Run("uintptr invalid", func(t *testing.T) { var i uintptr
intArg, err := arg.New(&i, "uintptr", "Set a uintptr value", arg.Config[uintptr]{}) test.Ok(t, err)
err = intArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("float32 valid", func(t *testing.T) { var f float32
floatArg, err := arg.New(&f, "float", "Set a float32 value", arg.Config[float32]{}) test.Ok(t, err)
err = floatArg.Set("3.14159") test.Ok(t, err) test.Equal(t, f, 3.14159) test.Equal(t, floatArg.Type(), format.TypeFloat32) test.Equal(t, floatArg.Usage(), "Set a float32 value") test.Equal(t, floatArg.String(), "3.14159") })
t.Run("float32 invalid", func(t *testing.T) { var f float32
floatArg, err := arg.New(&f, "float", "Set a float32 value", arg.Config[float32]{}) test.Ok(t, err)
err = floatArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("float64 valid", func(t *testing.T) { var f float64
floatArg, err := arg.New(&f, "float", "Set a float64 value", arg.Config[float64]{}) test.Ok(t, err)
err = floatArg.Set("3.14159") test.Ok(t, err) test.Equal(t, f, 3.14159) test.Equal(t, floatArg.Type(), format.TypeFloat64) test.Equal(t, floatArg.Usage(), "Set a float64 value") test.Equal(t, floatArg.String(), "3.14159") })
t.Run("float64 invalid", func(t *testing.T) { var f float64
floatArg, err := arg.New(&f, "float", "Set a float64 value", arg.Config[float64]{}) test.Ok(t, err)
err = floatArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("bool valid", func(t *testing.T) { var b bool
boolArg, err := arg.New(&b, "bool", "Set a bool value", arg.Config[bool]{}) test.Ok(t, err)
err = boolArg.Set(format.True) test.Ok(t, err) test.Equal(t, b, true) test.Equal(t, boolArg.Type(), format.TypeBool) test.Equal(t, boolArg.Usage(), "Set a bool value") test.Equal(t, boolArg.String(), format.True) })
t.Run("bool invalid", func(t *testing.T) { var b bool
boolArg, err := arg.New(&b, "bool", "Set a bool value", arg.Config[bool]{}) test.Ok(t, err)
err = boolArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
// No invalid case as all command line args are strings anyway so no real way of // getting an error here t.Run("string", func(t *testing.T) { var str string
strArg, err := arg.New(&str, "string", "Set a string value", arg.Config[string]{}) test.Ok(t, err)
err = strArg.Set("newvalue") test.Ok(t, err) test.Equal(t, str, "newvalue") test.Equal(t, strArg.Type(), format.TypeString) test.Equal(t, strArg.Usage(), "Set a string value") test.Equal(t, strArg.String(), "newvalue") })
t.Run("url valid", func(t *testing.T) { var u *url.URL
urlArg, err := arg.New(&u, "url", "Set a url value", arg.Config[*url.URL]{}) test.Ok(t, err)
rawURL := "https://github.com/FollowTheProcess/cli"
want, err := url.ParseRequestURI(rawURL) test.Ok(t, err)
err = urlArg.Set(rawURL) test.Ok(t, err) test.Equal(t, u.Scheme, want.Scheme) test.Equal(t, u.Host, want.Host) test.Equal(t, u.Path, want.Path)
test.Equal(t, urlArg.Type(), format.TypeURL) test.Equal(t, urlArg.Usage(), "Set a url value") test.Equal(t, urlArg.String(), rawURL) })
t.Run("url invalid", func(t *testing.T) { var u *url.URL
urlArg, err := arg.New(&u, "url", "Set a url value", arg.Config[*url.URL]{}) test.Ok(t, err)
err = urlArg.Set("word") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("byte slice valid", func(t *testing.T) { var byt []byte
byteArg, err := arg.New(&byt, "byte", "Set a byte slice value", arg.Config[[]byte]{}) test.Ok(t, err)
err = byteArg.Set("5e") test.Ok(t, err) test.EqualFunc(t, byt, []byte("^"), bytes.Equal) test.Equal(t, byteArg.Type(), format.TypeBytesHex) test.Equal(t, byteArg.Usage(), "Set a byte slice value") test.Equal(t, byteArg.String(), "5e") })
t.Run("byte slice invalid", func(t *testing.T) { var byt []byte
byteArg, err := arg.New(&byt, "byte", "Set a byte slice value", arg.Config[[]byte]{}) test.Ok(t, err)
err = byteArg.Set("0xF") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("time.Time valid", func(t *testing.T) { var tyme time.Time
timeArg, err := arg.New(&tyme, "time", "Set a time value", arg.Config[time.Time]{}) test.Ok(t, err)
err = timeArg.Set("2024-07-17T07:38:05Z") test.Ok(t, err)
want, err := time.Parse(time.RFC3339, "2024-07-17T07:38:05Z") test.Ok(t, err) test.Equal(t, tyme, want) test.Equal(t, timeArg.Type(), format.TypeTime) test.Equal(t, timeArg.Usage(), "Set a time value") test.Equal(t, timeArg.String(), "2024-07-17T07:38:05Z") })
t.Run("time.Time invalid", func(t *testing.T) { var tyme time.Time
timeArg, err := arg.New(&tyme, "time", "Set a time value", arg.Config[time.Time]{}) test.Ok(t, err)
err = timeArg.Set("not a time") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("time.Duration valid", func(t *testing.T) { var duration time.Duration
durationArg, err := arg.New(&duration, "duration", "Set a duration value", arg.Config[time.Duration]{}) test.Ok(t, err)
err = durationArg.Set("300ms") test.Ok(t, err)
want, err := time.ParseDuration("300ms") test.Ok(t, err) test.Equal(t, duration, want) test.Equal(t, durationArg.Type(), format.TypeDuration) test.Equal(t, durationArg.Usage(), "Set a duration value") test.Equal(t, durationArg.String(), "300ms") })
t.Run("time.Duration invalid", func(t *testing.T) { var duration time.Duration
durationArg, err := arg.New(&duration, "duration", "Set a duration value", arg.Config[time.Duration]{}) test.Ok(t, err)
err = durationArg.Set("not a duration") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })
t.Run("ip valid", func(t *testing.T) { var ip net.IP
ipArg, err := arg.New(&ip, "ip", "Set an IP address", arg.Config[net.IP]{}) test.Ok(t, err)
err = ipArg.Set("192.0.2.1") test.Ok(t, err) test.DiffBytes(t, ip, net.ParseIP("192.0.2.1")) test.Equal(t, ipArg.Type(), format.TypeIP) test.Equal(t, ipArg.Usage(), "Set an IP address") test.Equal(t, ipArg.String(), "192.0.2.1") })
t.Run("ip invalid", func(t *testing.T) { var ip net.IP
ipArg, err := arg.New(&ip, "ip", "Set an IP address", arg.Config[net.IP]{}) test.Ok(t, err)
err = ipArg.Set("not an ip") test.Err(t, err) test.True(t, errors.Is(err, parse.Err)) })}
func TestDefaults(t *testing.T) { str, err := arg.New(new(string), "str", "A string", arg.Config[string]{DefaultValue: new("hello")}) test.Ok(t, err)
intArg, err := arg.New(new(int), "int", "A string", arg.Config[int]{DefaultValue: new(27)}) test.Ok(t, err)
test.Equal(t, str.Default(), "hello") test.Equal(t, intArg.Default(), "27")}