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 ### Added
- Support for placeholders in flag usage strings - Support for placeholders in flag usage strings
### Fixed
- Added missing `*cli.Context.GlobalFloat64` method
## [2.0.0] ## [2.0.0]
### Added ### Added
- `NewStringSlice` and `NewIntSlice` for creating their related types - `NewStringSlice` and `NewIntSlice` for creating their related types

View File

@ -13,6 +13,10 @@ import (
"testing" "testing"
) )
type opCounts struct {
Total, BashComplete, OnUsageError, Before, CommandNotFound, Action, After, SubCommand int
}
func ExampleApp_Run() { func ExampleApp_Run() {
// set args for examples sake // set args for examples sake
os.Args = []string{"greet", "--name", "Jeremy"} os.Args = []string{"greet", "--name", "Jeremy"}
@ -439,14 +443,15 @@ func TestApp_SetStdout(t *testing.T) {
} }
func TestApp_BeforeFunc(t *testing.T) { func TestApp_BeforeFunc(t *testing.T) {
beforeRun, subcommandRun := false, false counts := &opCounts{}
beforeError := fmt.Errorf("fail") beforeError := fmt.Errorf("fail")
var err error var err error
app := NewApp() app := NewApp()
app.Before = func(c *Context) error { app.Before = func(c *Context) error {
beforeRun = true counts.Total++
counts.Before = counts.Total
s := c.String("opt") s := c.String("opt")
if s == "fail" { if s == "fail" {
return beforeError return beforeError
@ -459,7 +464,8 @@ func TestApp_BeforeFunc(t *testing.T) {
Command{ Command{
Name: "sub", Name: "sub",
Action: func(c *Context) { 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) t.Fatalf("Run error: %s", err)
} }
if beforeRun == false { if counts.Before != 1 {
t.Errorf("Before() not executed when expected") t.Errorf("Before() not executed when expected")
} }
if subcommandRun == false { if counts.SubCommand != 2 {
t.Errorf("Subcommand not executed when expected") t.Errorf("Subcommand not executed when expected")
} }
// reset // reset
beforeRun, subcommandRun = false, false counts = &opCounts{}
// run with the Before() func failing // run with the Before() func failing
err = app.Run([]string{"command", "--opt", "fail", "sub"}) 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") t.Errorf("Run error expected, but not received")
} }
if beforeRun == false { if counts.Before != 1 {
t.Errorf("Before() not executed when expected") t.Errorf("Before() not executed when expected")
} }
if subcommandRun == true { if counts.SubCommand != 0 {
t.Errorf("Subcommand executed when NOT expected") t.Errorf("Subcommand executed when NOT expected")
} }
} }
func TestApp_AfterFunc(t *testing.T) { func TestApp_AfterFunc(t *testing.T) {
afterRun, subcommandRun := false, false counts := &opCounts{}
afterError := fmt.Errorf("fail") afterError := fmt.Errorf("fail")
var err error var err error
app := NewApp() app := NewApp()
app.After = func(c *Context) error { app.After = func(c *Context) error {
afterRun = true counts.Total++
counts.After = counts.Total
s := c.String("opt") s := c.String("opt")
if s == "fail" { if s == "fail" {
return afterError return afterError
@ -525,7 +532,8 @@ func TestApp_AfterFunc(t *testing.T) {
Command{ Command{
Name: "sub", Name: "sub",
Action: func(c *Context) { 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) t.Fatalf("Run error: %s", err)
} }
if afterRun == false { if counts.After != 2 {
t.Errorf("After() not executed when expected") t.Errorf("After() not executed when expected")
} }
if subcommandRun == false { if counts.SubCommand != 1 {
t.Errorf("Subcommand not executed when expected") t.Errorf("Subcommand not executed when expected")
} }
// reset // reset
afterRun, subcommandRun = false, false counts = &opCounts{}
// run with the Before() func failing // run with the Before() func failing
err = app.Run([]string{"command", "--opt", "fail", "sub"}) 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") t.Errorf("Run error expected, but not received")
} }
if afterRun == false { if counts.After != 2 {
t.Errorf("After() not executed when expected") t.Errorf("After() not executed when expected")
} }
if subcommandRun == false { if counts.SubCommand != 1 {
t.Errorf("Subcommand not executed when expected") 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 oldPrinter := VersionPrinter
defer func() { defer func() {
VersionPrinter = oldPrinter VersionPrinter = oldPrinter
@ -625,81 +633,168 @@ func TestAppVersionPrinter(t *testing.T) {
} }
} }
func TestAppCommandNotFound(t *testing.T) { func TestApp_CommandNotFound(t *testing.T) {
beforeRun, subcommandRun := false, false counts := &opCounts{}
app := NewApp() app := NewApp()
app.CommandNotFound = func(c *Context, command string) { app.CommandNotFound = func(c *Context, command string) {
beforeRun = true counts.Total++
counts.CommandNotFound = counts.Total
} }
app.Commands = []Command{ app.Commands = []Command{
Command{ Command{
Name: "bar", Name: "bar",
Action: func(c *Context) { Action: func(c *Context) {
subcommandRun = true counts.Total++
counts.SubCommand = counts.Total
}, },
}, },
} }
app.Run([]string{"command", "foo"}) app.Run([]string{"command", "foo"})
expect(t, beforeRun, true) expect(t, counts.CommandNotFound, 1)
expect(t, subcommandRun, false) expect(t, counts.SubCommand, 0)
expect(t, counts.Total, 1)
} }
func TestGlobalFlag(t *testing.T) { func TestApp_OrderOfOperations(t *testing.T) {
var globalFlag string counts := &opCounts{}
var globalFlagSet bool
resetCounts := func() { counts = &opCounts{} }
app := NewApp() app := NewApp()
app.Flags = []Flag{ app.EnableBashCompletion = true
StringFlag{Name: "global, g", Usage: "global"}, app.BashComplete = func(c *Context) {
counts.Total++
counts.BashComplete = counts.Total
} }
app.Action = func(c *Context) { app.OnUsageError = func(c *Context, err error, isSubcommand bool) error {
globalFlag = c.GlobalString("global") counts.Total++
globalFlagSet = c.GlobalIsSet("global") counts.OnUsageError = counts.Total
} return errors.New("hay OnUsageError")
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"},
} }
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{ app.Commands = []Command{
Command{ Command{
Name: "foo", Name: "bar",
Flags: []Flag{ Action: func(c *Context) {
BoolFlag{Name: "parent, p", Usage: "Parent flag"}, counts.Total++
}, counts.SubCommand = counts.Total
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"}) app.Action = func(c *Context) {
counts.Total++
counts.Action = counts.Total
}
expect(t, subcommandRun, true) _ = app.Run([]string{"command", "--nope"})
expect(t, parentFlag, true) 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) { func TestApp_Run_CommandWithSubcommandHasHelpTopic(t *testing.T) {

View File

@ -79,6 +79,15 @@ func (c *Context) GlobalInt(name string) int {
return 0 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 // 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 { func (c *Context) GlobalDuration(name string) time.Duration {
if fs := lookupGlobalFlagSet(name, c); fs != nil { if fs := lookupGlobalFlagSet(name, c); fs != nil {

View File

@ -9,14 +9,18 @@ import (
func TestNewContext(t *testing.T) { func TestNewContext(t *testing.T) {
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
set.Int("myflag", 12, "doc") set.Int("myflag", 12, "doc")
set.Float64("myflag64", float64(17), "doc")
globalSet := flag.NewFlagSet("test", 0) globalSet := flag.NewFlagSet("test", 0)
globalSet.Int("myflag", 42, "doc") globalSet.Int("myflag", 42, "doc")
globalSet.Float64("myflag64", float64(47), "doc")
globalCtx := NewContext(nil, globalSet, nil) globalCtx := NewContext(nil, globalSet, nil)
command := Command{Name: "mycommand"} command := Command{Name: "mycommand"}
c := NewContext(nil, set, globalCtx) c := NewContext(nil, set, globalCtx)
c.Command = command c.Command = command
expect(t, c.Int("myflag"), 12) expect(t, c.Int("myflag"), 12)
expect(t, c.Float64("myflag64"), float64(17))
expect(t, c.GlobalInt("myflag"), 42) expect(t, c.GlobalInt("myflag"), 42)
expect(t, c.GlobalFloat64("myflag64"), float64(47))
expect(t, c.Command.Name, "mycommand") expect(t, c.Command.Name, "mycommand")
} }
@ -27,6 +31,29 @@ func TestContext_Int(t *testing.T) {
expect(t, c.Int("myflag"), 12) 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) { func TestContext_Duration(t *testing.T) {
set := flag.NewFlagSet("test", 0) set := flag.NewFlagSet("test", 0)
set.Duration("myflag", time.Duration(12*time.Second), "doc") set.Duration("myflag", time.Duration(12*time.Second), "doc")
@ -119,3 +146,57 @@ func TestContext_NumFlags(t *testing.T) {
globalSet.Parse([]string{"--myflagGlobal"}) globalSet.Parse([]string{"--myflagGlobal"})
expect(t, c.NumFlags(), 2) 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 package cli
import ( import (
"os"
"reflect" "reflect"
"runtime"
"strings"
"testing" "testing"
) )
/* Test Helpers */ var (
wd, _ = os.Getwd()
)
func expect(t *testing.T, a interface{}, b interface{}) { 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) { 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))
} }
} }