Signed-off-by: Brian Goff <cpuguy83@gmail.com>
| ... | ... |
@@ -3,6 +3,7 @@ |
| 3 | 3 |
package main |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 |
+ "bufio" |
|
| 6 | 7 |
"os/exec" |
| 7 | 8 |
"strings" |
| 8 | 9 |
"testing" |
| ... | ... |
@@ -137,3 +138,78 @@ func TestAttachAfterDetach(t *testing.T) {
|
| 137 | 137 |
|
| 138 | 138 |
logDone("attach - reconnect after detaching")
|
| 139 | 139 |
} |
| 140 |
+ |
|
| 141 |
+// TestAttachDetach checks that attach in tty mode can be detached using the long container ID |
|
| 142 |
+func TestAttachDetach(t *testing.T) {
|
|
| 143 |
+ out, _, _ := dockerCmd(t, "run", "-itd", "busybox", "cat") |
|
| 144 |
+ id := strings.TrimSpace(out) |
|
| 145 |
+ if err := waitRun(id); err != nil {
|
|
| 146 |
+ t.Fatal(err) |
|
| 147 |
+ } |
|
| 148 |
+ |
|
| 149 |
+ cpty, tty, err := pty.Open() |
|
| 150 |
+ if err != nil {
|
|
| 151 |
+ t.Fatal(err) |
|
| 152 |
+ } |
|
| 153 |
+ defer cpty.Close() |
|
| 154 |
+ |
|
| 155 |
+ cmd := exec.Command(dockerBinary, "attach", id) |
|
| 156 |
+ cmd.Stdin = tty |
|
| 157 |
+ stdout, err := cmd.StdoutPipe() |
|
| 158 |
+ if err != nil {
|
|
| 159 |
+ t.Fatal(err) |
|
| 160 |
+ } |
|
| 161 |
+ defer stdout.Close() |
|
| 162 |
+ if err := cmd.Start(); err != nil {
|
|
| 163 |
+ t.Fatal(err) |
|
| 164 |
+ } |
|
| 165 |
+ if err := waitRun(id); err != nil {
|
|
| 166 |
+ t.Fatalf("error waiting for container to start: %v", err)
|
|
| 167 |
+ } |
|
| 168 |
+ |
|
| 169 |
+ if _, err := cpty.Write([]byte("hello\n")); err != nil {
|
|
| 170 |
+ t.Fatal(err) |
|
| 171 |
+ } |
|
| 172 |
+ out, err = bufio.NewReader(stdout).ReadString('\n')
|
|
| 173 |
+ if err != nil {
|
|
| 174 |
+ t.Fatal(err) |
|
| 175 |
+ } |
|
| 176 |
+ if strings.TrimSpace(out) != "hello" {
|
|
| 177 |
+ t.Fatalf("exepected 'hello', got %q", out)
|
|
| 178 |
+ } |
|
| 179 |
+ |
|
| 180 |
+ // escape sequence |
|
| 181 |
+ if _, err := cpty.Write([]byte{16}); err != nil {
|
|
| 182 |
+ t.Fatal(err) |
|
| 183 |
+ } |
|
| 184 |
+ time.Sleep(100 * time.Millisecond) |
|
| 185 |
+ if _, err := cpty.Write([]byte{17}); err != nil {
|
|
| 186 |
+ t.Fatal(err) |
|
| 187 |
+ } |
|
| 188 |
+ |
|
| 189 |
+ ch := make(chan struct{})
|
|
| 190 |
+ go func() {
|
|
| 191 |
+ cmd.Wait() |
|
| 192 |
+ ch <- struct{}{}
|
|
| 193 |
+ }() |
|
| 194 |
+ |
|
| 195 |
+ running, err := inspectField(id, "State.Running") |
|
| 196 |
+ if err != nil {
|
|
| 197 |
+ t.Fatal(err) |
|
| 198 |
+ } |
|
| 199 |
+ if running != "true" {
|
|
| 200 |
+ t.Fatal("exepected container to still be running")
|
|
| 201 |
+ } |
|
| 202 |
+ |
|
| 203 |
+ go func() {
|
|
| 204 |
+ dockerCmd(t, "kill", id) |
|
| 205 |
+ }() |
|
| 206 |
+ |
|
| 207 |
+ select {
|
|
| 208 |
+ case <-ch: |
|
| 209 |
+ case <-time.After(10 * time.Millisecond): |
|
| 210 |
+ t.Fatal("timed out waiting for container to exit")
|
|
| 211 |
+ } |
|
| 212 |
+ |
|
| 213 |
+ logDone("attach - detach")
|
|
| 214 |
+} |
| ... | ... |
@@ -113,94 +113,6 @@ func assertPipe(input, output string, r io.Reader, w io.Writer, count int) error |
| 113 | 113 |
return nil |
| 114 | 114 |
} |
| 115 | 115 |
|
| 116 |
-// TestAttachDetach checks that attach in tty mode can be detached using the long container ID |
|
| 117 |
-func TestAttachDetach(t *testing.T) {
|
|
| 118 |
- stdout, stdoutPipe := io.Pipe() |
|
| 119 |
- cpty, tty, err := pty.Open() |
|
| 120 |
- if err != nil {
|
|
| 121 |
- t.Fatal(err) |
|
| 122 |
- } |
|
| 123 |
- |
|
| 124 |
- cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil) |
|
| 125 |
- defer cleanup(globalEngine, t) |
|
| 126 |
- |
|
| 127 |
- ch := make(chan struct{})
|
|
| 128 |
- go func() {
|
|
| 129 |
- defer close(ch) |
|
| 130 |
- if err := cli.CmdRun("-i", "-t", "-d", unitTestImageID, "cat"); err != nil {
|
|
| 131 |
- t.Fatal(err) |
|
| 132 |
- } |
|
| 133 |
- }() |
|
| 134 |
- |
|
| 135 |
- container := waitContainerStart(t, 10*time.Second) |
|
| 136 |
- |
|
| 137 |
- setTimeout(t, "Reading container's id timed out", 10*time.Second, func() {
|
|
| 138 |
- buf := make([]byte, 1024) |
|
| 139 |
- n, err := stdout.Read(buf) |
|
| 140 |
- if err != nil {
|
|
| 141 |
- t.Fatal(err) |
|
| 142 |
- } |
|
| 143 |
- |
|
| 144 |
- if strings.Trim(string(buf[:n]), " \r\n") != container.ID {
|
|
| 145 |
- t.Fatalf("Wrong ID received. Expect %s, received %s", container.ID, buf[:n])
|
|
| 146 |
- } |
|
| 147 |
- }) |
|
| 148 |
- setTimeout(t, "Starting container timed out", 10*time.Second, func() {
|
|
| 149 |
- <-ch |
|
| 150 |
- }) |
|
| 151 |
- |
|
| 152 |
- state := setRaw(t, container) |
|
| 153 |
- defer unsetRaw(t, container, state) |
|
| 154 |
- |
|
| 155 |
- stdout, stdoutPipe = io.Pipe() |
|
| 156 |
- cpty, tty, err = pty.Open() |
|
| 157 |
- if err != nil {
|
|
| 158 |
- t.Fatal(err) |
|
| 159 |
- } |
|
| 160 |
- |
|
| 161 |
- cli = client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil) |
|
| 162 |
- |
|
| 163 |
- ch = make(chan struct{})
|
|
| 164 |
- go func() {
|
|
| 165 |
- defer close(ch) |
|
| 166 |
- if err := cli.CmdAttach(container.ID); err != nil {
|
|
| 167 |
- if err != io.ErrClosedPipe {
|
|
| 168 |
- t.Fatal(err) |
|
| 169 |
- } |
|
| 170 |
- } |
|
| 171 |
- }() |
|
| 172 |
- |
|
| 173 |
- setTimeout(t, "First read/write assertion timed out", 2*time.Second, func() {
|
|
| 174 |
- if err := assertPipe("hello\n", "hello", stdout, cpty, 150); err != nil {
|
|
| 175 |
- if err != io.ErrClosedPipe {
|
|
| 176 |
- t.Fatal(err) |
|
| 177 |
- } |
|
| 178 |
- } |
|
| 179 |
- }) |
|
| 180 |
- |
|
| 181 |
- setTimeout(t, "Escape sequence timeout", 5*time.Second, func() {
|
|
| 182 |
- cpty.Write([]byte{16})
|
|
| 183 |
- time.Sleep(100 * time.Millisecond) |
|
| 184 |
- cpty.Write([]byte{17})
|
|
| 185 |
- }) |
|
| 186 |
- |
|
| 187 |
- // wait for CmdRun to return |
|
| 188 |
- setTimeout(t, "Waiting for CmdAttach timed out", 15*time.Second, func() {
|
|
| 189 |
- <-ch |
|
| 190 |
- }) |
|
| 191 |
- |
|
| 192 |
- closeWrap(cpty, stdout, stdoutPipe) |
|
| 193 |
- |
|
| 194 |
- time.Sleep(500 * time.Millisecond) |
|
| 195 |
- if !container.IsRunning() {
|
|
| 196 |
- t.Fatal("The detached container should be still running")
|
|
| 197 |
- } |
|
| 198 |
- |
|
| 199 |
- setTimeout(t, "Waiting for container to die timedout", 5*time.Second, func() {
|
|
| 200 |
- container.Kill() |
|
| 201 |
- }) |
|
| 202 |
-} |
|
| 203 |
- |
|
| 204 | 116 |
// TestAttachDetachTruncatedID checks that attach in tty mode can be detached |
| 205 | 117 |
func TestAttachDetachTruncatedID(t *testing.T) {
|
| 206 | 118 |
stdout, stdoutPipe := io.Pipe() |