github.com/kcburge/terraform@v0.11.12-beta1/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 "" }