Signed-off-by: Brian Goff <cpuguy83@gmail.com>
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
package main |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "bufio" |
|
| 4 | 5 |
"io" |
| 5 | 6 |
"os/exec" |
| 6 | 7 |
"strings" |
| ... | ... |
@@ -134,3 +135,51 @@ func TestAttachTtyWithoutStdin(t *testing.T) {
|
| 134 | 134 |
|
| 135 | 135 |
logDone("attach - forbid piped stdin to tty enabled container")
|
| 136 | 136 |
} |
| 137 |
+ |
|
| 138 |
+func TestAttachDisconnect(t *testing.T) {
|
|
| 139 |
+ defer deleteAllContainers() |
|
| 140 |
+ out, _, _ := dockerCmd(t, "run", "-di", "busybox", "/bin/cat") |
|
| 141 |
+ id := strings.TrimSpace(out) |
|
| 142 |
+ |
|
| 143 |
+ cmd := exec.Command(dockerBinary, "attach", id) |
|
| 144 |
+ stdin, err := cmd.StdinPipe() |
|
| 145 |
+ if err != nil {
|
|
| 146 |
+ t.Fatal(err) |
|
| 147 |
+ } |
|
| 148 |
+ defer stdin.Close() |
|
| 149 |
+ stdout, err := cmd.StdoutPipe() |
|
| 150 |
+ if err != nil {
|
|
| 151 |
+ t.Fatal(err) |
|
| 152 |
+ } |
|
| 153 |
+ defer stdout.Close() |
|
| 154 |
+ if err := cmd.Start(); err != nil {
|
|
| 155 |
+ t.Fatal(err) |
|
| 156 |
+ } |
|
| 157 |
+ defer cmd.Process.Kill() |
|
| 158 |
+ |
|
| 159 |
+ if _, err := stdin.Write([]byte("hello\n")); err != nil {
|
|
| 160 |
+ t.Fatal(err) |
|
| 161 |
+ } |
|
| 162 |
+ out, err = bufio.NewReader(stdout).ReadString('\n')
|
|
| 163 |
+ if err != nil {
|
|
| 164 |
+ t.Fatal(err) |
|
| 165 |
+ } |
|
| 166 |
+ if strings.TrimSpace(out) != "hello" {
|
|
| 167 |
+ t.Fatalf("exepected 'hello', got %q", out)
|
|
| 168 |
+ } |
|
| 169 |
+ |
|
| 170 |
+ if err := stdin.Close(); err != nil {
|
|
| 171 |
+ t.Fatal(err) |
|
| 172 |
+ } |
|
| 173 |
+ |
|
| 174 |
+ // Expect container to still be running after stdin is closed |
|
| 175 |
+ running, err := inspectField(id, "State.Running") |
|
| 176 |
+ if err != nil {
|
|
| 177 |
+ t.Fatal(err) |
|
| 178 |
+ } |
|
| 179 |
+ if running != "true" {
|
|
| 180 |
+ t.Fatal("exepected container to still be running")
|
|
| 181 |
+ } |
|
| 182 |
+ |
|
| 183 |
+ logDone("attach - disconnect")
|
|
| 184 |
+} |
| ... | ... |
@@ -9,11 +9,9 @@ import ( |
| 9 | 9 |
"testing" |
| 10 | 10 |
"time" |
| 11 | 11 |
|
| 12 |
- "github.com/Sirupsen/logrus" |
|
| 13 | 12 |
"github.com/docker/docker/api/client" |
| 14 | 13 |
"github.com/docker/docker/daemon" |
| 15 | 14 |
"github.com/docker/docker/pkg/term" |
| 16 |
- "github.com/kr/pty" |
|
| 17 | 15 |
) |
| 18 | 16 |
|
| 19 | 17 |
func closeWrap(args ...io.Closer) error {
|
| ... | ... |
@@ -112,79 +110,6 @@ func assertPipe(input, output string, r io.Reader, w io.Writer, count int) error |
| 112 | 112 |
return nil |
| 113 | 113 |
} |
| 114 | 114 |
|
| 115 |
-// Expected behaviour, the process stays alive when the client disconnects |
|
| 116 |
-func TestAttachDisconnect(t *testing.T) {
|
|
| 117 |
- stdout, stdoutPipe := io.Pipe() |
|
| 118 |
- cpty, tty, err := pty.Open() |
|
| 119 |
- if err != nil {
|
|
| 120 |
- t.Fatal(err) |
|
| 121 |
- } |
|
| 122 |
- |
|
| 123 |
- cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil) |
|
| 124 |
- defer cleanup(globalEngine, t) |
|
| 125 |
- |
|
| 126 |
- go func() {
|
|
| 127 |
- // Start a process in daemon mode |
|
| 128 |
- if err := cli.CmdRun("-d", "-i", unitTestImageID, "/bin/cat"); err != nil {
|
|
| 129 |
- logrus.Debugf("Error CmdRun: %s", err)
|
|
| 130 |
- } |
|
| 131 |
- }() |
|
| 132 |
- |
|
| 133 |
- setTimeout(t, "Waiting for CmdRun timed out", 10*time.Second, func() {
|
|
| 134 |
- if _, err := bufio.NewReader(stdout).ReadString('\n'); err != nil {
|
|
| 135 |
- t.Fatal(err) |
|
| 136 |
- } |
|
| 137 |
- }) |
|
| 138 |
- |
|
| 139 |
- setTimeout(t, "Waiting for the container to be started timed out", 10*time.Second, func() {
|
|
| 140 |
- for {
|
|
| 141 |
- l := globalDaemon.List() |
|
| 142 |
- if len(l) == 1 && l[0].IsRunning() {
|
|
| 143 |
- break |
|
| 144 |
- } |
|
| 145 |
- time.Sleep(10 * time.Millisecond) |
|
| 146 |
- } |
|
| 147 |
- }) |
|
| 148 |
- |
|
| 149 |
- container := globalDaemon.List()[0] |
|
| 150 |
- |
|
| 151 |
- // Attach to it |
|
| 152 |
- c1 := make(chan struct{})
|
|
| 153 |
- go func() {
|
|
| 154 |
- // We're simulating a disconnect so the return value doesn't matter. What matters is the |
|
| 155 |
- // fact that CmdAttach returns. |
|
| 156 |
- cli.CmdAttach(container.ID) |
|
| 157 |
- close(c1) |
|
| 158 |
- }() |
|
| 159 |
- |
|
| 160 |
- setTimeout(t, "First read/write assertion timed out", 2*time.Second, func() {
|
|
| 161 |
- if err := assertPipe("hello\n", "hello", stdout, cpty, 150); err != nil {
|
|
| 162 |
- t.Fatal(err) |
|
| 163 |
- } |
|
| 164 |
- }) |
|
| 165 |
- // Close pipes (client disconnects) |
|
| 166 |
- if err := closeWrap(cpty, stdout, stdoutPipe); err != nil {
|
|
| 167 |
- t.Fatal(err) |
|
| 168 |
- } |
|
| 169 |
- |
|
| 170 |
- // Wait for attach to finish, the client disconnected, therefore, Attach finished his job |
|
| 171 |
- setTimeout(t, "Waiting for CmdAttach timed out", 2*time.Second, func() {
|
|
| 172 |
- <-c1 |
|
| 173 |
- }) |
|
| 174 |
- |
|
| 175 |
- // We closed stdin, expect /bin/cat to still be running |
|
| 176 |
- // Wait a little bit to make sure container.monitor() did his thing |
|
| 177 |
- _, err = container.WaitStop(500 * time.Millisecond) |
|
| 178 |
- if err == nil || !container.IsRunning() {
|
|
| 179 |
- t.Fatalf("/bin/cat is not running after closing stdin")
|
|
| 180 |
- } |
|
| 181 |
- |
|
| 182 |
- // Try to avoid the timeout in destroy. Best effort, don't check error |
|
| 183 |
- cStdin := container.StdinPipe() |
|
| 184 |
- cStdin.Close() |
|
| 185 |
- container.WaitStop(-1 * time.Second) |
|
| 186 |
-} |
|
| 187 |
- |
|
| 188 | 115 |
// Expected behaviour: container gets deleted automatically after exit |
| 189 | 116 |
func TestRunAutoRemove(t *testing.T) {
|
| 190 | 117 |
t.Skip("Fixme. Skipping test for now, race condition")
|