OSDN Git Service

Update Go library to r60.
[pf3gnuchains/gcc-fork.git] / libgo / go / http / requestwrite_test.go
index bb000c7..458f0bd 100644 (file)
@@ -6,16 +6,18 @@ package http
 
 import (
        "bytes"
+       "fmt"
        "io"
        "io/ioutil"
        "os"
        "strings"
        "testing"
+       "url"
 )
 
 type reqWriteTest struct {
        Req      Request
-       Body     []byte
+       Body     interface{} // optional []byte or func() io.ReadCloser to populate Req.Body
        Raw      string
        RawProxy string
 }
@@ -26,7 +28,7 @@ var reqWriteTests = []reqWriteTest{
                Request{
                        Method: "GET",
                        RawURL: "http://www.techcrunch.com/",
-                       URL: &URL{
+                       URL: &url.URL{
                                Raw:          "http://www.techcrunch.com/",
                                Scheme:       "http",
                                RawPath:      "http://www.techcrunch.com/",
@@ -47,13 +49,12 @@ var reqWriteTests = []reqWriteTest{
                                "Accept-Language":  {"en-us,en;q=0.5"},
                                "Keep-Alive":       {"300"},
                                "Proxy-Connection": {"keep-alive"},
+                               "User-Agent":       {"Fake"},
                        },
-                       Body:      nil,
-                       Close:     false,
-                       Host:      "www.techcrunch.com",
-                       Referer:   "",
-                       UserAgent: "Fake",
-                       Form:      map[string][]string{},
+                       Body:  nil,
+                       Close: false,
+                       Host:  "www.techcrunch.com",
+                       Form:  map[string][]string{},
                },
 
                nil,
@@ -69,6 +70,7 @@ var reqWriteTests = []reqWriteTest{
                        "Proxy-Connection: keep-alive\r\n\r\n",
 
                "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" +
                        "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
@@ -81,7 +83,7 @@ var reqWriteTests = []reqWriteTest{
        {
                Request{
                        Method: "GET",
-                       URL: &URL{
+                       URL: &url.URL{
                                Scheme: "http",
                                Host:   "www.google.com",
                                Path:   "/search",
@@ -98,18 +100,19 @@ var reqWriteTests = []reqWriteTest{
                        "Host: www.google.com\r\n" +
                        "User-Agent: Go http package\r\n" +
                        "Transfer-Encoding: chunked\r\n\r\n" +
-                       "6\r\nabcdef\r\n0\r\n\r\n",
+                       chunk("abcdef") + chunk(""),
 
                "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" +
-                       "6\r\nabcdef\r\n0\r\n\r\n",
+                       chunk("abcdef") + chunk(""),
        },
        // HTTP/1.1 POST => chunked coding; body; empty trailer
        {
                Request{
                        Method: "POST",
-                       URL: &URL{
+                       URL: &url.URL{
                                Scheme: "http",
                                Host:   "www.google.com",
                                Path:   "/search",
@@ -128,20 +131,21 @@ var reqWriteTests = []reqWriteTest{
                        "User-Agent: Go http package\r\n" +
                        "Connection: close\r\n" +
                        "Transfer-Encoding: chunked\r\n\r\n" +
-                       "6\r\nabcdef\r\n0\r\n\r\n",
+                       chunk("abcdef") + chunk(""),
 
                "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" +
                        "Transfer-Encoding: chunked\r\n\r\n" +
-                       "6\r\nabcdef\r\n0\r\n\r\n",
+                       chunk("abcdef") + chunk(""),
        },
 
        // HTTP/1.1 POST with Content-Length, no chunking
        {
                Request{
                        Method: "POST",
-                       URL: &URL{
+                       URL: &url.URL{
                                Scheme: "http",
                                Host:   "www.google.com",
                                Path:   "/search",
@@ -164,6 +168,7 @@ var reqWriteTests = []reqWriteTest{
                        "abcdef",
 
                "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" +
                        "Content-Length: 6\r\n" +
@@ -171,6 +176,35 @@ var reqWriteTests = []reqWriteTest{
                        "abcdef",
        },
 
+       // HTTP/1.1 POST with Content-Length in headers
+       {
+               Request{
+                       Method: "POST",
+                       RawURL: "http://example.com/",
+                       Host:   "example.com",
+                       Header: Header{
+                               "Content-Length": []string{"10"}, // ignored
+                       },
+                       ContentLength: 6,
+               },
+
+               []byte("abcdef"),
+
+               "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" +
+                       "Host: example.com\r\n" +
+                       "User-Agent: Go http package\r\n" +
+                       "Content-Length: 6\r\n" +
+                       "\r\n" +
+                       "abcdef",
+       },
+
        // default to HTTP/1.1
        {
                Request{
@@ -188,16 +222,79 @@ var reqWriteTests = []reqWriteTest{
 
                // Looks weird but RawURL overrides what WriteProxy would choose.
                "GET /search HTTP/1.1\r\n" +
+                       "Host: www.google.com\r\n" +
                        "User-Agent: Go http package\r\n" +
                        "\r\n",
        },
+
+       // Request with a 0 ContentLength and a 0 byte body.
+       {
+               Request{
+                       Method:        "POST",
+                       RawURL:        "/",
+                       Host:          "example.com",
+                       ProtoMajor:    1,
+                       ProtoMinor:    1,
+                       ContentLength: 0, // as if unset by user
+               },
+
+               func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 0)) },
+
+               "POST / HTTP/1.1\r\n" +
+                       "Host: example.com\r\n" +
+                       "User-Agent: Go http package\r\n" +
+                       "\r\n",
+
+               "POST / HTTP/1.1\r\n" +
+                       "Host: example.com\r\n" +
+                       "User-Agent: Go http package\r\n" +
+                       "\r\n",
+       },
+
+       // Request with a 0 ContentLength and a 1 byte body.
+       {
+               Request{
+                       Method:        "POST",
+                       RawURL:        "/",
+                       Host:          "example.com",
+                       ProtoMajor:    1,
+                       ProtoMinor:    1,
+                       ContentLength: 0, // as if unset by user
+               },
+
+               func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 1)) },
+
+               "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" +
+                       "Host: example.com\r\n" +
+                       "User-Agent: Go http package\r\n" +
+                       "Transfer-Encoding: chunked\r\n\r\n" +
+                       chunk("x") + chunk(""),
+       },
 }
 
 func TestRequestWrite(t *testing.T) {
        for i := range reqWriteTests {
                tt := &reqWriteTests[i]
+
+               setBody := func() {
+                       switch b := tt.Body.(type) {
+                       case []byte:
+                               tt.Req.Body = ioutil.NopCloser(bytes.NewBuffer(b))
+                       case func() io.ReadCloser:
+                               tt.Req.Body = b()
+                       }
+               }
                if tt.Body != nil {
-                       tt.Req.Body = ioutil.NopCloser(bytes.NewBuffer(tt.Body))
+                       setBody()
+               }
+               if tt.Req.Header == nil {
+                       tt.Req.Header = make(Header)
                }
                var braw bytes.Buffer
                err := tt.Req.Write(&braw)
@@ -212,7 +309,7 @@ func TestRequestWrite(t *testing.T) {
                }
 
                if tt.Body != nil {
-                       tt.Req.Body = ioutil.NopCloser(bytes.NewBuffer(tt.Body))
+                       setBody()
                }
                var praw bytes.Buffer
                err = tt.Req.WriteProxy(&praw)
@@ -240,13 +337,34 @@ func (rc *closeChecker) Close() os.Error {
 
 // TestRequestWriteClosesBody tests that Request.Write does close its request.Body.
 // It also indirectly tests NewRequest and that it doesn't wrap an existing Closer
-// inside a NopCloser.
+// inside a NopCloser, and that it serializes it correctly.
 func TestRequestWriteClosesBody(t *testing.T) {
        rc := &closeChecker{Reader: strings.NewReader("my body")}
-       req, _ := NewRequest("GET", "http://foo.com/", rc)
+       req, _ := NewRequest("POST", "http://foo.com/", rc)
+       if req.ContentLength != 0 {
+               t.Errorf("got req.ContentLength %d, want 0", req.ContentLength)
+       }
        buf := new(bytes.Buffer)
        req.Write(buf)
        if !rc.closed {
                t.Error("body not closed after write")
        }
+       expected := "POST / HTTP/1.1\r\n" +
+               "Host: foo.com\r\n" +
+               "User-Agent: Go http package\r\n" +
+               "Transfer-Encoding: chunked\r\n\r\n" +
+               // TODO: currently we don't buffer before chunking, so we get a
+               // single "m" chunk before the other chunks, as this was the 1-byte
+               // read from our MultiReader where we stiched the Body back together
+               // after sniffing whether the Body was 0 bytes or not.
+               chunk("m") +
+               chunk("y body") +
+               chunk("")
+       if buf.String() != expected {
+               t.Errorf("write:\n got: %s\nwant: %s", buf.String(), expected)
+       }
+}
+
+func chunk(s string) string {
+       return fmt.Sprintf("%x\r\n%s\r\n", len(s), s)
 }