Browse code

Port POST container attach tests

Signed-off-by: Megan Kostick <mkostick@us.ibm.com>

Megan Kostick authored on 2015/07/10 03:49:41
Showing 1 changed files
... ...
@@ -2,7 +2,9 @@ package main
2 2
 
3 3
 import (
4 4
 	"bytes"
5
+	"io"
5 6
 	"net/http"
7
+	"net/http/httputil"
6 8
 	"os/exec"
7 9
 	"strings"
8 10
 	"time"
... ...
@@ -98,3 +100,133 @@ func (s *DockerSuite) TestGetContainersWsAttachContainerNotFound(c *check.C) {
98 98
 		c.Fatalf("Expected response body to contain %q", expected)
99 99
 	}
100 100
 }
101
+
102
+func (s *DockerSuite) TestPostContainersAttach(c *check.C) {
103
+	runCmd := exec.Command(dockerBinary, "run", "-dit", "busybox", "cat")
104
+	out, _, err := runCommandWithOutput(runCmd)
105
+	c.Assert(err, check.IsNil)
106
+
107
+	r, w := io.Pipe()
108
+	defer r.Close()
109
+	defer w.Close()
110
+
111
+	conn, err := sockConn(time.Duration(10 * time.Second))
112
+	c.Assert(err, check.IsNil)
113
+
114
+	containerID := strings.TrimSpace(out)
115
+
116
+	req, err := http.NewRequest("POST", "/containers/"+containerID+"/attach?stream=1&stdin=1&stdout=1&stderr=1", bytes.NewReader([]byte{}))
117
+	c.Assert(err, check.IsNil)
118
+
119
+	client := httputil.NewClientConn(conn, nil)
120
+	defer client.Close()
121
+
122
+	// Do POST attach request
123
+	resp, err := client.Do(req)
124
+	c.Assert(resp.StatusCode, check.Equals, http.StatusOK)
125
+	// If we check the err, we get a ErrPersistEOF = &http.ProtocolError{ErrorString: "persistent connection closed"}
126
+	// This means that the remote requested this be the last request serviced, is this okay?
127
+
128
+	// Test read and write to the attached container
129
+	expected := []byte("hello")
130
+	actual := make([]byte, len(expected))
131
+
132
+	outChan := make(chan error)
133
+	go func() {
134
+		_, err := r.Read(actual)
135
+		outChan <- err
136
+		close(outChan)
137
+	}()
138
+
139
+	inChan := make(chan error)
140
+	go func() {
141
+		_, err := w.Write(expected)
142
+		inChan <- err
143
+		close(inChan)
144
+	}()
145
+
146
+	select {
147
+	case err := <-inChan:
148
+		c.Assert(err, check.IsNil)
149
+	case <-time.After(5 * time.Second):
150
+		c.Fatal("Timeout writing to stdout")
151
+	}
152
+
153
+	select {
154
+	case err := <-outChan:
155
+		c.Assert(err, check.IsNil)
156
+	case <-time.After(5 * time.Second):
157
+		c.Fatal("Timeout reading from stdin")
158
+	}
159
+
160
+	if !bytes.Equal(expected, actual) {
161
+		c.Fatal("Expected output to match input")
162
+	}
163
+
164
+	resp.Body.Close()
165
+}
166
+
167
+func (s *DockerSuite) TestPostContainersAttachStderr(c *check.C) {
168
+	runCmd := exec.Command(dockerBinary, "run", "-dit", "busybox", "/bin/sh", "-c", "cat >&2")
169
+	out, _, err := runCommandWithOutput(runCmd)
170
+	c.Assert(err, check.IsNil)
171
+
172
+	r, w := io.Pipe()
173
+	defer r.Close()
174
+	defer w.Close()
175
+
176
+	conn, err := sockConn(time.Duration(10 * time.Second))
177
+	c.Assert(err, check.IsNil)
178
+
179
+	containerID := strings.TrimSpace(out)
180
+
181
+	req, err := http.NewRequest("POST", "/containers/"+containerID+"/attach?stream=1&stdin=1&stdout=1&stderr=1", bytes.NewReader([]byte{}))
182
+	c.Assert(err, check.IsNil)
183
+
184
+	client := httputil.NewClientConn(conn, nil)
185
+	defer client.Close()
186
+
187
+	// Do POST attach request
188
+	resp, err := client.Do(req)
189
+	c.Assert(resp.StatusCode, check.Equals, http.StatusOK)
190
+	// If we check the err, we get a ErrPersistEOF = &http.ProtocolError{ErrorString: "persistent connection closed"}
191
+	// This means that the remote requested this be the last request serviced, is this okay?
192
+
193
+	// Test read and write to the attached container
194
+	expected := []byte("hello")
195
+	actual := make([]byte, len(expected))
196
+
197
+	outChan := make(chan error)
198
+	go func() {
199
+		_, err := r.Read(actual)
200
+		outChan <- err
201
+		close(outChan)
202
+	}()
203
+
204
+	inChan := make(chan error)
205
+	go func() {
206
+		_, err := w.Write(expected)
207
+		inChan <- err
208
+		close(inChan)
209
+	}()
210
+
211
+	select {
212
+	case err := <-inChan:
213
+		c.Assert(err, check.IsNil)
214
+	case <-time.After(5 * time.Second):
215
+		c.Fatal("Timeout writing to stdout")
216
+	}
217
+
218
+	select {
219
+	case err := <-outChan:
220
+		c.Assert(err, check.IsNil)
221
+	case <-time.After(5 * time.Second):
222
+		c.Fatal("Timeout reading from stdin")
223
+	}
224
+
225
+	if !bytes.Equal(expected, actual) {
226
+		c.Fatal("Expected output to match input")
227
+	}
228
+
229
+	resp.Body.Close()
230
+}