2011-03-06 13:02:06 -07:00
|
|
|
// Copyright 2010 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
2011-11-08 16:41:54 -07:00
|
|
|
"encoding/json"
|
2011-03-07 12:45:45 -07:00
|
|
|
"fmt"
|
2011-03-06 13:02:06 -07:00
|
|
|
"reflect"
|
|
|
|
"testing"
|
2011-05-24 09:31:43 -06:00
|
|
|
"time"
|
2011-03-06 13:02:06 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
var writeSetCookiesTests = []struct {
|
2011-06-16 14:02:28 -06:00
|
|
|
Cookie *Cookie
|
|
|
|
Raw string
|
2011-03-06 13:02:06 -07:00
|
|
|
}{
|
|
|
|
{
|
2011-06-16 14:02:28 -06:00
|
|
|
&Cookie{Name: "cookie-1", Value: "v$1"},
|
|
|
|
"cookie-1=v$1",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600},
|
|
|
|
"cookie-2=two; Max-Age=3600",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
|
|
|
|
"cookie-3=three; Domain=.example.com",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&Cookie{Name: "cookie-4", Value: "four", Path: "/restricted/"},
|
|
|
|
"cookie-4=four; Path=/restricted/",
|
2011-03-06 13:02:06 -07:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWriteSetCookies(t *testing.T) {
|
|
|
|
for i, tt := range writeSetCookiesTests {
|
2011-06-16 14:02:28 -06:00
|
|
|
if g, e := tt.Cookie.String(), tt.Raw; g != e {
|
|
|
|
t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, e, g)
|
2011-03-06 13:02:06 -07:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-17 16:07:44 -06:00
|
|
|
type headerOnlyResponseWriter Header
|
|
|
|
|
|
|
|
func (ho headerOnlyResponseWriter) Header() Header {
|
|
|
|
return Header(ho)
|
|
|
|
}
|
|
|
|
|
2011-11-01 20:04:37 -06:00
|
|
|
func (ho headerOnlyResponseWriter) Write([]byte) (int, error) {
|
2011-05-17 16:07:44 -06:00
|
|
|
panic("NOIMPL")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ho headerOnlyResponseWriter) WriteHeader(int) {
|
|
|
|
panic("NOIMPL")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetCookie(t *testing.T) {
|
|
|
|
m := make(Header)
|
|
|
|
SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-1", Value: "one", Path: "/restricted/"})
|
|
|
|
SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600})
|
|
|
|
if l := len(m["Set-Cookie"]); l != 2 {
|
|
|
|
t.Fatalf("expected %d cookies, got %d", 2, l)
|
|
|
|
}
|
|
|
|
if g, e := m["Set-Cookie"][0], "cookie-1=one; Path=/restricted/"; g != e {
|
|
|
|
t.Errorf("cookie #1: want %q, got %q", e, g)
|
|
|
|
}
|
|
|
|
if g, e := m["Set-Cookie"][1], "cookie-2=two; Max-Age=3600"; g != e {
|
|
|
|
t.Errorf("cookie #2: want %q, got %q", e, g)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-16 14:02:28 -06:00
|
|
|
var addCookieTests = []struct {
|
2011-03-06 13:02:06 -07:00
|
|
|
Cookies []*Cookie
|
|
|
|
Raw string
|
|
|
|
}{
|
2011-05-11 14:33:27 -06:00
|
|
|
{
|
|
|
|
[]*Cookie{},
|
|
|
|
"",
|
|
|
|
},
|
2011-03-06 13:02:06 -07:00
|
|
|
{
|
2011-03-07 12:45:45 -07:00
|
|
|
[]*Cookie{&Cookie{Name: "cookie-1", Value: "v$1"}},
|
2011-06-16 14:02:28 -06:00
|
|
|
"cookie-1=v$1",
|
2011-03-06 13:02:06 -07:00
|
|
|
},
|
2011-05-11 14:33:27 -06:00
|
|
|
{
|
|
|
|
[]*Cookie{
|
|
|
|
&Cookie{Name: "cookie-1", Value: "v$1"},
|
|
|
|
&Cookie{Name: "cookie-2", Value: "v$2"},
|
|
|
|
&Cookie{Name: "cookie-3", Value: "v$3"},
|
|
|
|
},
|
2011-06-16 14:02:28 -06:00
|
|
|
"cookie-1=v$1; cookie-2=v$2; cookie-3=v$3",
|
2011-05-11 14:33:27 -06:00
|
|
|
},
|
2011-03-06 13:02:06 -07:00
|
|
|
}
|
|
|
|
|
2011-06-16 14:02:28 -06:00
|
|
|
func TestAddCookie(t *testing.T) {
|
|
|
|
for i, tt := range addCookieTests {
|
|
|
|
req, _ := NewRequest("GET", "http://example.com/", nil)
|
|
|
|
for _, c := range tt.Cookies {
|
|
|
|
req.AddCookie(c)
|
|
|
|
}
|
|
|
|
if g := req.Header.Get("Cookie"); g != tt.Raw {
|
|
|
|
t.Errorf("Test %d:\nwant: %s\n got: %s\n", i, tt.Raw, g)
|
2011-03-06 13:02:06 -07:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var readSetCookiesTests = []struct {
|
|
|
|
Header Header
|
|
|
|
Cookies []*Cookie
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
Header{"Set-Cookie": {"Cookie-1=v$1"}},
|
2011-03-07 12:45:45 -07:00
|
|
|
[]*Cookie{&Cookie{Name: "Cookie-1", Value: "v$1", Raw: "Cookie-1=v$1"}},
|
2011-03-06 13:02:06 -07:00
|
|
|
},
|
2011-05-24 09:31:43 -06:00
|
|
|
{
|
|
|
|
Header{"Set-Cookie": {"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly"}},
|
|
|
|
[]*Cookie{&Cookie{
|
|
|
|
Name: "NID",
|
|
|
|
Value: "99=YsDT5i3E-CXax-",
|
|
|
|
Path: "/",
|
|
|
|
Domain: ".google.ch",
|
|
|
|
HttpOnly: true,
|
2011-11-30 10:01:46 -07:00
|
|
|
Expires: time.Date(2011, 11, 23, 1, 5, 3, 0, time.UTC),
|
2011-05-24 09:31:43 -06:00
|
|
|
RawExpires: "Wed, 23-Nov-2011 01:05:03 GMT",
|
|
|
|
Raw: "NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly",
|
|
|
|
}},
|
|
|
|
},
|
2011-03-06 13:02:06 -07:00
|
|
|
}
|
|
|
|
|
2011-03-07 12:45:45 -07:00
|
|
|
func toJSON(v interface{}) string {
|
|
|
|
b, err := json.Marshal(v)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Sprintf("%#v", v)
|
|
|
|
}
|
|
|
|
return string(b)
|
|
|
|
}
|
|
|
|
|
2011-03-06 13:02:06 -07:00
|
|
|
func TestReadSetCookies(t *testing.T) {
|
|
|
|
for i, tt := range readSetCookiesTests {
|
2011-06-16 14:02:28 -06:00
|
|
|
for n := 0; n < 2; n++ { // to verify readSetCookies doesn't mutate its input
|
|
|
|
c := readSetCookies(tt.Header)
|
|
|
|
if !reflect.DeepEqual(c, tt.Cookies) {
|
|
|
|
t.Errorf("#%d readSetCookies: have\n%s\nwant\n%s\n", i, toJSON(c), toJSON(tt.Cookies))
|
|
|
|
continue
|
|
|
|
}
|
2011-03-06 13:02:06 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var readCookiesTests = []struct {
|
|
|
|
Header Header
|
2011-06-16 14:02:28 -06:00
|
|
|
Filter string
|
2011-03-06 13:02:06 -07:00
|
|
|
Cookies []*Cookie
|
|
|
|
}{
|
|
|
|
{
|
2011-06-16 14:02:28 -06:00
|
|
|
Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
|
|
|
|
"",
|
|
|
|
[]*Cookie{
|
|
|
|
&Cookie{Name: "Cookie-1", Value: "v$1"},
|
|
|
|
&Cookie{Name: "c2", Value: "v2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
|
|
|
|
"c2",
|
|
|
|
[]*Cookie{
|
|
|
|
&Cookie{Name: "c2", Value: "v2"},
|
|
|
|
},
|
2011-03-06 13:02:06 -07:00
|
|
|
},
|
2011-06-20 11:33:07 -06:00
|
|
|
{
|
|
|
|
Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
|
|
|
|
"",
|
|
|
|
[]*Cookie{
|
|
|
|
&Cookie{Name: "Cookie-1", Value: "v$1"},
|
|
|
|
&Cookie{Name: "c2", Value: "v2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
|
|
|
|
"c2",
|
|
|
|
[]*Cookie{
|
|
|
|
&Cookie{Name: "c2", Value: "v2"},
|
|
|
|
},
|
|
|
|
},
|
2011-03-06 13:02:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestReadCookies(t *testing.T) {
|
|
|
|
for i, tt := range readCookiesTests {
|
2011-06-16 14:02:28 -06:00
|
|
|
for n := 0; n < 2; n++ { // to verify readCookies doesn't mutate its input
|
|
|
|
c := readCookies(tt.Header, tt.Filter)
|
|
|
|
if !reflect.DeepEqual(c, tt.Cookies) {
|
2011-06-20 11:33:07 -06:00
|
|
|
t.Errorf("#%d readCookies:\nhave: %s\nwant: %s\n", i, toJSON(c), toJSON(tt.Cookies))
|
2011-06-16 14:02:28 -06:00
|
|
|
continue
|
|
|
|
}
|
2011-03-06 13:02:06 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|