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 }