github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/net/http/cookie_test.go (about)

     1  // 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  	"encoding/json"
     9  	"fmt"
    10  	"reflect"
    11  	"testing"
    12  	"time"
    13  )
    14  
    15  var writeSetCookiesTests = []struct {
    16  	Cookie *Cookie
    17  	Raw    string
    18  }{
    19  	{
    20  		&Cookie{Name: "cookie-1", Value: "v$1"},
    21  		"cookie-1=v$1",
    22  	},
    23  	{
    24  		&Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600},
    25  		"cookie-2=two; Max-Age=3600",
    26  	},
    27  	{
    28  		&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
    29  		"cookie-3=three; Domain=.example.com",
    30  	},
    31  	{
    32  		&Cookie{Name: "cookie-4", Value: "four", Path: "/restricted/"},
    33  		"cookie-4=four; Path=/restricted/",
    34  	},
    35  }
    36  
    37  func TestWriteSetCookies(t *testing.T) {
    38  	for i, tt := range writeSetCookiesTests {
    39  		if g, e := tt.Cookie.String(), tt.Raw; g != e {
    40  			t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, e, g)
    41  			continue
    42  		}
    43  	}
    44  }
    45  
    46  type headerOnlyResponseWriter Header
    47  
    48  func (ho headerOnlyResponseWriter) Header() Header {
    49  	return Header(ho)
    50  }
    51  
    52  func (ho headerOnlyResponseWriter) Write([]byte) (int, error) {
    53  	panic("NOIMPL")
    54  }
    55  
    56  func (ho headerOnlyResponseWriter) WriteHeader(int) {
    57  	panic("NOIMPL")
    58  }
    59  
    60  func TestSetCookie(t *testing.T) {
    61  	m := make(Header)
    62  	SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-1", Value: "one", Path: "/restricted/"})
    63  	SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600})
    64  	if l := len(m["Set-Cookie"]); l != 2 {
    65  		t.Fatalf("expected %d cookies, got %d", 2, l)
    66  	}
    67  	if g, e := m["Set-Cookie"][0], "cookie-1=one; Path=/restricted/"; g != e {
    68  		t.Errorf("cookie #1: want %q, got %q", e, g)
    69  	}
    70  	if g, e := m["Set-Cookie"][1], "cookie-2=two; Max-Age=3600"; g != e {
    71  		t.Errorf("cookie #2: want %q, got %q", e, g)
    72  	}
    73  }
    74  
    75  var addCookieTests = []struct {
    76  	Cookies []*Cookie
    77  	Raw     string
    78  }{
    79  	{
    80  		[]*Cookie{},
    81  		"",
    82  	},
    83  	{
    84  		[]*Cookie{{Name: "cookie-1", Value: "v$1"}},
    85  		"cookie-1=v$1",
    86  	},
    87  	{
    88  		[]*Cookie{
    89  			{Name: "cookie-1", Value: "v$1"},
    90  			{Name: "cookie-2", Value: "v$2"},
    91  			{Name: "cookie-3", Value: "v$3"},
    92  		},
    93  		"cookie-1=v$1; cookie-2=v$2; cookie-3=v$3",
    94  	},
    95  }
    96  
    97  func TestAddCookie(t *testing.T) {
    98  	for i, tt := range addCookieTests {
    99  		req, _ := NewRequest("GET", "http://example.com/", nil)
   100  		for _, c := range tt.Cookies {
   101  			req.AddCookie(c)
   102  		}
   103  		if g := req.Header.Get("Cookie"); g != tt.Raw {
   104  			t.Errorf("Test %d:\nwant: %s\n got: %s\n", i, tt.Raw, g)
   105  			continue
   106  		}
   107  	}
   108  }
   109  
   110  var readSetCookiesTests = []struct {
   111  	Header  Header
   112  	Cookies []*Cookie
   113  }{
   114  	{
   115  		Header{"Set-Cookie": {"Cookie-1=v$1"}},
   116  		[]*Cookie{{Name: "Cookie-1", Value: "v$1", Raw: "Cookie-1=v$1"}},
   117  	},
   118  	{
   119  		Header{"Set-Cookie": {"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly"}},
   120  		[]*Cookie{{
   121  			Name:       "NID",
   122  			Value:      "99=YsDT5i3E-CXax-",
   123  			Path:       "/",
   124  			Domain:     ".google.ch",
   125  			HttpOnly:   true,
   126  			Expires:    time.Date(2011, 11, 23, 1, 5, 3, 0, time.UTC),
   127  			RawExpires: "Wed, 23-Nov-2011 01:05:03 GMT",
   128  			Raw:        "NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly",
   129  		}},
   130  	},
   131  	{
   132  		Header{"Set-Cookie": {".ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly"}},
   133  		[]*Cookie{{
   134  			Name:       ".ASPXAUTH",
   135  			Value:      "7E3AA",
   136  			Path:       "/",
   137  			Expires:    time.Date(2012, 3, 7, 14, 25, 6, 0, time.UTC),
   138  			RawExpires: "Wed, 07-Mar-2012 14:25:06 GMT",
   139  			HttpOnly:   true,
   140  			Raw:        ".ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly",
   141  		}},
   142  	},
   143  	{
   144  		Header{"Set-Cookie": {"ASP.NET_SessionId=foo; path=/; HttpOnly"}},
   145  		[]*Cookie{{
   146  			Name:     "ASP.NET_SessionId",
   147  			Value:    "foo",
   148  			Path:     "/",
   149  			HttpOnly: true,
   150  			Raw:      "ASP.NET_SessionId=foo; path=/; HttpOnly",
   151  		}},
   152  	},
   153  
   154  	// TODO(bradfitz): users have reported seeing this in the
   155  	// wild, but do browsers handle it? RFC 6265 just says "don't
   156  	// do that" (section 3) and then never mentions header folding
   157  	// again.
   158  	// Header{"Set-Cookie": {"ASP.NET_SessionId=foo; path=/; HttpOnly, .ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly"}},
   159  }
   160  
   161  func toJSON(v interface{}) string {
   162  	b, err := json.Marshal(v)
   163  	if err != nil {
   164  		return fmt.Sprintf("%#v", v)
   165  	}
   166  	return string(b)
   167  }
   168  
   169  func TestReadSetCookies(t *testing.T) {
   170  	for i, tt := range readSetCookiesTests {
   171  		for n := 0; n < 2; n++ { // to verify readSetCookies doesn't mutate its input
   172  			c := readSetCookies(tt.Header)
   173  			if !reflect.DeepEqual(c, tt.Cookies) {
   174  				t.Errorf("#%d readSetCookies: have\n%s\nwant\n%s\n", i, toJSON(c), toJSON(tt.Cookies))
   175  				continue
   176  			}
   177  		}
   178  	}
   179  }
   180  
   181  var readCookiesTests = []struct {
   182  	Header  Header
   183  	Filter  string
   184  	Cookies []*Cookie
   185  }{
   186  	{
   187  		Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
   188  		"",
   189  		[]*Cookie{
   190  			{Name: "Cookie-1", Value: "v$1"},
   191  			{Name: "c2", Value: "v2"},
   192  		},
   193  	},
   194  	{
   195  		Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
   196  		"c2",
   197  		[]*Cookie{
   198  			{Name: "c2", Value: "v2"},
   199  		},
   200  	},
   201  	{
   202  		Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
   203  		"",
   204  		[]*Cookie{
   205  			{Name: "Cookie-1", Value: "v$1"},
   206  			{Name: "c2", Value: "v2"},
   207  		},
   208  	},
   209  	{
   210  		Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
   211  		"c2",
   212  		[]*Cookie{
   213  			{Name: "c2", Value: "v2"},
   214  		},
   215  	},
   216  }
   217  
   218  func TestReadCookies(t *testing.T) {
   219  	for i, tt := range readCookiesTests {
   220  		for n := 0; n < 2; n++ { // to verify readCookies doesn't mutate its input
   221  			c := readCookies(tt.Header, tt.Filter)
   222  			if !reflect.DeepEqual(c, tt.Cookies) {
   223  				t.Errorf("#%d readCookies:\nhave: %s\nwant: %s\n", i, toJSON(c), toJSON(tt.Cookies))
   224  				continue
   225  			}
   226  		}
   227  	}
   228  }