github.com/christopherobin/docker@v1.6.2/integration-cli/docker_cli_attach_test.go (about) 1 package main 2 3 import ( 4 "io" 5 "os/exec" 6 "strings" 7 "sync" 8 "testing" 9 "time" 10 ) 11 12 const attachWait = 5 * time.Second 13 14 func TestAttachMultipleAndRestart(t *testing.T) { 15 defer deleteAllContainers() 16 17 endGroup := &sync.WaitGroup{} 18 startGroup := &sync.WaitGroup{} 19 endGroup.Add(3) 20 startGroup.Add(3) 21 22 if err := waitForContainer("attacher", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 1; echo hello; done"); err != nil { 23 t.Fatal(err) 24 } 25 26 startDone := make(chan struct{}) 27 endDone := make(chan struct{}) 28 29 go func() { 30 endGroup.Wait() 31 close(endDone) 32 }() 33 34 go func() { 35 startGroup.Wait() 36 close(startDone) 37 }() 38 39 for i := 0; i < 3; i++ { 40 go func() { 41 c := exec.Command(dockerBinary, "attach", "attacher") 42 43 defer func() { 44 c.Wait() 45 endGroup.Done() 46 }() 47 48 out, err := c.StdoutPipe() 49 if err != nil { 50 t.Fatal(err) 51 } 52 53 if err := c.Start(); err != nil { 54 t.Fatal(err) 55 } 56 57 buf := make([]byte, 1024) 58 59 if _, err := out.Read(buf); err != nil && err != io.EOF { 60 t.Fatal(err) 61 } 62 63 startGroup.Done() 64 65 if !strings.Contains(string(buf), "hello") { 66 t.Fatalf("unexpected output %s expected hello\n", string(buf)) 67 } 68 }() 69 } 70 71 select { 72 case <-startDone: 73 case <-time.After(attachWait): 74 t.Fatalf("Attaches did not initialize properly") 75 } 76 77 cmd := exec.Command(dockerBinary, "kill", "attacher") 78 if _, err := runCommand(cmd); err != nil { 79 t.Fatal(err) 80 } 81 82 select { 83 case <-endDone: 84 case <-time.After(attachWait): 85 t.Fatalf("Attaches did not finish properly") 86 } 87 88 logDone("attach - multiple attach") 89 } 90 91 func TestAttachTtyWithoutStdin(t *testing.T) { 92 defer deleteAllContainers() 93 94 cmd := exec.Command(dockerBinary, "run", "-d", "-ti", "busybox") 95 out, _, err := runCommandWithOutput(cmd) 96 if err != nil { 97 t.Fatalf("failed to start container: %v (%v)", out, err) 98 } 99 100 id := strings.TrimSpace(out) 101 if err := waitRun(id); err != nil { 102 t.Fatal(err) 103 } 104 105 defer func() { 106 cmd := exec.Command(dockerBinary, "kill", id) 107 if out, _, err := runCommandWithOutput(cmd); err != nil { 108 t.Fatalf("failed to kill container: %v (%v)", out, err) 109 } 110 }() 111 112 done := make(chan struct{}) 113 go func() { 114 defer close(done) 115 116 cmd := exec.Command(dockerBinary, "attach", id) 117 if _, err := cmd.StdinPipe(); err != nil { 118 t.Fatal(err) 119 } 120 121 expected := "cannot enable tty mode" 122 if out, _, err := runCommandWithOutput(cmd); err == nil { 123 t.Fatal("attach should have failed") 124 } else if !strings.Contains(out, expected) { 125 t.Fatalf("attach failed with error %q: expected %q", out, expected) 126 } 127 }() 128 129 select { 130 case <-done: 131 case <-time.After(attachWait): 132 t.Fatal("attach is running but should have failed") 133 } 134 135 logDone("attach - forbid piped stdin to tty enabled container") 136 }