Merge remote-tracking branch 'origin/master' into string-slice-flag-default-160

This commit is contained in:
Dan Buch 2016-04-28 16:53:45 -04:00
commit ee736e063a
No known key found for this signature in database
GPG Key ID: FAEF12936DD3E3EC
5 changed files with 263 additions and 66 deletions

View File

@ -7,6 +7,9 @@
### Added
- Support for placeholders in flag usage strings
### Fixed
- Added missing `*cli.Context.GlobalFloat64` method
## [2.0.0]
### Added
- `NewStringSlice` and `NewIntSlice` for creating their related types

View File

@ -13,6 +13,10 @@ import (
"testing"
)
type opCounts struct {
Total, BashComplete, OnUsageError, Before, CommandNotFound, Action, After, SubCommand int
}
func ExampleApp_Run() {
// set args for examples sake
os.Args = []string{"greet", "--name", "Jeremy"}
@ -439,14 +443,15 @@ func TestApp_SetStdout(t *testing.T) {
}
func TestApp_BeforeFunc(t *testing.T) {
beforeRun, subcommandRun := false, false
counts := &opCounts{}
beforeError := fmt.Errorf("fail")
var err error
app := NewApp()
app.Before = func(c *Context) error {
beforeRun = true
counts.Total++
counts.Before = counts.Total
s := c.String("opt")
if s == "fail" {
return beforeError
@ -459,7 +464,8 @@ func TestApp_BeforeFunc(t *testing.T) {
Command{
Name: "sub",
Action: func(c *Context) {
subcommandRun = true
counts.Total++
counts.SubCommand = counts.Total
},
},
}
@ -475,16 +481,16 @@ func TestApp_BeforeFunc(t *testing.T) {
t.Fatalf("Run error: %s", err)
}
if beforeRun == false {
if counts.Before != 1 {
t.Errorf("Before() not executed when expected")
}
if subcommandRun == false {
if counts.SubCommand != 2 {
t.Errorf("Subcommand not executed when expected")
}
// reset
beforeRun, subcommandRun = false, false
counts = &opCounts{}
// run with the Before() func failing
err = app.Run([]string{"command", "--opt", "fail", "sub"})
@ -494,25 +500,26 @@ func TestApp_BeforeFunc(t *testing.T) {
t.Errorf("Run error expected, but not received")
}
if beforeRun == false {
if counts.Before != 1 {
t.Errorf("Before() not executed when expected")
}
if subcommandRun == true {
if counts.SubCommand != 0 {
t.Errorf("Subcommand executed when NOT expected")
}
}
func TestApp_AfterFunc(t *testing.T) {
afterRun, subcommandRun := false, false
counts := &opCounts{}
afterError := fmt.Errorf("fail")
var err error
app := NewApp()
app.After = func(c *Context) error {
afterRun = true
counts.Total++
counts.After = counts.Total
s := c.String("opt")
if s == "fail" {
return afterError
@ -525,7 +532,8 @@ func TestApp_AfterFunc(t *testing.T) {
Command{
Name: "sub",
Action: func(c *Context) {
subcommandRun = true
counts.Total++
counts.SubCommand = counts.Total
},
},
}
@ -541,16 +549,16 @@ func TestApp_AfterFunc(t *testing.T) {
t.Fatalf("Run error: %s", err)
}
if afterRun == false {
if counts.After != 2 {
t.Errorf("After() not executed when expected")
}
if subcommandRun == false {
if counts.SubCommand != 1 {
t.Errorf("Subcommand not executed when expected")
}
// reset
afterRun, subcommandRun = false, false
counts = &opCounts{}
// run with the Before() func failing
err = app.Run([]string{"command", "--opt", "fail", "sub"})
@ -560,11 +568,11 @@ func TestApp_AfterFunc(t *testing.T) {
t.Errorf("Run error expected, but not received")
}
if afterRun == false {
if counts.After != 2 {
t.Errorf("After() not executed when expected")
}
if subcommandRun == false {
if counts.SubCommand != 1 {
t.Errorf("Subcommand not executed when expected")
}
}
@ -605,7 +613,7 @@ func TestAppHelpPrinter(t *testing.T) {
}
}
func TestAppVersionPrinter(t *testing.T) {
func TestApp_VersionPrinter(t *testing.T) {
oldPrinter := VersionPrinter
defer func() {
VersionPrinter = oldPrinter
@ -625,81 +633,168 @@ func TestAppVersionPrinter(t *testing.T) {
}
}
func TestAppCommandNotFound(t *testing.T) {
beforeRun, subcommandRun := false, false
func TestApp_CommandNotFound(t *testing.T) {
counts := &opCounts{}
app := NewApp()
app.CommandNotFound = func(c *Context, command string) {
beforeRun = true
counts.Total++
counts.CommandNotFound = counts.Total
}
app.Commands = []Command{
Command{
Name: "bar",
Action: func(c *Context) {
subcommandRun = true
counts.Total++
counts.SubCommand = counts.Total
},
},
}
app.Run([]string{"command", "foo"})
expect(t, beforeRun, true)
expect(t, subcommandRun, false)
expect(t, counts.CommandNotFound, 1)
expect(t, counts.SubCommand, 0)
expect(t, counts.Total, 1)
}
func TestGlobalFlag(t *testing.T) {
var globalFlag string
var globalFlagSet bool
func TestApp_OrderOfOperations(t *testing.T) {
counts := &opCounts{}
resetCounts := func() { counts = &opCounts{} }
app := NewApp()
app.Flags = []Flag{
StringFlag{Name: "global, g", Usage: "global"},
app.EnableBashCompletion = true
app.BashComplete = func(c *Context) {
counts.Total++
counts.BashComplete = counts.Total
}
app.Action = func(c *Context) {
globalFlag = c.GlobalString("global")
globalFlagSet = c.GlobalIsSet("global")
}
app.Run([]string{"command", "-g", "foo"})
expect(t, globalFlag, "foo")
expect(t, globalFlagSet, true)
}
func TestGlobalFlagsInSubcommands(t *testing.T) {
subcommandRun := false
parentFlag := false
app := NewApp()
app.Flags = []Flag{
BoolFlag{Name: "debug, d", Usage: "Enable debugging"},
app.OnUsageError = func(c *Context, err error, isSubcommand bool) error {
counts.Total++
counts.OnUsageError = counts.Total
return errors.New("hay OnUsageError")
}
beforeNoError := func(c *Context) error {
counts.Total++
counts.Before = counts.Total
return nil
}
beforeError := func(c *Context) error {
counts.Total++
counts.Before = counts.Total
return errors.New("hay Before")
}
app.Before = beforeNoError
app.CommandNotFound = func(c *Context, command string) {
counts.Total++
counts.CommandNotFound = counts.Total
}
afterNoError := func(c *Context) error {
counts.Total++
counts.After = counts.Total
return nil
}
afterError := func(c *Context) error {
counts.Total++
counts.After = counts.Total
return errors.New("hay After")
}
app.After = afterNoError
app.Commands = []Command{
Command{
Name: "foo",
Flags: []Flag{
BoolFlag{Name: "parent, p", Usage: "Parent flag"},
},
Subcommands: []Command{
{
Name: "bar",
Action: func(c *Context) {
if c.GlobalBool("debug") {
subcommandRun = true
}
if c.GlobalBool("parent") {
parentFlag = true
}
},
},
counts.Total++
counts.SubCommand = counts.Total
},
},
}
app.Run([]string{"command", "-d", "foo", "-p", "bar"})
app.Action = func(c *Context) {
counts.Total++
counts.Action = counts.Total
}
expect(t, subcommandRun, true)
expect(t, parentFlag, true)
_ = app.Run([]string{"command", "--nope"})
expect(t, counts.OnUsageError, 1)
expect(t, counts.Total, 1)
resetCounts()
_ = app.Run([]string{"command", "--generate-bash-completion"})
expect(t, counts.BashComplete, 1)
expect(t, counts.Total, 1)
resetCounts()
oldOnUsageError := app.OnUsageError
app.OnUsageError = nil
_ = app.Run([]string{"command", "--nope"})
expect(t, counts.Total, 0)
app.OnUsageError = oldOnUsageError
resetCounts()
_ = app.Run([]string{"command", "foo"})
expect(t, counts.OnUsageError, 0)
expect(t, counts.Before, 1)
expect(t, counts.CommandNotFound, 0)
expect(t, counts.Action, 2)
expect(t, counts.After, 3)
expect(t, counts.Total, 3)
resetCounts()
app.Before = beforeError
_ = app.Run([]string{"command", "bar"})
expect(t, counts.OnUsageError, 0)
expect(t, counts.Before, 1)
expect(t, counts.After, 2)
expect(t, counts.Total, 2)
app.Before = beforeNoError
resetCounts()
app.After = nil
_ = app.Run([]string{"command", "bar"})
expect(t, counts.OnUsageError, 0)
expect(t, counts.Before, 1)
expect(t, counts.SubCommand, 2)
expect(t, counts.Total, 2)
app.After = afterNoError
resetCounts()
app.After = afterError
err := app.Run([]string{"command", "bar"})
if err == nil {
t.Fatalf("expected a non-nil error")
}
expect(t, counts.OnUsageError, 0)
expect(t, counts.Before, 1)
expect(t, counts.SubCommand, 2)
expect(t, counts.After, 3)
expect(t, counts.Total, 3)
app.After = afterNoError
resetCounts()
oldCommands := app.Commands
app.Commands = nil
_ = app.Run([]string{"command"})
expect(t, counts.OnUsageError, 0)
expect(t, counts.Before, 1)
expect(t, counts.Action, 2)
expect(t, counts.After, 3)
expect(t, counts.Total, 3)
app.Commands = oldCommands
}
func TestApp_Run_CommandWithSubcommandHasHelpTopic(t *testing.T) {

View File

@ -79,6 +79,15 @@ func (c *Context) GlobalInt(name string) int {
return 0
}
// Looks up the value of a global float64 flag, returns float64(0) if no float64
// flag exists
func (c *Context) GlobalFloat64(name string) float64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupFloat64(name, fs)
}
return float64(0)
}
// Looks up the value of a global time.Duration flag, returns 0 if no time.Duration flag exists
func (c *Context) GlobalDuration(name string) time.Duration {
if fs := lookupGlobalFlagSet(name, c); fs != nil {

View File

@ -9,14 +9,18 @@ import (
func TestNewContext(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Int("myflag", 12, "doc")
set.Float64("myflag64", float64(17), "doc")
globalSet := flag.NewFlagSet("test", 0)
globalSet.Int("myflag", 42, "doc")
globalSet.Float64("myflag64", float64(47), "doc")
globalCtx := NewContext(nil, globalSet, nil)
command := Command{Name: "mycommand"}
c := NewContext(nil, set, globalCtx)
c.Command = command
expect(t, c.Int("myflag"), 12)
expect(t, c.Float64("myflag64"), float64(17))
expect(t, c.GlobalInt("myflag"), 42)
expect(t, c.GlobalFloat64("myflag64"), float64(47))
expect(t, c.Command.Name, "mycommand")
}
@ -27,6 +31,29 @@ func TestContext_Int(t *testing.T) {
expect(t, c.Int("myflag"), 12)
}
func TestContext_GlobalInt(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Int("myflag", 12, "doc")
c := NewContext(nil, set, nil)
expect(t, c.GlobalInt("myflag"), 12)
expect(t, c.GlobalInt("nope"), 0)
}
func TestContext_Float64(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Float64("myflag", float64(17), "doc")
c := NewContext(nil, set, nil)
expect(t, c.Float64("myflag"), float64(17))
}
func TestContext_GlobalFloat64(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Float64("myflag", float64(17), "doc")
c := NewContext(nil, set, nil)
expect(t, c.GlobalFloat64("myflag"), float64(17))
expect(t, c.GlobalFloat64("nope"), float64(0))
}
func TestContext_Duration(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Duration("myflag", time.Duration(12*time.Second), "doc")
@ -119,3 +146,57 @@ func TestContext_NumFlags(t *testing.T) {
globalSet.Parse([]string{"--myflagGlobal"})
expect(t, c.NumFlags(), 2)
}
func TestContext_GlobalFlag(t *testing.T) {
var globalFlag string
var globalFlagSet bool
app := NewApp()
app.Flags = []Flag{
StringFlag{Name: "global, g", Usage: "global"},
}
app.Action = func(c *Context) {
globalFlag = c.GlobalString("global")
globalFlagSet = c.GlobalIsSet("global")
}
app.Run([]string{"command", "-g", "foo"})
expect(t, globalFlag, "foo")
expect(t, globalFlagSet, true)
}
func TestContext_GlobalFlagsInSubcommands(t *testing.T) {
subcommandRun := false
parentFlag := false
app := NewApp()
app.Flags = []Flag{
BoolFlag{Name: "debug, d", Usage: "Enable debugging"},
}
app.Commands = []Command{
Command{
Name: "foo",
Flags: []Flag{
BoolFlag{Name: "parent, p", Usage: "Parent flag"},
},
Subcommands: []Command{
{
Name: "bar",
Action: func(c *Context) {
if c.GlobalBool("debug") {
subcommandRun = true
}
if c.GlobalBool("parent") {
parentFlag = true
}
},
},
},
},
}
app.Run([]string{"command", "-d", "foo", "-p", "bar"})
expect(t, subcommandRun, true)
expect(t, parentFlag, true)
}

View File

@ -1,14 +1,23 @@
package cli
import (
"os"
"reflect"
"runtime"
"strings"
"testing"
)
/* Test Helpers */
var (
wd, _ = os.Getwd()
)
func expect(t *testing.T, a interface{}, b interface{}) {
_, fn, line, _ := runtime.Caller(1)
fn = strings.Replace(fn, wd+"/", "", -1)
if !reflect.DeepEqual(a, b) {
t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
t.Errorf("(%s:%d) Expected %v (type %v) - Got %v (type %v)", fn, line, b, reflect.TypeOf(b), a, reflect.TypeOf(a))
}
}