diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-10-06 09:35:45 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-10-06 09:35:45 +0200 |
commit | 6c7ca6e4d4e26e4c8cbe0d183966011b3b088a0a (patch) | |
tree | fddeb87db026d64a1d8e597dd0c69d685f433597 /src/pkg/http/requestwrite_test.go | |
parent | 04f99b387021a8ce32a8795360cba9beaf986a81 (diff) | |
download | golang-6c7ca6e4d4e26e4c8cbe0d183966011b3b088a0a.tar.gz |
Imported Upstream version 2011.09.21upstream-weekly/2011.09.21
Diffstat (limited to 'src/pkg/http/requestwrite_test.go')
-rw-r--r-- | src/pkg/http/requestwrite_test.go | 210 |
1 files changed, 153 insertions, 57 deletions
diff --git a/src/pkg/http/requestwrite_test.go b/src/pkg/http/requestwrite_test.go index 458f0bd7f..8c29c44f4 100644 --- a/src/pkg/http/requestwrite_test.go +++ b/src/pkg/http/requestwrite_test.go @@ -16,16 +16,21 @@ import ( ) type reqWriteTest struct { - Req Request - Body interface{} // optional []byte or func() io.ReadCloser to populate Req.Body - Raw string - RawProxy string + Req Request + Body interface{} // optional []byte or func() io.ReadCloser to populate Req.Body + + // Any of these three may be empty to skip that test. + WantWrite string // Request.Write + WantProxy string // Request.WriteProxy + WantDump string // DumpRequest + + WantError os.Error // wanted error from Request.Write } var reqWriteTests = []reqWriteTest{ // HTTP/1.1 => chunked coding; no body; no trailer { - Request{ + Req: Request{ Method: "GET", RawURL: "http://www.techcrunch.com/", URL: &url.URL{ @@ -57,9 +62,7 @@ var reqWriteTests = []reqWriteTest{ Form: map[string][]string{}, }, - nil, - - "GET http://www.techcrunch.com/ HTTP/1.1\r\n" + + WantWrite: "GET http://www.techcrunch.com/ HTTP/1.1\r\n" + "Host: www.techcrunch.com\r\n" + "User-Agent: Fake\r\n" + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" + @@ -69,7 +72,7 @@ var reqWriteTests = []reqWriteTest{ "Keep-Alive: 300\r\n" + "Proxy-Connection: keep-alive\r\n\r\n", - "GET http://www.techcrunch.com/ HTTP/1.1\r\n" + + WantProxy: "GET http://www.techcrunch.com/ HTTP/1.1\r\n" + "Host: www.techcrunch.com\r\n" + "User-Agent: Fake\r\n" + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" + @@ -81,7 +84,7 @@ var reqWriteTests = []reqWriteTest{ }, // HTTP/1.1 => chunked coding; body; empty trailer { - Request{ + Req: Request{ Method: "GET", URL: &url.URL{ Scheme: "http", @@ -94,23 +97,28 @@ var reqWriteTests = []reqWriteTest{ TransferEncoding: []string{"chunked"}, }, - []byte("abcdef"), + Body: []byte("abcdef"), - "GET /search HTTP/1.1\r\n" + + WantWrite: "GET /search HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "User-Agent: Go http package\r\n" + "Transfer-Encoding: chunked\r\n\r\n" + chunk("abcdef") + chunk(""), - "GET http://www.google.com/search HTTP/1.1\r\n" + + WantProxy: "GET http://www.google.com/search HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "User-Agent: Go http package\r\n" + "Transfer-Encoding: chunked\r\n\r\n" + chunk("abcdef") + chunk(""), + + WantDump: "GET /search HTTP/1.1\r\n" + + "Host: www.google.com\r\n" + + "Transfer-Encoding: chunked\r\n\r\n" + + chunk("abcdef") + chunk(""), }, // HTTP/1.1 POST => chunked coding; body; empty trailer { - Request{ + Req: Request{ Method: "POST", URL: &url.URL{ Scheme: "http", @@ -124,16 +132,16 @@ var reqWriteTests = []reqWriteTest{ TransferEncoding: []string{"chunked"}, }, - []byte("abcdef"), + Body: []byte("abcdef"), - "POST /search HTTP/1.1\r\n" + + WantWrite: "POST /search HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "User-Agent: Go http package\r\n" + "Connection: close\r\n" + "Transfer-Encoding: chunked\r\n\r\n" + chunk("abcdef") + chunk(""), - "POST http://www.google.com/search HTTP/1.1\r\n" + + WantProxy: "POST http://www.google.com/search HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "User-Agent: Go http package\r\n" + "Connection: close\r\n" + @@ -143,7 +151,7 @@ var reqWriteTests = []reqWriteTest{ // HTTP/1.1 POST with Content-Length, no chunking { - Request{ + Req: Request{ Method: "POST", URL: &url.URL{ Scheme: "http", @@ -157,9 +165,9 @@ var reqWriteTests = []reqWriteTest{ ContentLength: 6, }, - []byte("abcdef"), + Body: []byte("abcdef"), - "POST /search HTTP/1.1\r\n" + + WantWrite: "POST /search HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "User-Agent: Go http package\r\n" + "Connection: close\r\n" + @@ -167,7 +175,7 @@ var reqWriteTests = []reqWriteTest{ "\r\n" + "abcdef", - "POST http://www.google.com/search HTTP/1.1\r\n" + + WantProxy: "POST http://www.google.com/search HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "User-Agent: Go http package\r\n" + "Connection: close\r\n" + @@ -178,7 +186,7 @@ var reqWriteTests = []reqWriteTest{ // HTTP/1.1 POST with Content-Length in headers { - Request{ + Req: Request{ Method: "POST", RawURL: "http://example.com/", Host: "example.com", @@ -188,16 +196,16 @@ var reqWriteTests = []reqWriteTest{ ContentLength: 6, }, - []byte("abcdef"), + Body: []byte("abcdef"), - "POST http://example.com/ HTTP/1.1\r\n" + + WantWrite: "POST http://example.com/ HTTP/1.1\r\n" + "Host: example.com\r\n" + "User-Agent: Go http package\r\n" + "Content-Length: 6\r\n" + "\r\n" + "abcdef", - "POST http://example.com/ HTTP/1.1\r\n" + + WantProxy: "POST http://example.com/ HTTP/1.1\r\n" + "Host: example.com\r\n" + "User-Agent: Go http package\r\n" + "Content-Length: 6\r\n" + @@ -207,21 +215,19 @@ var reqWriteTests = []reqWriteTest{ // default to HTTP/1.1 { - Request{ + Req: Request{ Method: "GET", RawURL: "/search", Host: "www.google.com", }, - nil, - - "GET /search HTTP/1.1\r\n" + + WantWrite: "GET /search HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "User-Agent: Go http package\r\n" + "\r\n", // Looks weird but RawURL overrides what WriteProxy would choose. - "GET /search HTTP/1.1\r\n" + + WantProxy: "GET /search HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "User-Agent: Go http package\r\n" + "\r\n", @@ -229,7 +235,7 @@ var reqWriteTests = []reqWriteTest{ // Request with a 0 ContentLength and a 0 byte body. { - Request{ + Req: Request{ Method: "POST", RawURL: "/", Host: "example.com", @@ -238,22 +244,27 @@ var reqWriteTests = []reqWriteTest{ ContentLength: 0, // as if unset by user }, - func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 0)) }, + Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 0)) }, - "POST / HTTP/1.1\r\n" + + // RFC 2616 Section 14.13 says Content-Length should be specified + // unless body is prohibited by the request method. + // Also, nginx expects it for POST and PUT. + WantWrite: "POST / HTTP/1.1\r\n" + "Host: example.com\r\n" + "User-Agent: Go http package\r\n" + + "Content-Length: 0\r\n" + "\r\n", - "POST / HTTP/1.1\r\n" + + WantProxy: "POST / HTTP/1.1\r\n" + "Host: example.com\r\n" + "User-Agent: Go http package\r\n" + + "Content-Length: 0\r\n" + "\r\n", }, // Request with a 0 ContentLength and a 1 byte body. { - Request{ + Req: Request{ Method: "POST", RawURL: "/", Host: "example.com", @@ -262,20 +273,84 @@ var reqWriteTests = []reqWriteTest{ ContentLength: 0, // as if unset by user }, - func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 1)) }, + Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 1)) }, - "POST / HTTP/1.1\r\n" + + WantWrite: "POST / HTTP/1.1\r\n" + "Host: example.com\r\n" + "User-Agent: Go http package\r\n" + "Transfer-Encoding: chunked\r\n\r\n" + chunk("x") + chunk(""), - "POST / HTTP/1.1\r\n" + + WantProxy: "POST / HTTP/1.1\r\n" + "Host: example.com\r\n" + "User-Agent: Go http package\r\n" + "Transfer-Encoding: chunked\r\n\r\n" + chunk("x") + chunk(""), }, + + // Request with a ContentLength of 10 but a 5 byte body. + { + Req: Request{ + Method: "POST", + RawURL: "/", + Host: "example.com", + ProtoMajor: 1, + ProtoMinor: 1, + ContentLength: 10, // but we're going to send only 5 bytes + }, + Body: []byte("12345"), + WantError: os.NewError("http: Request.ContentLength=10 with Body length 5"), + }, + + // Request with a ContentLength of 4 but an 8 byte body. + { + Req: Request{ + Method: "POST", + RawURL: "/", + Host: "example.com", + ProtoMajor: 1, + ProtoMinor: 1, + ContentLength: 4, // but we're going to try to send 8 bytes + }, + Body: []byte("12345678"), + WantError: os.NewError("http: Request.ContentLength=4 with Body length 8"), + }, + + // Request with a 5 ContentLength and nil body. + { + Req: Request{ + Method: "POST", + RawURL: "/", + Host: "example.com", + ProtoMajor: 1, + ProtoMinor: 1, + ContentLength: 5, // but we'll omit the body + }, + WantError: os.NewError("http: Request.ContentLength=5 with nil Body"), + }, + + // Verify that DumpRequest preserves the HTTP version number, doesn't add a Host, + // and doesn't add a User-Agent. + { + Req: Request{ + Method: "GET", + RawURL: "/foo", + ProtoMajor: 1, + ProtoMinor: 0, + Header: Header{ + "X-Foo": []string{"X-Bar"}, + }, + }, + + // We can dump it: + WantDump: "GET /foo HTTP/1.0\r\n" + + "X-Foo: X-Bar\r\n\r\n", + + // .. but we can't call Request.Write on it, due to its lack of Host header. + // TODO(bradfitz): there might be an argument to allow this, but for now I'd + // rather let HTTP/1.0 continue to die. + WantError: os.NewError("http: Request.Write on Request with no Host or URL set"), + }, } func TestRequestWrite(t *testing.T) { @@ -283,6 +358,9 @@ func TestRequestWrite(t *testing.T) { tt := &reqWriteTests[i] setBody := func() { + if tt.Body == nil { + return + } switch b := tt.Body.(type) { case []byte: tt.Req.Body = ioutil.NopCloser(bytes.NewBuffer(b)) @@ -290,37 +368,55 @@ func TestRequestWrite(t *testing.T) { tt.Req.Body = b() } } - if tt.Body != nil { - setBody() - } + setBody() if tt.Req.Header == nil { tt.Req.Header = make(Header) } + var braw bytes.Buffer err := tt.Req.Write(&braw) - if err != nil { - t.Errorf("error writing #%d: %s", i, err) + if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.WantError); g != e { + t.Errorf("writing #%d, err = %q, want %q", i, g, e) continue } - sraw := braw.String() - if sraw != tt.Raw { - t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, tt.Raw, sraw) + if err != nil { continue } - if tt.Body != nil { - setBody() + if tt.WantWrite != "" { + sraw := braw.String() + if sraw != tt.WantWrite { + t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantWrite, sraw) + continue + } } - var praw bytes.Buffer - err = tt.Req.WriteProxy(&praw) - if err != nil { - t.Errorf("error writing #%d: %s", i, err) - continue + + if tt.WantProxy != "" { + setBody() + var praw bytes.Buffer + err = tt.Req.WriteProxy(&praw) + if err != nil { + t.Errorf("WriteProxy #%d: %s", i, err) + continue + } + sraw := praw.String() + if sraw != tt.WantProxy { + t.Errorf("Test Proxy %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantProxy, sraw) + continue + } } - sraw = praw.String() - if sraw != tt.RawProxy { - t.Errorf("Test Proxy %d, expecting:\n%s\nGot:\n%s\n", i, tt.RawProxy, sraw) - continue + + if tt.WantDump != "" { + setBody() + dump, err := DumpRequest(&tt.Req, true) + if err != nil { + t.Errorf("DumpRequest #%d: %s", i, err) + continue + } + if string(dump) != tt.WantDump { + t.Errorf("DumpRequest %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantDump, string(dump)) + continue + } } } } |