mirror of
https://github.com/spf13/cobra
synced 2024-11-04 21:07:19 +00:00
Merge 8e2c9596e1
into bd914e58d6
This commit is contained in:
commit
e067c98fad
2 changed files with 93 additions and 6 deletions
|
@ -1058,7 +1058,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
|
|||
|
||||
// Regardless of what command execute is called on, run on Root only
|
||||
if c.HasParent() {
|
||||
return c.Root().ExecuteC()
|
||||
return c.Root().ExecuteContextC(c.ctx)
|
||||
}
|
||||
|
||||
// windows hook
|
||||
|
@ -1108,11 +1108,8 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
|
|||
cmd.commandCalledAs.name = cmd.Name()
|
||||
}
|
||||
|
||||
// We have to pass global context to children command
|
||||
// if context is present on the parent command.
|
||||
if cmd.ctx == nil {
|
||||
cmd.ctx = c.ctx
|
||||
}
|
||||
// Pass context of root command to child command.
|
||||
cmd.ctx = c.ctx
|
||||
|
||||
err = cmd.execute(flags)
|
||||
if err != nil {
|
||||
|
|
|
@ -232,6 +232,96 @@ func TestExecuteContextC(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// This tests that the context passed to the root command propagates to its children
|
||||
// not only on the first execution but also subsequent calls.
|
||||
// Calling the same command multiple times is common when testing cobra applications.
|
||||
func TestExecuteContextMultiple(t *testing.T) {
|
||||
var key string
|
||||
|
||||
// Define unique contexts so we can tell them apart below.
|
||||
ctxs := []context.Context{
|
||||
context.WithValue(context.Background(), &key, "1"),
|
||||
context.WithValue(context.Background(), &key, "2"),
|
||||
}
|
||||
|
||||
// Shared reference to the context in the current iteration.
|
||||
var currentCtx context.Context
|
||||
|
||||
ctxRun := func(cmd *Command, args []string) {
|
||||
if cmd.Context() != currentCtx {
|
||||
t.Errorf("Command %q must have context with value %s", cmd.Use, currentCtx.Value(&key))
|
||||
}
|
||||
}
|
||||
|
||||
rootCmd := &Command{Use: "root", Run: ctxRun, PreRun: ctxRun}
|
||||
childCmd := &Command{Use: "child", Run: ctxRun, PreRun: ctxRun}
|
||||
granchildCmd := &Command{Use: "grandchild", Run: ctxRun, PreRun: ctxRun}
|
||||
|
||||
childCmd.AddCommand(granchildCmd)
|
||||
rootCmd.AddCommand(childCmd)
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
currentCtx = ctxs[i]
|
||||
|
||||
if _, err := executeCommandWithContext(currentCtx, rootCmd, ""); err != nil {
|
||||
t.Errorf("Root command must not fail: %+v", err)
|
||||
}
|
||||
|
||||
if _, err := executeCommandWithContext(currentCtx, rootCmd, "child"); err != nil {
|
||||
t.Errorf("Subcommand must not fail: %+v", err)
|
||||
}
|
||||
|
||||
if _, err := executeCommandWithContext(currentCtx, rootCmd, "child", "grandchild"); err != nil {
|
||||
t.Errorf("Command child must not fail: %+v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This tests that the context passed to a subcommand propagates to the root.
|
||||
// If the entry point happens to be different from the root command, the
|
||||
// context should still propagate throughout the execution.
|
||||
func TestExecuteContextOnSubcommand(t *testing.T) {
|
||||
var key string
|
||||
|
||||
// Define unique contexts so we can tell them apart below.
|
||||
ctxs := []context.Context{
|
||||
context.WithValue(context.Background(), &key, "1"),
|
||||
context.WithValue(context.Background(), &key, "2"),
|
||||
context.WithValue(context.Background(), &key, "3"),
|
||||
}
|
||||
|
||||
// Shared reference to the context in the current iteration.
|
||||
var currentCtx context.Context
|
||||
|
||||
ctxRun := func(cmd *Command, args []string) {
|
||||
if cmd.Context() != currentCtx {
|
||||
t.Errorf("Command %q must have context with value %s", cmd.Use, currentCtx.Value(&key))
|
||||
}
|
||||
}
|
||||
|
||||
rootCmd := &Command{Use: "root", Run: ctxRun, PreRun: ctxRun}
|
||||
childCmd := &Command{Use: "child", Run: ctxRun, PreRun: ctxRun}
|
||||
granchildCmd := &Command{Use: "grandchild", Run: ctxRun, PreRun: ctxRun}
|
||||
|
||||
childCmd.AddCommand(granchildCmd)
|
||||
rootCmd.AddCommand(childCmd)
|
||||
|
||||
currentCtx = ctxs[0]
|
||||
if _, err := executeCommandWithContext(currentCtx, rootCmd, ""); err != nil {
|
||||
t.Errorf("Root command must not fail: %+v", err)
|
||||
}
|
||||
|
||||
currentCtx = ctxs[1]
|
||||
if _, err := executeCommandWithContext(currentCtx, childCmd, "child"); err != nil {
|
||||
t.Errorf("Subcommand must not fail: %+v", err)
|
||||
}
|
||||
|
||||
currentCtx = ctxs[2]
|
||||
if _, err := executeCommandWithContext(currentCtx, granchildCmd, "child", "grandchild"); err != nil {
|
||||
t.Errorf("Command child must not fail: %+v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecute_NoContext(t *testing.T) {
|
||||
run := func(cmd *Command, args []string) {
|
||||
if cmd.Context() != context.Background() {
|
||||
|
|
Loading…
Reference in a new issue