github.com/guilhermebr/docker@v1.4.2-0.20150428121140-67da055cebca/integration-cli/docker_cli_attach_unix_test.go (about) 1 // +build !windows 2 3 package main 4 5 import ( 6 "bufio" 7 "os/exec" 8 "strings" 9 "time" 10 11 "github.com/docker/docker/pkg/stringid" 12 "github.com/go-check/check" 13 "github.com/kr/pty" 14 ) 15 16 // #9860 17 func (s *DockerSuite) TestAttachClosedOnContainerStop(c *check.C) { 18 19 cmd := exec.Command(dockerBinary, "run", "-dti", "busybox", "sleep", "2") 20 out, _, err := runCommandWithOutput(cmd) 21 if err != nil { 22 c.Fatalf("failed to start container: %v (%v)", out, err) 23 } 24 25 id := strings.TrimSpace(out) 26 if err := waitRun(id); err != nil { 27 c.Fatal(err) 28 } 29 30 done := make(chan struct{}) 31 32 go func() { 33 defer close(done) 34 35 _, tty, err := pty.Open() 36 if err != nil { 37 c.Fatalf("could not open pty: %v", err) 38 } 39 attachCmd := exec.Command(dockerBinary, "attach", id) 40 attachCmd.Stdin = tty 41 attachCmd.Stdout = tty 42 attachCmd.Stderr = tty 43 44 if err := attachCmd.Run(); err != nil { 45 c.Fatalf("attach returned error %s", err) 46 } 47 }() 48 49 waitCmd := exec.Command(dockerBinary, "wait", id) 50 if out, _, err = runCommandWithOutput(waitCmd); err != nil { 51 c.Fatalf("error thrown while waiting for container: %s, %v", out, err) 52 } 53 select { 54 case <-done: 55 case <-time.After(attachWait): 56 c.Fatal("timed out without attach returning") 57 } 58 59 } 60 61 func (s *DockerSuite) TestAttachAfterDetach(c *check.C) { 62 63 name := "detachtest" 64 65 cpty, tty, err := pty.Open() 66 if err != nil { 67 c.Fatalf("Could not open pty: %v", err) 68 } 69 cmd := exec.Command(dockerBinary, "run", "-ti", "--name", name, "busybox") 70 cmd.Stdin = tty 71 cmd.Stdout = tty 72 cmd.Stderr = tty 73 74 detached := make(chan struct{}) 75 go func() { 76 if err := cmd.Run(); err != nil { 77 c.Fatalf("attach returned error %s", err) 78 } 79 close(detached) 80 }() 81 82 time.Sleep(500 * time.Millisecond) 83 if err := waitRun(name); err != nil { 84 c.Fatal(err) 85 } 86 cpty.Write([]byte{16}) 87 time.Sleep(100 * time.Millisecond) 88 cpty.Write([]byte{17}) 89 90 <-detached 91 92 cpty, tty, err = pty.Open() 93 if err != nil { 94 c.Fatalf("Could not open pty: %v", err) 95 } 96 97 cmd = exec.Command(dockerBinary, "attach", name) 98 cmd.Stdin = tty 99 cmd.Stdout = tty 100 cmd.Stderr = tty 101 102 if err := cmd.Start(); err != nil { 103 c.Fatal(err) 104 } 105 106 bytes := make([]byte, 10) 107 var nBytes int 108 readErr := make(chan error, 1) 109 110 go func() { 111 time.Sleep(500 * time.Millisecond) 112 cpty.Write([]byte("\n")) 113 time.Sleep(500 * time.Millisecond) 114 115 nBytes, err = cpty.Read(bytes) 116 cpty.Close() 117 readErr <- err 118 }() 119 120 select { 121 case err := <-readErr: 122 if err != nil { 123 c.Fatal(err) 124 } 125 case <-time.After(2 * time.Second): 126 c.Fatal("timeout waiting for attach read") 127 } 128 129 if err := cmd.Wait(); err != nil { 130 c.Fatal(err) 131 } 132 133 if !strings.Contains(string(bytes[:nBytes]), "/ #") { 134 c.Fatalf("failed to get a new prompt. got %s", string(bytes[:nBytes])) 135 } 136 137 } 138 139 // TestAttachDetach checks that attach in tty mode can be detached using the long container ID 140 func (s *DockerSuite) TestAttachDetach(c *check.C) { 141 out, _ := dockerCmd(c, "run", "-itd", "busybox", "cat") 142 id := strings.TrimSpace(out) 143 if err := waitRun(id); err != nil { 144 c.Fatal(err) 145 } 146 147 cpty, tty, err := pty.Open() 148 if err != nil { 149 c.Fatal(err) 150 } 151 defer cpty.Close() 152 153 cmd := exec.Command(dockerBinary, "attach", id) 154 cmd.Stdin = tty 155 stdout, err := cmd.StdoutPipe() 156 if err != nil { 157 c.Fatal(err) 158 } 159 defer stdout.Close() 160 if err := cmd.Start(); err != nil { 161 c.Fatal(err) 162 } 163 if err := waitRun(id); err != nil { 164 c.Fatalf("error waiting for container to start: %v", err) 165 } 166 167 if _, err := cpty.Write([]byte("hello\n")); err != nil { 168 c.Fatal(err) 169 } 170 out, err = bufio.NewReader(stdout).ReadString('\n') 171 if err != nil { 172 c.Fatal(err) 173 } 174 if strings.TrimSpace(out) != "hello" { 175 c.Fatalf("expected 'hello', got %q", out) 176 } 177 178 // escape sequence 179 if _, err := cpty.Write([]byte{16}); err != nil { 180 c.Fatal(err) 181 } 182 time.Sleep(100 * time.Millisecond) 183 if _, err := cpty.Write([]byte{17}); err != nil { 184 c.Fatal(err) 185 } 186 187 ch := make(chan struct{}) 188 go func() { 189 cmd.Wait() 190 ch <- struct{}{} 191 }() 192 193 running, err := inspectField(id, "State.Running") 194 if err != nil { 195 c.Fatal(err) 196 } 197 if running != "true" { 198 c.Fatal("expected container to still be running") 199 } 200 201 go func() { 202 dockerCmd(c, "kill", id) 203 }() 204 205 select { 206 case <-ch: 207 case <-time.After(10 * time.Millisecond): 208 c.Fatal("timed out waiting for container to exit") 209 } 210 211 } 212 213 // TestAttachDetachTruncatedID checks that attach in tty mode can be detached 214 func (s *DockerSuite) TestAttachDetachTruncatedID(c *check.C) { 215 out, _ := dockerCmd(c, "run", "-itd", "busybox", "cat") 216 id := stringid.TruncateID(strings.TrimSpace(out)) 217 if err := waitRun(id); err != nil { 218 c.Fatal(err) 219 } 220 221 cpty, tty, err := pty.Open() 222 if err != nil { 223 c.Fatal(err) 224 } 225 defer cpty.Close() 226 227 cmd := exec.Command(dockerBinary, "attach", id) 228 cmd.Stdin = tty 229 stdout, err := cmd.StdoutPipe() 230 if err != nil { 231 c.Fatal(err) 232 } 233 defer stdout.Close() 234 if err := cmd.Start(); err != nil { 235 c.Fatal(err) 236 } 237 238 if _, err := cpty.Write([]byte("hello\n")); err != nil { 239 c.Fatal(err) 240 } 241 out, err = bufio.NewReader(stdout).ReadString('\n') 242 if err != nil { 243 c.Fatal(err) 244 } 245 if strings.TrimSpace(out) != "hello" { 246 c.Fatalf("expected 'hello', got %q", out) 247 } 248 249 // escape sequence 250 if _, err := cpty.Write([]byte{16}); err != nil { 251 c.Fatal(err) 252 } 253 time.Sleep(100 * time.Millisecond) 254 if _, err := cpty.Write([]byte{17}); err != nil { 255 c.Fatal(err) 256 } 257 258 ch := make(chan struct{}) 259 go func() { 260 cmd.Wait() 261 ch <- struct{}{} 262 }() 263 264 running, err := inspectField(id, "State.Running") 265 if err != nil { 266 c.Fatal(err) 267 } 268 if running != "true" { 269 c.Fatal("expected container to still be running") 270 } 271 272 go func() { 273 dockerCmd(c, "kill", id) 274 }() 275 276 select { 277 case <-ch: 278 case <-time.After(10 * time.Millisecond): 279 c.Fatal("timed out waiting for container to exit") 280 } 281 282 }