2013-09-25 01:04:00 +04:00
|
|
|
package cobra
|
2013-09-04 02:54:51 +04:00
|
|
|
|
|
|
|
import (
|
2013-09-24 20:12:32 +04:00
|
|
|
"bytes"
|
2013-09-04 19:27:10 +04:00
|
|
|
"fmt"
|
2015-04-06 20:43:44 +03:00
|
|
|
"os"
|
2015-05-13 04:38:01 +03:00
|
|
|
"reflect"
|
2015-04-07 22:50:08 +03:00
|
|
|
"runtime"
|
2013-09-04 02:54:51 +04:00
|
|
|
"strings"
|
|
|
|
"testing"
|
2015-09-01 06:36:55 +03:00
|
|
|
"text/template"
|
2015-05-14 20:38:15 +03:00
|
|
|
|
|
|
|
"github.com/spf13/pflag"
|
2013-09-04 02:54:51 +04:00
|
|
|
)
|
|
|
|
|
2013-09-04 19:27:10 +04:00
|
|
|
var _ = fmt.Println
|
2015-04-06 20:43:44 +03:00
|
|
|
var _ = os.Stderr
|
2013-09-04 19:27:10 +04:00
|
|
|
|
2015-05-13 04:38:01 +03:00
|
|
|
var tp, te, tt, t1, tr []string
|
2015-04-30 20:58:29 +03:00
|
|
|
var rootPersPre, echoPre, echoPersPre, timesPersPre []string
|
2015-03-19 00:42:38 +03:00
|
|
|
var flagb1, flagb2, flagb3, flagbr, flagbp bool
|
2015-09-04 23:34:51 +03:00
|
|
|
var flags1, flags2a, flags2b, flags3, outs string
|
2013-10-01 05:54:46 +04:00
|
|
|
var flagi1, flagi2, flagi3, flagir int
|
2013-09-04 02:54:51 +04:00
|
|
|
var globalFlag1 bool
|
2013-10-01 05:54:46 +04:00
|
|
|
var flagEcho, rootcalled bool
|
2015-03-13 10:30:33 +03:00
|
|
|
var versionUsed int
|
2013-09-04 02:54:51 +04:00
|
|
|
|
2015-02-28 03:26:56 +03:00
|
|
|
const strtwoParentHelp = "help message for parent flag strtwo"
|
|
|
|
const strtwoChildHelp = "help message for child flag strtwo"
|
|
|
|
|
2015-09-04 23:34:51 +03:00
|
|
|
var cmdHidden = &Command{
|
|
|
|
Use: "hide [secret string to print]",
|
|
|
|
Short: "Print anything to screen (if command is known)",
|
|
|
|
Long: `an absolutely utterly useless command for testing.`,
|
|
|
|
Run: func(cmd *Command, args []string) {
|
|
|
|
outs = "hidden"
|
|
|
|
},
|
|
|
|
Hidden: true,
|
|
|
|
}
|
|
|
|
|
2013-09-04 02:54:51 +04:00
|
|
|
var cmdPrint = &Command{
|
|
|
|
Use: "print [string to print]",
|
|
|
|
Short: "Print anything to the screen",
|
2015-04-06 20:43:44 +03:00
|
|
|
Long: `an absolutely utterly useless command for testing.`,
|
2013-09-04 02:54:51 +04:00
|
|
|
Run: func(cmd *Command, args []string) {
|
|
|
|
tp = args
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var cmdEcho = &Command{
|
2014-09-26 03:03:34 +04:00
|
|
|
Use: "echo [string to echo]",
|
|
|
|
Aliases: []string{"say"},
|
|
|
|
Short: "Echo anything to the screen",
|
|
|
|
Long: `an utterly useless command for testing.`,
|
Auto generation of markdown docs!
An example from the kubernetes project, for the `kubectl config`
command, which as subcommands, and flags, and all sorts of stuff, it
will generate markdown like so:
config modifies .kubeconfig files
config modifies .kubeconfig files using subcommands like "kubectl config set current-context my-context"
```
kubectl config SUBCOMMAND
```
```
--envvar=false: use the .kubeconfig from $KUBECONFIG
--global=false: use the .kubeconfig from /home/username
-h, --help=false: help for config
--kubeconfig="": use a particular .kubeconfig file
--local=false: use the .kubeconfig in the current directory
```
```
--alsologtostderr=false: log to standard error as well as files
--api-version="": The API version to use when talking to the server
-a, --auth-path="": Path to the auth info file. If missing, prompt the user. Only used if using https.
--certificate-authority="": Path to a cert. file for the certificate authority.
--client-certificate="": Path to a client key file for TLS.
--client-key="": Path to a client key file for TLS.
--cluster="": The name of the kubeconfig cluster to use
--context="": The name of the kubeconfig context to use
--insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
--log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
--log_dir=: If non-empty, write log files in this directory
--log_flush_frequency=5s: Maximum number of seconds between log flushes
--logtostderr=true: log to standard error instead of files
--match-server-version=false: Require server version to match client version
--namespace="": If present, the namespace scope for this CLI request.
--password="": Password for basic authentication to the API server.
-s, --server="": The address and port of the Kubernetes API server
--stderrthreshold=2: logs at or above this threshold go to stderr
--token="": Bearer token for authentication to the API server.
--user="": The name of the kubeconfig user to use
--username="": Username for basic authentication to the API server.
--v=0: log level for V logs
--validate=false: If true, use a schema to validate the input before sending it
--vmodule=: comma-separated list of pattern=N settings for file-filtered logging
```
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
* [kubectl config set](kubectl_config_set.md) - Sets an individual value in a .kubeconfig file
* [kubectl config set-cluster](kubectl_config_set-cluster.md) - Sets a cluster entry in .kubeconfig
* [kubectl config set-context](kubectl_config_set-context.md) - Sets a context entry in .kubeconfig
* [kubectl config set-credentials](kubectl_config_set-credentials.md) - Sets a user entry in .kubeconfig
* [kubectl config unset](kubectl_config_unset.md) - Unsets an individual value in a .kubeconfig file
* [kubectl config use-context](kubectl_config_use-context.md) - Sets the current-context in a .kubeconfig file
* [kubectl config view](kubectl_config_view.md) - displays merged .kubeconfig settings or a specified .kubeconfig file.
2015-04-07 06:38:51 +03:00
|
|
|
Example: "Just run cobra-test echo",
|
2015-04-30 20:58:29 +03:00
|
|
|
PersistentPreRun: func(cmd *Command, args []string) {
|
|
|
|
echoPersPre = args
|
|
|
|
},
|
|
|
|
PreRun: func(cmd *Command, args []string) {
|
|
|
|
echoPre = args
|
|
|
|
},
|
2013-09-04 02:54:51 +04:00
|
|
|
Run: func(cmd *Command, args []string) {
|
|
|
|
te = args
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
Auto generation of markdown docs!
An example from the kubernetes project, for the `kubectl config`
command, which as subcommands, and flags, and all sorts of stuff, it
will generate markdown like so:
config modifies .kubeconfig files
config modifies .kubeconfig files using subcommands like "kubectl config set current-context my-context"
```
kubectl config SUBCOMMAND
```
```
--envvar=false: use the .kubeconfig from $KUBECONFIG
--global=false: use the .kubeconfig from /home/username
-h, --help=false: help for config
--kubeconfig="": use a particular .kubeconfig file
--local=false: use the .kubeconfig in the current directory
```
```
--alsologtostderr=false: log to standard error as well as files
--api-version="": The API version to use when talking to the server
-a, --auth-path="": Path to the auth info file. If missing, prompt the user. Only used if using https.
--certificate-authority="": Path to a cert. file for the certificate authority.
--client-certificate="": Path to a client key file for TLS.
--client-key="": Path to a client key file for TLS.
--cluster="": The name of the kubeconfig cluster to use
--context="": The name of the kubeconfig context to use
--insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
--log_backtrace_at=:0: when logging hits line file:N, emit a stack trace
--log_dir=: If non-empty, write log files in this directory
--log_flush_frequency=5s: Maximum number of seconds between log flushes
--logtostderr=true: log to standard error instead of files
--match-server-version=false: Require server version to match client version
--namespace="": If present, the namespace scope for this CLI request.
--password="": Password for basic authentication to the API server.
-s, --server="": The address and port of the Kubernetes API server
--stderrthreshold=2: logs at or above this threshold go to stderr
--token="": Bearer token for authentication to the API server.
--user="": The name of the kubeconfig user to use
--username="": Username for basic authentication to the API server.
--v=0: log level for V logs
--validate=false: If true, use a schema to validate the input before sending it
--vmodule=: comma-separated list of pattern=N settings for file-filtered logging
```
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
* [kubectl config set](kubectl_config_set.md) - Sets an individual value in a .kubeconfig file
* [kubectl config set-cluster](kubectl_config_set-cluster.md) - Sets a cluster entry in .kubeconfig
* [kubectl config set-context](kubectl_config_set-context.md) - Sets a context entry in .kubeconfig
* [kubectl config set-credentials](kubectl_config_set-credentials.md) - Sets a user entry in .kubeconfig
* [kubectl config unset](kubectl_config_unset.md) - Unsets an individual value in a .kubeconfig file
* [kubectl config use-context](kubectl_config_use-context.md) - Sets the current-context in a .kubeconfig file
* [kubectl config view](kubectl_config_view.md) - displays merged .kubeconfig settings or a specified .kubeconfig file.
2015-04-07 06:38:51 +03:00
|
|
|
var cmdEchoSub = &Command{
|
|
|
|
Use: "echosub [string to print]",
|
|
|
|
Short: "second sub command for echo",
|
|
|
|
Long: `an absolutely utterly useless command for testing gendocs!.`,
|
|
|
|
Run: func(cmd *Command, args []string) {
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2015-04-08 00:38:22 +03:00
|
|
|
var cmdDeprecated = &Command{
|
|
|
|
Use: "deprecated [can't do anything here]",
|
|
|
|
Short: "A command which is deprecated",
|
|
|
|
Long: `an absolutely utterly useless command for testing deprecation!.`,
|
|
|
|
Deprecated: "Please use echo instead",
|
|
|
|
Run: func(cmd *Command, args []string) {
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2013-09-04 02:54:51 +04:00
|
|
|
var cmdTimes = &Command{
|
2015-09-25 18:04:28 +03:00
|
|
|
Use: "times [# times] [string to echo]",
|
|
|
|
SuggestFor: []string{"counts"},
|
|
|
|
Short: "Echo anything to the screen more times",
|
|
|
|
Long: `a slightly useless command for testing.`,
|
2015-04-30 20:58:29 +03:00
|
|
|
PersistentPreRun: func(cmd *Command, args []string) {
|
|
|
|
timesPersPre = args
|
|
|
|
},
|
2014-09-26 03:03:34 +04:00
|
|
|
Run: func(cmd *Command, args []string) {
|
|
|
|
tt = args
|
|
|
|
},
|
2013-09-04 03:04:50 +04:00
|
|
|
}
|
|
|
|
|
2013-11-02 02:36:24 +04:00
|
|
|
var cmdRootNoRun = &Command{
|
|
|
|
Use: "cobra-test",
|
|
|
|
Short: "The root can run it's own function",
|
|
|
|
Long: "The root description for help",
|
2015-04-30 20:58:29 +03:00
|
|
|
PersistentPreRun: func(cmd *Command, args []string) {
|
|
|
|
rootPersPre = args
|
|
|
|
},
|
2013-11-02 02:36:24 +04:00
|
|
|
}
|
|
|
|
|
2014-03-27 00:19:34 +04:00
|
|
|
var cmdRootSameName = &Command{
|
|
|
|
Use: "print",
|
|
|
|
Short: "Root with the same name as a subcommand",
|
|
|
|
Long: "The root description for help",
|
|
|
|
}
|
|
|
|
|
2013-11-02 02:36:24 +04:00
|
|
|
var cmdRootWithRun = &Command{
|
2013-10-01 05:54:46 +04:00
|
|
|
Use: "cobra-test",
|
|
|
|
Short: "The root can run it's own function",
|
|
|
|
Long: "The root description for help",
|
|
|
|
Run: func(cmd *Command, args []string) {
|
2015-05-13 04:38:01 +03:00
|
|
|
tr = args
|
2013-10-01 05:54:46 +04:00
|
|
|
rootcalled = true
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2015-04-07 18:56:08 +03:00
|
|
|
var cmdSubNoRun = &Command{
|
|
|
|
Use: "subnorun",
|
|
|
|
Short: "A subcommand without a Run function",
|
|
|
|
Long: "A long output about a subcommand without a Run function",
|
|
|
|
}
|
|
|
|
|
2015-03-13 10:30:33 +03:00
|
|
|
var cmdVersion1 = &Command{
|
|
|
|
Use: "version",
|
|
|
|
Short: "Print the version number",
|
|
|
|
Long: `First version of the version command`,
|
|
|
|
Run: func(cmd *Command, args []string) {
|
|
|
|
versionUsed = 1
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var cmdVersion2 = &Command{
|
|
|
|
Use: "version",
|
|
|
|
Short: "Print the version number",
|
|
|
|
Long: `Second version of the version command`,
|
|
|
|
Run: func(cmd *Command, args []string) {
|
|
|
|
versionUsed = 2
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2013-09-04 02:54:51 +04:00
|
|
|
func flagInit() {
|
|
|
|
cmdEcho.ResetFlags()
|
|
|
|
cmdPrint.ResetFlags()
|
|
|
|
cmdTimes.ResetFlags()
|
2013-11-02 02:36:24 +04:00
|
|
|
cmdRootNoRun.ResetFlags()
|
2014-03-27 00:19:34 +04:00
|
|
|
cmdRootSameName.ResetFlags()
|
2013-11-02 02:36:24 +04:00
|
|
|
cmdRootWithRun.ResetFlags()
|
2015-04-07 18:56:08 +03:00
|
|
|
cmdSubNoRun.ResetFlags()
|
2015-02-28 03:26:56 +03:00
|
|
|
cmdRootNoRun.PersistentFlags().StringVarP(&flags2a, "strtwo", "t", "two", strtwoParentHelp)
|
2013-09-04 02:54:51 +04:00
|
|
|
cmdEcho.Flags().IntVarP(&flagi1, "intone", "i", 123, "help message for flag intone")
|
|
|
|
cmdTimes.Flags().IntVarP(&flagi2, "inttwo", "j", 234, "help message for flag inttwo")
|
|
|
|
cmdPrint.Flags().IntVarP(&flagi3, "intthree", "i", 345, "help message for flag intthree")
|
|
|
|
cmdEcho.PersistentFlags().StringVarP(&flags1, "strone", "s", "one", "help message for flag strone")
|
2015-03-19 00:42:38 +03:00
|
|
|
cmdEcho.PersistentFlags().BoolVarP(&flagbp, "persistentbool", "p", false, "help message for flag persistentbool")
|
2015-02-28 03:26:56 +03:00
|
|
|
cmdTimes.PersistentFlags().StringVarP(&flags2b, "strtwo", "t", "2", strtwoChildHelp)
|
2013-09-04 02:54:51 +04:00
|
|
|
cmdPrint.PersistentFlags().StringVarP(&flags3, "strthree", "s", "three", "help message for flag strthree")
|
|
|
|
cmdEcho.Flags().BoolVarP(&flagb1, "boolone", "b", true, "help message for flag boolone")
|
|
|
|
cmdTimes.Flags().BoolVarP(&flagb2, "booltwo", "c", false, "help message for flag booltwo")
|
|
|
|
cmdPrint.Flags().BoolVarP(&flagb3, "boolthree", "b", true, "help message for flag boolthree")
|
2015-03-13 10:30:33 +03:00
|
|
|
cmdVersion1.ResetFlags()
|
|
|
|
cmdVersion2.ResetFlags()
|
2013-09-04 02:54:51 +04:00
|
|
|
}
|
|
|
|
|
2013-09-04 19:25:32 +04:00
|
|
|
func commandInit() {
|
|
|
|
cmdEcho.ResetCommands()
|
|
|
|
cmdPrint.ResetCommands()
|
|
|
|
cmdTimes.ResetCommands()
|
2014-03-26 12:54:47 +04:00
|
|
|
cmdRootNoRun.ResetCommands()
|
2014-03-27 00:19:34 +04:00
|
|
|
cmdRootSameName.ResetCommands()
|
2014-03-26 12:54:47 +04:00
|
|
|
cmdRootWithRun.ResetCommands()
|
2015-04-07 18:56:08 +03:00
|
|
|
cmdSubNoRun.ResetCommands()
|
2013-09-04 19:25:32 +04:00
|
|
|
}
|
|
|
|
|
2013-11-02 02:36:24 +04:00
|
|
|
func initialize() *Command {
|
2013-09-04 02:54:51 +04:00
|
|
|
tt, tp, te = nil, nil, nil
|
2015-04-30 20:58:29 +03:00
|
|
|
rootPersPre, echoPre, echoPersPre, timesPersPre = nil, nil, nil, nil
|
|
|
|
|
2013-11-02 02:36:24 +04:00
|
|
|
var c = cmdRootNoRun
|
2013-09-04 19:25:32 +04:00
|
|
|
flagInit()
|
|
|
|
commandInit()
|
2013-09-04 02:54:51 +04:00
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
2014-03-27 00:19:34 +04:00
|
|
|
func initializeWithSameName() *Command {
|
|
|
|
tt, tp, te = nil, nil, nil
|
2015-04-30 20:58:29 +03:00
|
|
|
rootPersPre, echoPre, echoPersPre, timesPersPre = nil, nil, nil, nil
|
2014-03-27 00:19:34 +04:00
|
|
|
var c = cmdRootSameName
|
|
|
|
flagInit()
|
|
|
|
commandInit()
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
2013-11-02 02:36:24 +04:00
|
|
|
func initializeWithRootCmd() *Command {
|
|
|
|
cmdRootWithRun.ResetCommands()
|
2015-05-13 04:38:01 +03:00
|
|
|
tt, tp, te, tr, rootcalled = nil, nil, nil, nil, false
|
2013-10-01 05:54:46 +04:00
|
|
|
flagInit()
|
2013-11-02 02:36:24 +04:00
|
|
|
cmdRootWithRun.Flags().BoolVarP(&flagbr, "boolroot", "b", false, "help message for flag boolroot")
|
2014-06-17 20:28:42 +04:00
|
|
|
cmdRootWithRun.Flags().IntVarP(&flagir, "introot", "i", 321, "help message for flag introot")
|
2013-10-01 05:54:46 +04:00
|
|
|
commandInit()
|
2013-11-02 02:36:24 +04:00
|
|
|
return cmdRootWithRun
|
2013-10-01 05:54:46 +04:00
|
|
|
}
|
|
|
|
|
2014-06-17 20:28:42 +04:00
|
|
|
type resulter struct {
|
|
|
|
Error error
|
|
|
|
Output string
|
|
|
|
Command *Command
|
|
|
|
}
|
|
|
|
|
|
|
|
func fullSetupTest(input string) resulter {
|
|
|
|
c := initializeWithRootCmd()
|
|
|
|
|
|
|
|
return fullTester(c, input)
|
|
|
|
}
|
|
|
|
|
2015-10-26 04:58:53 +03:00
|
|
|
func noRRSetupTestSilenced(input string) resulter {
|
|
|
|
c := initialize()
|
|
|
|
c.SilenceErrors = true
|
2015-10-27 02:38:08 +03:00
|
|
|
c.SilenceUsage = true
|
2015-10-26 04:58:53 +03:00
|
|
|
return fullTester(c, input)
|
|
|
|
}
|
|
|
|
|
2014-06-17 20:28:42 +04:00
|
|
|
func noRRSetupTest(input string) resulter {
|
|
|
|
c := initialize()
|
|
|
|
|
|
|
|
return fullTester(c, input)
|
|
|
|
}
|
|
|
|
|
2014-11-12 07:32:54 +03:00
|
|
|
func rootOnlySetupTest(input string) resulter {
|
|
|
|
c := initializeWithRootCmd()
|
|
|
|
|
|
|
|
return simpleTester(c, input)
|
|
|
|
}
|
|
|
|
|
|
|
|
func simpleTester(c *Command, input string) resulter {
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Testing flag with invalid input
|
|
|
|
c.SetOutput(buf)
|
|
|
|
c.SetArgs(strings.Split(input, " "))
|
|
|
|
|
|
|
|
err := c.Execute()
|
|
|
|
output := buf.String()
|
|
|
|
|
|
|
|
return resulter{err, output, c}
|
|
|
|
}
|
|
|
|
|
2014-06-17 20:28:42 +04:00
|
|
|
func fullTester(c *Command, input string) resulter {
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Testing flag with invalid input
|
|
|
|
c.SetOutput(buf)
|
|
|
|
cmdEcho.AddCommand(cmdTimes)
|
2015-04-08 00:38:22 +03:00
|
|
|
c.AddCommand(cmdPrint, cmdEcho, cmdSubNoRun, cmdDeprecated)
|
2014-06-17 20:28:42 +04:00
|
|
|
c.SetArgs(strings.Split(input, " "))
|
|
|
|
|
|
|
|
err := c.Execute()
|
|
|
|
output := buf.String()
|
|
|
|
|
|
|
|
return resulter{err, output, c}
|
|
|
|
}
|
|
|
|
|
2015-04-07 22:50:08 +03:00
|
|
|
func logErr(t *testing.T, found, expected string) {
|
|
|
|
out := new(bytes.Buffer)
|
|
|
|
|
|
|
|
_, _, line, ok := runtime.Caller(2)
|
|
|
|
if ok {
|
|
|
|
fmt.Fprintf(out, "Line: %d ", line)
|
|
|
|
}
|
|
|
|
fmt.Fprintf(out, "Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found)
|
|
|
|
t.Errorf(out.String())
|
|
|
|
}
|
|
|
|
|
2015-09-08 19:32:15 +03:00
|
|
|
func checkStringContains(t *testing.T, found, expected string) {
|
|
|
|
if !strings.Contains(found, expected) {
|
|
|
|
logErr(t, found, expected)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-17 20:28:42 +04:00
|
|
|
func checkResultContains(t *testing.T, x resulter, check string) {
|
2015-09-08 19:32:15 +03:00
|
|
|
checkStringContains(t, x.Output, check)
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkStringOmits(t *testing.T, found, expected string) {
|
|
|
|
if strings.Contains(found, expected) {
|
|
|
|
logErr(t, found, expected)
|
2014-06-17 20:28:42 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-12 07:32:54 +03:00
|
|
|
func checkResultOmits(t *testing.T, x resulter, check string) {
|
2015-09-08 19:32:15 +03:00
|
|
|
checkStringOmits(t, x.Output, check)
|
2014-11-12 07:32:54 +03:00
|
|
|
}
|
|
|
|
|
2014-06-14 04:00:56 +04:00
|
|
|
func checkOutputContains(t *testing.T, c *Command, check string) {
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
c.SetOutput(buf)
|
|
|
|
c.Execute()
|
|
|
|
|
|
|
|
if !strings.Contains(buf.String(), check) {
|
2015-04-07 22:50:08 +03:00
|
|
|
logErr(t, buf.String(), check)
|
2014-06-14 04:00:56 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-04 02:54:51 +04:00
|
|
|
func TestSingleCommand(t *testing.T) {
|
2014-06-17 20:32:27 +04:00
|
|
|
noRRSetupTest("print one two")
|
2013-09-04 02:54:51 +04:00
|
|
|
|
|
|
|
if te != nil || tt != nil {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
|
|
|
if tp == nil {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
|
|
|
if strings.Join(tp, " ") != "one two" {
|
|
|
|
t.Error("Command didn't parse correctly")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestChildCommand(t *testing.T) {
|
2014-06-17 20:32:27 +04:00
|
|
|
noRRSetupTest("echo times one two")
|
2013-09-04 02:54:51 +04:00
|
|
|
|
|
|
|
if te != nil || tp != nil {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
|
|
|
if tt == nil {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
|
|
|
if strings.Join(tt, " ") != "one two" {
|
|
|
|
t.Error("Command didn't parse correctly")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-26 03:03:34 +04:00
|
|
|
func TestCommandAlias(t *testing.T) {
|
|
|
|
noRRSetupTest("say times one two")
|
2014-03-26 12:56:46 +04:00
|
|
|
|
|
|
|
if te != nil || tp != nil {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
|
|
|
if tt == nil {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
|
|
|
if strings.Join(tt, " ") != "one two" {
|
|
|
|
t.Error("Command didn't parse correctly")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-07 23:41:19 +04:00
|
|
|
func TestPrefixMatching(t *testing.T) {
|
2014-10-08 00:15:19 +04:00
|
|
|
EnablePrefixMatching = true
|
2014-10-07 23:41:19 +04:00
|
|
|
noRRSetupTest("ech times one two")
|
|
|
|
|
|
|
|
if te != nil || tp != nil {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
|
|
|
if tt == nil {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
|
|
|
if strings.Join(tt, " ") != "one two" {
|
|
|
|
t.Error("Command didn't parse correctly")
|
|
|
|
}
|
2014-10-08 00:15:19 +04:00
|
|
|
|
|
|
|
EnablePrefixMatching = false
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNoPrefixMatching(t *testing.T) {
|
|
|
|
EnablePrefixMatching = false
|
|
|
|
|
|
|
|
noRRSetupTest("ech times one two")
|
|
|
|
|
|
|
|
if !(tt == nil && te == nil && tp == nil) {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
2014-10-07 23:41:19 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestAliasPrefixMatching(t *testing.T) {
|
2014-10-08 00:15:19 +04:00
|
|
|
EnablePrefixMatching = true
|
2014-10-07 23:41:19 +04:00
|
|
|
noRRSetupTest("sa times one two")
|
|
|
|
|
|
|
|
if te != nil || tp != nil {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
|
|
|
if tt == nil {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
|
|
|
if strings.Join(tt, " ") != "one two" {
|
|
|
|
t.Error("Command didn't parse correctly")
|
|
|
|
}
|
2014-10-08 00:15:19 +04:00
|
|
|
EnablePrefixMatching = false
|
2014-10-07 23:41:19 +04:00
|
|
|
}
|
|
|
|
|
2014-03-27 00:19:34 +04:00
|
|
|
func TestChildSameName(t *testing.T) {
|
|
|
|
c := initializeWithSameName()
|
|
|
|
c.AddCommand(cmdPrint, cmdEcho)
|
|
|
|
c.SetArgs(strings.Split("print one two", " "))
|
|
|
|
c.Execute()
|
|
|
|
|
2015-06-23 00:26:11 +03:00
|
|
|
if te != nil || tt != nil {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
|
|
|
if tp == nil {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
|
|
|
if strings.Join(tp, " ") != "one two" {
|
|
|
|
t.Error("Command didn't parse correctly")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGrandChildSameName(t *testing.T) {
|
|
|
|
c := initializeWithSameName()
|
|
|
|
cmdTimes.AddCommand(cmdPrint)
|
|
|
|
c.AddCommand(cmdTimes)
|
|
|
|
c.SetArgs(strings.Split("times print one two", " "))
|
|
|
|
c.Execute()
|
|
|
|
|
2014-03-27 00:19:34 +04:00
|
|
|
if te != nil || tt != nil {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
|
|
|
if tp == nil {
|
|
|
|
t.Error("Wrong command called")
|
|
|
|
}
|
|
|
|
if strings.Join(tp, " ") != "one two" {
|
|
|
|
t.Error("Command didn't parse correctly")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-04 02:54:51 +04:00
|
|
|
func TestFlagLong(t *testing.T) {
|
2015-09-16 19:31:41 +03:00
|
|
|
noRRSetupTest("echo --intone=13 something -- here")
|
2013-09-04 02:54:51 +04:00
|
|
|
|
2015-09-16 19:31:41 +03:00
|
|
|
if cmdEcho.ArgsLenAtDash() != 1 {
|
|
|
|
t.Errorf("expected argsLenAtDash: %d but got %d", 1, cmdRootNoRun.ArgsLenAtDash())
|
|
|
|
}
|
2013-09-04 02:54:51 +04:00
|
|
|
if strings.Join(te, " ") != "something here" {
|
|
|
|
t.Errorf("flags didn't leave proper args remaining..%s given", te)
|
|
|
|
}
|
|
|
|
if flagi1 != 13 {
|
|
|
|
t.Errorf("int flag didn't get correct value, had %d", flagi1)
|
|
|
|
}
|
|
|
|
if flagi2 != 234 {
|
|
|
|
t.Errorf("default flag value changed, 234 expected, %d given", flagi2)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestFlagShort(t *testing.T) {
|
2015-09-16 19:31:41 +03:00
|
|
|
noRRSetupTest("echo -i13 -- something here")
|
2013-09-04 02:54:51 +04:00
|
|
|
|
2015-09-16 19:31:41 +03:00
|
|
|
if cmdEcho.ArgsLenAtDash() != 0 {
|
|
|
|
t.Errorf("expected argsLenAtDash: %d but got %d", 0, cmdRootNoRun.ArgsLenAtDash())
|
|
|
|
}
|
2013-09-04 02:54:51 +04:00
|
|
|
if strings.Join(te, " ") != "something here" {
|
|
|
|
t.Errorf("flags didn't leave proper args remaining..%s given", te)
|
|
|
|
}
|
|
|
|
if flagi1 != 13 {
|
|
|
|
t.Errorf("int flag didn't get correct value, had %d", flagi1)
|
|
|
|
}
|
|
|
|
if flagi2 != 234 {
|
|
|
|
t.Errorf("default flag value changed, 234 expected, %d given", flagi2)
|
|
|
|
}
|
|
|
|
|
2014-06-17 20:32:27 +04:00
|
|
|
noRRSetupTest("echo -i 13 something here")
|
2013-09-04 02:54:51 +04:00
|
|
|
|
|
|
|
if strings.Join(te, " ") != "something here" {
|
|
|
|
t.Errorf("flags didn't leave proper args remaining..%s given", te)
|
|
|
|
}
|
|
|
|
if flagi1 != 13 {
|
|
|
|
t.Errorf("int flag didn't get correct value, had %d", flagi1)
|
|
|
|
}
|
|
|
|
if flagi2 != 234 {
|
|
|
|
t.Errorf("default flag value changed, 234 expected, %d given", flagi2)
|
|
|
|
}
|
|
|
|
|
2014-06-17 20:32:27 +04:00
|
|
|
noRRSetupTest("print -i99 one two")
|
2013-09-04 02:54:51 +04:00
|
|
|
|
|
|
|
if strings.Join(tp, " ") != "one two" {
|
|
|
|
t.Errorf("flags didn't leave proper args remaining..%s given", tp)
|
|
|
|
}
|
|
|
|
if flagi3 != 99 {
|
|
|
|
t.Errorf("int flag didn't get correct value, had %d", flagi3)
|
|
|
|
}
|
|
|
|
if flagi1 != 123 {
|
2013-09-04 19:27:10 +04:00
|
|
|
t.Errorf("default flag value changed on different command with same shortname, 234 expected, %d given", flagi2)
|
2013-09-04 02:54:51 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestChildCommandFlags(t *testing.T) {
|
2014-06-17 20:32:27 +04:00
|
|
|
noRRSetupTest("echo times -j 99 one two")
|
2013-09-04 02:54:51 +04:00
|
|
|
|
|
|
|
if strings.Join(tt, " ") != "one two" {
|
|
|
|
t.Errorf("flags didn't leave proper args remaining..%s given", tt)
|
|
|
|
}
|
|
|
|
|
2013-09-04 19:27:10 +04:00
|
|
|
// Testing with flag that shouldn't be persistent
|
2014-06-17 20:32:27 +04:00
|
|
|
r := noRRSetupTest("echo times -j 99 -i77 one two")
|
2013-09-04 19:27:10 +04:00
|
|
|
|
2014-06-17 20:32:27 +04:00
|
|
|
if r.Error == nil {
|
2013-09-04 19:27:10 +04:00
|
|
|
t.Errorf("invalid flag should generate error")
|
|
|
|
}
|
2013-09-04 02:54:51 +04:00
|
|
|
|
2015-10-26 04:58:53 +03:00
|
|
|
if !strings.Contains(r.Error.Error(), "unknown shorthand") {
|
|
|
|
t.Errorf("Wrong error message displayed, \n %s", r.Error)
|
2013-09-24 20:12:32 +04:00
|
|
|
}
|
|
|
|
|
2013-09-04 19:27:10 +04:00
|
|
|
if flagi2 != 99 {
|
|
|
|
t.Errorf("flag value should be 99, %d given", flagi2)
|
|
|
|
}
|
|
|
|
|
|
|
|
if flagi1 != 123 {
|
|
|
|
t.Errorf("unset flag should have default value, expecting 123, given %d", flagi1)
|
|
|
|
}
|
2013-09-24 20:12:32 +04:00
|
|
|
|
|
|
|
// Testing with flag only existing on child
|
2014-06-17 20:32:27 +04:00
|
|
|
r = noRRSetupTest("echo -j 99 -i77 one two")
|
2013-09-24 20:12:32 +04:00
|
|
|
|
2014-06-17 20:32:27 +04:00
|
|
|
if r.Error == nil {
|
2013-09-24 21:15:30 +04:00
|
|
|
t.Errorf("invalid flag should generate error")
|
|
|
|
}
|
2015-10-26 04:58:53 +03:00
|
|
|
if !strings.Contains(r.Error.Error(), "unknown shorthand flag") {
|
|
|
|
t.Errorf("Wrong error message displayed, \n %s", r.Error)
|
2013-09-24 21:15:30 +04:00
|
|
|
}
|
2014-06-14 04:45:55 +04:00
|
|
|
|
2015-02-28 03:26:56 +03:00
|
|
|
// Testing with persistent flag overwritten by child
|
|
|
|
noRRSetupTest("echo times --strtwo=child one two")
|
|
|
|
|
|
|
|
if flags2b != "child" {
|
|
|
|
t.Errorf("flag value should be child, %s given", flags2b)
|
|
|
|
}
|
|
|
|
|
|
|
|
if flags2a != "two" {
|
|
|
|
t.Errorf("unset flag should have default value, expecting two, given %s", flags2a)
|
|
|
|
}
|
|
|
|
|
2014-06-14 04:45:55 +04:00
|
|
|
// Testing flag with invalid input
|
2014-06-17 20:32:27 +04:00
|
|
|
r = noRRSetupTest("echo -i10E")
|
2014-06-14 04:45:55 +04:00
|
|
|
|
2014-06-17 20:32:27 +04:00
|
|
|
if r.Error == nil {
|
2014-06-14 04:45:55 +04:00
|
|
|
t.Errorf("invalid input should generate error")
|
|
|
|
}
|
2015-10-26 04:58:53 +03:00
|
|
|
if !strings.Contains(r.Error.Error(), "invalid argument \"10E\" for i10E") {
|
|
|
|
t.Errorf("Wrong error message displayed, \n %s", r.Error)
|
2014-06-14 04:45:55 +04:00
|
|
|
}
|
2013-09-04 02:54:51 +04:00
|
|
|
}
|
|
|
|
|
2013-11-06 04:50:47 +04:00
|
|
|
func TestTrailingCommandFlags(t *testing.T) {
|
2014-06-17 20:32:27 +04:00
|
|
|
x := fullSetupTest("echo two -x")
|
2013-11-06 04:50:47 +04:00
|
|
|
|
2014-06-17 20:32:27 +04:00
|
|
|
if x.Error == nil {
|
2013-11-06 04:50:47 +04:00
|
|
|
t.Errorf("invalid flag should generate error")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-13 04:38:01 +03:00
|
|
|
func TestInvalidSubcommandFlags(t *testing.T) {
|
2015-04-06 20:43:44 +03:00
|
|
|
cmd := initializeWithRootCmd()
|
|
|
|
cmd.AddCommand(cmdTimes)
|
|
|
|
|
|
|
|
result := simpleTester(cmd, "times --inttwo=2 --badflag=bar")
|
2015-10-26 04:58:53 +03:00
|
|
|
// given that we are not checking here result.Error we check for
|
|
|
|
// stock usage message
|
|
|
|
checkResultContains(t, result, "cobra-test times [# times]")
|
|
|
|
if strings.Contains(result.Error.Error(), "unknown flag: --inttwo") {
|
2015-04-06 20:43:44 +03:00
|
|
|
t.Errorf("invalid --badflag flag shouldn't fail on 'unknown' --inttwo flag")
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-05-13 04:38:01 +03:00
|
|
|
func TestSubcommandArgEvaluation(t *testing.T) {
|
2015-04-24 18:39:11 +03:00
|
|
|
cmd := initializeWithRootCmd()
|
|
|
|
|
|
|
|
first := &Command{
|
|
|
|
Use: "first",
|
|
|
|
Run: func(cmd *Command, args []string) {
|
|
|
|
},
|
|
|
|
}
|
|
|
|
cmd.AddCommand(first)
|
|
|
|
|
|
|
|
second := &Command{
|
|
|
|
Use: "second",
|
|
|
|
Run: func(cmd *Command, args []string) {
|
|
|
|
fmt.Fprintf(cmd.Out(), "%v", args)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
first.AddCommand(second)
|
|
|
|
|
|
|
|
result := simpleTester(cmd, "first second first third")
|
|
|
|
|
|
|
|
expectedOutput := fmt.Sprintf("%v", []string{"first third"})
|
|
|
|
if result.Output != expectedOutput {
|
|
|
|
t.Errorf("exptected %v, got %v", expectedOutput, result.Output)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-04 02:54:51 +04:00
|
|
|
func TestPersistentFlags(t *testing.T) {
|
2015-03-19 00:42:38 +03:00
|
|
|
fullSetupTest("echo -s something -p more here")
|
2013-09-04 02:54:51 +04:00
|
|
|
|
|
|
|
// persistentFlag should act like normal flag on it's own command
|
|
|
|
if strings.Join(te, " ") != "more here" {
|
|
|
|
t.Errorf("flags didn't leave proper args remaining..%s given", te)
|
|
|
|
}
|
|
|
|
if flags1 != "something" {
|
|
|
|
t.Errorf("string flag didn't get correct value, had %v", flags1)
|
|
|
|
}
|
2015-03-19 00:42:38 +03:00
|
|
|
if !flagbp {
|
|
|
|
t.Errorf("persistent bool flag not parsed correctly. Expected true, had %v", flagbp)
|
|
|
|
}
|
2013-09-04 02:54:51 +04:00
|
|
|
|
2015-03-19 00:42:38 +03:00
|
|
|
// persistentFlag should act like normal flag on it's own command
|
|
|
|
fullSetupTest("echo times -s again -c -p test here")
|
2013-09-11 02:26:46 +04:00
|
|
|
|
|
|
|
if strings.Join(tt, " ") != "test here" {
|
|
|
|
t.Errorf("flags didn't leave proper args remaining..%s given", tt)
|
|
|
|
}
|
|
|
|
|
|
|
|
if flags1 != "again" {
|
|
|
|
t.Errorf("string flag didn't get correct value, had %v", flags1)
|
|
|
|
}
|
|
|
|
|
2015-03-19 00:42:38 +03:00
|
|
|
if !flagb2 {
|
|
|
|
t.Errorf("local flag not parsed correctly. Expected true, had %v", flagb2)
|
|
|
|
}
|
|
|
|
if !flagbp {
|
|
|
|
t.Errorf("persistent bool flag not parsed correctly. Expected true, had %v", flagbp)
|
2013-09-11 02:26:46 +04:00
|
|
|
}
|
2013-09-04 02:54:51 +04:00
|
|
|
}
|
2013-09-25 00:03:22 +04:00
|
|
|
|
|
|
|
func TestHelpCommand(t *testing.T) {
|
2015-04-07 18:56:08 +03:00
|
|
|
x := fullSetupTest("help")
|
|
|
|
checkResultContains(t, x, cmdRootWithRun.Long)
|
2013-09-25 00:03:22 +04:00
|
|
|
|
2015-04-07 18:56:08 +03:00
|
|
|
x = fullSetupTest("help echo")
|
|
|
|
checkResultContains(t, x, cmdEcho.Long)
|
|
|
|
|
|
|
|
x = fullSetupTest("help echo times")
|
|
|
|
checkResultContains(t, x, cmdTimes.Long)
|
2013-09-25 00:03:22 +04:00
|
|
|
}
|
2013-10-01 05:54:46 +04:00
|
|
|
|
2015-02-28 03:26:56 +03:00
|
|
|
func TestChildCommandHelp(t *testing.T) {
|
|
|
|
c := noRRSetupTest("print --help")
|
|
|
|
checkResultContains(t, c, strtwoParentHelp)
|
|
|
|
r := noRRSetupTest("echo times --help")
|
|
|
|
checkResultContains(t, r, strtwoChildHelp)
|
|
|
|
}
|
|
|
|
|
2015-04-07 18:56:08 +03:00
|
|
|
func TestNonRunChildHelp(t *testing.T) {
|
|
|
|
x := noRRSetupTest("subnorun")
|
|
|
|
checkResultContains(t, x, cmdSubNoRun.Long)
|
|
|
|
}
|
|
|
|
|
2013-11-02 02:36:24 +04:00
|
|
|
func TestRunnableRootCommand(t *testing.T) {
|
2015-09-16 01:02:03 +03:00
|
|
|
x := fullSetupTest("")
|
2013-10-01 05:54:46 +04:00
|
|
|
|
|
|
|
if rootcalled != true {
|
2015-09-16 01:02:03 +03:00
|
|
|
t.Errorf("Root Function was not called\n out:%v", x.Error)
|
2013-10-01 05:54:46 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-08 04:21:25 +03:00
|
|
|
func TestVisitParents(t *testing.T) {
|
|
|
|
c := &Command{Use: "app"}
|
|
|
|
sub := &Command{Use: "sub"}
|
|
|
|
dsub := &Command{Use: "dsub"}
|
|
|
|
sub.AddCommand(dsub)
|
|
|
|
c.AddCommand(sub)
|
|
|
|
total := 0
|
|
|
|
add := func(x *Command) {
|
|
|
|
total++
|
|
|
|
}
|
|
|
|
sub.VisitParents(add)
|
|
|
|
if total != 1 {
|
|
|
|
t.Errorf("Should have visited 1 parent but visited %d", total)
|
|
|
|
}
|
|
|
|
|
|
|
|
total = 0
|
|
|
|
dsub.VisitParents(add)
|
|
|
|
if total != 2 {
|
|
|
|
t.Errorf("Should have visited 2 parent but visited %d", total)
|
|
|
|
}
|
|
|
|
|
|
|
|
total = 0
|
|
|
|
c.VisitParents(add)
|
|
|
|
if total != 0 {
|
|
|
|
t.Errorf("Should have not visited any parent but visited %d", total)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-06 20:43:44 +03:00
|
|
|
func TestRunnableRootCommandNilInput(t *testing.T) {
|
|
|
|
empty_arg := make([]string, 0)
|
|
|
|
c := initializeWithRootCmd()
|
|
|
|
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Testing flag with invalid input
|
|
|
|
c.SetOutput(buf)
|
|
|
|
cmdEcho.AddCommand(cmdTimes)
|
|
|
|
c.AddCommand(cmdPrint, cmdEcho)
|
|
|
|
c.SetArgs(empty_arg)
|
|
|
|
|
2015-09-16 01:02:03 +03:00
|
|
|
err := c.Execute()
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Execute() failed with %v", err)
|
|
|
|
}
|
2015-04-06 20:43:44 +03:00
|
|
|
|
|
|
|
if rootcalled != true {
|
|
|
|
t.Errorf("Root Function was not called")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRunnableRootCommandEmptyInput(t *testing.T) {
|
|
|
|
args := make([]string, 3)
|
|
|
|
args[0] = ""
|
|
|
|
args[1] = "--introot=12"
|
|
|
|
args[2] = ""
|
|
|
|
c := initializeWithRootCmd()
|
|
|
|
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Testing flag with invalid input
|
|
|
|
c.SetOutput(buf)
|
|
|
|
cmdEcho.AddCommand(cmdTimes)
|
|
|
|
c.AddCommand(cmdPrint, cmdEcho)
|
|
|
|
c.SetArgs(args)
|
|
|
|
|
|
|
|
c.Execute()
|
|
|
|
|
|
|
|
if rootcalled != true {
|
|
|
|
t.Errorf("Root Function was not called.\n\nOutput was:\n\n%s\n", buf)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInvalidSubcommandWhenArgsAllowed(t *testing.T) {
|
|
|
|
fullSetupTest("echo invalid-sub")
|
|
|
|
|
|
|
|
if te[0] != "invalid-sub" {
|
|
|
|
t.Errorf("Subcommand didn't work...")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-01 05:54:46 +04:00
|
|
|
func TestRootFlags(t *testing.T) {
|
2014-06-17 20:32:27 +04:00
|
|
|
fullSetupTest("-i 17 -b")
|
2013-10-01 05:54:46 +04:00
|
|
|
|
|
|
|
if flagbr != true {
|
|
|
|
t.Errorf("flag value should be true, %v given", flagbr)
|
|
|
|
}
|
|
|
|
|
|
|
|
if flagir != 17 {
|
|
|
|
t.Errorf("flag value should be 17, %d given", flagir)
|
|
|
|
}
|
2014-06-14 04:00:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestRootHelp(t *testing.T) {
|
2014-06-17 20:28:42 +04:00
|
|
|
x := fullSetupTest("--help")
|
|
|
|
|
|
|
|
checkResultContains(t, x, "Available Commands:")
|
2015-01-31 19:08:05 +03:00
|
|
|
checkResultContains(t, x, "for more information about a command")
|
2014-06-17 20:28:42 +04:00
|
|
|
|
|
|
|
if strings.Contains(x.Output, "unknown flag: --help") {
|
|
|
|
t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output)
|
|
|
|
}
|
|
|
|
|
2015-02-11 12:20:29 +03:00
|
|
|
if strings.Contains(x.Output, cmdEcho.Use) {
|
|
|
|
t.Errorf("--help shouldn't display subcommand's usage, Got: \n %s", x.Output)
|
|
|
|
}
|
|
|
|
|
2014-06-17 20:28:42 +04:00
|
|
|
x = fullSetupTest("echo --help")
|
|
|
|
|
2015-02-11 12:20:29 +03:00
|
|
|
if strings.Contains(x.Output, cmdTimes.Use) {
|
|
|
|
t.Errorf("--help shouldn't display subsubcommand's usage, Got: \n %s", x.Output)
|
|
|
|
}
|
|
|
|
|
2014-06-17 20:28:42 +04:00
|
|
|
checkResultContains(t, x, "Available Commands:")
|
2015-01-31 19:08:05 +03:00
|
|
|
checkResultContains(t, x, "for more information about a command")
|
2014-06-17 20:28:42 +04:00
|
|
|
|
|
|
|
if strings.Contains(x.Output, "unknown flag: --help") {
|
|
|
|
t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2013-10-01 05:54:46 +04:00
|
|
|
|
2015-02-28 03:26:56 +03:00
|
|
|
func TestFlagAccess(t *testing.T) {
|
|
|
|
initialize()
|
|
|
|
|
|
|
|
local := cmdTimes.LocalFlags()
|
|
|
|
inherited := cmdTimes.InheritedFlags()
|
|
|
|
|
|
|
|
for _, f := range []string{"inttwo", "strtwo", "booltwo"} {
|
|
|
|
if local.Lookup(f) == nil {
|
|
|
|
t.Errorf("LocalFlags expected to contain %s, Got: nil", f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if inherited.Lookup("strone") == nil {
|
|
|
|
t.Errorf("InheritedFlags expected to contain strone, Got: nil")
|
|
|
|
}
|
|
|
|
if inherited.Lookup("strtwo") != nil {
|
|
|
|
t.Errorf("InheritedFlags shouldn not contain overwritten flag strtwo")
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-06 20:43:44 +03:00
|
|
|
func TestNoNRunnableRootCommandNilInput(t *testing.T) {
|
|
|
|
args := make([]string, 0)
|
|
|
|
c := initialize()
|
|
|
|
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Testing flag with invalid input
|
|
|
|
c.SetOutput(buf)
|
|
|
|
cmdEcho.AddCommand(cmdTimes)
|
|
|
|
c.AddCommand(cmdPrint, cmdEcho)
|
|
|
|
c.SetArgs(args)
|
|
|
|
|
|
|
|
c.Execute()
|
|
|
|
|
|
|
|
if !strings.Contains(buf.String(), cmdRootNoRun.Long) {
|
|
|
|
t.Errorf("Expected to get help output, Got: \n %s", buf)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-12 07:32:54 +03:00
|
|
|
func TestRootNoCommandHelp(t *testing.T) {
|
|
|
|
x := rootOnlySetupTest("--help")
|
|
|
|
|
|
|
|
checkResultOmits(t, x, "Available Commands:")
|
2015-01-31 19:08:05 +03:00
|
|
|
checkResultOmits(t, x, "for more information about a command")
|
2014-11-12 07:32:54 +03:00
|
|
|
|
|
|
|
if strings.Contains(x.Output, "unknown flag: --help") {
|
|
|
|
t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output)
|
|
|
|
}
|
|
|
|
|
|
|
|
x = rootOnlySetupTest("echo --help")
|
|
|
|
|
|
|
|
checkResultOmits(t, x, "Available Commands:")
|
2015-01-31 19:08:05 +03:00
|
|
|
checkResultOmits(t, x, "for more information about a command")
|
2014-11-12 07:32:54 +03:00
|
|
|
|
|
|
|
if strings.Contains(x.Output, "unknown flag: --help") {
|
|
|
|
t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-03 08:07:34 +03:00
|
|
|
func TestRootUnknownCommand(t *testing.T) {
|
|
|
|
r := noRRSetupTest("bogus")
|
2015-06-30 00:05:49 +03:00
|
|
|
s := "Error: unknown command \"bogus\" for \"cobra-test\"\nRun 'cobra-test --help' for usage.\n"
|
2015-04-03 08:07:34 +03:00
|
|
|
|
|
|
|
if r.Output != s {
|
|
|
|
t.Errorf("Unexpected response.\nExpecting to be:\n %q\nGot:\n %q\n", s, r.Output)
|
|
|
|
}
|
2015-06-22 11:14:37 +03:00
|
|
|
|
|
|
|
r = noRRSetupTest("--strtwo=a bogus")
|
|
|
|
if r.Output != s {
|
|
|
|
t.Errorf("Unexpected response.\nExpecting to be:\n %q\nGot:\n %q\n", s, r.Output)
|
|
|
|
}
|
2015-04-03 08:07:34 +03:00
|
|
|
}
|
|
|
|
|
2015-10-26 04:58:53 +03:00
|
|
|
func TestRootUnknownCommandSilenced(t *testing.T) {
|
|
|
|
r := noRRSetupTestSilenced("bogus")
|
|
|
|
s := "Run 'cobra-test --help' for usage.\n"
|
|
|
|
|
|
|
|
if r.Output != "" {
|
|
|
|
t.Errorf("Unexpected response.\nExpecting to be: \n\"\"\n Got:\n %q\n", s, r.Output)
|
|
|
|
}
|
|
|
|
|
|
|
|
r = noRRSetupTestSilenced("--strtwo=a bogus")
|
|
|
|
if r.Output != "" {
|
|
|
|
t.Errorf("Unexpected response.\nExpecting to be:\n\"\"\nGot:\n %q\n", s, r.Output)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-11 23:04:58 +03:00
|
|
|
func TestRootSuggestions(t *testing.T) {
|
|
|
|
outputWithSuggestions := "Error: unknown command \"%s\" for \"cobra-test\"\n\nDid you mean this?\n\t%s\n\nRun 'cobra-test --help' for usage.\n"
|
|
|
|
outputWithoutSuggestions := "Error: unknown command \"%s\" for \"cobra-test\"\nRun 'cobra-test --help' for usage.\n"
|
|
|
|
|
|
|
|
cmd := initializeWithRootCmd()
|
|
|
|
cmd.AddCommand(cmdTimes)
|
|
|
|
|
|
|
|
tests := map[string]string{
|
2015-09-25 17:41:47 +03:00
|
|
|
"time": "times",
|
|
|
|
"tiems": "times",
|
|
|
|
"tims": "times",
|
|
|
|
"timeS": "times",
|
|
|
|
"rimes": "times",
|
|
|
|
"ti": "times",
|
|
|
|
"t": "times",
|
|
|
|
"timely": "times",
|
|
|
|
"ri": "",
|
|
|
|
"timezone": "",
|
|
|
|
"foo": "",
|
2015-09-25 18:04:28 +03:00
|
|
|
"counts": "times",
|
2015-09-11 23:04:58 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
for typo, suggestion := range tests {
|
2015-09-25 17:41:47 +03:00
|
|
|
for _, suggestionsDisabled := range []bool{false, true} {
|
|
|
|
cmd.DisableSuggestions = suggestionsDisabled
|
|
|
|
result := simpleTester(cmd, typo)
|
|
|
|
expected := ""
|
|
|
|
if len(suggestion) == 0 || suggestionsDisabled {
|
|
|
|
expected = fmt.Sprintf(outputWithoutSuggestions, typo)
|
|
|
|
} else {
|
|
|
|
expected = fmt.Sprintf(outputWithSuggestions, typo, suggestion)
|
|
|
|
}
|
|
|
|
if result.Output != expected {
|
|
|
|
t.Errorf("Unexpected response.\nExpecting to be:\n %q\nGot:\n %q\n", expected, result.Output)
|
|
|
|
}
|
2015-09-11 23:04:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-17 20:32:27 +04:00
|
|
|
func TestFlagsBeforeCommand(t *testing.T) {
|
|
|
|
// short without space
|
|
|
|
x := fullSetupTest("-i10 echo")
|
|
|
|
if x.Error != nil {
|
|
|
|
t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
// short (int) with equals
|
|
|
|
// It appears that pflags doesn't support this...
|
|
|
|
// Commenting out until support can be added
|
|
|
|
|
|
|
|
//x = noRRSetupTest("echo -i=10")
|
|
|
|
//if x.Error != nil {
|
|
|
|
//t.Errorf("Valid Input shouldn't have errors, got:\n %s", x.Error)
|
|
|
|
//}
|
|
|
|
|
|
|
|
// long with equals
|
|
|
|
x = noRRSetupTest("--intone=123 echo one two")
|
|
|
|
if x.Error != nil {
|
|
|
|
t.Errorf("Valid Input shouldn't have errors, got:\n %s", x.Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
// With parsing error properly reported
|
|
|
|
x = fullSetupTest("-i10E echo")
|
2015-10-26 04:58:53 +03:00
|
|
|
if !strings.Contains(x.Error.Error(), "invalid argument \"10E\" for i10E") {
|
|
|
|
t.Errorf("Wrong error message displayed, \n %s", x.Error)
|
2014-06-17 20:32:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
//With quotes
|
|
|
|
x = fullSetupTest("-s=\"walking\" echo")
|
|
|
|
if x.Error != nil {
|
|
|
|
t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
//With quotes and space
|
|
|
|
x = fullSetupTest("-s=\"walking fast\" echo")
|
|
|
|
if x.Error != nil {
|
|
|
|
t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
//With inner quote
|
|
|
|
x = fullSetupTest("-s=\"walking \\\"Inner Quote\\\" fast\" echo")
|
|
|
|
if x.Error != nil {
|
|
|
|
t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
//With quotes and space
|
|
|
|
x = fullSetupTest("-s=\"walking \\\"Inner Quote\\\" fast\" echo")
|
|
|
|
if x.Error != nil {
|
|
|
|
t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error)
|
|
|
|
}
|
|
|
|
|
2013-10-01 05:54:46 +04:00
|
|
|
}
|
2015-03-13 10:30:33 +03:00
|
|
|
|
|
|
|
func TestRemoveCommand(t *testing.T) {
|
|
|
|
versionUsed = 0
|
|
|
|
c := initializeWithRootCmd()
|
|
|
|
c.AddCommand(cmdVersion1)
|
|
|
|
c.RemoveCommand(cmdVersion1)
|
|
|
|
x := fullTester(c, "version")
|
|
|
|
if x.Error == nil {
|
|
|
|
t.Errorf("Removed command should not have been called\n")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-13 04:38:01 +03:00
|
|
|
func TestCommandWithoutSubcommands(t *testing.T) {
|
|
|
|
c := initializeWithRootCmd()
|
|
|
|
|
|
|
|
x := simpleTester(c, "")
|
|
|
|
if x.Error != nil {
|
|
|
|
t.Errorf("Calling command without subcommands should not have error: %v", x.Error)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommandWithoutSubcommandsWithArg(t *testing.T) {
|
|
|
|
c := initializeWithRootCmd()
|
|
|
|
expectedArgs := []string{"arg"}
|
|
|
|
|
|
|
|
x := simpleTester(c, "arg")
|
|
|
|
if x.Error != nil {
|
|
|
|
t.Errorf("Calling command without subcommands but with arg should not have error: %v", x.Error)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(expectedArgs, tr) {
|
|
|
|
t.Errorf("Calling command without subcommands but with arg has wrong args: expected: %v, actual: %v", expectedArgs, tr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-13 10:30:33 +03:00
|
|
|
func TestReplaceCommandWithRemove(t *testing.T) {
|
|
|
|
versionUsed = 0
|
|
|
|
c := initializeWithRootCmd()
|
|
|
|
c.AddCommand(cmdVersion1)
|
|
|
|
c.RemoveCommand(cmdVersion1)
|
|
|
|
c.AddCommand(cmdVersion2)
|
|
|
|
x := fullTester(c, "version")
|
|
|
|
if x.Error != nil {
|
|
|
|
t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if versionUsed == 1 {
|
|
|
|
t.Errorf("Removed command shouldn't be called\n")
|
|
|
|
}
|
|
|
|
if versionUsed != 2 {
|
|
|
|
t.Errorf("Replacing command should have been called but didn't\n")
|
|
|
|
}
|
|
|
|
}
|
2015-04-08 00:38:22 +03:00
|
|
|
|
|
|
|
func TestDeprecatedSub(t *testing.T) {
|
|
|
|
c := fullSetupTest("deprecated")
|
|
|
|
|
|
|
|
checkResultContains(t, c, cmdDeprecated.Deprecated)
|
|
|
|
}
|
2015-04-30 20:58:29 +03:00
|
|
|
|
|
|
|
func TestPreRun(t *testing.T) {
|
|
|
|
noRRSetupTest("echo one two")
|
|
|
|
if echoPre == nil || echoPersPre == nil {
|
|
|
|
t.Error("PreRun or PersistentPreRun not called")
|
|
|
|
}
|
|
|
|
if rootPersPre != nil || timesPersPre != nil {
|
|
|
|
t.Error("Wrong *Pre functions called!")
|
|
|
|
}
|
|
|
|
|
|
|
|
noRRSetupTest("echo times one two")
|
|
|
|
if timesPersPre == nil {
|
|
|
|
t.Error("PreRun or PersistentPreRun not called")
|
|
|
|
}
|
|
|
|
if echoPre != nil || echoPersPre != nil || rootPersPre != nil {
|
|
|
|
t.Error("Wrong *Pre functions called!")
|
|
|
|
}
|
|
|
|
|
|
|
|
noRRSetupTest("print one two")
|
|
|
|
if rootPersPre == nil {
|
|
|
|
t.Error("Parent PersistentPreRun not called but should not have been")
|
|
|
|
}
|
|
|
|
if echoPre != nil || echoPersPre != nil || timesPersPre != nil {
|
|
|
|
t.Error("Wrong *Pre functions called!")
|
|
|
|
}
|
|
|
|
}
|
2015-05-04 18:57:46 +03:00
|
|
|
|
|
|
|
// Check if cmdEchoSub gets PersistentPreRun from rootCmd even if is added last
|
|
|
|
func TestPeristentPreRunPropagation(t *testing.T) {
|
|
|
|
rootCmd := initialize()
|
|
|
|
|
|
|
|
// First add the cmdEchoSub to cmdPrint
|
|
|
|
cmdPrint.AddCommand(cmdEchoSub)
|
|
|
|
// Now add cmdPrint to rootCmd
|
|
|
|
rootCmd.AddCommand(cmdPrint)
|
|
|
|
|
|
|
|
rootCmd.SetArgs(strings.Split("print echosub lala", " "))
|
|
|
|
rootCmd.Execute()
|
|
|
|
|
|
|
|
if rootPersPre == nil || len(rootPersPre) == 0 || rootPersPre[0] != "lala" {
|
|
|
|
t.Error("RootCmd PersistentPreRun not called but should have been")
|
|
|
|
}
|
|
|
|
}
|
2015-05-14 20:38:15 +03:00
|
|
|
|
|
|
|
func TestGlobalNormFuncPropagation(t *testing.T) {
|
|
|
|
normFunc := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
|
|
|
return pflag.NormalizedName(name)
|
|
|
|
}
|
|
|
|
|
|
|
|
rootCmd := initialize()
|
|
|
|
rootCmd.SetGlobalNormalizationFunc(normFunc)
|
|
|
|
if reflect.ValueOf(normFunc) != reflect.ValueOf(rootCmd.GlobalNormalizationFunc()) {
|
|
|
|
t.Error("rootCmd seems to have a wrong normalization function")
|
|
|
|
}
|
|
|
|
|
|
|
|
// First add the cmdEchoSub to cmdPrint
|
|
|
|
cmdPrint.AddCommand(cmdEchoSub)
|
|
|
|
if cmdPrint.GlobalNormalizationFunc() != nil && cmdEchoSub.GlobalNormalizationFunc() != nil {
|
|
|
|
t.Error("cmdPrint and cmdEchoSub should had no normalization functions")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now add cmdPrint to rootCmd
|
|
|
|
rootCmd.AddCommand(cmdPrint)
|
|
|
|
if reflect.ValueOf(cmdPrint.GlobalNormalizationFunc()).Pointer() != reflect.ValueOf(rootCmd.GlobalNormalizationFunc()).Pointer() ||
|
|
|
|
reflect.ValueOf(cmdEchoSub.GlobalNormalizationFunc()).Pointer() != reflect.ValueOf(rootCmd.GlobalNormalizationFunc()).Pointer() {
|
|
|
|
t.Error("cmdPrint and cmdEchoSub should had the normalization function of rootCmd")
|
|
|
|
}
|
|
|
|
}
|
2015-08-17 08:14:43 +03:00
|
|
|
|
|
|
|
func TestFlagOnPflagCommandLine(t *testing.T) {
|
|
|
|
flagName := "flagOnCommandLine"
|
|
|
|
pflag.CommandLine.String(flagName, "", "about my flag")
|
|
|
|
r := fullSetupTest("--help")
|
|
|
|
|
|
|
|
checkResultContains(t, r, flagName)
|
|
|
|
}
|
2015-09-01 06:36:55 +03:00
|
|
|
|
|
|
|
func TestAddTemplateFunctions(t *testing.T) {
|
|
|
|
AddTemplateFunc("t", func() bool { return true })
|
|
|
|
AddTemplateFuncs(template.FuncMap{
|
2015-09-04 23:34:51 +03:00
|
|
|
"f": func() bool { return false },
|
|
|
|
"h": func() string { return "Hello," },
|
2015-09-01 06:36:55 +03:00
|
|
|
"w": func() string { return "world." }})
|
|
|
|
|
|
|
|
const usage = "Hello, world."
|
2015-09-04 23:34:51 +03:00
|
|
|
|
2015-09-01 06:36:55 +03:00
|
|
|
c := &Command{}
|
|
|
|
c.SetUsageTemplate(`{{if t}}{{h}}{{end}}{{if f}}{{h}}{{end}} {{w}}`)
|
2015-09-04 23:34:51 +03:00
|
|
|
|
2015-09-01 06:36:55 +03:00
|
|
|
if us := c.UsageString(); us != usage {
|
|
|
|
t.Errorf("c.UsageString() != \"%s\", is \"%s\"", usage, us)
|
|
|
|
}
|
|
|
|
}
|
2015-10-31 16:22:19 +03:00
|
|
|
|
|
|
|
func TestUsageIsNotPrintedTwice(t *testing.T) {
|
|
|
|
var cmd = &Command{Use: "root"}
|
|
|
|
var sub = &Command{Use: "sub"}
|
|
|
|
cmd.AddCommand(sub)
|
|
|
|
|
|
|
|
r := simpleTester(cmd, "")
|
|
|
|
if strings.Count(r.Output, "Usage:") != 1 {
|
|
|
|
t.Error("Usage output is not printed exactly once")
|
|
|
|
}
|
|
|
|
}
|