Merge pull request #364 from codegangsta/assert-before-command-after-ordering

Revising/adding tests that assert order of operations inside App.Run
This commit is contained in:
Dan Buch 2016-04-28 16:12:29 -04:00
commit 222ec6fb7e
3 changed files with 224 additions and 66 deletions

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
}
},
},
Name: "bar",
Action: func(c *Context) {
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

@ -146,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))
}
}