github.com/rsampaio/docker@v0.7.2-0.20150827203920-fdc73cc3fc31/integration-cli/docker_cli_attach_test.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "os/exec" 8 "strings" 9 "sync" 10 "time" 11 12 "github.com/go-check/check" 13 ) 14 15 const attachWait = 5 * time.Second 16 17 func (s *DockerSuite) TestAttachMultipleAndRestart(c *check.C) { 18 19 endGroup := &sync.WaitGroup{} 20 startGroup := &sync.WaitGroup{} 21 endGroup.Add(3) 22 startGroup.Add(3) 23 24 if err := waitForContainer("attacher", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 1; echo hello; done"); err != nil { 25 c.Fatal(err) 26 } 27 28 startDone := make(chan struct{}) 29 endDone := make(chan struct{}) 30 31 go func() { 32 endGroup.Wait() 33 close(endDone) 34 }() 35 36 go func() { 37 startGroup.Wait() 38 close(startDone) 39 }() 40 41 for i := 0; i < 3; i++ { 42 go func() { 43 cmd := exec.Command(dockerBinary, "attach", "attacher") 44 45 defer func() { 46 cmd.Wait() 47 endGroup.Done() 48 }() 49 50 out, err := cmd.StdoutPipe() 51 if err != nil { 52 c.Fatal(err) 53 } 54 55 if err := cmd.Start(); err != nil { 56 c.Fatal(err) 57 } 58 59 buf := make([]byte, 1024) 60 61 if _, err := out.Read(buf); err != nil && err != io.EOF { 62 c.Fatal(err) 63 } 64 65 startGroup.Done() 66 67 if !strings.Contains(string(buf), "hello") { 68 c.Fatalf("unexpected output %s expected hello\n", string(buf)) 69 } 70 }() 71 } 72 73 select { 74 case <-startDone: 75 case <-time.After(attachWait): 76 c.Fatalf("Attaches did not initialize properly") 77 } 78 79 dockerCmd(c, "kill", "attacher") 80 81 select { 82 case <-endDone: 83 case <-time.After(attachWait): 84 c.Fatalf("Attaches did not finish properly") 85 } 86 87 } 88 89 func (s *DockerSuite) TestAttachTtyWithoutStdin(c *check.C) { 90 out, _ := dockerCmd(c, "run", "-d", "-ti", "busybox") 91 92 id := strings.TrimSpace(out) 93 c.Assert(waitRun(id), check.IsNil) 94 95 defer func() { 96 cmd := exec.Command(dockerBinary, "kill", id) 97 if out, _, err := runCommandWithOutput(cmd); err != nil { 98 c.Fatalf("failed to kill container: %v (%v)", out, err) 99 } 100 }() 101 102 done := make(chan error) 103 go func() { 104 defer close(done) 105 106 cmd := exec.Command(dockerBinary, "attach", id) 107 if _, err := cmd.StdinPipe(); err != nil { 108 done <- err 109 return 110 } 111 112 expected := "cannot enable tty mode" 113 if out, _, err := runCommandWithOutput(cmd); err == nil { 114 done <- fmt.Errorf("attach should have failed") 115 return 116 } else if !strings.Contains(out, expected) { 117 done <- fmt.Errorf("attach failed with error %q: expected %q", out, expected) 118 return 119 } 120 }() 121 122 select { 123 case err := <-done: 124 c.Assert(err, check.IsNil) 125 case <-time.After(attachWait): 126 c.Fatal("attach is running but should have failed") 127 } 128 } 129 130 func (s *DockerSuite) TestAttachDisconnect(c *check.C) { 131 out, _ := dockerCmd(c, "run", "-di", "busybox", "/bin/cat") 132 id := strings.TrimSpace(out) 133 134 cmd := exec.Command(dockerBinary, "attach", id) 135 stdin, err := cmd.StdinPipe() 136 if err != nil { 137 c.Fatal(err) 138 } 139 defer stdin.Close() 140 stdout, err := cmd.StdoutPipe() 141 if err != nil { 142 c.Fatal(err) 143 } 144 defer stdout.Close() 145 if err := cmd.Start(); err != nil { 146 c.Fatal(err) 147 } 148 defer cmd.Process.Kill() 149 150 if _, err := stdin.Write([]byte("hello\n")); err != nil { 151 c.Fatal(err) 152 } 153 out, err = bufio.NewReader(stdout).ReadString('\n') 154 if err != nil { 155 c.Fatal(err) 156 } 157 if strings.TrimSpace(out) != "hello" { 158 c.Fatalf("expected 'hello', got %q", out) 159 } 160 161 if err := stdin.Close(); err != nil { 162 c.Fatal(err) 163 } 164 165 // Expect container to still be running after stdin is closed 166 running, err := inspectField(id, "State.Running") 167 if err != nil { 168 c.Fatal(err) 169 } 170 if running != "true" { 171 c.Fatal("expected container to still be running") 172 } 173 174 }