github.com/slava-ustovytski/docker@v1.8.2-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 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 if err := waitRun(id); err != nil { 94 c.Fatal(err) 95 } 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 out, _ := dockerCmd(c, "run", "-di", "busybox", "/bin/cat") 134 id := strings.TrimSpace(out) 135 136 cmd := exec.Command(dockerBinary, "attach", id) 137 stdin, err := cmd.StdinPipe() 138 if err != nil { 139 c.Fatal(err) 140 } 141 defer stdin.Close() 142 stdout, err := cmd.StdoutPipe() 143 if err != nil { 144 c.Fatal(err) 145 } 146 defer stdout.Close() 147 if err := cmd.Start(); err != nil { 148 c.Fatal(err) 149 } 150 defer cmd.Process.Kill() 151 152 if _, err := stdin.Write([]byte("hello\n")); err != nil { 153 c.Fatal(err) 154 } 155 out, err = bufio.NewReader(stdout).ReadString('\n') 156 if err != nil { 157 c.Fatal(err) 158 } 159 if strings.TrimSpace(out) != "hello" { 160 c.Fatalf("expected 'hello', got %q", out) 161 } 162 163 if err := stdin.Close(); err != nil { 164 c.Fatal(err) 165 } 166 167 // Expect container to still be running after stdin is closed 168 running, err := inspectField(id, "State.Running") 169 if err != nil { 170 c.Fatal(err) 171 } 172 if running != "true" { 173 c.Fatal("expected container to still be running") 174 } 175 176 }