github.com/christopherobin/docker@v1.6.2/integration-cli/docker_cli_attach_unix_test.go (about) 1 // +build !windows 2 3 package main 4 5 import ( 6 "os/exec" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/kr/pty" 12 ) 13 14 // #9860 15 func TestAttachClosedOnContainerStop(t *testing.T) { 16 defer deleteAllContainers() 17 18 cmd := exec.Command(dockerBinary, "run", "-dti", "busybox", "sleep", "2") 19 out, _, err := runCommandWithOutput(cmd) 20 if err != nil { 21 t.Fatalf("failed to start container: %v (%v)", out, err) 22 } 23 24 id := stripTrailingCharacters(out) 25 if err := waitRun(id); err != nil { 26 t.Fatal(err) 27 } 28 29 done := make(chan struct{}) 30 31 go func() { 32 defer close(done) 33 34 _, tty, err := pty.Open() 35 if err != nil { 36 t.Fatalf("could not open pty: %v", err) 37 } 38 attachCmd := exec.Command(dockerBinary, "attach", id) 39 attachCmd.Stdin = tty 40 attachCmd.Stdout = tty 41 attachCmd.Stderr = tty 42 43 if err := attachCmd.Run(); err != nil { 44 t.Fatalf("attach returned error %s", err) 45 } 46 }() 47 48 waitCmd := exec.Command(dockerBinary, "wait", id) 49 if out, _, err = runCommandWithOutput(waitCmd); err != nil { 50 t.Fatalf("error thrown while waiting for container: %s, %v", out, err) 51 } 52 select { 53 case <-done: 54 case <-time.After(attachWait): 55 t.Fatal("timed out without attach returning") 56 } 57 58 logDone("attach - return after container finished") 59 } 60 61 func TestAttachAfterDetach(t *testing.T) { 62 defer deleteAllContainers() 63 64 name := "detachtest" 65 66 cpty, tty, err := pty.Open() 67 if err != nil { 68 t.Fatalf("Could not open pty: %v", err) 69 } 70 cmd := exec.Command(dockerBinary, "run", "-ti", "--name", name, "busybox") 71 cmd.Stdin = tty 72 cmd.Stdout = tty 73 cmd.Stderr = tty 74 75 detached := make(chan struct{}) 76 go func() { 77 if err := cmd.Run(); err != nil { 78 t.Fatalf("attach returned error %s", err) 79 } 80 close(detached) 81 }() 82 83 time.Sleep(500 * time.Millisecond) 84 if err := waitRun(name); err != nil { 85 t.Fatal(err) 86 } 87 cpty.Write([]byte{16}) 88 time.Sleep(100 * time.Millisecond) 89 cpty.Write([]byte{17}) 90 91 <-detached 92 93 cpty, tty, err = pty.Open() 94 if err != nil { 95 t.Fatalf("Could not open pty: %v", err) 96 } 97 98 cmd = exec.Command(dockerBinary, "attach", name) 99 cmd.Stdin = tty 100 cmd.Stdout = tty 101 cmd.Stderr = tty 102 103 if err := cmd.Start(); err != nil { 104 t.Fatal(err) 105 } 106 107 bytes := make([]byte, 10) 108 var nBytes int 109 readErr := make(chan error, 1) 110 111 go func() { 112 time.Sleep(500 * time.Millisecond) 113 cpty.Write([]byte("\n")) 114 time.Sleep(500 * time.Millisecond) 115 116 nBytes, err = cpty.Read(bytes) 117 cpty.Close() 118 readErr <- err 119 }() 120 121 select { 122 case err := <-readErr: 123 if err != nil { 124 t.Fatal(err) 125 } 126 case <-time.After(2 * time.Second): 127 t.Fatal("timeout waiting for attach read") 128 } 129 130 if err := cmd.Wait(); err != nil { 131 t.Fatal(err) 132 } 133 134 if !strings.Contains(string(bytes[:nBytes]), "/ #") { 135 t.Fatalf("failed to get a new prompt. got %s", string(bytes[:nBytes])) 136 } 137 138 logDone("attach - reconnect after detaching") 139 }