mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-26 00:41:27 -06:00
270ab97418
The shell autocomplete command will use the binary name as the first argument which does not show up under the list of subcommands.
312 lines
6.3 KiB
Go
312 lines
6.3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/mitchellh/cli"
|
|
)
|
|
|
|
func TestMain_cliArgsFromEnv(t *testing.T) {
|
|
// Set up the state. This test really messes with the environment and
|
|
// global state so we set things up to be restored.
|
|
|
|
// Restore original CLI args
|
|
oldArgs := os.Args
|
|
defer func() { os.Args = oldArgs }()
|
|
|
|
// Set up test command and restore that
|
|
Commands = make(map[string]cli.CommandFactory)
|
|
defer func() {
|
|
Commands = nil
|
|
}()
|
|
testCommandName := "unit-test-cli-args"
|
|
testCommand := &testCommandCLI{}
|
|
Commands[testCommandName] = func() (cli.Command, error) {
|
|
return testCommand, nil
|
|
}
|
|
|
|
cases := []struct {
|
|
Name string
|
|
Args []string
|
|
Value string
|
|
Expected []string
|
|
Err bool
|
|
}{
|
|
{
|
|
"no env",
|
|
[]string{testCommandName, "foo", "bar"},
|
|
"",
|
|
[]string{"foo", "bar"},
|
|
false,
|
|
},
|
|
|
|
{
|
|
"both env var and CLI",
|
|
[]string{testCommandName, "foo", "bar"},
|
|
"-foo bar",
|
|
[]string{"-foo", "bar", "foo", "bar"},
|
|
false,
|
|
},
|
|
|
|
{
|
|
"only env var",
|
|
[]string{testCommandName},
|
|
"-foo bar",
|
|
[]string{"-foo", "bar"},
|
|
false,
|
|
},
|
|
|
|
{
|
|
"cli string has blank values",
|
|
[]string{testCommandName, "bar", "", "baz"},
|
|
"-foo bar",
|
|
[]string{"-foo", "bar", "bar", "", "baz"},
|
|
false,
|
|
},
|
|
|
|
{
|
|
"cli string has blank values before the command",
|
|
[]string{"", testCommandName, "bar"},
|
|
"-foo bar",
|
|
[]string{"-foo", "bar", "bar"},
|
|
false,
|
|
},
|
|
|
|
{
|
|
// this should fail gracefully, this is just testing
|
|
// that we don't panic with our slice arithmetic
|
|
"no command",
|
|
[]string{},
|
|
"-foo bar",
|
|
nil,
|
|
true,
|
|
},
|
|
|
|
{
|
|
"single quoted strings",
|
|
[]string{testCommandName, "foo"},
|
|
"-foo 'bar baz'",
|
|
[]string{"-foo", "bar baz", "foo"},
|
|
false,
|
|
},
|
|
|
|
{
|
|
"double quoted strings",
|
|
[]string{testCommandName, "foo"},
|
|
`-foo "bar baz"`,
|
|
[]string{"-foo", "bar baz", "foo"},
|
|
false,
|
|
},
|
|
|
|
{
|
|
"double quoted single quoted strings",
|
|
[]string{testCommandName, "foo"},
|
|
`-foo "'bar baz'"`,
|
|
[]string{"-foo", "'bar baz'", "foo"},
|
|
false,
|
|
},
|
|
}
|
|
|
|
for i, tc := range cases {
|
|
t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) {
|
|
os.Unsetenv(EnvCLI)
|
|
defer os.Unsetenv(EnvCLI)
|
|
|
|
// Set the env var value
|
|
if tc.Value != "" {
|
|
if err := os.Setenv(EnvCLI, tc.Value); err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
}
|
|
|
|
// Set up the args
|
|
args := make([]string, len(tc.Args)+1)
|
|
args[0] = oldArgs[0] // process name
|
|
copy(args[1:], tc.Args)
|
|
|
|
// Run it!
|
|
os.Args = args
|
|
testCommand.Args = nil
|
|
exit := wrappedMain()
|
|
if (exit != 0) != tc.Err {
|
|
t.Fatalf("bad: %d", exit)
|
|
}
|
|
if tc.Err {
|
|
return
|
|
}
|
|
|
|
// Verify
|
|
if !reflect.DeepEqual(testCommand.Args, tc.Expected) {
|
|
t.Fatalf("bad: %#v", testCommand.Args)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// This test just has more options than the test above. Use this for
|
|
// more control over behavior at the expense of more complex test structures.
|
|
func TestMain_cliArgsFromEnvAdvanced(t *testing.T) {
|
|
// Restore original CLI args
|
|
oldArgs := os.Args
|
|
defer func() { os.Args = oldArgs }()
|
|
|
|
// Set up test command and restore that
|
|
Commands = make(map[string]cli.CommandFactory)
|
|
defer func() {
|
|
Commands = nil
|
|
}()
|
|
|
|
cases := []struct {
|
|
Name string
|
|
Command string
|
|
EnvVar string
|
|
Args []string
|
|
Value string
|
|
Expected []string
|
|
Err bool
|
|
}{
|
|
{
|
|
"targeted to another command",
|
|
"command",
|
|
EnvCLI + "_foo",
|
|
[]string{"command", "foo", "bar"},
|
|
"-flag",
|
|
[]string{"foo", "bar"},
|
|
false,
|
|
},
|
|
|
|
{
|
|
"targeted to this command",
|
|
"command",
|
|
EnvCLI + "_command",
|
|
[]string{"command", "foo", "bar"},
|
|
"-flag",
|
|
[]string{"-flag", "foo", "bar"},
|
|
false,
|
|
},
|
|
|
|
{
|
|
"targeted to a command with a hyphen",
|
|
"command-name",
|
|
EnvCLI + "_command_name",
|
|
[]string{"command-name", "foo", "bar"},
|
|
"-flag",
|
|
[]string{"-flag", "foo", "bar"},
|
|
false,
|
|
},
|
|
|
|
{
|
|
"targeted to a command with a space",
|
|
"command name",
|
|
EnvCLI + "_command_name",
|
|
[]string{"command", "name", "foo", "bar"},
|
|
"-flag",
|
|
[]string{"-flag", "foo", "bar"},
|
|
false,
|
|
},
|
|
}
|
|
|
|
for i, tc := range cases {
|
|
t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) {
|
|
// Set up test command and restore that
|
|
testCommandName := tc.Command
|
|
testCommand := &testCommandCLI{}
|
|
defer func() { delete(Commands, testCommandName) }()
|
|
Commands[testCommandName] = func() (cli.Command, error) {
|
|
return testCommand, nil
|
|
}
|
|
|
|
os.Unsetenv(tc.EnvVar)
|
|
defer os.Unsetenv(tc.EnvVar)
|
|
|
|
// Set the env var value
|
|
if tc.Value != "" {
|
|
if err := os.Setenv(tc.EnvVar, tc.Value); err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
}
|
|
|
|
// Set up the args
|
|
args := make([]string, len(tc.Args)+1)
|
|
args[0] = oldArgs[0] // process name
|
|
copy(args[1:], tc.Args)
|
|
|
|
// Run it!
|
|
os.Args = args
|
|
testCommand.Args = nil
|
|
exit := wrappedMain()
|
|
if (exit != 0) != tc.Err {
|
|
t.Fatalf("unexpected exit status %d; want 0", exit)
|
|
}
|
|
if tc.Err {
|
|
return
|
|
}
|
|
|
|
// Verify
|
|
if !reflect.DeepEqual(testCommand.Args, tc.Expected) {
|
|
t.Fatalf("bad: %#v", testCommand.Args)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// verify that we output valid autocomplete results
|
|
func TestMain_autoComplete(t *testing.T) {
|
|
// Restore original CLI args
|
|
oldArgs := os.Args
|
|
defer func() { os.Args = oldArgs }()
|
|
|
|
// Set up test command and restore that
|
|
Commands = make(map[string]cli.CommandFactory)
|
|
defer func() {
|
|
Commands = nil
|
|
}()
|
|
|
|
// Set up test command and restore that
|
|
Commands["foo"] = func() (cli.Command, error) {
|
|
return &testCommandCLI{}, nil
|
|
}
|
|
|
|
os.Setenv("COMP_LINE", "terraform versio")
|
|
defer os.Unsetenv("COMP_LINE")
|
|
|
|
// Run it!
|
|
os.Args = []string{"terraform", "terraform", "versio"}
|
|
exit := wrappedMain()
|
|
if exit != 0 {
|
|
t.Fatalf("unexpected exit status %d; want 0", exit)
|
|
}
|
|
}
|
|
|
|
type testCommandCLI struct {
|
|
Args []string
|
|
}
|
|
|
|
func (c *testCommandCLI) Run(args []string) int {
|
|
c.Args = args
|
|
return 0
|
|
}
|
|
|
|
func (c *testCommandCLI) Synopsis() string { return "" }
|
|
func (c *testCommandCLI) Help() string { return "" }
|
|
|
|
func TestWarnOutput(t *testing.T) {
|
|
mock := cli.NewMockUi()
|
|
wrapped := &ui{mock}
|
|
wrapped.Warn("WARNING")
|
|
|
|
stderr := mock.ErrorWriter.String()
|
|
stdout := mock.OutputWriter.String()
|
|
|
|
if stderr != "" {
|
|
t.Fatalf("unexpected stderr: %q", stderr)
|
|
}
|
|
|
|
if stdout != "WARNING\n" {
|
|
t.Fatalf("unexpected stdout: %q\n", stdout)
|
|
}
|
|
}
|