161 lines
8.3 KiB
Go
161 lines
8.3 KiB
Go
package cobra
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
commandmeta "gitea.maximumdirect.net/eric/CommandKit/internal/commandmeta"
|
|
)
|
|
|
|
func flagGrammarTree() *commandmeta.Command {
|
|
return &commandmeta.Command{Name: "app", Children: []*commandmeta.Command{{
|
|
Name: "run", Runnable: true,
|
|
Flags: []commandmeta.Flag{
|
|
{Name: "color", Short: "c"},
|
|
{Name: "verbose", Short: "v", Boolean: true},
|
|
{Name: "quiet", Short: "q", Boolean: true},
|
|
{Name: "message", Short: "m"},
|
|
{Name: "tag", Short: "t", Repeated: true},
|
|
},
|
|
}}}
|
|
}
|
|
|
|
func flagGrammarOptions() ParseOptions {
|
|
return ParseOptions{FlagAliases: []commandmeta.FlagAlias{
|
|
{Source: "--colour", Target: "--color"},
|
|
{Source: "-C", Target: "--color"},
|
|
{Source: "-w", Target: "--verbose"},
|
|
{Source: "-z", Target: "--quiet"},
|
|
{Source: "--taggy", Target: "-t"},
|
|
{Source: "--hlep", Target: "--help"},
|
|
}}
|
|
}
|
|
|
|
func TestParseCanonicalAndAliasShortGrammar(t *testing.T) {
|
|
for _, test := range []struct {
|
|
name string
|
|
args []string
|
|
values [][]string
|
|
spellings [][]string
|
|
}{
|
|
{"boolean cluster", []string{"run", "-vq"}, [][]string{nil, {"true"}, {"true"}, nil, nil}, [][]string{nil, {"-v"}, {"-q"}, nil, nil}},
|
|
{"aliased boolean cluster", []string{"run", "-wz"}, [][]string{nil, {"true"}, {"true"}, nil, nil}, [][]string{nil, {"-w"}, {"-z"}, nil, nil}},
|
|
{"value short separated", []string{"run", "-c", "blue"}, [][]string{{"blue"}, nil, nil, nil, nil}, [][]string{{"-c"}, nil, nil, nil, nil}},
|
|
{"value short equals", []string{"run", "-c=blue"}, [][]string{{"blue"}, nil, nil, nil, nil}, [][]string{{"-c"}, nil, nil, nil, nil}},
|
|
{"value short attached", []string{"run", "-cblue"}, [][]string{{"blue"}, nil, nil, nil, nil}, [][]string{{"-c"}, nil, nil, nil, nil}},
|
|
{"long alias", []string{"run", "--colour=blue"}, [][]string{{"blue"}, nil, nil, nil, nil}, [][]string{{"--colour"}, nil, nil, nil, nil}},
|
|
{"short alias", []string{"run", "-Cblue"}, [][]string{{"blue"}, nil, nil, nil, nil}, [][]string{{"-C"}, nil, nil, nil, nil}},
|
|
{"cluster value consumes suffix", []string{"run", "-vqcblue"}, [][]string{{"blue"}, {"true"}, {"true"}, nil, nil}, [][]string{{"-c"}, {"-v"}, {"-q"}, nil, nil}},
|
|
{"cluster value consumes next", []string{"run", "-vqc", "blue"}, [][]string{{"blue"}, {"true"}, {"true"}, nil, nil}, [][]string{{"-c"}, {"-v"}, {"-q"}, nil, nil}},
|
|
{"mixed canonical and alias cluster", []string{"run", "-wqcblue"}, [][]string{{"blue"}, {"true"}, {"true"}, nil, nil}, [][]string{{"-c"}, {"-w"}, {"-q"}, nil, nil}},
|
|
{"value takes remaining suffix", []string{"run", "-cvq"}, [][]string{{"vq"}, nil, nil, nil, nil}, [][]string{{"-c"}, nil, nil, nil, nil}},
|
|
{"boolean explicit false", []string{"run", "-v=false"}, [][]string{nil, {"false"}, nil, nil, nil}, [][]string{nil, {"-v"}, nil, nil, nil}},
|
|
{"boolean explicit false in cluster", []string{"run", "-qv=false"}, [][]string{nil, {"false"}, {"true"}, nil, nil}, [][]string{nil, {"-v"}, {"-q"}, nil, nil}},
|
|
{"empty canonical short", []string{"run", "-c="}, [][]string{{""}, nil, nil, nil, nil}, [][]string{{"-c"}, nil, nil, nil, nil}},
|
|
{"empty canonical long", []string{"run", "--color="}, [][]string{{""}, nil, nil, nil, nil}, [][]string{{"--color"}, nil, nil, nil, nil}},
|
|
{"empty separated short", []string{"run", "-c", ""}, [][]string{{""}, nil, nil, nil, nil}, [][]string{{"-c"}, nil, nil, nil, nil}},
|
|
{"empty aliased long", []string{"run", "--colour="}, [][]string{{""}, nil, nil, nil, nil}, [][]string{{"--colour"}, nil, nil, nil, nil}},
|
|
{"empty aliased short", []string{"run", "-C="}, [][]string{{""}, nil, nil, nil, nil}, [][]string{{"-C"}, nil, nil, nil, nil}},
|
|
{"empty boolean short", []string{"run", "-v="}, [][]string{nil, {""}, nil, nil, nil}, [][]string{nil, {"-v"}, nil, nil, nil}},
|
|
} {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
result := Parse(flagGrammarTree(), test.args, flagGrammarOptions())
|
|
if result.Failure != nil {
|
|
t.Fatalf("parse failed: %s", result.Failure.Message)
|
|
}
|
|
if !reflect.DeepEqual(result.FlagValues, test.values) {
|
|
t.Errorf("values = %#v, want %#v", result.FlagValues, test.values)
|
|
}
|
|
if !reflect.DeepEqual(result.FlagSpellings, test.spellings) {
|
|
t.Errorf("spellings = %#v, want %#v", result.FlagSpellings, test.spellings)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseFlagAliasesPreserveValuesAndTerminators(t *testing.T) {
|
|
result := Parse(flagGrammarTree(), []string{"run", "--message", "--hlep", "--message=--hlep", "--taggy", "one", "--", "--taggy"}, flagGrammarOptions())
|
|
if result.Failure != nil {
|
|
t.Fatalf("parse failed: %s", result.Failure.Message)
|
|
}
|
|
if got, want := result.FlagValues[3], []string{"--hlep", "--hlep"}; !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("message values = %#v, want %#v", got, want)
|
|
}
|
|
if got, want := result.FlagSpellings[3], []string{"--message", "--message"}; !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("message spellings = %#v, want %#v", got, want)
|
|
}
|
|
if got, want := result.FlagValues[4], []string{"one"}; !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("tag values = %#v, want %#v", got, want)
|
|
}
|
|
if got, want := result.Operands, []string{"--taggy"}; !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("operands = %#v, want %#v", got, want)
|
|
}
|
|
}
|
|
|
|
func TestParseConsumesDoubleDashAsAFlagValue(t *testing.T) {
|
|
for _, spelling := range []string{"--color", "--colour", "-c", "-C"} {
|
|
t.Run(spelling, func(t *testing.T) {
|
|
result := Parse(flagGrammarTree(), []string{"run", spelling, "--", "--taggy=one", "--colour=red", "--", "--taggy=operand"}, flagGrammarOptions())
|
|
if result.Failure != nil {
|
|
t.Fatalf("parse failed: %s", result.Failure.Message)
|
|
}
|
|
if !reflect.DeepEqual(result.FlagValues[0], []string{"--", "red"}) || !reflect.DeepEqual(result.FlagValues[4], []string{"one"}) {
|
|
t.Errorf("flag values = %#v", result.FlagValues)
|
|
}
|
|
if !reflect.DeepEqual(result.FlagSpellings[0], []string{spelling, "--colour"}) || !reflect.DeepEqual(result.Operands, []string{"--taggy=operand"}) {
|
|
t.Errorf("spellings = %#v, operands = %#v", result.FlagSpellings, result.Operands)
|
|
}
|
|
})
|
|
}
|
|
for _, args := range [][]string{{"run", "-v", "--", "--colour"}, {"run", "--color", "blue", "--", "--colour"}} {
|
|
result := Parse(flagGrammarTree(), args, flagGrammarOptions())
|
|
if result.Failure != nil || !reflect.DeepEqual(result.Operands, []string{"--colour"}) {
|
|
t.Errorf("Parse(%q) = %#v", args, result)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseHelpAliasAndUnknownShortMembers(t *testing.T) {
|
|
result := Parse(flagGrammarTree(), []string{"run", "--hlep"}, flagGrammarOptions())
|
|
if result.Failure != nil || !result.HelpRequested {
|
|
t.Fatalf("help alias result = %#v", result)
|
|
}
|
|
result = Parse(flagGrammarTree(), []string{"run", "-vx"}, flagGrammarOptions())
|
|
if result.Failure == nil || result.Failure.Message == "" {
|
|
t.Fatalf("unknown short cluster member result = %#v", result)
|
|
}
|
|
result = Parse(flagGrammarTree(), []string{"run", "--color"}, flagGrammarOptions())
|
|
if result.Failure == nil || result.Failure.Message == "" {
|
|
t.Fatalf("missing value result = %#v", result)
|
|
}
|
|
result = Parse(flagGrammarTree(), []string{"run", "--colour"}, flagGrammarOptions())
|
|
if result.Failure == nil || result.Failure.Message == "" {
|
|
t.Fatalf("missing aliased value result = %#v", result)
|
|
}
|
|
result = Parse(flagGrammarTree(), []string{"run", "-c"}, flagGrammarOptions())
|
|
if result.Failure == nil || result.Failure.Message == "" {
|
|
t.Fatalf("missing short value result = %#v", result)
|
|
}
|
|
result = Parse(flagGrammarTree(), []string{"run", "-C"}, flagGrammarOptions())
|
|
if result.Failure == nil || result.Failure.Message == "" {
|
|
t.Fatalf("missing aliased short value result = %#v", result)
|
|
}
|
|
result = Parse(flagGrammarTree(), []string{"run", "-vfalse"}, flagGrammarOptions())
|
|
if result.Failure == nil || result.Failure.Message == "" {
|
|
t.Fatalf("boolean suffix without equals result = %#v", result)
|
|
}
|
|
}
|
|
|
|
func TestParseFlagAliasOccurrenceOrderAndSpellings(t *testing.T) {
|
|
result := Parse(flagGrammarTree(), []string{"run", "--taggy=first", "-t", "second", "--taggy", "third"}, flagGrammarOptions())
|
|
if result.Failure != nil {
|
|
t.Fatalf("parse failed: %s", result.Failure.Message)
|
|
}
|
|
if got, want := result.FlagValues[4], []string{"first", "second", "third"}; !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("tag values = %#v, want %#v", got, want)
|
|
}
|
|
if got, want := result.FlagSpellings[4], []string{"--taggy", "-t", "--taggy"}; !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("tag spellings = %#v, want %#v", got, want)
|
|
}
|
|
}
|