github.com/mheon/docker@v0.11.2-0.20150922122814-44f47903a831/pkg/integration/dockerCmd_utils_test.go (about) 1 package integration 2 3 import ( 4 "fmt" 5 "os" 6 "os/exec" 7 "testing" 8 9 "io/ioutil" 10 "strings" 11 "time" 12 13 "github.com/go-check/check" 14 ) 15 16 const dockerBinary = "docker" 17 18 // Setup go-check for this test 19 func Test(t *testing.T) { 20 check.TestingT(t) 21 } 22 23 func init() { 24 check.Suite(&DockerCmdSuite{}) 25 } 26 27 type DockerCmdSuite struct{} 28 29 // Fake the exec.Command to use our mock. 30 func (s *DockerCmdSuite) SetUpTest(c *check.C) { 31 execCommand = fakeExecCommand 32 } 33 34 // And bring it back to normal after the test. 35 func (s *DockerCmdSuite) TearDownTest(c *check.C) { 36 execCommand = exec.Command 37 } 38 39 // DockerCmdWithError tests 40 41 func (s *DockerCmdSuite) TestDockerCmdWithError(c *check.C) { 42 cmds := []struct { 43 binary string 44 args []string 45 expectedOut string 46 expectedExitCode int 47 expectedError error 48 }{ 49 { 50 "doesnotexists", 51 []string{}, 52 "Command doesnotexists not found.", 53 1, 54 fmt.Errorf("exit status 1"), 55 }, 56 { 57 dockerBinary, 58 []string{"an", "error"}, 59 "an error has occurred", 60 1, 61 fmt.Errorf("exit status 1"), 62 }, 63 { 64 dockerBinary, 65 []string{"an", "exitCode", "127"}, 66 "an error has occurred with exitCode 127", 67 127, 68 fmt.Errorf("exit status 127"), 69 }, 70 { 71 dockerBinary, 72 []string{"run", "-ti", "ubuntu", "echo", "hello"}, 73 "hello", 74 0, 75 nil, 76 }, 77 } 78 for _, cmd := range cmds { 79 out, exitCode, error := DockerCmdWithError(cmd.binary, cmd.args...) 80 c.Assert(out, check.Equals, cmd.expectedOut, check.Commentf("Expected output %q for arguments %v, got %q", cmd.expectedOut, cmd.args, out)) 81 c.Assert(exitCode, check.Equals, cmd.expectedExitCode, check.Commentf("Expected exitCode %q for arguments %v, got %q", cmd.expectedExitCode, cmd.args, exitCode)) 82 if cmd.expectedError != nil { 83 c.Assert(error, check.NotNil, check.Commentf("Expected an error %q, got nothing", cmd.expectedError)) 84 c.Assert(error.Error(), check.Equals, cmd.expectedError.Error(), check.Commentf("Expected error %q for arguments %v, got %q", cmd.expectedError.Error(), cmd.args, error.Error())) 85 } else { 86 c.Assert(error, check.IsNil, check.Commentf("Expected no error, got %v", error)) 87 } 88 } 89 } 90 91 // DockerCmdWithStdoutStderr tests 92 93 type dockerCmdWithStdoutStderrErrorSuite struct{} 94 95 func (s *dockerCmdWithStdoutStderrErrorSuite) Test(c *check.C) { 96 // Should fail, the test too 97 DockerCmdWithStdoutStderr(dockerBinary, c, "an", "error") 98 } 99 100 type dockerCmdWithStdoutStderrSuccessSuite struct{} 101 102 func (s *dockerCmdWithStdoutStderrSuccessSuite) Test(c *check.C) { 103 stdout, stderr, exitCode := DockerCmdWithStdoutStderr(dockerBinary, c, "run", "-ti", "ubuntu", "echo", "hello") 104 c.Assert(stdout, check.Equals, "hello") 105 c.Assert(stderr, check.Equals, "") 106 c.Assert(exitCode, check.Equals, 0) 107 108 } 109 110 func (s *DockerCmdSuite) TestDockerCmdWithStdoutStderrError(c *check.C) { 111 // Run error suite, should fail. 112 output := String{} 113 result := check.Run(&dockerCmdWithStdoutStderrErrorSuite{}, &check.RunConf{Output: &output}) 114 c.Check(result.Succeeded, check.Equals, 0) 115 c.Check(result.Failed, check.Equals, 1) 116 } 117 118 func (s *DockerCmdSuite) TestDockerCmdWithStdoutStderrSuccess(c *check.C) { 119 // Run error suite, should fail. 120 output := String{} 121 result := check.Run(&dockerCmdWithStdoutStderrSuccessSuite{}, &check.RunConf{Output: &output}) 122 c.Check(result.Succeeded, check.Equals, 1) 123 c.Check(result.Failed, check.Equals, 0) 124 } 125 126 // DockerCmd tests 127 128 type dockerCmdErrorSuite struct{} 129 130 func (s *dockerCmdErrorSuite) Test(c *check.C) { 131 // Should fail, the test too 132 DockerCmd(dockerBinary, c, "an", "error") 133 } 134 135 type dockerCmdSuccessSuite struct{} 136 137 func (s *dockerCmdSuccessSuite) Test(c *check.C) { 138 stdout, exitCode := DockerCmd(dockerBinary, c, "run", "-ti", "ubuntu", "echo", "hello") 139 c.Assert(stdout, check.Equals, "hello") 140 c.Assert(exitCode, check.Equals, 0) 141 142 } 143 144 func (s *DockerCmdSuite) TestDockerCmdError(c *check.C) { 145 // Run error suite, should fail. 146 output := String{} 147 result := check.Run(&dockerCmdErrorSuite{}, &check.RunConf{Output: &output}) 148 c.Check(result.Succeeded, check.Equals, 0) 149 c.Check(result.Failed, check.Equals, 1) 150 } 151 152 func (s *DockerCmdSuite) TestDockerCmdSuccess(c *check.C) { 153 // Run error suite, should fail. 154 output := String{} 155 result := check.Run(&dockerCmdSuccessSuite{}, &check.RunConf{Output: &output}) 156 c.Check(result.Succeeded, check.Equals, 1) 157 c.Check(result.Failed, check.Equals, 0) 158 } 159 160 // DockerCmdWithTimeout tests 161 162 func (s *DockerCmdSuite) TestDockerCmdWithTimeout(c *check.C) { 163 c.Skip("racey test") 164 cmds := []struct { 165 binary string 166 args []string 167 timeout time.Duration 168 expectedOut string 169 expectedExitCode int 170 expectedError error 171 }{ 172 { 173 "doesnotexists", 174 []string{}, 175 5 * time.Millisecond, 176 `Command doesnotexists not found.`, 177 1, 178 fmt.Errorf(`"" failed with errors: exit status 1 : "Command doesnotexists not found."`), 179 }, 180 { 181 dockerBinary, 182 []string{"an", "error"}, 183 5 * time.Millisecond, 184 `an error has occurred`, 185 1, 186 fmt.Errorf(`"an error" failed with errors: exit status 1 : "an error has occurred"`), 187 }, 188 { 189 dockerBinary, 190 []string{"a", "command", "that", "times", "out"}, 191 5 * time.Millisecond, 192 "", 193 0, 194 fmt.Errorf(`"a command that times out" failed with errors: command timed out : ""`), 195 }, 196 { 197 dockerBinary, 198 []string{"run", "-ti", "ubuntu", "echo", "hello"}, 199 5 * time.Millisecond, 200 "hello", 201 0, 202 nil, 203 }, 204 } 205 for _, cmd := range cmds { 206 out, exitCode, error := DockerCmdWithTimeout(cmd.binary, cmd.timeout, cmd.args...) 207 c.Assert(out, check.Equals, cmd.expectedOut, check.Commentf("Expected output %q for arguments %v, got %q", cmd.expectedOut, cmd.args, out)) 208 c.Assert(exitCode, check.Equals, cmd.expectedExitCode, check.Commentf("Expected exitCode %q for arguments %v, got %q", cmd.expectedExitCode, cmd.args, exitCode)) 209 if cmd.expectedError != nil { 210 c.Assert(error, check.NotNil, check.Commentf("Expected an error %q, got nothing", cmd.expectedError)) 211 c.Assert(error.Error(), check.Equals, cmd.expectedError.Error(), check.Commentf("Expected error %q for arguments %v, got %q", cmd.expectedError.Error(), cmd.args, error.Error())) 212 } else { 213 c.Assert(error, check.IsNil, check.Commentf("Expected no error, got %v", error)) 214 } 215 } 216 } 217 218 // DockerCmdInDir tests 219 220 func (s *DockerCmdSuite) TestDockerCmdInDir(c *check.C) { 221 tempFolder, err := ioutil.TempDir("", "test-docker-cmd-in-dir") 222 c.Assert(err, check.IsNil) 223 224 cmds := []struct { 225 binary string 226 args []string 227 expectedOut string 228 expectedExitCode int 229 expectedError error 230 }{ 231 { 232 "doesnotexists", 233 []string{}, 234 `Command doesnotexists not found.`, 235 1, 236 fmt.Errorf(`"dir:%s" failed with errors: exit status 1 : "Command doesnotexists not found."`, tempFolder), 237 }, 238 { 239 dockerBinary, 240 []string{"an", "error"}, 241 `an error has occurred`, 242 1, 243 fmt.Errorf(`"dir:%s an error" failed with errors: exit status 1 : "an error has occurred"`, tempFolder), 244 }, 245 { 246 dockerBinary, 247 []string{"run", "-ti", "ubuntu", "echo", "hello"}, 248 "hello", 249 0, 250 nil, 251 }, 252 } 253 for _, cmd := range cmds { 254 // We prepend the arguments with dir:thefolder.. the fake command will check 255 // that the current workdir is the same as the one we are passing. 256 args := append([]string{"dir:" + tempFolder}, cmd.args...) 257 out, exitCode, error := DockerCmdInDir(cmd.binary, tempFolder, args...) 258 c.Assert(out, check.Equals, cmd.expectedOut, check.Commentf("Expected output %q for arguments %v, got %q", cmd.expectedOut, cmd.args, out)) 259 c.Assert(exitCode, check.Equals, cmd.expectedExitCode, check.Commentf("Expected exitCode %q for arguments %v, got %q", cmd.expectedExitCode, cmd.args, exitCode)) 260 if cmd.expectedError != nil { 261 c.Assert(error, check.NotNil, check.Commentf("Expected an error %q, got nothing", cmd.expectedError)) 262 c.Assert(error.Error(), check.Equals, cmd.expectedError.Error(), check.Commentf("Expected error %q for arguments %v, got %q", cmd.expectedError.Error(), cmd.args, error.Error())) 263 } else { 264 c.Assert(error, check.IsNil, check.Commentf("Expected no error, got %v", error)) 265 } 266 } 267 } 268 269 // DockerCmdInDirWithTimeout tests 270 271 func (s *DockerCmdSuite) TestDockerCmdInDirWithTimeout(c *check.C) { 272 c.Skip("racey test") 273 tempFolder, err := ioutil.TempDir("", "test-docker-cmd-in-dir") 274 c.Assert(err, check.IsNil) 275 276 cmds := []struct { 277 binary string 278 args []string 279 timeout time.Duration 280 expectedOut string 281 expectedExitCode int 282 expectedError error 283 }{ 284 { 285 "doesnotexists", 286 []string{}, 287 5 * time.Millisecond, 288 `Command doesnotexists not found.`, 289 1, 290 fmt.Errorf(`"dir:%s" failed with errors: exit status 1 : "Command doesnotexists not found."`, tempFolder), 291 }, 292 { 293 dockerBinary, 294 []string{"an", "error"}, 295 5 * time.Millisecond, 296 `an error has occurred`, 297 1, 298 fmt.Errorf(`"dir:%s an error" failed with errors: exit status 1 : "an error has occurred"`, tempFolder), 299 }, 300 { 301 dockerBinary, 302 []string{"a", "command", "that", "times", "out"}, 303 5 * time.Millisecond, 304 "", 305 0, 306 fmt.Errorf(`"dir:%s a command that times out" failed with errors: command timed out : ""`, tempFolder), 307 }, 308 { 309 dockerBinary, 310 []string{"run", "-ti", "ubuntu", "echo", "hello"}, 311 5 * time.Millisecond, 312 "hello", 313 0, 314 nil, 315 }, 316 } 317 for _, cmd := range cmds { 318 // We prepend the arguments with dir:thefolder.. the fake command will check 319 // that the current workdir is the same as the one we are passing. 320 args := append([]string{"dir:" + tempFolder}, cmd.args...) 321 out, exitCode, error := DockerCmdInDirWithTimeout(cmd.binary, cmd.timeout, tempFolder, args...) 322 c.Assert(out, check.Equals, cmd.expectedOut, check.Commentf("Expected output %q for arguments %v, got %q", cmd.expectedOut, cmd.args, out)) 323 c.Assert(exitCode, check.Equals, cmd.expectedExitCode, check.Commentf("Expected exitCode %q for arguments %v, got %q", cmd.expectedExitCode, cmd.args, exitCode)) 324 if cmd.expectedError != nil { 325 c.Assert(error, check.NotNil, check.Commentf("Expected an error %q, got nothing", cmd.expectedError)) 326 c.Assert(error.Error(), check.Equals, cmd.expectedError.Error(), check.Commentf("Expected error %q for arguments %v, got %q", cmd.expectedError.Error(), cmd.args, error.Error())) 327 } else { 328 c.Assert(error, check.IsNil, check.Commentf("Expected no error, got %v", error)) 329 } 330 } 331 } 332 333 // Helpers :) 334 335 // Type implementing the io.Writer interface for analyzing output. 336 type String struct { 337 value string 338 } 339 340 // The only function required by the io.Writer interface. Will append 341 // written data to the String.value string. 342 func (s *String) Write(p []byte) (n int, err error) { 343 s.value += string(p) 344 return len(p), nil 345 } 346 347 // Helper function that mock the exec.Command call (and call the test binary) 348 func fakeExecCommand(command string, args ...string) *exec.Cmd { 349 cs := []string{"-test.run=TestHelperProcess", "--", command} 350 cs = append(cs, args...) 351 cmd := exec.Command(os.Args[0], cs...) 352 cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} 353 return cmd 354 } 355 356 func TestHelperProcess(t *testing.T) { 357 if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" { 358 return 359 } 360 args := os.Args 361 362 // Previous arguments are tests stuff, that looks like : 363 // /tmp/go-build970079519/…/_test/integration.test -test.run=TestHelperProcess -- 364 cmd, args := args[3], args[4:] 365 // Handle the case where args[0] is dir:... 366 if len(args) > 0 && strings.HasPrefix(args[0], "dir:") { 367 expectedCwd := args[0][4:] 368 if len(args) > 1 { 369 args = args[1:] 370 } 371 cwd, err := os.Getwd() 372 if err != nil { 373 fmt.Fprintf(os.Stderr, "Failed to get workingdir: %v", err) 374 os.Exit(1) 375 } 376 // This checks that the given path is the same as the currend working dire 377 if expectedCwd != cwd { 378 fmt.Fprintf(os.Stderr, "Current workdir should be %q, but is %q", expectedCwd, cwd) 379 } 380 } 381 switch cmd { 382 case dockerBinary: 383 argsStr := strings.Join(args, " ") 384 switch argsStr { 385 case "an exitCode 127": 386 fmt.Fprintf(os.Stderr, "an error has occurred with exitCode 127") 387 os.Exit(127) 388 case "an error": 389 fmt.Fprintf(os.Stderr, "an error has occurred") 390 os.Exit(1) 391 case "a command that times out": 392 time.Sleep(10 * time.Millisecond) 393 fmt.Fprintf(os.Stdout, "too long, should be killed") 394 os.Exit(0) 395 case "run -ti ubuntu echo hello": 396 fmt.Fprintf(os.Stdout, "hello") 397 default: 398 fmt.Fprintf(os.Stdout, "no arguments") 399 } 400 default: 401 fmt.Fprintf(os.Stderr, "Command %s not found.", cmd) 402 os.Exit(1) 403 } 404 // some code here to check arguments perhaps? 405 os.Exit(0) 406 }