OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [net/] [http/] [requestwrite_test.go] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2010 The Go Authors.  All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
 
5
package http
6
 
7
import (
8
        "bytes"
9
        "errors"
10
        "fmt"
11
        "io"
12
        "io/ioutil"
13
        "net/url"
14
        "strings"
15
        "testing"
16
)
17
 
18
type reqWriteTest struct {
19
        Req  Request
20
        Body interface{} // optional []byte or func() io.ReadCloser to populate Req.Body
21
 
22
        // Any of these three may be empty to skip that test.
23
        WantWrite string // Request.Write
24
        WantProxy string // Request.WriteProxy
25
 
26
        WantError error // wanted error from Request.Write
27
}
28
 
29
var reqWriteTests = []reqWriteTest{
30
        // HTTP/1.1 => chunked coding; no body; no trailer
31
        {
32
                Req: Request{
33
                        Method: "GET",
34
                        URL: &url.URL{
35
                                Scheme: "http",
36
                                Host:   "www.techcrunch.com",
37
                                Path:   "/",
38
                        },
39
                        Proto:      "HTTP/1.1",
40
                        ProtoMajor: 1,
41
                        ProtoMinor: 1,
42
                        Header: Header{
43
                                "Accept":           {"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"},
44
                                "Accept-Charset":   {"ISO-8859-1,utf-8;q=0.7,*;q=0.7"},
45
                                "Accept-Encoding":  {"gzip,deflate"},
46
                                "Accept-Language":  {"en-us,en;q=0.5"},
47
                                "Keep-Alive":       {"300"},
48
                                "Proxy-Connection": {"keep-alive"},
49
                                "User-Agent":       {"Fake"},
50
                        },
51
                        Body:  nil,
52
                        Close: false,
53
                        Host:  "www.techcrunch.com",
54
                        Form:  map[string][]string{},
55
                },
56
 
57
                WantWrite: "GET / HTTP/1.1\r\n" +
58
                        "Host: www.techcrunch.com\r\n" +
59
                        "User-Agent: Fake\r\n" +
60
                        "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
61
                        "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
62
                        "Accept-Encoding: gzip,deflate\r\n" +
63
                        "Accept-Language: en-us,en;q=0.5\r\n" +
64
                        "Keep-Alive: 300\r\n" +
65
                        "Proxy-Connection: keep-alive\r\n\r\n",
66
 
67
                WantProxy: "GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
68
                        "Host: www.techcrunch.com\r\n" +
69
                        "User-Agent: Fake\r\n" +
70
                        "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
71
                        "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
72
                        "Accept-Encoding: gzip,deflate\r\n" +
73
                        "Accept-Language: en-us,en;q=0.5\r\n" +
74
                        "Keep-Alive: 300\r\n" +
75
                        "Proxy-Connection: keep-alive\r\n\r\n",
76
        },
77
        // HTTP/1.1 => chunked coding; body; empty trailer
78
        {
79
                Req: Request{
80
                        Method: "GET",
81
                        URL: &url.URL{
82
                                Scheme: "http",
83
                                Host:   "www.google.com",
84
                                Path:   "/search",
85
                        },
86
                        ProtoMajor:       1,
87
                        ProtoMinor:       1,
88
                        Header:           Header{},
89
                        TransferEncoding: []string{"chunked"},
90
                },
91
 
92
                Body: []byte("abcdef"),
93
 
94
                WantWrite: "GET /search HTTP/1.1\r\n" +
95
                        "Host: www.google.com\r\n" +
96
                        "User-Agent: Go http package\r\n" +
97
                        "Transfer-Encoding: chunked\r\n\r\n" +
98
                        chunk("abcdef") + chunk(""),
99
 
100
                WantProxy: "GET http://www.google.com/search HTTP/1.1\r\n" +
101
                        "Host: www.google.com\r\n" +
102
                        "User-Agent: Go http package\r\n" +
103
                        "Transfer-Encoding: chunked\r\n\r\n" +
104
                        chunk("abcdef") + chunk(""),
105
        },
106
        // HTTP/1.1 POST => chunked coding; body; empty trailer
107
        {
108
                Req: Request{
109
                        Method: "POST",
110
                        URL: &url.URL{
111
                                Scheme: "http",
112
                                Host:   "www.google.com",
113
                                Path:   "/search",
114
                        },
115
                        ProtoMajor:       1,
116
                        ProtoMinor:       1,
117
                        Header:           Header{},
118
                        Close:            true,
119
                        TransferEncoding: []string{"chunked"},
120
                },
121
 
122
                Body: []byte("abcdef"),
123
 
124
                WantWrite: "POST /search HTTP/1.1\r\n" +
125
                        "Host: www.google.com\r\n" +
126
                        "User-Agent: Go http package\r\n" +
127
                        "Connection: close\r\n" +
128
                        "Transfer-Encoding: chunked\r\n\r\n" +
129
                        chunk("abcdef") + chunk(""),
130
 
131
                WantProxy: "POST http://www.google.com/search HTTP/1.1\r\n" +
132
                        "Host: www.google.com\r\n" +
133
                        "User-Agent: Go http package\r\n" +
134
                        "Connection: close\r\n" +
135
                        "Transfer-Encoding: chunked\r\n\r\n" +
136
                        chunk("abcdef") + chunk(""),
137
        },
138
 
139
        // HTTP/1.1 POST with Content-Length, no chunking
140
        {
141
                Req: Request{
142
                        Method: "POST",
143
                        URL: &url.URL{
144
                                Scheme: "http",
145
                                Host:   "www.google.com",
146
                                Path:   "/search",
147
                        },
148
                        ProtoMajor:    1,
149
                        ProtoMinor:    1,
150
                        Header:        Header{},
151
                        Close:         true,
152
                        ContentLength: 6,
153
                },
154
 
155
                Body: []byte("abcdef"),
156
 
157
                WantWrite: "POST /search HTTP/1.1\r\n" +
158
                        "Host: www.google.com\r\n" +
159
                        "User-Agent: Go http package\r\n" +
160
                        "Connection: close\r\n" +
161
                        "Content-Length: 6\r\n" +
162
                        "\r\n" +
163
                        "abcdef",
164
 
165
                WantProxy: "POST http://www.google.com/search HTTP/1.1\r\n" +
166
                        "Host: www.google.com\r\n" +
167
                        "User-Agent: Go http package\r\n" +
168
                        "Connection: close\r\n" +
169
                        "Content-Length: 6\r\n" +
170
                        "\r\n" +
171
                        "abcdef",
172
        },
173
 
174
        // HTTP/1.1 POST with Content-Length in headers
175
        {
176
                Req: Request{
177
                        Method: "POST",
178
                        URL:    mustParseURL("http://example.com/"),
179
                        Host:   "example.com",
180
                        Header: Header{
181
                                "Content-Length": []string{"10"}, // ignored
182
                        },
183
                        ContentLength: 6,
184
                },
185
 
186
                Body: []byte("abcdef"),
187
 
188
                WantWrite: "POST / HTTP/1.1\r\n" +
189
                        "Host: example.com\r\n" +
190
                        "User-Agent: Go http package\r\n" +
191
                        "Content-Length: 6\r\n" +
192
                        "\r\n" +
193
                        "abcdef",
194
 
195
                WantProxy: "POST http://example.com/ HTTP/1.1\r\n" +
196
                        "Host: example.com\r\n" +
197
                        "User-Agent: Go http package\r\n" +
198
                        "Content-Length: 6\r\n" +
199
                        "\r\n" +
200
                        "abcdef",
201
        },
202
 
203
        // default to HTTP/1.1
204
        {
205
                Req: Request{
206
                        Method: "GET",
207
                        URL:    mustParseURL("/search"),
208
                        Host:   "www.google.com",
209
                },
210
 
211
                WantWrite: "GET /search HTTP/1.1\r\n" +
212
                        "Host: www.google.com\r\n" +
213
                        "User-Agent: Go http package\r\n" +
214
                        "\r\n",
215
        },
216
 
217
        // Request with a 0 ContentLength and a 0 byte body.
218
        {
219
                Req: Request{
220
                        Method:        "POST",
221
                        URL:           mustParseURL("/"),
222
                        Host:          "example.com",
223
                        ProtoMajor:    1,
224
                        ProtoMinor:    1,
225
                        ContentLength: 0, // as if unset by user
226
                },
227
 
228
                Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 0)) },
229
 
230
                // RFC 2616 Section 14.13 says Content-Length should be specified
231
                // unless body is prohibited by the request method.
232
                // Also, nginx expects it for POST and PUT.
233
                WantWrite: "POST / HTTP/1.1\r\n" +
234
                        "Host: example.com\r\n" +
235
                        "User-Agent: Go http package\r\n" +
236
                        "Content-Length: 0\r\n" +
237
                        "\r\n",
238
 
239
                WantProxy: "POST / HTTP/1.1\r\n" +
240
                        "Host: example.com\r\n" +
241
                        "User-Agent: Go http package\r\n" +
242
                        "Content-Length: 0\r\n" +
243
                        "\r\n",
244
        },
245
 
246
        // Request with a 0 ContentLength and a 1 byte body.
247
        {
248
                Req: Request{
249
                        Method:        "POST",
250
                        URL:           mustParseURL("/"),
251
                        Host:          "example.com",
252
                        ProtoMajor:    1,
253
                        ProtoMinor:    1,
254
                        ContentLength: 0, // as if unset by user
255
                },
256
 
257
                Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 1)) },
258
 
259
                WantWrite: "POST / HTTP/1.1\r\n" +
260
                        "Host: example.com\r\n" +
261
                        "User-Agent: Go http package\r\n" +
262
                        "Transfer-Encoding: chunked\r\n\r\n" +
263
                        chunk("x") + chunk(""),
264
 
265
                WantProxy: "POST / HTTP/1.1\r\n" +
266
                        "Host: example.com\r\n" +
267
                        "User-Agent: Go http package\r\n" +
268
                        "Transfer-Encoding: chunked\r\n\r\n" +
269
                        chunk("x") + chunk(""),
270
        },
271
 
272
        // Request with a ContentLength of 10 but a 5 byte body.
273
        {
274
                Req: Request{
275
                        Method:        "POST",
276
                        URL:           mustParseURL("/"),
277
                        Host:          "example.com",
278
                        ProtoMajor:    1,
279
                        ProtoMinor:    1,
280
                        ContentLength: 10, // but we're going to send only 5 bytes
281
                },
282
                Body:      []byte("12345"),
283
                WantError: errors.New("http: Request.ContentLength=10 with Body length 5"),
284
        },
285
 
286
        // Request with a ContentLength of 4 but an 8 byte body.
287
        {
288
                Req: Request{
289
                        Method:        "POST",
290
                        URL:           mustParseURL("/"),
291
                        Host:          "example.com",
292
                        ProtoMajor:    1,
293
                        ProtoMinor:    1,
294
                        ContentLength: 4, // but we're going to try to send 8 bytes
295
                },
296
                Body:      []byte("12345678"),
297
                WantError: errors.New("http: Request.ContentLength=4 with Body length 8"),
298
        },
299
 
300
        // Request with a 5 ContentLength and nil body.
301
        {
302
                Req: Request{
303
                        Method:        "POST",
304
                        URL:           mustParseURL("/"),
305
                        Host:          "example.com",
306
                        ProtoMajor:    1,
307
                        ProtoMinor:    1,
308
                        ContentLength: 5, // but we'll omit the body
309
                },
310
                WantError: errors.New("http: Request.ContentLength=5 with nil Body"),
311
        },
312
 
313
        // Verify that DumpRequest preserves the HTTP version number, doesn't add a Host,
314
        // and doesn't add a User-Agent.
315
        {
316
                Req: Request{
317
                        Method:     "GET",
318
                        URL:        mustParseURL("/foo"),
319
                        ProtoMajor: 1,
320
                        ProtoMinor: 0,
321
                        Header: Header{
322
                                "X-Foo": []string{"X-Bar"},
323
                        },
324
                },
325
 
326
                WantWrite: "GET /foo HTTP/1.1\r\n" +
327
                        "Host: \r\n" +
328
                        "User-Agent: Go http package\r\n" +
329
                        "X-Foo: X-Bar\r\n\r\n",
330
        },
331
}
332
 
333
func TestRequestWrite(t *testing.T) {
334
        for i := range reqWriteTests {
335
                tt := &reqWriteTests[i]
336
 
337
                setBody := func() {
338
                        if tt.Body == nil {
339
                                return
340
                        }
341
                        switch b := tt.Body.(type) {
342
                        case []byte:
343
                                tt.Req.Body = ioutil.NopCloser(bytes.NewBuffer(b))
344
                        case func() io.ReadCloser:
345
                                tt.Req.Body = b()
346
                        }
347
                }
348
                setBody()
349
                if tt.Req.Header == nil {
350
                        tt.Req.Header = make(Header)
351
                }
352
 
353
                var braw bytes.Buffer
354
                err := tt.Req.Write(&braw)
355
                if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.WantError); g != e {
356
                        t.Errorf("writing #%d, err = %q, want %q", i, g, e)
357
                        continue
358
                }
359
                if err != nil {
360
                        continue
361
                }
362
 
363
                if tt.WantWrite != "" {
364
                        sraw := braw.String()
365
                        if sraw != tt.WantWrite {
366
                                t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantWrite, sraw)
367
                                continue
368
                        }
369
                }
370
 
371
                if tt.WantProxy != "" {
372
                        setBody()
373
                        var praw bytes.Buffer
374
                        err = tt.Req.WriteProxy(&praw)
375
                        if err != nil {
376
                                t.Errorf("WriteProxy #%d: %s", i, err)
377
                                continue
378
                        }
379
                        sraw := praw.String()
380
                        if sraw != tt.WantProxy {
381
                                t.Errorf("Test Proxy %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantProxy, sraw)
382
                                continue
383
                        }
384
                }
385
        }
386
}
387
 
388
type closeChecker struct {
389
        io.Reader
390
        closed bool
391
}
392
 
393
func (rc *closeChecker) Close() error {
394
        rc.closed = true
395
        return nil
396
}
397
 
398
// TestRequestWriteClosesBody tests that Request.Write does close its request.Body.
399
// It also indirectly tests NewRequest and that it doesn't wrap an existing Closer
400
// inside a NopCloser, and that it serializes it correctly.
401
func TestRequestWriteClosesBody(t *testing.T) {
402
        rc := &closeChecker{Reader: strings.NewReader("my body")}
403
        req, _ := NewRequest("POST", "http://foo.com/", rc)
404
        if req.ContentLength != 0 {
405
                t.Errorf("got req.ContentLength %d, want 0", req.ContentLength)
406
        }
407
        buf := new(bytes.Buffer)
408
        req.Write(buf)
409
        if !rc.closed {
410
                t.Error("body not closed after write")
411
        }
412
        expected := "POST / HTTP/1.1\r\n" +
413
                "Host: foo.com\r\n" +
414
                "User-Agent: Go http package\r\n" +
415
                "Transfer-Encoding: chunked\r\n\r\n" +
416
                // TODO: currently we don't buffer before chunking, so we get a
417
                // single "m" chunk before the other chunks, as this was the 1-byte
418
                // read from our MultiReader where we stiched the Body back together
419
                // after sniffing whether the Body was 0 bytes or not.
420
                chunk("m") +
421
                chunk("y body") +
422
                chunk("")
423
        if buf.String() != expected {
424
                t.Errorf("write:\n got: %s\nwant: %s", buf.String(), expected)
425
        }
426
}
427
 
428
func chunk(s string) string {
429
        return fmt.Sprintf("%x\r\n%s\r\n", len(s), s)
430
}
431
 
432
func mustParseURL(s string) *url.URL {
433
        u, err := url.Parse(s)
434
        if err != nil {
435
                panic(fmt.Sprintf("Error parsing URL %q: %v", s, err))
436
        }
437
        return u
438
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.