func TestGlobalFlagsInSubcommands(t *testing.T) { subcommandRun := false app := cli.NewApp() app.Flags = []cli.Flag{ cli.BoolFlag{Name: "debug, d", Usage: "Enable debugging"}, } app.Commands = []cli.Command{ cli.Command{ Name: "foo", Subcommands: []cli.Command{ { Name: "bar", Action: func(c *cli.Context) { if c.GlobalBool("debug") { subcommandRun = true } }, }, }, }, } app.Run([]string{"command", "-d", "foo", "bar"}) expect(t, subcommandRun, true) }
func TestApp_DefaultStdout(t *testing.T) { app := cli.NewApp() if app.Writer != os.Stdout { t.Error("Default output writer not set.") } }
func ExampleAppBashComplete() { // set args for examples sake os.Args = []string{"greet", "--generate-bash-completion"} app := cli.NewApp() app.Name = "greet" app.EnableBashCompletion = true app.Commands = []cli.Command{ { Name: "describeit", Aliases: []string{"d"}, Usage: "use it to see a description", Description: "This is how we describe describeit the function", Action: func(c *cli.Context) { fmt.Printf("i like to describe things") }, }, { Name: "next", Usage: "next example", Description: "more stuff to see when generating bash completion", Action: func(c *cli.Context) { fmt.Printf("the next example") }, }, } app.Run(os.Args) // Output: // describeit // d // next // help // h }
func ExampleAppHelp() { // set args for examples sake os.Args = []string{"greet", "h", "describeit"} app := cli.NewApp() app.Name = "greet" app.Flags = []cli.Flag{ cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"}, } app.Commands = []cli.Command{ { Name: "describeit", Aliases: []string{"d"}, Usage: "use it to see a description", Description: "This is how we describe describeit the function", Action: func(c *cli.Context) { fmt.Printf("i like to describe things") }, }, } app.Run(os.Args) // Output: // NAME: // describeit - use it to see a description // // USAGE: // command describeit [arguments...] // // DESCRIPTION: // This is how we describe describeit the function }
func TestApp_RunAsSubcommandParseFlags(t *testing.T) { var context *cli.Context a := cli.NewApp() a.Commands = []cli.Command{ { Name: "foo", Action: func(c *cli.Context) { context = c }, Flags: []cli.Flag{ cli.StringFlag{ Name: "lang", Value: "english", Usage: "language for the greeting", }, }, Before: func(_ *cli.Context) error { return nil }, }, } a.Run([]string{"", "foo", "--lang", "spanish", "abcd"}) expect(t, context.Args().Get(0), "abcd") expect(t, context.String("lang"), "spanish") }
func TestApp_ParseSliceFlags(t *testing.T) { var parsedOption, firstArg string var parsedIntSlice []int var parsedStringSlice []string app := cli.NewApp() command := cli.Command{ Name: "cmd", Flags: []cli.Flag{ cli.IntSliceFlag{Name: "p", Value: &cli.IntSlice{}, Usage: "set one or more ip addr"}, cli.StringSliceFlag{Name: "ip", Value: &cli.StringSlice{}, Usage: "set one or more ports to open"}, }, Action: func(c *cli.Context) { parsedIntSlice = c.IntSlice("p") parsedStringSlice = c.StringSlice("ip") parsedOption = c.String("option") firstArg = c.Args().First() }, } app.Commands = []cli.Command{command} app.Run([]string{"", "cmd", "my-arg", "-p", "22", "-p", "80", "-ip", "8.8.8.8", "-ip", "8.8.4.4"}) IntsEquals := func(a, b []int) bool { if len(a) != len(b) { return false } for i, v := range a { if v != b[i] { return false } } return true } StrsEquals := func(a, b []string) bool { if len(a) != len(b) { return false } for i, v := range a { if v != b[i] { return false } } return true } var expectedIntSlice = []int{22, 80} var expectedStringSlice = []string{"8.8.8.8", "8.8.4.4"} if !IntsEquals(parsedIntSlice, expectedIntSlice) { t.Errorf("%v does not match %v", parsedIntSlice, expectedIntSlice) } if !StrsEquals(parsedStringSlice, expectedStringSlice) { t.Errorf("%v does not match %v", parsedStringSlice, expectedStringSlice) } }
func TestApp_Run_CommandWithSubcommandHasHelpTopic(t *testing.T) { var subcommandHelpTopics = [][]string{ {"command", "foo", "--help"}, {"command", "foo", "-h"}, {"command", "foo", "help"}, } for _, flagSet := range subcommandHelpTopics { t.Logf("==> checking with flags %v", flagSet) app := cli.NewApp() buf := new(bytes.Buffer) app.Writer = buf subCmdBar := cli.Command{ Name: "bar", Usage: "does bar things", } subCmdBaz := cli.Command{ Name: "baz", Usage: "does baz things", } cmd := cli.Command{ Name: "foo", Description: "descriptive wall of text about how it does foo things", Subcommands: []cli.Command{subCmdBar, subCmdBaz}, } app.Commands = []cli.Command{cmd} err := app.Run(flagSet) if err != nil { t.Error(err) } output := buf.String() t.Logf("output: %q\n", buf.Bytes()) if strings.Contains(output, "No help topic for") { t.Errorf("expect a help topic, got none: \n%q", output) } for _, shouldContain := range []string{ cmd.Name, cmd.Description, subCmdBar.Name, subCmdBar.Usage, subCmdBaz.Name, subCmdBaz.Usage, } { if !strings.Contains(output, shouldContain) { t.Errorf("want help to contain %q, did not: \n%q", shouldContain, output) } } } }
func TestApp_Command(t *testing.T) { app := cli.NewApp() fooCommand := cli.Command{Name: "foobar", Aliases: []string{"f"}} batCommand := cli.Command{Name: "batbaz", Aliases: []string{"b"}} app.Commands = []cli.Command{ fooCommand, batCommand, } for _, test := range commandAppTests { expect(t, app.Command(test.name) != nil, test.expected) } }
func Test_ShowAppHelp_NoAuthor(t *testing.T) { output := new(bytes.Buffer) app := cli.NewApp() app.Writer = output c := cli.NewContext(app, nil, nil) cli.ShowAppHelp(c) if bytes.Index(output.Bytes(), []byte("AUTHOR(S):")) != -1 { t.Errorf("expected\n%snot to include %s", output.String(), "AUTHOR(S):") } }
func TestApp_Run(t *testing.T) { s := "" app := cli.NewApp() app.Action = func(c *cli.Context) { s = s + c.Args().First() } err := app.Run([]string{"command", "foo"}) expect(t, err, nil) err = app.Run([]string{"command", "bar"}) expect(t, err, nil) expect(t, s, "foobar") }
func TestApp_Float64Flag(t *testing.T) { var meters float64 app := cli.NewApp() app.Flags = []cli.Flag{ cli.Float64Flag{Name: "height", Value: 1.5, Usage: "Set the height, in meters"}, } app.Action = func(c *cli.Context) { meters = c.Float64("height") } app.Run([]string{"", "--height", "1.93"}) expect(t, meters, 1.93) }
func TestAppNoHelpFlag(t *testing.T) { oldFlag := cli.HelpFlag defer func() { cli.HelpFlag = oldFlag }() cli.HelpFlag = cli.BoolFlag{} app := cli.NewApp() err := app.Run([]string{"test", "-h"}) if err != flag.ErrHelp { t.Errorf("expected error about missing help flag, but got: %s (%T)", err, err) } }
func TestApp_SetStdout(t *testing.T) { w := &mockWriter{} app := cli.NewApp() app.Name = "test" app.Writer = w err := app.Run([]string{"help"}) if err != nil { t.Fatalf("Run error: %s", err) } if len(w.written) == 0 { t.Error("App did not write output to desired writer.") } }
func TestAppHelpPrinter(t *testing.T) { oldPrinter := cli.HelpPrinter defer func() { cli.HelpPrinter = oldPrinter }() var wasCalled = false cli.HelpPrinter = func(w io.Writer, template string, data interface{}) { wasCalled = true } app := cli.NewApp() app.Run([]string{"-h"}) if wasCalled == false { t.Errorf("Help printer expected to be called, but was not") } }
func TestApp_CommandWithNoFlagBeforeTerminator(t *testing.T) { var args []string app := cli.NewApp() command := cli.Command{ Name: "cmd", Action: func(c *cli.Context) { args = c.Args() }, } app.Commands = []cli.Command{command} app.Run([]string{"", "cmd", "my-arg", "--", "notAFlagAtAll"}) expect(t, args[0], "my-arg") expect(t, args[1], "--") expect(t, args[2], "notAFlagAtAll") }
func TestAppVersionPrinter(t *testing.T) { oldPrinter := cli.VersionPrinter defer func() { cli.VersionPrinter = oldPrinter }() var wasCalled = false cli.VersionPrinter = func(c *cli.Context) { wasCalled = true } app := cli.NewApp() ctx := cli.NewContext(app, nil, nil) cli.ShowVersion(ctx) if wasCalled == false { t.Errorf("Version printer expected to be called, but was not") } }
func ExampleApp() { // set args for examples sake os.Args = []string{"greet", "--name", "Jeremy"} app := cli.NewApp() app.Name = "greet" app.Flags = []cli.Flag{ cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"}, } app.Action = func(c *cli.Context) { fmt.Printf("Hello %v\n", c.String("name")) } app.Author = "Harrison" app.Email = "*****@*****.**" app.Authors = []cli.Author{cli.Author{Name: "Oliver Allen", Email: "*****@*****.**"}} app.Run(os.Args) // Output: // Hello Jeremy }
func TestCommandDoNotIgnoreFlags(t *testing.T) { app := cli.NewApp() set := flag.NewFlagSet("test", 0) test := []string{"blah", "blah", "-break"} set.Parse(test) c := cli.NewContext(app, set, set) command := cli.Command{ Name: "test-cmd", Aliases: []string{"tc"}, Usage: "this is for testing", Description: "testing", Action: func(_ *cli.Context) {}, } err := command.Run(c) expect(t, err.Error(), "flag provided but not defined: -break") }
func TestCommandIgnoreFlags(t *testing.T) { app := cli.NewApp() set := flag.NewFlagSet("test", 0) test := []string{"blah", "blah"} set.Parse(test) c := cli.NewContext(app, set, set) command := cli.Command{ Name: "test-cmd", Aliases: []string{"tc"}, Usage: "this is for testing", Description: "testing", Action: func(_ *cli.Context) {}, SkipFlagParsing: true, } err := command.Run(c) expect(t, err, nil) }
func TestApp_CommandWithArgBeforeFlags(t *testing.T) { var parsedOption, firstArg string app := cli.NewApp() command := cli.Command{ Name: "cmd", Flags: []cli.Flag{ cli.StringFlag{Name: "option", Value: "", Usage: "some option"}, }, Action: func(c *cli.Context) { parsedOption = c.String("option") firstArg = c.Args().First() }, } app.Commands = []cli.Command{command} app.Run([]string{"", "cmd", "my-arg", "--option", "my-option"}) expect(t, parsedOption, "my-option") expect(t, firstArg, "my-arg") }
func TestAppCommandNotFound(t *testing.T) { beforeRun, subcommandRun := false, false app := cli.NewApp() app.CommandNotFound = func(c *cli.Context, command string) { beforeRun = true } app.Commands = []cli.Command{ cli.Command{ Name: "bar", Action: func(c *cli.Context) { subcommandRun = true }, }, } app.Run([]string{"command", "foo"}) expect(t, beforeRun, true) expect(t, subcommandRun, false) }
func TestApp_CommandWithFlagBeforeTerminator(t *testing.T) { var parsedOption string var args []string app := cli.NewApp() command := cli.Command{ Name: "cmd", Flags: []cli.Flag{ cli.StringFlag{Name: "option", Value: "", Usage: "some option"}, }, Action: func(c *cli.Context) { parsedOption = c.String("option") args = c.Args() }, } app.Commands = []cli.Command{command} app.Run([]string{"", "cmd", "my-arg", "--option", "my-option", "--", "--notARealFlag"}) expect(t, parsedOption, "my-option") expect(t, args[0], "my-arg") expect(t, args[1], "--") expect(t, args[2], "--notARealFlag") }
func ExampleAppSubcommand() { // set args for examples sake os.Args = []string{"say", "hi", "english", "--name", "Jeremy"} app := cli.NewApp() app.Name = "say" app.Commands = []cli.Command{ { Name: "hello", Aliases: []string{"hi"}, Usage: "use it to see a description", Description: "This is how we describe hello the function", Subcommands: []cli.Command{ { Name: "english", Aliases: []string{"en"}, Usage: "sends a greeting in english", Description: "greets someone in english", Flags: []cli.Flag{ cli.StringFlag{ Name: "name", Value: "Bob", Usage: "Name of the person to greet", }, }, Action: func(c *cli.Context) { fmt.Println("Hello,", c.String("name")) }, }, }, }, } app.Run(os.Args) // Output: // Hello, Jeremy }
func main() { // these are defined in here so we can update the // defaults with env variables first var ( //---------------------------------------------------------------- // flags with env var defaults nodeAddrFlag = cli.StringFlag{ Name: "node-addr", Usage: "set the address of the tendermint rpc server", Value: DefaultNodeRPCAddr, } chainidFlag = cli.StringFlag{ Name: "chainID", Usage: "specify the chainID", Value: DefaultChainID, } //---------------------------------------------------------------- statusCmd = cli.Command{ Name: "status", Usage: "Get a node's status", Action: cliStatus, } netInfoCmd = cli.Command{ Name: "net-info", Usage: "Get a node's network info", Action: cliNetInfo, } genesisCmd = cli.Command{ Name: "genesis", Usage: "Get a node's genesis.json", Action: cliGenesis, } validatorsCmd = cli.Command{ Name: "validators", Usage: "List the chain's validator set", Action: cliValidators, } consensusCmd = cli.Command{ Name: "consensus", Usage: "Dump a node's consensus state", Action: cliConsensus, } unconfirmedCmd = cli.Command{ Name: "unconfirmed", Usage: "List the txs in a node's mempool", Action: cliUnconfirmed, } accountsCmd = cli.Command{ Name: "accounts", Usage: "List all accounts on the chain, or specify an address", Action: cliAccounts, } namesCmd = cli.Command{ Name: "names", Usage: "List all name reg entries on the chain", Action: cliNames, } blocksCmd = cli.Command{ Name: "blocks", Usage: "Get a sequence of blocks between two heights, or get a single block by height", Action: cliBlocks, } storageCmd = cli.Command{ Name: "storage", Usage: "Get the storage for an account, or for a particular key in that account's storage", Action: cliStorage, } callCmd = cli.Command{ Name: "call", Usage: "Call an address with some data", Action: cliCall, } callCodeCmd = cli.Command{ Name: "call-code", Usage: "Run some code on some data", Action: cliCallCode, } broadcastCmd = cli.Command{ Name: "broadcast", Usage: "Broadcast some tx bytes", Action: cliBroadcast, } ) app := cli.NewApp() app.Name = "mintinfo" app.Usage = "Fetch data from a tendermint node via rpc" app.Version = "0.0.1" app.Author = "Ethan Buchman" app.Email = "*****@*****.**" app.Commands = []cli.Command{ statusCmd, netInfoCmd, genesisCmd, validatorsCmd, consensusCmd, unconfirmedCmd, accountsCmd, namesCmd, blocksCmd, storageCmd, callCmd, callCodeCmd, broadcastCmd, } app.Flags = []cli.Flag{ nodeAddrFlag, chainidFlag, } app.Before = before app.Run(os.Args) }
func main() { // these are defined in here so we can update the // defaults with env variables first var ( //---------------------------------------------------------------- // flags with env var defaults signAddrFlag = cli.StringFlag{ Name: "sign-addr", Usage: "set the address of the eris-keys daemon", Value: DefaultKeyDaemonAddr, } nodeAddrFlag = cli.StringFlag{ Name: "node-addr", Usage: "set the address of the tendermint rpc server", Value: DefaultNodeRPCAddr, } pubkeyFlag = cli.StringFlag{ Name: "pubkey", Usage: "specify the pubkey", Value: DefaultPubKey, } chainidFlag = cli.StringFlag{ Name: "chainID", Usage: "specify the chainID", Value: DefaultChainID, } //---------------------------------------------------------------- // optional action flags signFlag = cli.BoolFlag{ Name: "sign", Usage: "sign the transaction using the daemon at MINTX_SIGN_ADDR", } broadcastFlag = cli.BoolFlag{ Name: "broadcast", Usage: "broadcast the transaction using the daemon at MINTX_NODE_ADDR", } waitFlag = cli.BoolFlag{ Name: "wait", Usage: "wait for the transaction to be committed in a block", } //---------------------------------------------------------------- // tx data flags amtFlag = cli.StringFlag{ Name: "amt", Usage: "specify an amount", } nonceFlag = cli.StringFlag{ Name: "nonce", Usage: "set the account nonce", } addrFlag = cli.StringFlag{ Name: "addr", Usage: "specify an address", } nameFlag = cli.StringFlag{ Name: "name", Usage: "specify a name", } dataFlag = cli.StringFlag{ Name: "data", Usage: "specify some data", } dataFileFlag = cli.StringFlag{ Name: "data-file", Usage: "specify a file with some data", } toFlag = cli.StringFlag{ Name: "to", Usage: "specify an address to send to", } feeFlag = cli.StringFlag{ Name: "fee", Usage: "specify the fee to send", } gasFlag = cli.StringFlag{ Name: "gas", Usage: "specify the gas limit for a CallTx", } unbondtoFlag = cli.StringFlag{ Name: "unbond-to", Usage: "specify an address to unbond to", } heightFlag = cli.StringFlag{ Name: "height", Usage: "specify a height to unbond at", } //Formatting Flags debugFlag = cli.BoolFlag{ Name: "debug", Usage: "print debug messages", } //------------------------------------------------------------ // main tx commands sendCmd = cli.Command{ Name: "send", Usage: "mintx send --amt <amt> --to <addr>", Action: cliSend, Flags: []cli.Flag{ signAddrFlag, nodeAddrFlag, chainidFlag, pubkeyFlag, addrFlag, signFlag, broadcastFlag, waitFlag, amtFlag, toFlag, nonceFlag, }, } nameCmd = cli.Command{ Name: "name", Usage: "mintx name --amt <amt> --name <name> --data <data>", Action: cliName, Flags: []cli.Flag{ signAddrFlag, nodeAddrFlag, chainidFlag, pubkeyFlag, addrFlag, signFlag, broadcastFlag, waitFlag, amtFlag, nameFlag, dataFlag, dataFileFlag, feeFlag, nonceFlag, }, } callCmd = cli.Command{ Name: "call", Usage: "mintx call --amt <amt> --fee <fee> --gas <gas> --to <contract addr> --data <data>", Action: cliCall, Flags: []cli.Flag{ signAddrFlag, nodeAddrFlag, chainidFlag, pubkeyFlag, addrFlag, signFlag, broadcastFlag, waitFlag, amtFlag, toFlag, dataFlag, feeFlag, gasFlag, nonceFlag, }, } bondCmd = cli.Command{ Name: "bond", Usage: "mintx bond --pubkey <pubkey> --amt <amt> --unbond-to <address>", Action: cliBond, Flags: []cli.Flag{ signAddrFlag, nodeAddrFlag, chainidFlag, pubkeyFlag, addrFlag, signFlag, broadcastFlag, waitFlag, amtFlag, unbondtoFlag, nonceFlag, }, } unbondCmd = cli.Command{ Name: "unbond", Usage: "mintx unbond --addr <address> --height <block_height>", Action: cliUnbond, Flags: []cli.Flag{ signAddrFlag, nodeAddrFlag, chainidFlag, signFlag, broadcastFlag, waitFlag, addrFlag, heightFlag, }, } rebondCmd = cli.Command{ Name: "rebond", Usage: "mintx rebond --addr <address> --height <block_height>", Action: cliRebond, Flags: []cli.Flag{ signAddrFlag, nodeAddrFlag, chainidFlag, signFlag, broadcastFlag, waitFlag, addrFlag, heightFlag, }, } permissionsCmd = cli.Command{ Name: "perm", Usage: "mintx perm <function name> <args ...>", Action: cliPermissions, Flags: []cli.Flag{ signAddrFlag, nodeAddrFlag, chainidFlag, pubkeyFlag, addrFlag, signFlag, broadcastFlag, waitFlag, nonceFlag, }, } newAccountCmd = cli.Command{ Name: "new", Usage: "mintx new", Action: cliNewAccount, Flags: []cli.Flag{ signAddrFlag, nodeAddrFlag, chainidFlag, pubkeyFlag, signFlag, broadcastFlag, waitFlag, }, } /* inputCmd = cli.Command{ Name: "input", Usage: "mintx input --pubkey <pubkey> --amt <amt> --nonce <nonce>", Action: cliInput, Flags: []cli.Flag{ pubkeyFlag, amtFlag, nonceFlag, addrFlag, }, } outputCmd = cli.Command{ Name: "output", Usage: "mintx output --addr <addr> --amt <amt>", Action: cliOutput, Flags: []cli.Flag{ addrFlag, amtFlag, }, }*/ ) app := cli.NewApp() app.Name = "mintx" app.Usage = "Create and broadcast tendermint txs" app.Version = "0.1.0" // add --wait to everything, return block hash app.Author = "Ethan Buchman" app.Email = "*****@*****.**" app.Before = before app.After = after app.Flags = []cli.Flag{ debugFlag, } app.Commands = []cli.Command{ // inputCmd, // outputCmd, sendCmd, nameCmd, callCmd, bondCmd, unbondCmd, rebondCmd, // dupeoutCmd, permissionsCmd, newAccountCmd, } app.Run(os.Args) }
func TestApp_AfterFunc(t *testing.T) { afterRun, subcommandRun := false, false afterError := fmt.Errorf("fail") var err error app := cli.NewApp() app.After = func(c *cli.Context) error { afterRun = true s := c.String("opt") if s == "fail" { return afterError } return nil } app.Commands = []cli.Command{ cli.Command{ Name: "sub", Action: func(c *cli.Context) { subcommandRun = true }, }, } app.Flags = []cli.Flag{ cli.StringFlag{Name: "opt"}, } // run with the After() func succeeding err = app.Run([]string{"command", "--opt", "succeed", "sub"}) if err != nil { t.Fatalf("Run error: %s", err) } if afterRun == false { t.Errorf("After() not executed when expected") } if subcommandRun == false { t.Errorf("Subcommand not executed when expected") } // reset afterRun, subcommandRun = false, false // run with the Before() func failing err = app.Run([]string{"command", "--opt", "fail", "sub"}) // should be the same error produced by the Before func if err != afterError { t.Errorf("Run error expected, but not received") } if afterRun == false { t.Errorf("After() not executed when expected") } if subcommandRun == false { t.Errorf("Subcommand not executed when expected") } }