...

Source file src/net/http/cookie_test.go

Documentation: net/http

		 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  	"bytes"
		 9  	"encoding/json"
		10  	"fmt"
		11  	"log"
		12  	"os"
		13  	"reflect"
		14  	"strings"
		15  	"testing"
		16  	"time"
		17  )
		18  
		19  var writeSetCookiesTests = []struct {
		20  	Cookie *Cookie
		21  	Raw		string
		22  }{
		23  	{
		24  		&Cookie{Name: "cookie-1", Value: "v$1"},
		25  		"cookie-1=v$1",
		26  	},
		27  	{
		28  		&Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600},
		29  		"cookie-2=two; Max-Age=3600",
		30  	},
		31  	{
		32  		&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
		33  		"cookie-3=three; Domain=example.com",
		34  	},
		35  	{
		36  		&Cookie{Name: "cookie-4", Value: "four", Path: "/restricted/"},
		37  		"cookie-4=four; Path=/restricted/",
		38  	},
		39  	{
		40  		&Cookie{Name: "cookie-5", Value: "five", Domain: "wrong;bad.abc"},
		41  		"cookie-5=five",
		42  	},
		43  	{
		44  		&Cookie{Name: "cookie-6", Value: "six", Domain: "bad-.abc"},
		45  		"cookie-6=six",
		46  	},
		47  	{
		48  		&Cookie{Name: "cookie-7", Value: "seven", Domain: "127.0.0.1"},
		49  		"cookie-7=seven; Domain=127.0.0.1",
		50  	},
		51  	{
		52  		&Cookie{Name: "cookie-8", Value: "eight", Domain: "::1"},
		53  		"cookie-8=eight",
		54  	},
		55  	{
		56  		&Cookie{Name: "cookie-9", Value: "expiring", Expires: time.Unix(1257894000, 0)},
		57  		"cookie-9=expiring; Expires=Tue, 10 Nov 2009 23:00:00 GMT",
		58  	},
		59  	// According to IETF 6265 Section 5.1.1.5, the year cannot be less than 1601
		60  	{
		61  		&Cookie{Name: "cookie-10", Value: "expiring-1601", Expires: time.Date(1601, 1, 1, 1, 1, 1, 1, time.UTC)},
		62  		"cookie-10=expiring-1601; Expires=Mon, 01 Jan 1601 01:01:01 GMT",
		63  	},
		64  	{
		65  		&Cookie{Name: "cookie-11", Value: "invalid-expiry", Expires: time.Date(1600, 1, 1, 1, 1, 1, 1, time.UTC)},
		66  		"cookie-11=invalid-expiry",
		67  	},
		68  	{
		69  		&Cookie{Name: "cookie-12", Value: "samesite-default", SameSite: SameSiteDefaultMode},
		70  		"cookie-12=samesite-default",
		71  	},
		72  	{
		73  		&Cookie{Name: "cookie-13", Value: "samesite-lax", SameSite: SameSiteLaxMode},
		74  		"cookie-13=samesite-lax; SameSite=Lax",
		75  	},
		76  	{
		77  		&Cookie{Name: "cookie-14", Value: "samesite-strict", SameSite: SameSiteStrictMode},
		78  		"cookie-14=samesite-strict; SameSite=Strict",
		79  	},
		80  	{
		81  		&Cookie{Name: "cookie-15", Value: "samesite-none", SameSite: SameSiteNoneMode},
		82  		"cookie-15=samesite-none; SameSite=None",
		83  	},
		84  	// The "special" cookies have values containing commas or spaces which
		85  	// are disallowed by RFC 6265 but are common in the wild.
		86  	{
		87  		&Cookie{Name: "special-1", Value: "a z"},
		88  		`special-1="a z"`,
		89  	},
		90  	{
		91  		&Cookie{Name: "special-2", Value: " z"},
		92  		`special-2=" z"`,
		93  	},
		94  	{
		95  		&Cookie{Name: "special-3", Value: "a "},
		96  		`special-3="a "`,
		97  	},
		98  	{
		99  		&Cookie{Name: "special-4", Value: " "},
	 100  		`special-4=" "`,
	 101  	},
	 102  	{
	 103  		&Cookie{Name: "special-5", Value: "a,z"},
	 104  		`special-5="a,z"`,
	 105  	},
	 106  	{
	 107  		&Cookie{Name: "special-6", Value: ",z"},
	 108  		`special-6=",z"`,
	 109  	},
	 110  	{
	 111  		&Cookie{Name: "special-7", Value: "a,"},
	 112  		`special-7="a,"`,
	 113  	},
	 114  	{
	 115  		&Cookie{Name: "special-8", Value: ","},
	 116  		`special-8=","`,
	 117  	},
	 118  	{
	 119  		&Cookie{Name: "empty-value", Value: ""},
	 120  		`empty-value=`,
	 121  	},
	 122  	{
	 123  		nil,
	 124  		``,
	 125  	},
	 126  	{
	 127  		&Cookie{Name: ""},
	 128  		``,
	 129  	},
	 130  	{
	 131  		&Cookie{Name: "\t"},
	 132  		``,
	 133  	},
	 134  	{
	 135  		&Cookie{Name: "\r"},
	 136  		``,
	 137  	},
	 138  	{
	 139  		&Cookie{Name: "a\nb", Value: "v"},
	 140  		``,
	 141  	},
	 142  	{
	 143  		&Cookie{Name: "a\nb", Value: "v"},
	 144  		``,
	 145  	},
	 146  	{
	 147  		&Cookie{Name: "a\rb", Value: "v"},
	 148  		``,
	 149  	},
	 150  }
	 151  
	 152  func TestWriteSetCookies(t *testing.T) {
	 153  	defer log.SetOutput(os.Stderr)
	 154  	var logbuf bytes.Buffer
	 155  	log.SetOutput(&logbuf)
	 156  
	 157  	for i, tt := range writeSetCookiesTests {
	 158  		if g, e := tt.Cookie.String(), tt.Raw; g != e {
	 159  			t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, e, g)
	 160  			continue
	 161  		}
	 162  	}
	 163  
	 164  	if got, sub := logbuf.String(), "dropping domain attribute"; !strings.Contains(got, sub) {
	 165  		t.Errorf("Expected substring %q in log output. Got:\n%s", sub, got)
	 166  	}
	 167  }
	 168  
	 169  type headerOnlyResponseWriter Header
	 170  
	 171  func (ho headerOnlyResponseWriter) Header() Header {
	 172  	return Header(ho)
	 173  }
	 174  
	 175  func (ho headerOnlyResponseWriter) Write([]byte) (int, error) {
	 176  	panic("NOIMPL")
	 177  }
	 178  
	 179  func (ho headerOnlyResponseWriter) WriteHeader(int) {
	 180  	panic("NOIMPL")
	 181  }
	 182  
	 183  func TestSetCookie(t *testing.T) {
	 184  	m := make(Header)
	 185  	SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-1", Value: "one", Path: "/restricted/"})
	 186  	SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600})
	 187  	if l := len(m["Set-Cookie"]); l != 2 {
	 188  		t.Fatalf("expected %d cookies, got %d", 2, l)
	 189  	}
	 190  	if g, e := m["Set-Cookie"][0], "cookie-1=one; Path=/restricted/"; g != e {
	 191  		t.Errorf("cookie #1: want %q, got %q", e, g)
	 192  	}
	 193  	if g, e := m["Set-Cookie"][1], "cookie-2=two; Max-Age=3600"; g != e {
	 194  		t.Errorf("cookie #2: want %q, got %q", e, g)
	 195  	}
	 196  }
	 197  
	 198  var addCookieTests = []struct {
	 199  	Cookies []*Cookie
	 200  	Raw		 string
	 201  }{
	 202  	{
	 203  		[]*Cookie{},
	 204  		"",
	 205  	},
	 206  	{
	 207  		[]*Cookie{{Name: "cookie-1", Value: "v$1"}},
	 208  		"cookie-1=v$1",
	 209  	},
	 210  	{
	 211  		[]*Cookie{
	 212  			{Name: "cookie-1", Value: "v$1"},
	 213  			{Name: "cookie-2", Value: "v$2"},
	 214  			{Name: "cookie-3", Value: "v$3"},
	 215  		},
	 216  		"cookie-1=v$1; cookie-2=v$2; cookie-3=v$3",
	 217  	},
	 218  }
	 219  
	 220  func TestAddCookie(t *testing.T) {
	 221  	for i, tt := range addCookieTests {
	 222  		req, _ := NewRequest("GET", "http://example.com/", nil)
	 223  		for _, c := range tt.Cookies {
	 224  			req.AddCookie(c)
	 225  		}
	 226  		if g := req.Header.Get("Cookie"); g != tt.Raw {
	 227  			t.Errorf("Test %d:\nwant: %s\n got: %s\n", i, tt.Raw, g)
	 228  			continue
	 229  		}
	 230  	}
	 231  }
	 232  
	 233  var readSetCookiesTests = []struct {
	 234  	Header	Header
	 235  	Cookies []*Cookie
	 236  }{
	 237  	{
	 238  		Header{"Set-Cookie": {"Cookie-1=v$1"}},
	 239  		[]*Cookie{{Name: "Cookie-1", Value: "v$1", Raw: "Cookie-1=v$1"}},
	 240  	},
	 241  	{
	 242  		Header{"Set-Cookie": {"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly"}},
	 243  		[]*Cookie{{
	 244  			Name:			 "NID",
	 245  			Value:			"99=YsDT5i3E-CXax-",
	 246  			Path:			 "/",
	 247  			Domain:		 ".google.ch",
	 248  			HttpOnly:	 true,
	 249  			Expires:		time.Date(2011, 11, 23, 1, 5, 3, 0, time.UTC),
	 250  			RawExpires: "Wed, 23-Nov-2011 01:05:03 GMT",
	 251  			Raw:				"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly",
	 252  		}},
	 253  	},
	 254  	{
	 255  		Header{"Set-Cookie": {".ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly"}},
	 256  		[]*Cookie{{
	 257  			Name:			 ".ASPXAUTH",
	 258  			Value:			"7E3AA",
	 259  			Path:			 "/",
	 260  			Expires:		time.Date(2012, 3, 7, 14, 25, 6, 0, time.UTC),
	 261  			RawExpires: "Wed, 07-Mar-2012 14:25:06 GMT",
	 262  			HttpOnly:	 true,
	 263  			Raw:				".ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly",
	 264  		}},
	 265  	},
	 266  	{
	 267  		Header{"Set-Cookie": {"ASP.NET_SessionId=foo; path=/; HttpOnly"}},
	 268  		[]*Cookie{{
	 269  			Name:		 "ASP.NET_SessionId",
	 270  			Value:		"foo",
	 271  			Path:		 "/",
	 272  			HttpOnly: true,
	 273  			Raw:			"ASP.NET_SessionId=foo; path=/; HttpOnly",
	 274  		}},
	 275  	},
	 276  	{
	 277  		Header{"Set-Cookie": {"samesitedefault=foo; SameSite"}},
	 278  		[]*Cookie{{
	 279  			Name:		 "samesitedefault",
	 280  			Value:		"foo",
	 281  			SameSite: SameSiteDefaultMode,
	 282  			Raw:			"samesitedefault=foo; SameSite",
	 283  		}},
	 284  	},
	 285  	{
	 286  		Header{"Set-Cookie": {"samesiteinvalidisdefault=foo; SameSite=invalid"}},
	 287  		[]*Cookie{{
	 288  			Name:		 "samesiteinvalidisdefault",
	 289  			Value:		"foo",
	 290  			SameSite: SameSiteDefaultMode,
	 291  			Raw:			"samesiteinvalidisdefault=foo; SameSite=invalid",
	 292  		}},
	 293  	},
	 294  	{
	 295  		Header{"Set-Cookie": {"samesitelax=foo; SameSite=Lax"}},
	 296  		[]*Cookie{{
	 297  			Name:		 "samesitelax",
	 298  			Value:		"foo",
	 299  			SameSite: SameSiteLaxMode,
	 300  			Raw:			"samesitelax=foo; SameSite=Lax",
	 301  		}},
	 302  	},
	 303  	{
	 304  		Header{"Set-Cookie": {"samesitestrict=foo; SameSite=Strict"}},
	 305  		[]*Cookie{{
	 306  			Name:		 "samesitestrict",
	 307  			Value:		"foo",
	 308  			SameSite: SameSiteStrictMode,
	 309  			Raw:			"samesitestrict=foo; SameSite=Strict",
	 310  		}},
	 311  	},
	 312  	{
	 313  		Header{"Set-Cookie": {"samesitenone=foo; SameSite=None"}},
	 314  		[]*Cookie{{
	 315  			Name:		 "samesitenone",
	 316  			Value:		"foo",
	 317  			SameSite: SameSiteNoneMode,
	 318  			Raw:			"samesitenone=foo; SameSite=None",
	 319  		}},
	 320  	},
	 321  	// Make sure we can properly read back the Set-Cookie headers we create
	 322  	// for values containing spaces or commas:
	 323  	{
	 324  		Header{"Set-Cookie": {`special-1=a z`}},
	 325  		[]*Cookie{{Name: "special-1", Value: "a z", Raw: `special-1=a z`}},
	 326  	},
	 327  	{
	 328  		Header{"Set-Cookie": {`special-2=" z"`}},
	 329  		[]*Cookie{{Name: "special-2", Value: " z", Raw: `special-2=" z"`}},
	 330  	},
	 331  	{
	 332  		Header{"Set-Cookie": {`special-3="a "`}},
	 333  		[]*Cookie{{Name: "special-3", Value: "a ", Raw: `special-3="a "`}},
	 334  	},
	 335  	{
	 336  		Header{"Set-Cookie": {`special-4=" "`}},
	 337  		[]*Cookie{{Name: "special-4", Value: " ", Raw: `special-4=" "`}},
	 338  	},
	 339  	{
	 340  		Header{"Set-Cookie": {`special-5=a,z`}},
	 341  		[]*Cookie{{Name: "special-5", Value: "a,z", Raw: `special-5=a,z`}},
	 342  	},
	 343  	{
	 344  		Header{"Set-Cookie": {`special-6=",z"`}},
	 345  		[]*Cookie{{Name: "special-6", Value: ",z", Raw: `special-6=",z"`}},
	 346  	},
	 347  	{
	 348  		Header{"Set-Cookie": {`special-7=a,`}},
	 349  		[]*Cookie{{Name: "special-7", Value: "a,", Raw: `special-7=a,`}},
	 350  	},
	 351  	{
	 352  		Header{"Set-Cookie": {`special-8=","`}},
	 353  		[]*Cookie{{Name: "special-8", Value: ",", Raw: `special-8=","`}},
	 354  	},
	 355  
	 356  	// TODO(bradfitz): users have reported seeing this in the
	 357  	// wild, but do browsers handle it? RFC 6265 just says "don't
	 358  	// do that" (section 3) and then never mentions header folding
	 359  	// again.
	 360  	// Header{"Set-Cookie": {"ASP.NET_SessionId=foo; path=/; HttpOnly, .ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly"}},
	 361  }
	 362  
	 363  func toJSON(v interface{}) string {
	 364  	b, err := json.Marshal(v)
	 365  	if err != nil {
	 366  		return fmt.Sprintf("%#v", v)
	 367  	}
	 368  	return string(b)
	 369  }
	 370  
	 371  func TestReadSetCookies(t *testing.T) {
	 372  	for i, tt := range readSetCookiesTests {
	 373  		for n := 0; n < 2; n++ { // to verify readSetCookies doesn't mutate its input
	 374  			c := readSetCookies(tt.Header)
	 375  			if !reflect.DeepEqual(c, tt.Cookies) {
	 376  				t.Errorf("#%d readSetCookies: have\n%s\nwant\n%s\n", i, toJSON(c), toJSON(tt.Cookies))
	 377  				continue
	 378  			}
	 379  		}
	 380  	}
	 381  }
	 382  
	 383  var readCookiesTests = []struct {
	 384  	Header	Header
	 385  	Filter	string
	 386  	Cookies []*Cookie
	 387  }{
	 388  	{
	 389  		Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
	 390  		"",
	 391  		[]*Cookie{
	 392  			{Name: "Cookie-1", Value: "v$1"},
	 393  			{Name: "c2", Value: "v2"},
	 394  		},
	 395  	},
	 396  	{
	 397  		Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
	 398  		"c2",
	 399  		[]*Cookie{
	 400  			{Name: "c2", Value: "v2"},
	 401  		},
	 402  	},
	 403  	{
	 404  		Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
	 405  		"",
	 406  		[]*Cookie{
	 407  			{Name: "Cookie-1", Value: "v$1"},
	 408  			{Name: "c2", Value: "v2"},
	 409  		},
	 410  	},
	 411  	{
	 412  		Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
	 413  		"c2",
	 414  		[]*Cookie{
	 415  			{Name: "c2", Value: "v2"},
	 416  		},
	 417  	},
	 418  	{
	 419  		Header{"Cookie": {`Cookie-1="v$1"; c2="v2"`}},
	 420  		"",
	 421  		[]*Cookie{
	 422  			{Name: "Cookie-1", Value: "v$1"},
	 423  			{Name: "c2", Value: "v2"},
	 424  		},
	 425  	},
	 426  	{
	 427  		Header{"Cookie": {`Cookie-1="v$1"; c2=v2;`}},
	 428  		"",
	 429  		[]*Cookie{
	 430  			{Name: "Cookie-1", Value: "v$1"},
	 431  			{Name: "c2", Value: "v2"},
	 432  		},
	 433  	},
	 434  	{
	 435  		Header{"Cookie": {``}},
	 436  		"",
	 437  		[]*Cookie{},
	 438  	},
	 439  }
	 440  
	 441  func TestReadCookies(t *testing.T) {
	 442  	for i, tt := range readCookiesTests {
	 443  		for n := 0; n < 2; n++ { // to verify readCookies doesn't mutate its input
	 444  			c := readCookies(tt.Header, tt.Filter)
	 445  			if !reflect.DeepEqual(c, tt.Cookies) {
	 446  				t.Errorf("#%d readCookies:\nhave: %s\nwant: %s\n", i, toJSON(c), toJSON(tt.Cookies))
	 447  				continue
	 448  			}
	 449  		}
	 450  	}
	 451  }
	 452  
	 453  func TestSetCookieDoubleQuotes(t *testing.T) {
	 454  	res := &Response{Header: Header{}}
	 455  	res.Header.Add("Set-Cookie", `quoted0=none; max-age=30`)
	 456  	res.Header.Add("Set-Cookie", `quoted1="cookieValue"; max-age=31`)
	 457  	res.Header.Add("Set-Cookie", `quoted2=cookieAV; max-age="32"`)
	 458  	res.Header.Add("Set-Cookie", `quoted3="both"; max-age="33"`)
	 459  	got := res.Cookies()
	 460  	want := []*Cookie{
	 461  		{Name: "quoted0", Value: "none", MaxAge: 30},
	 462  		{Name: "quoted1", Value: "cookieValue", MaxAge: 31},
	 463  		{Name: "quoted2", Value: "cookieAV"},
	 464  		{Name: "quoted3", Value: "both"},
	 465  	}
	 466  	if len(got) != len(want) {
	 467  		t.Fatalf("got %d cookies, want %d", len(got), len(want))
	 468  	}
	 469  	for i, w := range want {
	 470  		g := got[i]
	 471  		if g.Name != w.Name || g.Value != w.Value || g.MaxAge != w.MaxAge {
	 472  			t.Errorf("cookie #%d:\ngot	%v\nwant %v", i, g, w)
	 473  		}
	 474  	}
	 475  }
	 476  
	 477  func TestCookieSanitizeValue(t *testing.T) {
	 478  	defer log.SetOutput(os.Stderr)
	 479  	var logbuf bytes.Buffer
	 480  	log.SetOutput(&logbuf)
	 481  
	 482  	tests := []struct {
	 483  		in, want string
	 484  	}{
	 485  		{"foo", "foo"},
	 486  		{"foo;bar", "foobar"},
	 487  		{"foo\\bar", "foobar"},
	 488  		{"foo\"bar", "foobar"},
	 489  		{"\x00\x7e\x7f\x80", "\x7e"},
	 490  		{`"withquotes"`, "withquotes"},
	 491  		{"a z", `"a z"`},
	 492  		{" z", `" z"`},
	 493  		{"a ", `"a "`},
	 494  		{"a,z", `"a,z"`},
	 495  		{",z", `",z"`},
	 496  		{"a,", `"a,"`},
	 497  	}
	 498  	for _, tt := range tests {
	 499  		if got := sanitizeCookieValue(tt.in); got != tt.want {
	 500  			t.Errorf("sanitizeCookieValue(%q) = %q; want %q", tt.in, got, tt.want)
	 501  		}
	 502  	}
	 503  
	 504  	if got, sub := logbuf.String(), "dropping invalid bytes"; !strings.Contains(got, sub) {
	 505  		t.Errorf("Expected substring %q in log output. Got:\n%s", sub, got)
	 506  	}
	 507  }
	 508  
	 509  func TestCookieSanitizePath(t *testing.T) {
	 510  	defer log.SetOutput(os.Stderr)
	 511  	var logbuf bytes.Buffer
	 512  	log.SetOutput(&logbuf)
	 513  
	 514  	tests := []struct {
	 515  		in, want string
	 516  	}{
	 517  		{"/path", "/path"},
	 518  		{"/path with space/", "/path with space/"},
	 519  		{"/just;no;semicolon\x00orstuff/", "/justnosemicolonorstuff/"},
	 520  	}
	 521  	for _, tt := range tests {
	 522  		if got := sanitizeCookiePath(tt.in); got != tt.want {
	 523  			t.Errorf("sanitizeCookiePath(%q) = %q; want %q", tt.in, got, tt.want)
	 524  		}
	 525  	}
	 526  
	 527  	if got, sub := logbuf.String(), "dropping invalid bytes"; !strings.Contains(got, sub) {
	 528  		t.Errorf("Expected substring %q in log output. Got:\n%s", sub, got)
	 529  	}
	 530  }
	 531  
	 532  func BenchmarkCookieString(b *testing.B) {
	 533  	const wantCookieString = `cookie-9=i3e01nf61b6t23bvfmplnanol3; Path=/restricted/; Domain=example.com; Expires=Tue, 10 Nov 2009 23:00:00 GMT; Max-Age=3600`
	 534  	c := &Cookie{
	 535  		Name:		"cookie-9",
	 536  		Value:	 "i3e01nf61b6t23bvfmplnanol3",
	 537  		Expires: time.Unix(1257894000, 0),
	 538  		Path:		"/restricted/",
	 539  		Domain:	".example.com",
	 540  		MaxAge:	3600,
	 541  	}
	 542  	var benchmarkCookieString string
	 543  	b.ReportAllocs()
	 544  	b.ResetTimer()
	 545  	for i := 0; i < b.N; i++ {
	 546  		benchmarkCookieString = c.String()
	 547  	}
	 548  	if have, want := benchmarkCookieString, wantCookieString; have != want {
	 549  		b.Fatalf("Have: %v Want: %v", have, want)
	 550  	}
	 551  }
	 552  
	 553  func BenchmarkReadSetCookies(b *testing.B) {
	 554  	header := Header{
	 555  		"Set-Cookie": {
	 556  			"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly",
	 557  			".ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly",
	 558  		},
	 559  	}
	 560  	wantCookies := []*Cookie{
	 561  		{
	 562  			Name:			 "NID",
	 563  			Value:			"99=YsDT5i3E-CXax-",
	 564  			Path:			 "/",
	 565  			Domain:		 ".google.ch",
	 566  			HttpOnly:	 true,
	 567  			Expires:		time.Date(2011, 11, 23, 1, 5, 3, 0, time.UTC),
	 568  			RawExpires: "Wed, 23-Nov-2011 01:05:03 GMT",
	 569  			Raw:				"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly",
	 570  		},
	 571  		{
	 572  			Name:			 ".ASPXAUTH",
	 573  			Value:			"7E3AA",
	 574  			Path:			 "/",
	 575  			Expires:		time.Date(2012, 3, 7, 14, 25, 6, 0, time.UTC),
	 576  			RawExpires: "Wed, 07-Mar-2012 14:25:06 GMT",
	 577  			HttpOnly:	 true,
	 578  			Raw:				".ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly",
	 579  		},
	 580  	}
	 581  	var c []*Cookie
	 582  	b.ReportAllocs()
	 583  	b.ResetTimer()
	 584  	for i := 0; i < b.N; i++ {
	 585  		c = readSetCookies(header)
	 586  	}
	 587  	if !reflect.DeepEqual(c, wantCookies) {
	 588  		b.Fatalf("readSetCookies:\nhave: %s\nwant: %s\n", toJSON(c), toJSON(wantCookies))
	 589  	}
	 590  }
	 591  
	 592  func BenchmarkReadCookies(b *testing.B) {
	 593  	header := Header{
	 594  		"Cookie": {
	 595  			`de=; client_region=0; rpld1=0:hispeed.ch|20:che|21:zh|22:zurich|23:47.36|24:8.53|; rpld0=1:08|; backplane-channel=newspaper.com:1471; devicetype=0; osfam=0; rplmct=2; s_pers=%20s_vmonthnum%3D1472680800496%2526vn%253D1%7C1472680800496%3B%20s_nr%3D1471686767664-New%7C1474278767664%3B%20s_lv%3D1471686767669%7C1566294767669%3B%20s_lv_s%3DFirst%2520Visit%7C1471688567669%3B%20s_monthinvisit%3Dtrue%7C1471688567677%3B%20gvp_p5%3Dsports%253Ablog%253Aearly-lead%2520-%2520184693%2520-%252020160820%2520-%2520u-s%7C1471688567681%3B%20gvp_p51%3Dwp%2520-%2520sports%7C1471688567684%3B; s_sess=%20s_wp_ep%3Dhomepage%3B%20s._ref%3Dhttps%253A%252F%252Fwww.google.ch%252F%3B%20s_cc%3Dtrue%3B%20s_ppvl%3Dsports%25253Ablog%25253Aearly-lead%252520-%252520184693%252520-%25252020160820%252520-%252520u-lawyer%252C12%252C12%252C502%252C1231%252C502%252C1680%252C1050%252C2%252CP%3B%20s_ppv%3Dsports%25253Ablog%25253Aearly-lead%252520-%252520184693%252520-%25252020160820%252520-%252520u-s-lawyer%252C12%252C12%252C502%252C1231%252C502%252C1680%252C1050%252C2%252CP%3B%20s_dslv%3DFirst%2520Visit%3B%20s_sq%3Dwpninewspapercom%253D%252526pid%25253Dsports%2525253Ablog%2525253Aearly-lead%25252520-%25252520184693%25252520-%2525252020160820%25252520-%25252520u-s%252526pidt%25253D1%252526oid%25253Dhttps%2525253A%2525252F%2525252Fwww.newspaper.com%2525252F%2525253Fnid%2525253Dmenu_nav_homepage%252526ot%25253DA%3B`,
	 596  		},
	 597  	}
	 598  	wantCookies := []*Cookie{
	 599  		{Name: "de", Value: ""},
	 600  		{Name: "client_region", Value: "0"},
	 601  		{Name: "rpld1", Value: "0:hispeed.ch|20:che|21:zh|22:zurich|23:47.36|24:8.53|"},
	 602  		{Name: "rpld0", Value: "1:08|"},
	 603  		{Name: "backplane-channel", Value: "newspaper.com:1471"},
	 604  		{Name: "devicetype", Value: "0"},
	 605  		{Name: "osfam", Value: "0"},
	 606  		{Name: "rplmct", Value: "2"},
	 607  		{Name: "s_pers", Value: "%20s_vmonthnum%3D1472680800496%2526vn%253D1%7C1472680800496%3B%20s_nr%3D1471686767664-New%7C1474278767664%3B%20s_lv%3D1471686767669%7C1566294767669%3B%20s_lv_s%3DFirst%2520Visit%7C1471688567669%3B%20s_monthinvisit%3Dtrue%7C1471688567677%3B%20gvp_p5%3Dsports%253Ablog%253Aearly-lead%2520-%2520184693%2520-%252020160820%2520-%2520u-s%7C1471688567681%3B%20gvp_p51%3Dwp%2520-%2520sports%7C1471688567684%3B"},
	 608  		{Name: "s_sess", Value: "%20s_wp_ep%3Dhomepage%3B%20s._ref%3Dhttps%253A%252F%252Fwww.google.ch%252F%3B%20s_cc%3Dtrue%3B%20s_ppvl%3Dsports%25253Ablog%25253Aearly-lead%252520-%252520184693%252520-%25252020160820%252520-%252520u-lawyer%252C12%252C12%252C502%252C1231%252C502%252C1680%252C1050%252C2%252CP%3B%20s_ppv%3Dsports%25253Ablog%25253Aearly-lead%252520-%252520184693%252520-%25252020160820%252520-%252520u-s-lawyer%252C12%252C12%252C502%252C1231%252C502%252C1680%252C1050%252C2%252CP%3B%20s_dslv%3DFirst%2520Visit%3B%20s_sq%3Dwpninewspapercom%253D%252526pid%25253Dsports%2525253Ablog%2525253Aearly-lead%25252520-%25252520184693%25252520-%2525252020160820%25252520-%25252520u-s%252526pidt%25253D1%252526oid%25253Dhttps%2525253A%2525252F%2525252Fwww.newspaper.com%2525252F%2525253Fnid%2525253Dmenu_nav_homepage%252526ot%25253DA%3B"},
	 609  	}
	 610  	var c []*Cookie
	 611  	b.ReportAllocs()
	 612  	b.ResetTimer()
	 613  	for i := 0; i < b.N; i++ {
	 614  		c = readCookies(header, "")
	 615  	}
	 616  	if !reflect.DeepEqual(c, wantCookies) {
	 617  		b.Fatalf("readCookies:\nhave: %s\nwant: %s\n", toJSON(c), toJSON(wantCookies))
	 618  	}
	 619  }
	 620  

View as plain text