github.com/brahmaroutu/docker@v1.2.1-0.20160809185609-eb28dde01f16/integration-cli/docker_api_attach_test.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "io" 6 "net" 7 "net/http" 8 "strings" 9 "time" 10 11 "github.com/docker/docker/pkg/integration/checker" 12 "github.com/go-check/check" 13 "golang.org/x/net/websocket" 14 ) 15 16 func (s *DockerSuite) TestGetContainersAttachWebsocket(c *check.C) { 17 testRequires(c, DaemonIsLinux) 18 out, _ := dockerCmd(c, "run", "-dit", "busybox", "cat") 19 20 rwc, err := sockConn(time.Duration(10*time.Second), "") 21 c.Assert(err, checker.IsNil) 22 23 cleanedContainerID := strings.TrimSpace(out) 24 config, err := websocket.NewConfig( 25 "/containers/"+cleanedContainerID+"/attach/ws?stream=1&stdin=1&stdout=1&stderr=1", 26 "http://localhost", 27 ) 28 c.Assert(err, checker.IsNil) 29 30 ws, err := websocket.NewClient(config, rwc) 31 c.Assert(err, checker.IsNil) 32 defer ws.Close() 33 34 expected := []byte("hello") 35 actual := make([]byte, len(expected)) 36 37 outChan := make(chan error) 38 go func() { 39 _, err := io.ReadFull(ws, actual) 40 outChan <- err 41 close(outChan) 42 }() 43 44 inChan := make(chan error) 45 go func() { 46 _, err := ws.Write(expected) 47 inChan <- err 48 close(inChan) 49 }() 50 51 select { 52 case err := <-inChan: 53 c.Assert(err, checker.IsNil) 54 case <-time.After(5 * time.Second): 55 c.Fatal("Timeout writing to ws") 56 } 57 58 select { 59 case err := <-outChan: 60 c.Assert(err, checker.IsNil) 61 case <-time.After(5 * time.Second): 62 c.Fatal("Timeout reading from ws") 63 } 64 65 c.Assert(actual, checker.DeepEquals, expected, check.Commentf("Websocket didn't return the expected data")) 66 } 67 68 // regression gh14320 69 func (s *DockerSuite) TestPostContainersAttachContainerNotFound(c *check.C) { 70 req, client, err := newRequestClient("POST", "/containers/doesnotexist/attach", nil, "", "") 71 c.Assert(err, checker.IsNil) 72 73 resp, err := client.Do(req) 74 // connection will shutdown, err should be "persistent connection closed" 75 c.Assert(err, checker.NotNil) // Server shutdown connection 76 77 body, err := readBody(resp.Body) 78 c.Assert(err, checker.IsNil) 79 c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound) 80 expected := "No such container: doesnotexist\r\n" 81 c.Assert(string(body), checker.Equals, expected) 82 } 83 84 func (s *DockerSuite) TestGetContainersWsAttachContainerNotFound(c *check.C) { 85 status, body, err := sockRequest("GET", "/containers/doesnotexist/attach/ws", nil) 86 c.Assert(status, checker.Equals, http.StatusNotFound) 87 c.Assert(err, checker.IsNil) 88 expected := "No such container: doesnotexist" 89 c.Assert(getErrorMessage(c, body), checker.Contains, expected) 90 } 91 92 func (s *DockerSuite) TestPostContainersAttach(c *check.C) { 93 testRequires(c, DaemonIsLinux) 94 95 expectSuccess := func(conn net.Conn, br *bufio.Reader, stream string, tty bool) { 96 defer conn.Close() 97 expected := []byte("success") 98 _, err := conn.Write(expected) 99 c.Assert(err, checker.IsNil) 100 101 conn.SetReadDeadline(time.Now().Add(time.Second)) 102 lenHeader := 0 103 if !tty { 104 lenHeader = 8 105 } 106 actual := make([]byte, len(expected)+lenHeader) 107 _, err = io.ReadFull(br, actual) 108 c.Assert(err, checker.IsNil) 109 if !tty { 110 fdMap := map[string]byte{ 111 "stdin": 0, 112 "stdout": 1, 113 "stderr": 2, 114 } 115 c.Assert(actual[0], checker.Equals, fdMap[stream]) 116 } 117 c.Assert(actual[lenHeader:], checker.DeepEquals, expected, check.Commentf("Attach didn't return the expected data from %s", stream)) 118 } 119 120 expectTimeout := func(conn net.Conn, br *bufio.Reader, stream string) { 121 defer conn.Close() 122 _, err := conn.Write([]byte{'t'}) 123 c.Assert(err, checker.IsNil) 124 125 conn.SetReadDeadline(time.Now().Add(time.Second)) 126 actual := make([]byte, 1) 127 _, err = io.ReadFull(br, actual) 128 opErr, ok := err.(*net.OpError) 129 c.Assert(ok, checker.Equals, true, check.Commentf("Error is expected to be *net.OpError, got %v", err)) 130 c.Assert(opErr.Timeout(), checker.Equals, true, check.Commentf("Read from %s is expected to timeout", stream)) 131 } 132 133 // Create a container that only emits stdout. 134 cid, _ := dockerCmd(c, "run", "-di", "busybox", "cat") 135 cid = strings.TrimSpace(cid) 136 // Attach to the container's stdout stream. 137 conn, br, err := sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stdout=1", nil, "text/plain") 138 c.Assert(err, checker.IsNil) 139 // Check if the data from stdout can be received. 140 expectSuccess(conn, br, "stdout", false) 141 // Attach to the container's stderr stream. 142 conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stderr=1", nil, "text/plain") 143 c.Assert(err, checker.IsNil) 144 // Since the container only emits stdout, attaching to stderr should return nothing. 145 expectTimeout(conn, br, "stdout") 146 147 // Test the similar functions of the stderr stream. 148 cid, _ = dockerCmd(c, "run", "-di", "busybox", "/bin/sh", "-c", "cat >&2") 149 cid = strings.TrimSpace(cid) 150 conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stderr=1", nil, "text/plain") 151 c.Assert(err, checker.IsNil) 152 expectSuccess(conn, br, "stderr", false) 153 conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stdout=1", nil, "text/plain") 154 c.Assert(err, checker.IsNil) 155 expectTimeout(conn, br, "stderr") 156 157 // Test with tty. 158 cid, _ = dockerCmd(c, "run", "-dit", "busybox", "/bin/sh", "-c", "cat >&2") 159 cid = strings.TrimSpace(cid) 160 // Attach to stdout only. 161 conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stdout=1", nil, "text/plain") 162 c.Assert(err, checker.IsNil) 163 expectSuccess(conn, br, "stdout", true) 164 165 // Attach without stdout stream. 166 conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stderr=1", nil, "text/plain") 167 c.Assert(err, checker.IsNil) 168 // Nothing should be received because both the stdout and stderr of the container will be 169 // sent to the client as stdout when tty is enabled. 170 expectTimeout(conn, br, "stdout") 171 }