github.com/ben-turner/terraform@v0.11.8-0.20180503104400-0cc9e050ecd4/main_test.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"reflect"
     7  	"testing"
     8  
     9  	"github.com/mitchellh/cli"
    10  )
    11  
    12  func TestMain_cliArgsFromEnv(t *testing.T) {
    13  	// Setup the state. This test really messes with the environment and
    14  	// global state so we set things up to be restored.
    15  
    16  	// Restore original CLI args
    17  	oldArgs := os.Args
    18  	defer func() { os.Args = oldArgs }()
    19  
    20  	// Setup test command and restore that
    21  	Commands = make(map[string]cli.CommandFactory)
    22  	defer func() {
    23  		Commands = nil
    24  	}()
    25  	testCommandName := "unit-test-cli-args"
    26  	testCommand := &testCommandCLI{}
    27  	Commands[testCommandName] = func() (cli.Command, error) {
    28  		return testCommand, nil
    29  	}
    30  
    31  	cases := []struct {
    32  		Name     string
    33  		Args     []string
    34  		Value    string
    35  		Expected []string
    36  		Err      bool
    37  	}{
    38  		{
    39  			"no env",
    40  			[]string{testCommandName, "foo", "bar"},
    41  			"",
    42  			[]string{"foo", "bar"},
    43  			false,
    44  		},
    45  
    46  		{
    47  			"both env var and CLI",
    48  			[]string{testCommandName, "foo", "bar"},
    49  			"-foo bar",
    50  			[]string{"-foo", "bar", "foo", "bar"},
    51  			false,
    52  		},
    53  
    54  		{
    55  			"only env var",
    56  			[]string{testCommandName},
    57  			"-foo bar",
    58  			[]string{"-foo", "bar"},
    59  			false,
    60  		},
    61  
    62  		{
    63  			"cli string has blank values",
    64  			[]string{testCommandName, "bar", "", "baz"},
    65  			"-foo bar",
    66  			[]string{"-foo", "bar", "bar", "", "baz"},
    67  			false,
    68  		},
    69  
    70  		{
    71  			"cli string has blank values before the command",
    72  			[]string{"", testCommandName, "bar"},
    73  			"-foo bar",
    74  			[]string{"-foo", "bar", "bar"},
    75  			false,
    76  		},
    77  
    78  		{
    79  			// this should fail gracefully, this is just testing
    80  			// that we don't panic with our slice arithmetic
    81  			"no command",
    82  			[]string{},
    83  			"-foo bar",
    84  			nil,
    85  			true,
    86  		},
    87  
    88  		{
    89  			"single quoted strings",
    90  			[]string{testCommandName, "foo"},
    91  			"-foo 'bar baz'",
    92  			[]string{"-foo", "bar baz", "foo"},
    93  			false,
    94  		},
    95  
    96  		{
    97  			"double quoted strings",
    98  			[]string{testCommandName, "foo"},
    99  			`-foo "bar baz"`,
   100  			[]string{"-foo", "bar baz", "foo"},
   101  			false,
   102  		},
   103  
   104  		{
   105  			"double quoted single quoted strings",
   106  			[]string{testCommandName, "foo"},
   107  			`-foo "'bar baz'"`,
   108  			[]string{"-foo", "'bar baz'", "foo"},
   109  			false,
   110  		},
   111  	}
   112  
   113  	for i, tc := range cases {
   114  		t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) {
   115  			os.Unsetenv(EnvCLI)
   116  			defer os.Unsetenv(EnvCLI)
   117  
   118  			// Set the env var value
   119  			if tc.Value != "" {
   120  				if err := os.Setenv(EnvCLI, tc.Value); err != nil {
   121  					t.Fatalf("err: %s", err)
   122  				}
   123  			}
   124  
   125  			// Setup the args
   126  			args := make([]string, len(tc.Args)+1)
   127  			args[0] = oldArgs[0] // process name
   128  			copy(args[1:], tc.Args)
   129  
   130  			// Run it!
   131  			os.Args = args
   132  			testCommand.Args = nil
   133  			exit := wrappedMain()
   134  			if (exit != 0) != tc.Err {
   135  				t.Fatalf("bad: %d", exit)
   136  			}
   137  			if tc.Err {
   138  				return
   139  			}
   140  
   141  			// Verify
   142  			if !reflect.DeepEqual(testCommand.Args, tc.Expected) {
   143  				t.Fatalf("bad: %#v", testCommand.Args)
   144  			}
   145  		})
   146  	}
   147  }
   148  
   149  // This test just has more options than the test above. Use this for
   150  // more control over behavior at the expense of more complex test structures.
   151  func TestMain_cliArgsFromEnvAdvanced(t *testing.T) {
   152  	// Restore original CLI args
   153  	oldArgs := os.Args
   154  	defer func() { os.Args = oldArgs }()
   155  
   156  	// Setup test command and restore that
   157  	Commands = make(map[string]cli.CommandFactory)
   158  	defer func() {
   159  		Commands = nil
   160  	}()
   161  
   162  	cases := []struct {
   163  		Name     string
   164  		Command  string
   165  		EnvVar   string
   166  		Args     []string
   167  		Value    string
   168  		Expected []string
   169  		Err      bool
   170  	}{
   171  		{
   172  			"targeted to another command",
   173  			"command",
   174  			EnvCLI + "_foo",
   175  			[]string{"command", "foo", "bar"},
   176  			"-flag",
   177  			[]string{"foo", "bar"},
   178  			false,
   179  		},
   180  
   181  		{
   182  			"targeted to this command",
   183  			"command",
   184  			EnvCLI + "_command",
   185  			[]string{"command", "foo", "bar"},
   186  			"-flag",
   187  			[]string{"-flag", "foo", "bar"},
   188  			false,
   189  		},
   190  
   191  		{
   192  			"targeted to a command with a hyphen",
   193  			"command-name",
   194  			EnvCLI + "_command_name",
   195  			[]string{"command-name", "foo", "bar"},
   196  			"-flag",
   197  			[]string{"-flag", "foo", "bar"},
   198  			false,
   199  		},
   200  
   201  		{
   202  			"targeted to a command with a space",
   203  			"command name",
   204  			EnvCLI + "_command_name",
   205  			[]string{"command", "name", "foo", "bar"},
   206  			"-flag",
   207  			[]string{"-flag", "foo", "bar"},
   208  			false,
   209  		},
   210  	}
   211  
   212  	for i, tc := range cases {
   213  		t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) {
   214  			// Setup test command and restore that
   215  			testCommandName := tc.Command
   216  			testCommand := &testCommandCLI{}
   217  			defer func() { delete(Commands, testCommandName) }()
   218  			Commands[testCommandName] = func() (cli.Command, error) {
   219  				return testCommand, nil
   220  			}
   221  
   222  			os.Unsetenv(tc.EnvVar)
   223  			defer os.Unsetenv(tc.EnvVar)
   224  
   225  			// Set the env var value
   226  			if tc.Value != "" {
   227  				if err := os.Setenv(tc.EnvVar, tc.Value); err != nil {
   228  					t.Fatalf("err: %s", err)
   229  				}
   230  			}
   231  
   232  			// Setup the args
   233  			args := make([]string, len(tc.Args)+1)
   234  			args[0] = oldArgs[0] // process name
   235  			copy(args[1:], tc.Args)
   236  
   237  			// Run it!
   238  			os.Args = args
   239  			testCommand.Args = nil
   240  			exit := wrappedMain()
   241  			if (exit != 0) != tc.Err {
   242  				t.Fatalf("unexpected exit status %d; want 0", exit)
   243  			}
   244  			if tc.Err {
   245  				return
   246  			}
   247  
   248  			// Verify
   249  			if !reflect.DeepEqual(testCommand.Args, tc.Expected) {
   250  				t.Fatalf("bad: %#v", testCommand.Args)
   251  			}
   252  		})
   253  	}
   254  }
   255  
   256  type testCommandCLI struct {
   257  	Args []string
   258  }
   259  
   260  func (c *testCommandCLI) Run(args []string) int {
   261  	c.Args = args
   262  	return 0
   263  }
   264  
   265  func (c *testCommandCLI) Synopsis() string { return "" }
   266  func (c *testCommandCLI) Help() string     { return "" }