docker_cli_attach_unix_test.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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. if err := waitRun(name); err != nil {
  68. t.Fatal(err)
  69. }
  70. cpty.Write([]byte{16})
  71. time.Sleep(100 * time.Millisecond)
  72. cpty.Write([]byte{17})
  73. <-detached
  74. cpty, tty, err = pty.Open()
  75. if err != nil {
  76. t.Fatalf("Could not open pty: %v", err)
  77. }
  78. cmd = exec.Command(dockerBinary, "attach", name)
  79. cmd.Stdin = tty
  80. cmd.Stdout = tty
  81. cmd.Stderr = tty
  82. if err := cmd.Start(); err != nil {
  83. t.Fatal(err)
  84. }
  85. bytes := make([]byte, 10)
  86. var nBytes int
  87. readErr := make(chan error, 1)
  88. go func() {
  89. time.Sleep(500 * time.Millisecond)
  90. cpty.Write([]byte("\n"))
  91. time.Sleep(500 * time.Millisecond)
  92. nBytes, err = cpty.Read(bytes)
  93. cpty.Close()
  94. readErr <- err
  95. }()
  96. select {
  97. case err := <-readErr:
  98. if err != nil {
  99. t.Fatal(err)
  100. }
  101. case <-time.After(2 * time.Second):
  102. t.Fatal("timeout waiting for attach read")
  103. }
  104. if err := cmd.Wait(); err != nil {
  105. t.Fatal(err)
  106. }
  107. if !strings.Contains(string(bytes[:nBytes]), "/ #") {
  108. t.Fatalf("failed to get a new prompt. got %s", string(bytes[:nBytes]))
  109. }
  110. logDone("attach - reconnect after detaching")
  111. }