github.com/OpenFlowLabs/moby@v17.12.1-ce-rc2+incompatible/integration-cli/docker_cli_attach_test.go (about)

     1  package main
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"os/exec"
     8  	"runtime"
     9  	"strings"
    10  	"sync"
    11  	"time"
    12  
    13  	"github.com/docker/docker/integration-cli/cli"
    14  	"github.com/go-check/check"
    15  	"github.com/gotestyourself/gotestyourself/icmd"
    16  )
    17  
    18  const attachWait = 5 * time.Second
    19  
    20  func (s *DockerSuite) TestAttachMultipleAndRestart(c *check.C) {
    21  	endGroup := &sync.WaitGroup{}
    22  	startGroup := &sync.WaitGroup{}
    23  	endGroup.Add(3)
    24  	startGroup.Add(3)
    25  
    26  	cli.DockerCmd(c, "run", "--name", "attacher", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 1; echo hello; done")
    27  	cli.WaitRun(c, "attacher")
    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  			defer out.Close()
    56  
    57  			if err := cmd.Start(); err != nil {
    58  				c.Fatal(err)
    59  			}
    60  
    61  			buf := make([]byte, 1024)
    62  
    63  			if _, err := out.Read(buf); err != nil && err != io.EOF {
    64  				c.Fatal(err)
    65  			}
    66  
    67  			startGroup.Done()
    68  
    69  			if !strings.Contains(string(buf), "hello") {
    70  				c.Fatalf("unexpected output %s expected hello\n", string(buf))
    71  			}
    72  		}()
    73  	}
    74  
    75  	select {
    76  	case <-startDone:
    77  	case <-time.After(attachWait):
    78  		c.Fatalf("Attaches did not initialize properly")
    79  	}
    80  
    81  	cli.DockerCmd(c, "kill", "attacher")
    82  
    83  	select {
    84  	case <-endDone:
    85  	case <-time.After(attachWait):
    86  		c.Fatalf("Attaches did not finish properly")
    87  	}
    88  }
    89  
    90  func (s *DockerSuite) TestAttachTTYWithoutStdin(c *check.C) {
    91  	// TODO @jhowardmsft. Figure out how to get this running again reliable on Windows.
    92  	// It works by accident at the moment. Sometimes. I've gone back to v1.13.0 and see the same.
    93  	// On Windows, docker run -d -ti busybox causes the container to exit immediately.
    94  	// Obviously a year back when I updated the test, that was not the case. However,
    95  	// with this, and the test racing with the tear-down which panic's, sometimes CI
    96  	// will just fail and `MISS` all the other tests. For now, disabling it. Will
    97  	// open an issue to track re-enabling this and root-causing the problem.
    98  	testRequires(c, DaemonIsLinux)
    99  	out, _ := dockerCmd(c, "run", "-d", "-ti", "busybox")
   100  
   101  	id := strings.TrimSpace(out)
   102  	c.Assert(waitRun(id), check.IsNil)
   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 := "the input device is not a TTY"
   115  		if runtime.GOOS == "windows" {
   116  			expected += ".  If you are using mintty, try prefixing the command with 'winpty'"
   117  		}
   118  		if out, _, err := runCommandWithOutput(cmd); err == nil {
   119  			done <- fmt.Errorf("attach should have failed")
   120  			return
   121  		} else if !strings.Contains(out, expected) {
   122  			done <- fmt.Errorf("attach failed with error %q: expected %q", out, expected)
   123  			return
   124  		}
   125  	}()
   126  
   127  	select {
   128  	case err := <-done:
   129  		c.Assert(err, check.IsNil)
   130  	case <-time.After(attachWait):
   131  		c.Fatal("attach is running but should have failed")
   132  	}
   133  }
   134  
   135  func (s *DockerSuite) TestAttachDisconnect(c *check.C) {
   136  	testRequires(c, DaemonIsLinux)
   137  	out, _ := dockerCmd(c, "run", "-di", "busybox", "/bin/cat")
   138  	id := strings.TrimSpace(out)
   139  
   140  	cmd := exec.Command(dockerBinary, "attach", id)
   141  	stdin, err := cmd.StdinPipe()
   142  	if err != nil {
   143  		c.Fatal(err)
   144  	}
   145  	defer stdin.Close()
   146  	stdout, err := cmd.StdoutPipe()
   147  	c.Assert(err, check.IsNil)
   148  	defer stdout.Close()
   149  	c.Assert(cmd.Start(), check.IsNil)
   150  	defer func() {
   151  		cmd.Process.Kill()
   152  		cmd.Wait()
   153  	}()
   154  
   155  	_, err = stdin.Write([]byte("hello\n"))
   156  	c.Assert(err, check.IsNil)
   157  	out, err = bufio.NewReader(stdout).ReadString('\n')
   158  	c.Assert(err, check.IsNil)
   159  	c.Assert(strings.TrimSpace(out), check.Equals, "hello")
   160  
   161  	c.Assert(stdin.Close(), check.IsNil)
   162  
   163  	// Expect container to still be running after stdin is closed
   164  	running := inspectField(c, id, "State.Running")
   165  	c.Assert(running, check.Equals, "true")
   166  }
   167  
   168  func (s *DockerSuite) TestAttachPausedContainer(c *check.C) {
   169  	testRequires(c, IsPausable)
   170  	runSleepingContainer(c, "-d", "--name=test")
   171  	dockerCmd(c, "pause", "test")
   172  
   173  	result := dockerCmdWithResult("attach", "test")
   174  	result.Assert(c, icmd.Expected{
   175  		Error:    "exit status 1",
   176  		ExitCode: 1,
   177  		Err:      "You cannot attach to a paused container, unpause it first",
   178  	})
   179  }