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