docker_cli_attach_unix_test.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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. if err := cmd.Start(); err != nil {
  80. t.Fatal(err)
  81. }
  82. bytes := make([]byte, 10)
  83. var nBytes int
  84. readErr := make(chan error, 1)
  85. go func() {
  86. time.Sleep(500 * time.Millisecond)
  87. cpty.Write([]byte("\n"))
  88. time.Sleep(500 * time.Millisecond)
  89. nBytes, err = cpty.Read(bytes)
  90. cpty.Close()
  91. readErr <- err
  92. }()
  93. select {
  94. case err := <-readErr:
  95. if err != nil {
  96. t.Fatal(err)
  97. }
  98. case <-time.After(2 * time.Second):
  99. t.Fatal("timeout waiting for attach read")
  100. }
  101. if err := cmd.Wait(); err != nil {
  102. t.Fatal(err)
  103. }
  104. if !strings.Contains(string(bytes[:nBytes]), "/ #") {
  105. t.Fatalf("failed to get a new prompt. got %s", string(bytes[:nBytes]))
  106. }
  107. logDone("attach - reconnect after detaching")
  108. }