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