github.com/mheon/docker@v0.11.2-0.20150922122814-44f47903a831/pkg/integration/utils_test.go (about) 1 package integration 2 3 import ( 4 "io" 5 "io/ioutil" 6 "os" 7 "os/exec" 8 "path" 9 "strings" 10 "testing" 11 "time" 12 ) 13 14 func TestIsKilledFalseWithNonKilledProcess(t *testing.T) { 15 lsCmd := exec.Command("ls") 16 lsCmd.Start() 17 // Wait for it to finish 18 err := lsCmd.Wait() 19 if IsKilled(err) { 20 t.Fatalf("Expected the ls command to not be killed, was.") 21 } 22 } 23 24 func TestIsKilledTrueWithKilledProcess(t *testing.T) { 25 longCmd := exec.Command("top") 26 // Start a command 27 longCmd.Start() 28 // Capture the error when *dying* 29 done := make(chan error, 1) 30 go func() { 31 done <- longCmd.Wait() 32 }() 33 // Then kill it 34 longCmd.Process.Kill() 35 // Get the error 36 err := <-done 37 if !IsKilled(err) { 38 t.Fatalf("Expected the command to be killed, was not.") 39 } 40 } 41 42 func TestRunCommandWithOutput(t *testing.T) { 43 echoHelloWorldCmd := exec.Command("echo", "hello", "world") 44 out, exitCode, err := RunCommandWithOutput(echoHelloWorldCmd) 45 expected := "hello world\n" 46 if out != expected || exitCode != 0 || err != nil { 47 t.Fatalf("Expected command to output %s, got %s, %v with exitCode %v", expected, out, err, exitCode) 48 } 49 } 50 51 func TestRunCommandWithOutputError(t *testing.T) { 52 cmd := exec.Command("doesnotexists") 53 out, exitCode, err := RunCommandWithOutput(cmd) 54 expectedError := `exec: "doesnotexists": executable file not found in $PATH` 55 if out != "" || exitCode != 127 || err == nil || err.Error() != expectedError { 56 t.Fatalf("Expected command to output %s, got %s, %v with exitCode %v", expectedError, out, err, exitCode) 57 } 58 59 wrongLsCmd := exec.Command("ls", "-z") 60 expected := `ls: invalid option -- 'z' 61 Try 'ls --help' for more information. 62 ` 63 out, exitCode, err = RunCommandWithOutput(wrongLsCmd) 64 65 if out != expected || exitCode != 2 || err == nil || err.Error() != "exit status 2" { 66 t.Fatalf("Expected command to output %s, got out:%s, err:%v with exitCode %v", expected, out, err, exitCode) 67 } 68 } 69 70 func TestRunCommandWithStdoutStderr(t *testing.T) { 71 echoHelloWorldCmd := exec.Command("echo", "hello", "world") 72 stdout, stderr, exitCode, err := RunCommandWithStdoutStderr(echoHelloWorldCmd) 73 expected := "hello world\n" 74 if stdout != expected || stderr != "" || exitCode != 0 || err != nil { 75 t.Fatalf("Expected command to output %s, got stdout:%s, stderr:%s, err:%v with exitCode %v", expected, stdout, stderr, err, exitCode) 76 } 77 } 78 79 func TestRunCommandWithStdoutStderrError(t *testing.T) { 80 cmd := exec.Command("doesnotexists") 81 stdout, stderr, exitCode, err := RunCommandWithStdoutStderr(cmd) 82 expectedError := `exec: "doesnotexists": executable file not found in $PATH` 83 if stdout != "" || stderr != "" || exitCode != 127 || err == nil || err.Error() != expectedError { 84 t.Fatalf("Expected command to output out:%s, stderr:%s, got stdout:%s, stderr:%s, err:%v with exitCode %v", "", "", stdout, stderr, err, exitCode) 85 } 86 87 wrongLsCmd := exec.Command("ls", "-z") 88 expected := `ls: invalid option -- 'z' 89 Try 'ls --help' for more information. 90 ` 91 92 stdout, stderr, exitCode, err = RunCommandWithStdoutStderr(wrongLsCmd) 93 if stdout != "" && stderr != expected || exitCode != 2 || err == nil || err.Error() != "exit status 2" { 94 t.Fatalf("Expected command to output out:%s, stderr:%s, got stdout:%s, stderr:%s, err:%v with exitCode %v", "", expectedError, stdout, stderr, err, exitCode) 95 } 96 } 97 98 func TestRunCommandWithOutputForDurationFinished(t *testing.T) { 99 cmd := exec.Command("ls") 100 out, exitCode, timedOut, err := RunCommandWithOutputForDuration(cmd, 50*time.Millisecond) 101 if out == "" || exitCode != 0 || timedOut || err != nil { 102 t.Fatalf("Expected the command to run for less 50 milliseconds and thus not time out, but did not : out:[%s], exitCode:[%d], timedOut:[%v], err:[%v]", out, exitCode, timedOut, err) 103 } 104 } 105 106 func TestRunCommandWithOutputForDurationKilled(t *testing.T) { 107 cmd := exec.Command("sh", "-c", "while true ; do echo 1 ; sleep .1 ; done") 108 out, exitCode, timedOut, err := RunCommandWithOutputForDuration(cmd, 500*time.Millisecond) 109 ones := strings.Split(out, "\n") 110 if len(ones) != 6 || exitCode != 0 || !timedOut || err != nil { 111 t.Fatalf("Expected the command to run for 500 milliseconds (and thus print six lines (five with 1, one empty) and time out, but did not : out:[%s], exitCode:%d, timedOut:%v, err:%v", out, exitCode, timedOut, err) 112 } 113 } 114 115 func TestRunCommandWithOutputForDurationErrors(t *testing.T) { 116 cmd := exec.Command("ls") 117 cmd.Stdout = os.Stdout 118 if _, _, _, err := RunCommandWithOutputForDuration(cmd, 1*time.Millisecond); err == nil || err.Error() != "cmd.Stdout already set" { 119 t.Fatalf("Expected an error as cmd.Stdout was already set, did not (err:%s).", err) 120 } 121 cmd = exec.Command("ls") 122 cmd.Stderr = os.Stderr 123 if _, _, _, err := RunCommandWithOutputForDuration(cmd, 1*time.Millisecond); err == nil || err.Error() != "cmd.Stderr already set" { 124 t.Fatalf("Expected an error as cmd.Stderr was already set, did not (err:%s).", err) 125 } 126 } 127 128 func TestRunCommandWithOutputAndTimeoutFinished(t *testing.T) { 129 cmd := exec.Command("ls") 130 out, exitCode, err := RunCommandWithOutputAndTimeout(cmd, 50*time.Millisecond) 131 if out == "" || exitCode != 0 || err != nil { 132 t.Fatalf("Expected the command to run for less 50 milliseconds and thus not time out, but did not : out:[%s], exitCode:[%d], err:[%v]", out, exitCode, err) 133 } 134 } 135 136 func TestRunCommandWithOutputAndTimeoutKilled(t *testing.T) { 137 cmd := exec.Command("sh", "-c", "while true ; do echo 1 ; sleep .1 ; done") 138 out, exitCode, err := RunCommandWithOutputAndTimeout(cmd, 500*time.Millisecond) 139 ones := strings.Split(out, "\n") 140 if len(ones) != 6 || exitCode != 0 || err == nil || err.Error() != "command timed out" { 141 t.Fatalf("Expected the command to run for 500 milliseconds (and thus print six lines (five with 1, one empty) and time out with an error 'command timed out', but did not : out:[%s], exitCode:%d, err:%v", out, exitCode, err) 142 } 143 } 144 145 func TestRunCommandWithOutputAndTimeoutErrors(t *testing.T) { 146 cmd := exec.Command("ls") 147 cmd.Stdout = os.Stdout 148 if _, _, err := RunCommandWithOutputAndTimeout(cmd, 1*time.Millisecond); err == nil || err.Error() != "cmd.Stdout already set" { 149 t.Fatalf("Expected an error as cmd.Stdout was already set, did not (err:%s).", err) 150 } 151 cmd = exec.Command("ls") 152 cmd.Stderr = os.Stderr 153 if _, _, err := RunCommandWithOutputAndTimeout(cmd, 1*time.Millisecond); err == nil || err.Error() != "cmd.Stderr already set" { 154 t.Fatalf("Expected an error as cmd.Stderr was already set, did not (err:%s).", err) 155 } 156 } 157 158 func TestRunCommand(t *testing.T) { 159 lsCmd := exec.Command("ls") 160 exitCode, err := RunCommand(lsCmd) 161 if exitCode != 0 || err != nil { 162 t.Fatalf("Expected runCommand to run the command successfully, got: exitCode:%d, err:%v", exitCode, err) 163 } 164 165 var expectedError string 166 167 exitCode, err = RunCommand(exec.Command("doesnotexists")) 168 expectedError = `exec: "doesnotexists": executable file not found in $PATH` 169 if exitCode != 127 || err == nil || err.Error() != expectedError { 170 t.Fatalf("Expected runCommand to run the command successfully, got: exitCode:%d, err:%v", exitCode, err) 171 } 172 wrongLsCmd := exec.Command("ls", "-z") 173 expected := 2 174 expectedError = `exit status 2` 175 exitCode, err = RunCommand(wrongLsCmd) 176 if exitCode != expected || err == nil || err.Error() != expectedError { 177 t.Fatalf("Expected runCommand to run the command successfully, got: exitCode:%d, err:%v", exitCode, err) 178 } 179 } 180 181 func TestRunCommandPipelineWithOutputWithNotEnoughCmds(t *testing.T) { 182 _, _, err := RunCommandPipelineWithOutput(exec.Command("ls")) 183 expectedError := "pipeline does not have multiple cmds" 184 if err == nil || err.Error() != expectedError { 185 t.Fatalf("Expected an error with %s, got err:%s", expectedError, err) 186 } 187 } 188 189 func TestRunCommandPipelineWithOutputErrors(t *testing.T) { 190 cmd1 := exec.Command("ls") 191 cmd1.Stdout = os.Stdout 192 cmd2 := exec.Command("anything really") 193 _, _, err := RunCommandPipelineWithOutput(cmd1, cmd2) 194 if err == nil || err.Error() != "cannot set stdout pipe for anything really: exec: Stdout already set" { 195 t.Fatalf("Expected an error, got %v", err) 196 } 197 198 cmdWithError := exec.Command("doesnotexists") 199 cmdCat := exec.Command("cat") 200 _, _, err = RunCommandPipelineWithOutput(cmdWithError, cmdCat) 201 if err == nil || err.Error() != `starting doesnotexists failed with error: exec: "doesnotexists": executable file not found in $PATH` { 202 t.Fatalf("Expected an error, got %v", err) 203 } 204 } 205 206 func TestRunCommandPipelineWithOutput(t *testing.T) { 207 cmds := []*exec.Cmd{ 208 // Print 2 characters 209 exec.Command("echo", "-n", "11"), 210 // Count the number or char from stdin (previous command) 211 exec.Command("wc", "-m"), 212 } 213 out, exitCode, err := RunCommandPipelineWithOutput(cmds...) 214 expectedOutput := "2\n" 215 if out != expectedOutput || exitCode != 0 || err != nil { 216 t.Fatalf("Expected %s for commands %v, got out:%s, exitCode:%d, err:%v", expectedOutput, cmds, out, exitCode, err) 217 } 218 } 219 220 // Simple simple test as it is just a passthrough for json.Unmarshal 221 func TestUnmarshalJSON(t *testing.T) { 222 emptyResult := struct{}{} 223 if err := UnmarshalJSON([]byte(""), &emptyResult); err == nil { 224 t.Fatalf("Expected an error, got nothing") 225 } 226 result := struct{ Name string }{} 227 if err := UnmarshalJSON([]byte(`{"name": "name"}`), &result); err != nil { 228 t.Fatal(err) 229 } 230 if result.Name != "name" { 231 t.Fatalf("Expected result.name to be 'name', was '%s'", result.Name) 232 } 233 } 234 235 func TestConvertSliceOfStringsToMap(t *testing.T) { 236 input := []string{"a", "b"} 237 actual := ConvertSliceOfStringsToMap(input) 238 for _, key := range input { 239 if _, ok := actual[key]; !ok { 240 t.Fatalf("Expected output to contains key %s, did not: %v", key, actual) 241 } 242 } 243 } 244 245 func TestCompareDirectoryEntries(t *testing.T) { 246 tmpFolder, err := ioutil.TempDir("", "integration-cli-utils-compare-directories") 247 if err != nil { 248 t.Fatal(err) 249 } 250 defer os.RemoveAll(tmpFolder) 251 252 file1 := path.Join(tmpFolder, "file1") 253 file2 := path.Join(tmpFolder, "file2") 254 os.Create(file1) 255 os.Create(file2) 256 257 fi1, err := os.Stat(file1) 258 if err != nil { 259 t.Fatal(err) 260 } 261 fi1bis, err := os.Stat(file1) 262 if err != nil { 263 t.Fatal(err) 264 } 265 fi2, err := os.Stat(file2) 266 if err != nil { 267 t.Fatal(err) 268 } 269 270 cases := []struct { 271 e1 []os.FileInfo 272 e2 []os.FileInfo 273 shouldError bool 274 }{ 275 // Empty directories 276 { 277 []os.FileInfo{}, 278 []os.FileInfo{}, 279 false, 280 }, 281 // Same FileInfos 282 { 283 []os.FileInfo{fi1}, 284 []os.FileInfo{fi1}, 285 false, 286 }, 287 // Different FileInfos but same names 288 { 289 []os.FileInfo{fi1}, 290 []os.FileInfo{fi1bis}, 291 false, 292 }, 293 // Different FileInfos, different names 294 { 295 []os.FileInfo{fi1}, 296 []os.FileInfo{fi2}, 297 true, 298 }, 299 } 300 for _, elt := range cases { 301 err := CompareDirectoryEntries(elt.e1, elt.e2) 302 if elt.shouldError && err == nil { 303 t.Fatalf("Should have return an error, did not with %v and %v", elt.e1, elt.e2) 304 } 305 if !elt.shouldError && err != nil { 306 t.Fatalf("Should have not returned an error, but did : %v with %v and %v", err, elt.e1, elt.e2) 307 } 308 } 309 } 310 311 // FIXME make an "unhappy path" test for ListTar without "panicing" :-) 312 func TestListTar(t *testing.T) { 313 tmpFolder, err := ioutil.TempDir("", "integration-cli-utils-list-tar") 314 if err != nil { 315 t.Fatal(err) 316 } 317 defer os.RemoveAll(tmpFolder) 318 319 // Let's create a Tar file 320 srcFile := path.Join(tmpFolder, "src") 321 tarFile := path.Join(tmpFolder, "src.tar") 322 os.Create(srcFile) 323 cmd := exec.Command("/bin/sh", "-c", "tar cf "+tarFile+" "+srcFile) 324 _, err = cmd.CombinedOutput() 325 if err != nil { 326 t.Fatal(err) 327 } 328 329 reader, err := os.Open(tarFile) 330 if err != nil { 331 t.Fatal(err) 332 } 333 defer reader.Close() 334 335 entries, err := ListTar(reader) 336 if err != nil { 337 t.Fatal(err) 338 } 339 if len(entries) != 1 && entries[0] != "src" { 340 t.Fatalf("Expected a tar file with 1 entry (%s), got %v", srcFile, entries) 341 } 342 } 343 344 func TestRandomUnixTmpDirPath(t *testing.T) { 345 path := RandomUnixTmpDirPath("something") 346 347 prefix := "/tmp/something" 348 expectedSize := len(prefix) + 11 349 350 if !strings.HasPrefix(path, prefix) { 351 t.Fatalf("Expected generated path to have '%s' as prefix, got %s'", prefix, path) 352 } 353 if len(path) != expectedSize { 354 t.Fatalf("Expected generated path to be %d, got %d", expectedSize, len(path)) 355 } 356 } 357 358 func TestConsumeWithSpeed(t *testing.T) { 359 reader := strings.NewReader("1234567890") 360 chunksize := 2 361 362 bytes1, err := ConsumeWithSpeed(reader, chunksize, 1*time.Millisecond, nil) 363 if err != nil { 364 t.Fatal(err) 365 } 366 367 if bytes1 != 10 { 368 t.Fatalf("Expected to have read 10 bytes, got %d", bytes1) 369 } 370 371 } 372 373 func TestConsumeWithSpeedWithStop(t *testing.T) { 374 reader := strings.NewReader("1234567890") 375 chunksize := 2 376 377 stopIt := make(chan bool) 378 379 go func() { 380 time.Sleep(1 * time.Millisecond) 381 stopIt <- true 382 }() 383 384 bytes1, err := ConsumeWithSpeed(reader, chunksize, 2*time.Millisecond, stopIt) 385 if err != nil { 386 t.Fatal(err) 387 } 388 389 if bytes1 != 2 { 390 t.Fatalf("Expected to have read 2 bytes, got %d", bytes1) 391 } 392 393 } 394 395 func TestParseCgroupPathsEmpty(t *testing.T) { 396 cgroupMap := ParseCgroupPaths("") 397 if len(cgroupMap) != 0 { 398 t.Fatalf("Expected an empty map, got %v", cgroupMap) 399 } 400 cgroupMap = ParseCgroupPaths("\n") 401 if len(cgroupMap) != 0 { 402 t.Fatalf("Expected an empty map, got %v", cgroupMap) 403 } 404 cgroupMap = ParseCgroupPaths("something:else\nagain:here") 405 if len(cgroupMap) != 0 { 406 t.Fatalf("Expected an empty map, got %v", cgroupMap) 407 } 408 } 409 410 func TestParseCgroupPaths(t *testing.T) { 411 cgroupMap := ParseCgroupPaths("2:memory:/a\n1:cpuset:/b") 412 if len(cgroupMap) != 2 { 413 t.Fatalf("Expected a map with 2 entries, got %v", cgroupMap) 414 } 415 if value, ok := cgroupMap["memory"]; !ok || value != "/a" { 416 t.Fatalf("Expected cgroupMap to contains an entry for 'memory' with value '/a', got %v", cgroupMap) 417 } 418 if value, ok := cgroupMap["cpuset"]; !ok || value != "/b" { 419 t.Fatalf("Expected cgroupMap to contains an entry for 'cpuset' with value '/b', got %v", cgroupMap) 420 } 421 } 422 423 func TestChannelBufferTimeout(t *testing.T) { 424 expected := "11" 425 426 buf := &ChannelBuffer{make(chan []byte, 1)} 427 defer buf.Close() 428 429 go func() { 430 time.Sleep(100 * time.Millisecond) 431 io.Copy(buf, strings.NewReader(expected)) 432 }() 433 434 // Wait long enough 435 b := make([]byte, 2) 436 _, err := buf.ReadTimeout(b, 50*time.Millisecond) 437 if err == nil && err.Error() != "timeout reading from channel" { 438 t.Fatalf("Expected an error, got %s", err) 439 } 440 441 // Wait for the end :) 442 time.Sleep(150 * time.Millisecond) 443 } 444 445 func TestChannelBuffer(t *testing.T) { 446 expected := "11" 447 448 buf := &ChannelBuffer{make(chan []byte, 1)} 449 defer buf.Close() 450 451 go func() { 452 time.Sleep(100 * time.Millisecond) 453 io.Copy(buf, strings.NewReader(expected)) 454 }() 455 456 // Wait long enough 457 b := make([]byte, 2) 458 _, err := buf.ReadTimeout(b, 200*time.Millisecond) 459 if err != nil { 460 t.Fatal(err) 461 } 462 463 if string(b) != expected { 464 t.Fatalf("Expected '%s', got '%s'", expected, string(b)) 465 } 466 } 467 468 // FIXME doesn't work 469 // func TestRunAtDifferentDate(t *testing.T) { 470 // var date string 471 472 // // Layout for date. MMDDhhmmYYYY 473 // const timeLayout = "20060102" 474 // expectedDate := "20100201" 475 // theDate, err := time.Parse(timeLayout, expectedDate) 476 // if err != nil { 477 // t.Fatal(err) 478 // } 479 480 // RunAtDifferentDate(theDate, func() { 481 // cmd := exec.Command("date", "+%Y%M%d") 482 // out, err := cmd.Output() 483 // if err != nil { 484 // t.Fatal(err) 485 // } 486 // date = string(out) 487 // }) 488 // }