docker_cli_attach_unix_test.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // +build !windows
  2. package main
  3. import (
  4. "os/exec"
  5. "strings"
  6. "testing"
  7. "time"
  8. "github.com/kr/pty"
  9. )
  10. // #9860
  11. func TestAttachClosedOnContainerStop(t *testing.T) {
  12. defer deleteAllContainers()
  13. cmd := exec.Command(dockerBinary, "run", "-dti", "busybox", "sleep", "2")
  14. out, _, err := runCommandWithOutput(cmd)
  15. if err != nil {
  16. t.Fatalf("failed to start container: %v (%v)", out, err)
  17. }
  18. id := stripTrailingCharacters(out)
  19. if err := waitRun(id); err != nil {
  20. t.Fatal(err)
  21. }
  22. done := make(chan struct{})
  23. go func() {
  24. defer close(done)
  25. _, tty, err := pty.Open()
  26. if err != nil {
  27. t.Fatalf("could not open pty: %v", err)
  28. }
  29. attachCmd := exec.Command(dockerBinary, "attach", id)
  30. attachCmd.Stdin = tty
  31. attachCmd.Stdout = tty
  32. attachCmd.Stderr = tty
  33. if err := attachCmd.Run(); err != nil {
  34. t.Fatalf("attach returned error %s", err)
  35. }
  36. }()
  37. waitCmd := exec.Command(dockerBinary, "wait", id)
  38. if out, _, err = runCommandWithOutput(waitCmd); err != nil {
  39. t.Fatalf("error thrown while waiting for container: %s, %v", out, err)
  40. }
  41. select {
  42. case <-done:
  43. case <-time.After(attachWait):
  44. t.Fatal("timed out without attach returning")
  45. }
  46. logDone("attach - return after container finished")
  47. }
  48. func TestAttachAfterDetach(t *testing.T) {
  49. defer deleteAllContainers()
  50. name := "detachtest"
  51. cpty, tty, err := pty.Open()
  52. if err != nil {
  53. t.Fatalf("Could not open pty: %v", err)
  54. }
  55. cmd := exec.Command(dockerBinary, "run", "-ti", "--name", name, "busybox")
  56. cmd.Stdin = tty
  57. cmd.Stdout = tty
  58. cmd.Stderr = tty
  59. detached := make(chan struct{})
  60. go func() {
  61. if err := cmd.Run(); err != nil {
  62. t.Fatalf("attach returned error %s", err)
  63. }
  64. close(detached)
  65. }()
  66. time.Sleep(500 * time.Millisecond)
  67. cpty.Write([]byte{16})
  68. time.Sleep(100 * time.Millisecond)
  69. cpty.Write([]byte{17})
  70. <-detached
  71. cpty, tty, err = pty.Open()
  72. if err != nil {
  73. t.Fatalf("Could not open pty: %v", err)
  74. }
  75. cmd = exec.Command(dockerBinary, "attach", name)
  76. cmd.Stdin = tty
  77. cmd.Stdout = tty
  78. cmd.Stderr = tty
  79. go func() {
  80. if err := cmd.Run(); err != nil {
  81. t.Fatalf("attach returned error %s", err)
  82. }
  83. cpty.Close() // unblocks the reader in case of a failure
  84. }()
  85. time.Sleep(500 * time.Millisecond)
  86. cpty.Write([]byte("\n"))
  87. time.Sleep(500 * time.Millisecond)
  88. bytes := make([]byte, 10)
  89. n, err := cpty.Read(bytes)
  90. if err != nil {
  91. t.Fatalf("prompt read failed: %v", err)
  92. }
  93. if !strings.Contains(string(bytes[:n]), "/ #") {
  94. t.Fatalf("failed to get a new prompt. got %s", string(bytes[:n]))
  95. }
  96. cpty.Write([]byte("exit\n"))
  97. logDone("attach - reconnect after detaching")
  98. }