docker_cli_attach_unix_test.go 2.5 KB

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