223 lines
7.2 KiB
Go
223 lines
7.2 KiB
Go
package flag
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/spf13/cobra"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestOptionalBoolSet(t *testing.T) {
|
|
for _, c := range []struct {
|
|
input string
|
|
accepted bool
|
|
value bool
|
|
}{
|
|
// Valid inputs documented for strconv.ParseBool == flag.BoolVar
|
|
{"1", true, true},
|
|
{"t", true, true},
|
|
{"T", true, true},
|
|
{"TRUE", true, true},
|
|
{"true", true, true},
|
|
{"True", true, true},
|
|
{"0", true, false},
|
|
{"f", true, false},
|
|
{"F", true, false},
|
|
{"FALSE", true, false},
|
|
{"false", true, false},
|
|
{"False", true, false},
|
|
// A few invalid inputs
|
|
{"", false, false},
|
|
{"yes", false, false},
|
|
{"no", false, false},
|
|
{"2", false, false},
|
|
} {
|
|
var ob OptionalBool
|
|
v := internalNewOptionalBoolValue(&ob)
|
|
require.False(t, ob.Present())
|
|
err := v.Set(c.input)
|
|
if c.accepted {
|
|
assert.NoError(t, err, c.input)
|
|
assert.Equal(t, c.value, ob.Value())
|
|
} else {
|
|
assert.Error(t, err, c.input)
|
|
assert.False(t, ob.Present()) // Just to be extra paranoid.
|
|
}
|
|
}
|
|
|
|
// Nothing actually explicitly says that .Set() is never called when the flag is not present on the command line;
|
|
// so, check that it is not being called, at least in the straightforward case (it's not possible to test that it
|
|
// is not called in any possible situation).
|
|
var globalOB, commandOB OptionalBool
|
|
actionRun := false
|
|
app := &cobra.Command{
|
|
Use: "app",
|
|
}
|
|
OptionalBoolFlag(app.PersistentFlags(), &globalOB, "global-OB", "")
|
|
cmd := &cobra.Command{
|
|
Use: "cmd",
|
|
RunE: func(_ *cobra.Command, args []string) error {
|
|
assert.False(t, globalOB.Present())
|
|
assert.False(t, commandOB.Present())
|
|
actionRun = true
|
|
return nil
|
|
},
|
|
}
|
|
OptionalBoolFlag(cmd.Flags(), &commandOB, "command-OB", "")
|
|
app.AddCommand(cmd)
|
|
app.SetArgs([]string{"cmd"})
|
|
err := app.Execute()
|
|
require.NoError(t, err)
|
|
assert.True(t, actionRun)
|
|
}
|
|
|
|
func TestOptionalBoolString(t *testing.T) {
|
|
for _, c := range []struct {
|
|
input OptionalBool
|
|
expected string
|
|
}{
|
|
{OptionalBool{present: true, value: true}, "true"},
|
|
{OptionalBool{present: true, value: false}, "false"},
|
|
{OptionalBool{present: false, value: true}, ""},
|
|
{OptionalBool{present: false, value: false}, ""},
|
|
} {
|
|
var ob OptionalBool
|
|
v := internalNewOptionalBoolValue(&ob)
|
|
ob = c.input
|
|
res := v.String()
|
|
assert.Equal(t, c.expected, res)
|
|
}
|
|
}
|
|
|
|
func TestOptionalBoolIsBoolFlag(t *testing.T) {
|
|
// IsBoolFlag means that the argument value must either be part of the same argument, with =;
|
|
// if there is no =, the value is set to true.
|
|
// This differs form other flags, where the argument is required and may be either separated with = or supplied in the next argument.
|
|
for _, c := range []struct {
|
|
input []string
|
|
expectedOB OptionalBool
|
|
expectedArgs []string
|
|
}{
|
|
{[]string{"1", "2"}, OptionalBool{present: false}, []string{"1", "2"}}, // Flag not present
|
|
{[]string{"--OB=true", "1", "2"}, OptionalBool{present: true, value: true}, []string{"1", "2"}}, // --OB=true
|
|
{[]string{"--OB=false", "1", "2"}, OptionalBool{present: true, value: false}, []string{"1", "2"}}, // --OB=false
|
|
{[]string{"--OB", "true", "1", "2"}, OptionalBool{present: true, value: true}, []string{"true", "1", "2"}}, // --OB true
|
|
{[]string{"--OB", "false", "1", "2"}, OptionalBool{present: true, value: true}, []string{"false", "1", "2"}}, // --OB false
|
|
} {
|
|
var ob OptionalBool
|
|
actionRun := false
|
|
app := &cobra.Command{Use: "app"}
|
|
cmd := &cobra.Command{
|
|
Use: "cmd",
|
|
RunE: func(_ *cobra.Command, args []string) error {
|
|
assert.Equal(t, c.expectedOB, ob) // nolint
|
|
assert.Equal(t, c.expectedArgs, args) //nolint
|
|
actionRun = true
|
|
return nil
|
|
},
|
|
}
|
|
OptionalBoolFlag(cmd.Flags(), &ob, "OB", "")
|
|
app.AddCommand(cmd)
|
|
|
|
app.SetArgs(append([]string{"cmd"}, c.input...))
|
|
err := app.Execute()
|
|
require.NoError(t, err)
|
|
assert.True(t, actionRun)
|
|
}
|
|
}
|
|
|
|
func TestOptionalStringSet(t *testing.T) {
|
|
// Really just a smoke test, but differentiating between not present and empty.
|
|
for _, c := range []string{"", "hello"} {
|
|
var os OptionalString
|
|
v := NewOptionalStringValue(&os)
|
|
require.False(t, os.Present())
|
|
err := v.Set(c)
|
|
assert.NoError(t, err, c)
|
|
assert.Equal(t, c, os.Value())
|
|
}
|
|
|
|
// Nothing actually explicitly says that .Set() is never called when the flag is not present on the command line;
|
|
// so, check that it is not being called, at least in the straightforward case (it's not possible to test that it
|
|
// is not called in any possible situation).
|
|
var globalOS, commandOS OptionalString
|
|
actionRun := false
|
|
app := &cobra.Command{
|
|
Use: "app",
|
|
}
|
|
app.PersistentFlags().Var(NewOptionalStringValue(&globalOS), "global-OS", "")
|
|
cmd := &cobra.Command{
|
|
Use: "cmd",
|
|
RunE: func(_ *cobra.Command, args []string) error {
|
|
assert.False(t, globalOS.Present())
|
|
assert.False(t, commandOS.Present())
|
|
actionRun = true
|
|
return nil
|
|
},
|
|
}
|
|
cmd.Flags().Var(NewOptionalStringValue(&commandOS), "command-OS", "")
|
|
app.AddCommand(cmd)
|
|
app.SetArgs([]string{"cmd"})
|
|
err := app.Execute()
|
|
require.NoError(t, err)
|
|
assert.True(t, actionRun)
|
|
}
|
|
|
|
func TestOptionalStringString(t *testing.T) {
|
|
for _, c := range []struct {
|
|
input OptionalString
|
|
expected string
|
|
}{
|
|
{OptionalString{present: true, value: "hello"}, "hello"},
|
|
{OptionalString{present: true, value: ""}, ""},
|
|
{OptionalString{present: false, value: "hello"}, ""},
|
|
{OptionalString{present: false, value: ""}, ""},
|
|
} {
|
|
var os OptionalString
|
|
v := NewOptionalStringValue(&os)
|
|
os = c.input
|
|
res := v.String()
|
|
assert.Equal(t, c.expected, res)
|
|
}
|
|
}
|
|
|
|
func TestOptionalStringIsBoolFlag(t *testing.T) {
|
|
// NOTE: OptionalStringValue does not implement IsBoolFlag!
|
|
// IsBoolFlag means that the argument value must either be part of the same argument, with =;
|
|
// if there is no =, the value is set to true.
|
|
// This differs form other flags, where the argument is required and may be either separated with = or supplied in the next argument.
|
|
for _, c := range []struct {
|
|
input []string
|
|
expectedOS OptionalString
|
|
expectedArgs []string
|
|
}{
|
|
{[]string{"1", "2"}, OptionalString{present: false}, []string{"1", "2"}}, // Flag not present
|
|
{[]string{"--OS=hello", "1", "2"}, OptionalString{present: true, value: "hello"}, []string{"1", "2"}}, // --OS=true
|
|
{[]string{"--OS=", "1", "2"}, OptionalString{present: true, value: ""}, []string{"1", "2"}}, // --OS=false
|
|
{[]string{"--OS", "hello", "1", "2"}, OptionalString{present: true, value: "hello"}, []string{"1", "2"}}, // --OS true
|
|
{[]string{"--OS", "", "1", "2"}, OptionalString{present: true, value: ""}, []string{"1", "2"}}, // --OS false
|
|
} {
|
|
var os OptionalString
|
|
actionRun := false
|
|
app := &cobra.Command{
|
|
Use: "app",
|
|
}
|
|
cmd := &cobra.Command{
|
|
Use: "cmd",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
assert.Equal(t, c.expectedOS, os) // nolint
|
|
assert.Equal(t, c.expectedArgs, args) // nolint
|
|
actionRun = true
|
|
return nil
|
|
},
|
|
}
|
|
cmd.Flags().Var(NewOptionalStringValue(&os), "OS", "")
|
|
app.AddCommand(cmd)
|
|
app.SetArgs(append([]string{"cmd"}, c.input...))
|
|
err := app.Execute()
|
|
require.NoError(t, err)
|
|
assert.True(t, actionRun)
|
|
}
|
|
}
|