...

Source file src/net/http/cookiejar/jar_test.go

Documentation: net/http/cookiejar

		 1  // Copyright 2013 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 cookiejar
		 6  
		 7  import (
		 8  	"fmt"
		 9  	"net/http"
		10  	"net/url"
		11  	"sort"
		12  	"strings"
		13  	"testing"
		14  	"time"
		15  )
		16  
		17  // tNow is the synthetic current time used as now during testing.
		18  var tNow = time.Date(2013, 1, 1, 12, 0, 0, 0, time.UTC)
		19  
		20  // testPSL implements PublicSuffixList with just two rules: "co.uk"
		21  // and the default rule "*".
		22  // The implementation has two intentional bugs:
		23  //		PublicSuffix("www.buggy.psl") == "xy"
		24  //		PublicSuffix("www2.buggy.psl") == "com"
		25  type testPSL struct{}
		26  
		27  func (testPSL) String() string {
		28  	return "testPSL"
		29  }
		30  func (testPSL) PublicSuffix(d string) string {
		31  	if d == "co.uk" || strings.HasSuffix(d, ".co.uk") {
		32  		return "co.uk"
		33  	}
		34  	if d == "www.buggy.psl" {
		35  		return "xy"
		36  	}
		37  	if d == "www2.buggy.psl" {
		38  		return "com"
		39  	}
		40  	return d[strings.LastIndex(d, ".")+1:]
		41  }
		42  
		43  // newTestJar creates an empty Jar with testPSL as the public suffix list.
		44  func newTestJar() *Jar {
		45  	jar, err := New(&Options{PublicSuffixList: testPSL{}})
		46  	if err != nil {
		47  		panic(err)
		48  	}
		49  	return jar
		50  }
		51  
		52  var hasDotSuffixTests = [...]struct {
		53  	s, suffix string
		54  }{
		55  	{"", ""},
		56  	{"", "."},
		57  	{"", "x"},
		58  	{".", ""},
		59  	{".", "."},
		60  	{".", ".."},
		61  	{".", "x"},
		62  	{".", "x."},
		63  	{".", ".x"},
		64  	{".", ".x."},
		65  	{"x", ""},
		66  	{"x", "."},
		67  	{"x", ".."},
		68  	{"x", "x"},
		69  	{"x", "x."},
		70  	{"x", ".x"},
		71  	{"x", ".x."},
		72  	{".x", ""},
		73  	{".x", "."},
		74  	{".x", ".."},
		75  	{".x", "x"},
		76  	{".x", "x."},
		77  	{".x", ".x"},
		78  	{".x", ".x."},
		79  	{"x.", ""},
		80  	{"x.", "."},
		81  	{"x.", ".."},
		82  	{"x.", "x"},
		83  	{"x.", "x."},
		84  	{"x.", ".x"},
		85  	{"x.", ".x."},
		86  	{"com", ""},
		87  	{"com", "m"},
		88  	{"com", "om"},
		89  	{"com", "com"},
		90  	{"com", ".com"},
		91  	{"com", "x.com"},
		92  	{"com", "xcom"},
		93  	{"com", "xorg"},
		94  	{"com", "org"},
		95  	{"com", "rg"},
		96  	{"foo.com", ""},
		97  	{"foo.com", "m"},
		98  	{"foo.com", "om"},
		99  	{"foo.com", "com"},
	 100  	{"foo.com", ".com"},
	 101  	{"foo.com", "o.com"},
	 102  	{"foo.com", "oo.com"},
	 103  	{"foo.com", "foo.com"},
	 104  	{"foo.com", ".foo.com"},
	 105  	{"foo.com", "x.foo.com"},
	 106  	{"foo.com", "xfoo.com"},
	 107  	{"foo.com", "xfoo.org"},
	 108  	{"foo.com", "foo.org"},
	 109  	{"foo.com", "oo.org"},
	 110  	{"foo.com", "o.org"},
	 111  	{"foo.com", ".org"},
	 112  	{"foo.com", "org"},
	 113  	{"foo.com", "rg"},
	 114  }
	 115  
	 116  func TestHasDotSuffix(t *testing.T) {
	 117  	for _, tc := range hasDotSuffixTests {
	 118  		got := hasDotSuffix(tc.s, tc.suffix)
	 119  		want := strings.HasSuffix(tc.s, "."+tc.suffix)
	 120  		if got != want {
	 121  			t.Errorf("s=%q, suffix=%q: got %v, want %v", tc.s, tc.suffix, got, want)
	 122  		}
	 123  	}
	 124  }
	 125  
	 126  var canonicalHostTests = map[string]string{
	 127  	"www.example.com":				 "www.example.com",
	 128  	"WWW.EXAMPLE.COM":				 "www.example.com",
	 129  	"wWw.eXAmple.CoM":				 "www.example.com",
	 130  	"www.example.com:80":			"www.example.com",
	 131  	"192.168.0.10":						"192.168.0.10",
	 132  	"192.168.0.5:8080":				"192.168.0.5",
	 133  	"2001:4860:0:2001::68":		"2001:4860:0:2001::68",
	 134  	"[2001:4860:0:::68]:8080": "2001:4860:0:::68",
	 135  	"www.bücher.de":					 "www.xn--bcher-kva.de",
	 136  	"www.example.com.":				"www.example.com",
	 137  	// TODO: Fix canonicalHost so that all of the following malformed
	 138  	// domain names trigger an error. (This list is not exhaustive, e.g.
	 139  	// malformed internationalized domain names are missing.)
	 140  	".":											 "",
	 141  	"..":											".",
	 142  	"...":										 "..",
	 143  	".net":										".net",
	 144  	".net.":									 ".net",
	 145  	"a..":										 "a.",
	 146  	"b.a..":									 "b.a.",
	 147  	"weird.stuff...":					"weird.stuff..",
	 148  	"[bad.unmatched.bracket:": "error",
	 149  }
	 150  
	 151  func TestCanonicalHost(t *testing.T) {
	 152  	for h, want := range canonicalHostTests {
	 153  		got, err := canonicalHost(h)
	 154  		if want == "error" {
	 155  			if err == nil {
	 156  				t.Errorf("%q: got %q and nil error, want non-nil", h, got)
	 157  			}
	 158  			continue
	 159  		}
	 160  		if err != nil {
	 161  			t.Errorf("%q: %v", h, err)
	 162  			continue
	 163  		}
	 164  		if got != want {
	 165  			t.Errorf("%q: got %q, want %q", h, got, want)
	 166  			continue
	 167  		}
	 168  	}
	 169  }
	 170  
	 171  var hasPortTests = map[string]bool{
	 172  	"www.example.com":			false,
	 173  	"www.example.com:80":	 true,
	 174  	"127.0.0.1":						false,
	 175  	"127.0.0.1:8080":			 true,
	 176  	"2001:4860:0:2001::68": false,
	 177  	"[2001::0:::68]:80":		true,
	 178  }
	 179  
	 180  func TestHasPort(t *testing.T) {
	 181  	for host, want := range hasPortTests {
	 182  		if got := hasPort(host); got != want {
	 183  			t.Errorf("%q: got %t, want %t", host, got, want)
	 184  		}
	 185  	}
	 186  }
	 187  
	 188  var jarKeyTests = map[string]string{
	 189  	"foo.www.example.com": "example.com",
	 190  	"www.example.com":		 "example.com",
	 191  	"example.com":				 "example.com",
	 192  	"com":								 "com",
	 193  	"foo.www.bbc.co.uk":	 "bbc.co.uk",
	 194  	"www.bbc.co.uk":			 "bbc.co.uk",
	 195  	"bbc.co.uk":					 "bbc.co.uk",
	 196  	"co.uk":							 "co.uk",
	 197  	"uk":									"uk",
	 198  	"192.168.0.5":				 "192.168.0.5",
	 199  	"www.buggy.psl":			 "www.buggy.psl",
	 200  	"www2.buggy.psl":			"buggy.psl",
	 201  	// The following are actual outputs of canonicalHost for
	 202  	// malformed inputs to canonicalHost (see above).
	 203  	"":							"",
	 204  	".":						 ".",
	 205  	"..":						".",
	 206  	".net":					".net",
	 207  	"a.":						"a.",
	 208  	"b.a.":					"a.",
	 209  	"weird.stuff..": ".",
	 210  }
	 211  
	 212  func TestJarKey(t *testing.T) {
	 213  	for host, want := range jarKeyTests {
	 214  		if got := jarKey(host, testPSL{}); got != want {
	 215  			t.Errorf("%q: got %q, want %q", host, got, want)
	 216  		}
	 217  	}
	 218  }
	 219  
	 220  var jarKeyNilPSLTests = map[string]string{
	 221  	"foo.www.example.com": "example.com",
	 222  	"www.example.com":		 "example.com",
	 223  	"example.com":				 "example.com",
	 224  	"com":								 "com",
	 225  	"foo.www.bbc.co.uk":	 "co.uk",
	 226  	"www.bbc.co.uk":			 "co.uk",
	 227  	"bbc.co.uk":					 "co.uk",
	 228  	"co.uk":							 "co.uk",
	 229  	"uk":									"uk",
	 230  	"192.168.0.5":				 "192.168.0.5",
	 231  	// The following are actual outputs of canonicalHost for
	 232  	// malformed inputs to canonicalHost.
	 233  	"":							"",
	 234  	".":						 ".",
	 235  	"..":						"..",
	 236  	".net":					".net",
	 237  	"a.":						"a.",
	 238  	"b.a.":					"a.",
	 239  	"weird.stuff..": "stuff..",
	 240  }
	 241  
	 242  func TestJarKeyNilPSL(t *testing.T) {
	 243  	for host, want := range jarKeyNilPSLTests {
	 244  		if got := jarKey(host, nil); got != want {
	 245  			t.Errorf("%q: got %q, want %q", host, got, want)
	 246  		}
	 247  	}
	 248  }
	 249  
	 250  var isIPTests = map[string]bool{
	 251  	"127.0.0.1":						true,
	 252  	"1.2.3.4":							true,
	 253  	"2001:4860:0:2001::68": true,
	 254  	"example.com":					false,
	 255  	"1.1.1.300":						false,
	 256  	"www.foo.bar.net":			false,
	 257  	"123.foo.bar.net":			false,
	 258  }
	 259  
	 260  func TestIsIP(t *testing.T) {
	 261  	for host, want := range isIPTests {
	 262  		if got := isIP(host); got != want {
	 263  			t.Errorf("%q: got %t, want %t", host, got, want)
	 264  		}
	 265  	}
	 266  }
	 267  
	 268  var defaultPathTests = map[string]string{
	 269  	"/":					 "/",
	 270  	"/abc":				"/",
	 271  	"/abc/":			 "/abc",
	 272  	"/abc/xyz":		"/abc",
	 273  	"/abc/xyz/":	 "/abc/xyz",
	 274  	"/a/b/c.html": "/a/b",
	 275  	"":						"/",
	 276  	"strange":		 "/",
	 277  	"//":					"/",
	 278  	"/a//b":			 "/a/",
	 279  	"/a/./b":			"/a/.",
	 280  	"/a/../b":		 "/a/..",
	 281  }
	 282  
	 283  func TestDefaultPath(t *testing.T) {
	 284  	for path, want := range defaultPathTests {
	 285  		if got := defaultPath(path); got != want {
	 286  			t.Errorf("%q: got %q, want %q", path, got, want)
	 287  		}
	 288  	}
	 289  }
	 290  
	 291  var domainAndTypeTests = [...]struct {
	 292  	host				 string // host Set-Cookie header was received from
	 293  	domain			 string // domain attribute in Set-Cookie header
	 294  	wantDomain	 string // expected domain of cookie
	 295  	wantHostOnly bool	 // expected host-cookie flag
	 296  	wantErr			error	// expected error
	 297  }{
	 298  	{"www.example.com", "", "www.example.com", true, nil},
	 299  	{"127.0.0.1", "", "127.0.0.1", true, nil},
	 300  	{"2001:4860:0:2001::68", "", "2001:4860:0:2001::68", true, nil},
	 301  	{"www.example.com", "example.com", "example.com", false, nil},
	 302  	{"www.example.com", ".example.com", "example.com", false, nil},
	 303  	{"www.example.com", "www.example.com", "www.example.com", false, nil},
	 304  	{"www.example.com", ".www.example.com", "www.example.com", false, nil},
	 305  	{"foo.sso.example.com", "sso.example.com", "sso.example.com", false, nil},
	 306  	{"bar.co.uk", "bar.co.uk", "bar.co.uk", false, nil},
	 307  	{"foo.bar.co.uk", ".bar.co.uk", "bar.co.uk", false, nil},
	 308  	{"127.0.0.1", "127.0.0.1", "", false, errNoHostname},
	 309  	{"2001:4860:0:2001::68", "2001:4860:0:2001::68", "2001:4860:0:2001::68", false, errNoHostname},
	 310  	{"www.example.com", ".", "", false, errMalformedDomain},
	 311  	{"www.example.com", "..", "", false, errMalformedDomain},
	 312  	{"www.example.com", "other.com", "", false, errIllegalDomain},
	 313  	{"www.example.com", "com", "", false, errIllegalDomain},
	 314  	{"www.example.com", ".com", "", false, errIllegalDomain},
	 315  	{"foo.bar.co.uk", ".co.uk", "", false, errIllegalDomain},
	 316  	{"127.www.0.0.1", "127.0.0.1", "", false, errIllegalDomain},
	 317  	{"com", "", "com", true, nil},
	 318  	{"com", "com", "com", true, nil},
	 319  	{"com", ".com", "com", true, nil},
	 320  	{"co.uk", "", "co.uk", true, nil},
	 321  	{"co.uk", "co.uk", "co.uk", true, nil},
	 322  	{"co.uk", ".co.uk", "co.uk", true, nil},
	 323  }
	 324  
	 325  func TestDomainAndType(t *testing.T) {
	 326  	jar := newTestJar()
	 327  	for _, tc := range domainAndTypeTests {
	 328  		domain, hostOnly, err := jar.domainAndType(tc.host, tc.domain)
	 329  		if err != tc.wantErr {
	 330  			t.Errorf("%q/%q: got %q error, want %q",
	 331  				tc.host, tc.domain, err, tc.wantErr)
	 332  			continue
	 333  		}
	 334  		if err != nil {
	 335  			continue
	 336  		}
	 337  		if domain != tc.wantDomain || hostOnly != tc.wantHostOnly {
	 338  			t.Errorf("%q/%q: got %q/%t want %q/%t",
	 339  				tc.host, tc.domain, domain, hostOnly,
	 340  				tc.wantDomain, tc.wantHostOnly)
	 341  		}
	 342  	}
	 343  }
	 344  
	 345  // expiresIn creates an expires attribute delta seconds from tNow.
	 346  func expiresIn(delta int) string {
	 347  	t := tNow.Add(time.Duration(delta) * time.Second)
	 348  	return "expires=" + t.Format(time.RFC1123)
	 349  }
	 350  
	 351  // mustParseURL parses s to an URL and panics on error.
	 352  func mustParseURL(s string) *url.URL {
	 353  	u, err := url.Parse(s)
	 354  	if err != nil || u.Scheme == "" || u.Host == "" {
	 355  		panic(fmt.Sprintf("Unable to parse URL %s.", s))
	 356  	}
	 357  	return u
	 358  }
	 359  
	 360  // jarTest encapsulates the following actions on a jar:
	 361  //	 1. Perform SetCookies with fromURL and the cookies from setCookies.
	 362  //			(Done at time tNow + 0 ms.)
	 363  //	 2. Check that the entries in the jar matches content.
	 364  //			(Done at time tNow + 1001 ms.)
	 365  //	 3. For each query in tests: Check that Cookies with toURL yields the
	 366  //			cookies in want.
	 367  //			(Query n done at tNow + (n+2)*1001 ms.)
	 368  type jarTest struct {
	 369  	description string	 // The description of what this test is supposed to test
	 370  	fromURL		 string	 // The full URL of the request from which Set-Cookie headers where received
	 371  	setCookies	[]string // All the cookies received from fromURL
	 372  	content		 string	 // The whole (non-expired) content of the jar
	 373  	queries		 []query	// Queries to test the Jar.Cookies method
	 374  }
	 375  
	 376  // query contains one test of the cookies returned from Jar.Cookies.
	 377  type query struct {
	 378  	toURL string // the URL in the Cookies call
	 379  	want	string // the expected list of cookies (order matters)
	 380  }
	 381  
	 382  // run runs the jarTest.
	 383  func (test jarTest) run(t *testing.T, jar *Jar) {
	 384  	now := tNow
	 385  
	 386  	// Populate jar with cookies.
	 387  	setCookies := make([]*http.Cookie, len(test.setCookies))
	 388  	for i, cs := range test.setCookies {
	 389  		cookies := (&http.Response{Header: http.Header{"Set-Cookie": {cs}}}).Cookies()
	 390  		if len(cookies) != 1 {
	 391  			panic(fmt.Sprintf("Wrong cookie line %q: %#v", cs, cookies))
	 392  		}
	 393  		setCookies[i] = cookies[0]
	 394  	}
	 395  	jar.setCookies(mustParseURL(test.fromURL), setCookies, now)
	 396  	now = now.Add(1001 * time.Millisecond)
	 397  
	 398  	// Serialize non-expired entries in the form "name1=val1 name2=val2".
	 399  	var cs []string
	 400  	for _, submap := range jar.entries {
	 401  		for _, cookie := range submap {
	 402  			if !cookie.Expires.After(now) {
	 403  				continue
	 404  			}
	 405  			cs = append(cs, cookie.Name+"="+cookie.Value)
	 406  		}
	 407  	}
	 408  	sort.Strings(cs)
	 409  	got := strings.Join(cs, " ")
	 410  
	 411  	// Make sure jar content matches our expectations.
	 412  	if got != test.content {
	 413  		t.Errorf("Test %q Content\ngot	%q\nwant %q",
	 414  			test.description, got, test.content)
	 415  	}
	 416  
	 417  	// Test different calls to Cookies.
	 418  	for i, query := range test.queries {
	 419  		now = now.Add(1001 * time.Millisecond)
	 420  		var s []string
	 421  		for _, c := range jar.cookies(mustParseURL(query.toURL), now) {
	 422  			s = append(s, c.Name+"="+c.Value)
	 423  		}
	 424  		if got := strings.Join(s, " "); got != query.want {
	 425  			t.Errorf("Test %q #%d\ngot	%q\nwant %q", test.description, i, got, query.want)
	 426  		}
	 427  	}
	 428  }
	 429  
	 430  // basicsTests contains fundamental tests. Each jarTest has to be performed on
	 431  // a fresh, empty Jar.
	 432  var basicsTests = [...]jarTest{
	 433  	{
	 434  		"Retrieval of a plain host cookie.",
	 435  		"http://www.host.test/",
	 436  		[]string{"A=a"},
	 437  		"A=a",
	 438  		[]query{
	 439  			{"http://www.host.test", "A=a"},
	 440  			{"http://www.host.test/", "A=a"},
	 441  			{"http://www.host.test/some/path", "A=a"},
	 442  			{"https://www.host.test", "A=a"},
	 443  			{"https://www.host.test/", "A=a"},
	 444  			{"https://www.host.test/some/path", "A=a"},
	 445  			{"ftp://www.host.test", ""},
	 446  			{"ftp://www.host.test/", ""},
	 447  			{"ftp://www.host.test/some/path", ""},
	 448  			{"http://www.other.org", ""},
	 449  			{"http://sibling.host.test", ""},
	 450  			{"http://deep.www.host.test", ""},
	 451  		},
	 452  	},
	 453  	{
	 454  		"Secure cookies are not returned to http.",
	 455  		"http://www.host.test/",
	 456  		[]string{"A=a; secure"},
	 457  		"A=a",
	 458  		[]query{
	 459  			{"http://www.host.test", ""},
	 460  			{"http://www.host.test/", ""},
	 461  			{"http://www.host.test/some/path", ""},
	 462  			{"https://www.host.test", "A=a"},
	 463  			{"https://www.host.test/", "A=a"},
	 464  			{"https://www.host.test/some/path", "A=a"},
	 465  		},
	 466  	},
	 467  	{
	 468  		"Explicit path.",
	 469  		"http://www.host.test/",
	 470  		[]string{"A=a; path=/some/path"},
	 471  		"A=a",
	 472  		[]query{
	 473  			{"http://www.host.test", ""},
	 474  			{"http://www.host.test/", ""},
	 475  			{"http://www.host.test/some", ""},
	 476  			{"http://www.host.test/some/", ""},
	 477  			{"http://www.host.test/some/path", "A=a"},
	 478  			{"http://www.host.test/some/paths", ""},
	 479  			{"http://www.host.test/some/path/foo", "A=a"},
	 480  			{"http://www.host.test/some/path/foo/", "A=a"},
	 481  		},
	 482  	},
	 483  	{
	 484  		"Implicit path #1: path is a directory.",
	 485  		"http://www.host.test/some/path/",
	 486  		[]string{"A=a"},
	 487  		"A=a",
	 488  		[]query{
	 489  			{"http://www.host.test", ""},
	 490  			{"http://www.host.test/", ""},
	 491  			{"http://www.host.test/some", ""},
	 492  			{"http://www.host.test/some/", ""},
	 493  			{"http://www.host.test/some/path", "A=a"},
	 494  			{"http://www.host.test/some/paths", ""},
	 495  			{"http://www.host.test/some/path/foo", "A=a"},
	 496  			{"http://www.host.test/some/path/foo/", "A=a"},
	 497  		},
	 498  	},
	 499  	{
	 500  		"Implicit path #2: path is not a directory.",
	 501  		"http://www.host.test/some/path/index.html",
	 502  		[]string{"A=a"},
	 503  		"A=a",
	 504  		[]query{
	 505  			{"http://www.host.test", ""},
	 506  			{"http://www.host.test/", ""},
	 507  			{"http://www.host.test/some", ""},
	 508  			{"http://www.host.test/some/", ""},
	 509  			{"http://www.host.test/some/path", "A=a"},
	 510  			{"http://www.host.test/some/paths", ""},
	 511  			{"http://www.host.test/some/path/foo", "A=a"},
	 512  			{"http://www.host.test/some/path/foo/", "A=a"},
	 513  		},
	 514  	},
	 515  	{
	 516  		"Implicit path #3: no path in URL at all.",
	 517  		"http://www.host.test",
	 518  		[]string{"A=a"},
	 519  		"A=a",
	 520  		[]query{
	 521  			{"http://www.host.test", "A=a"},
	 522  			{"http://www.host.test/", "A=a"},
	 523  			{"http://www.host.test/some/path", "A=a"},
	 524  		},
	 525  	},
	 526  	{
	 527  		"Cookies are sorted by path length.",
	 528  		"http://www.host.test/",
	 529  		[]string{
	 530  			"A=a; path=/foo/bar",
	 531  			"B=b; path=/foo/bar/baz/qux",
	 532  			"C=c; path=/foo/bar/baz",
	 533  			"D=d; path=/foo"},
	 534  		"A=a B=b C=c D=d",
	 535  		[]query{
	 536  			{"http://www.host.test/foo/bar/baz/qux", "B=b C=c A=a D=d"},
	 537  			{"http://www.host.test/foo/bar/baz/", "C=c A=a D=d"},
	 538  			{"http://www.host.test/foo/bar", "A=a D=d"},
	 539  		},
	 540  	},
	 541  	{
	 542  		"Creation time determines sorting on same length paths.",
	 543  		"http://www.host.test/",
	 544  		[]string{
	 545  			"A=a; path=/foo/bar",
	 546  			"X=x; path=/foo/bar",
	 547  			"Y=y; path=/foo/bar/baz/qux",
	 548  			"B=b; path=/foo/bar/baz/qux",
	 549  			"C=c; path=/foo/bar/baz",
	 550  			"W=w; path=/foo/bar/baz",
	 551  			"Z=z; path=/foo",
	 552  			"D=d; path=/foo"},
	 553  		"A=a B=b C=c D=d W=w X=x Y=y Z=z",
	 554  		[]query{
	 555  			{"http://www.host.test/foo/bar/baz/qux", "Y=y B=b C=c W=w A=a X=x Z=z D=d"},
	 556  			{"http://www.host.test/foo/bar/baz/", "C=c W=w A=a X=x Z=z D=d"},
	 557  			{"http://www.host.test/foo/bar", "A=a X=x Z=z D=d"},
	 558  		},
	 559  	},
	 560  	{
	 561  		"Sorting of same-name cookies.",
	 562  		"http://www.host.test/",
	 563  		[]string{
	 564  			"A=1; path=/",
	 565  			"A=2; path=/path",
	 566  			"A=3; path=/quux",
	 567  			"A=4; path=/path/foo",
	 568  			"A=5; domain=.host.test; path=/path",
	 569  			"A=6; domain=.host.test; path=/quux",
	 570  			"A=7; domain=.host.test; path=/path/foo",
	 571  		},
	 572  		"A=1 A=2 A=3 A=4 A=5 A=6 A=7",
	 573  		[]query{
	 574  			{"http://www.host.test/path", "A=2 A=5 A=1"},
	 575  			{"http://www.host.test/path/foo", "A=4 A=7 A=2 A=5 A=1"},
	 576  		},
	 577  	},
	 578  	{
	 579  		"Disallow domain cookie on public suffix.",
	 580  		"http://www.bbc.co.uk",
	 581  		[]string{
	 582  			"a=1",
	 583  			"b=2; domain=co.uk",
	 584  		},
	 585  		"a=1",
	 586  		[]query{{"http://www.bbc.co.uk", "a=1"}},
	 587  	},
	 588  	{
	 589  		"Host cookie on IP.",
	 590  		"http://192.168.0.10",
	 591  		[]string{"a=1"},
	 592  		"a=1",
	 593  		[]query{{"http://192.168.0.10", "a=1"}},
	 594  	},
	 595  	{
	 596  		"Port is ignored #1.",
	 597  		"http://www.host.test/",
	 598  		[]string{"a=1"},
	 599  		"a=1",
	 600  		[]query{
	 601  			{"http://www.host.test", "a=1"},
	 602  			{"http://www.host.test:8080/", "a=1"},
	 603  		},
	 604  	},
	 605  	{
	 606  		"Port is ignored #2.",
	 607  		"http://www.host.test:8080/",
	 608  		[]string{"a=1"},
	 609  		"a=1",
	 610  		[]query{
	 611  			{"http://www.host.test", "a=1"},
	 612  			{"http://www.host.test:8080/", "a=1"},
	 613  			{"http://www.host.test:1234/", "a=1"},
	 614  		},
	 615  	},
	 616  }
	 617  
	 618  func TestBasics(t *testing.T) {
	 619  	for _, test := range basicsTests {
	 620  		jar := newTestJar()
	 621  		test.run(t, jar)
	 622  	}
	 623  }
	 624  
	 625  // updateAndDeleteTests contains jarTests which must be performed on the same
	 626  // Jar.
	 627  var updateAndDeleteTests = [...]jarTest{
	 628  	{
	 629  		"Set initial cookies.",
	 630  		"http://www.host.test",
	 631  		[]string{
	 632  			"a=1",
	 633  			"b=2; secure",
	 634  			"c=3; httponly",
	 635  			"d=4; secure; httponly"},
	 636  		"a=1 b=2 c=3 d=4",
	 637  		[]query{
	 638  			{"http://www.host.test", "a=1 c=3"},
	 639  			{"https://www.host.test", "a=1 b=2 c=3 d=4"},
	 640  		},
	 641  	},
	 642  	{
	 643  		"Update value via http.",
	 644  		"http://www.host.test",
	 645  		[]string{
	 646  			"a=w",
	 647  			"b=x; secure",
	 648  			"c=y; httponly",
	 649  			"d=z; secure; httponly"},
	 650  		"a=w b=x c=y d=z",
	 651  		[]query{
	 652  			{"http://www.host.test", "a=w c=y"},
	 653  			{"https://www.host.test", "a=w b=x c=y d=z"},
	 654  		},
	 655  	},
	 656  	{
	 657  		"Clear Secure flag from a http.",
	 658  		"http://www.host.test/",
	 659  		[]string{
	 660  			"b=xx",
	 661  			"d=zz; httponly"},
	 662  		"a=w b=xx c=y d=zz",
	 663  		[]query{{"http://www.host.test", "a=w b=xx c=y d=zz"}},
	 664  	},
	 665  	{
	 666  		"Delete all.",
	 667  		"http://www.host.test/",
	 668  		[]string{
	 669  			"a=1; max-Age=-1",										// delete via MaxAge
	 670  			"b=2; " + expiresIn(-10),						 // delete via Expires
	 671  			"c=2; max-age=-1; " + expiresIn(-10), // delete via both
	 672  			"d=4; max-age=-1; " + expiresIn(10)}, // MaxAge takes precedence
	 673  		"",
	 674  		[]query{{"http://www.host.test", ""}},
	 675  	},
	 676  	{
	 677  		"Refill #1.",
	 678  		"http://www.host.test",
	 679  		[]string{
	 680  			"A=1",
	 681  			"A=2; path=/foo",
	 682  			"A=3; domain=.host.test",
	 683  			"A=4; path=/foo; domain=.host.test"},
	 684  		"A=1 A=2 A=3 A=4",
	 685  		[]query{{"http://www.host.test/foo", "A=2 A=4 A=1 A=3"}},
	 686  	},
	 687  	{
	 688  		"Refill #2.",
	 689  		"http://www.google.com",
	 690  		[]string{
	 691  			"A=6",
	 692  			"A=7; path=/foo",
	 693  			"A=8; domain=.google.com",
	 694  			"A=9; path=/foo; domain=.google.com"},
	 695  		"A=1 A=2 A=3 A=4 A=6 A=7 A=8 A=9",
	 696  		[]query{
	 697  			{"http://www.host.test/foo", "A=2 A=4 A=1 A=3"},
	 698  			{"http://www.google.com/foo", "A=7 A=9 A=6 A=8"},
	 699  		},
	 700  	},
	 701  	{
	 702  		"Delete A7.",
	 703  		"http://www.google.com",
	 704  		[]string{"A=; path=/foo; max-age=-1"},
	 705  		"A=1 A=2 A=3 A=4 A=6 A=8 A=9",
	 706  		[]query{
	 707  			{"http://www.host.test/foo", "A=2 A=4 A=1 A=3"},
	 708  			{"http://www.google.com/foo", "A=9 A=6 A=8"},
	 709  		},
	 710  	},
	 711  	{
	 712  		"Delete A4.",
	 713  		"http://www.host.test",
	 714  		[]string{"A=; path=/foo; domain=host.test; max-age=-1"},
	 715  		"A=1 A=2 A=3 A=6 A=8 A=9",
	 716  		[]query{
	 717  			{"http://www.host.test/foo", "A=2 A=1 A=3"},
	 718  			{"http://www.google.com/foo", "A=9 A=6 A=8"},
	 719  		},
	 720  	},
	 721  	{
	 722  		"Delete A6.",
	 723  		"http://www.google.com",
	 724  		[]string{"A=; max-age=-1"},
	 725  		"A=1 A=2 A=3 A=8 A=9",
	 726  		[]query{
	 727  			{"http://www.host.test/foo", "A=2 A=1 A=3"},
	 728  			{"http://www.google.com/foo", "A=9 A=8"},
	 729  		},
	 730  	},
	 731  	{
	 732  		"Delete A3.",
	 733  		"http://www.host.test",
	 734  		[]string{"A=; domain=host.test; max-age=-1"},
	 735  		"A=1 A=2 A=8 A=9",
	 736  		[]query{
	 737  			{"http://www.host.test/foo", "A=2 A=1"},
	 738  			{"http://www.google.com/foo", "A=9 A=8"},
	 739  		},
	 740  	},
	 741  	{
	 742  		"No cross-domain delete.",
	 743  		"http://www.host.test",
	 744  		[]string{
	 745  			"A=; domain=google.com; max-age=-1",
	 746  			"A=; path=/foo; domain=google.com; max-age=-1"},
	 747  		"A=1 A=2 A=8 A=9",
	 748  		[]query{
	 749  			{"http://www.host.test/foo", "A=2 A=1"},
	 750  			{"http://www.google.com/foo", "A=9 A=8"},
	 751  		},
	 752  	},
	 753  	{
	 754  		"Delete A8 and A9.",
	 755  		"http://www.google.com",
	 756  		[]string{
	 757  			"A=; domain=google.com; max-age=-1",
	 758  			"A=; path=/foo; domain=google.com; max-age=-1"},
	 759  		"A=1 A=2",
	 760  		[]query{
	 761  			{"http://www.host.test/foo", "A=2 A=1"},
	 762  			{"http://www.google.com/foo", ""},
	 763  		},
	 764  	},
	 765  }
	 766  
	 767  func TestUpdateAndDelete(t *testing.T) {
	 768  	jar := newTestJar()
	 769  	for _, test := range updateAndDeleteTests {
	 770  		test.run(t, jar)
	 771  	}
	 772  }
	 773  
	 774  func TestExpiration(t *testing.T) {
	 775  	jar := newTestJar()
	 776  	jarTest{
	 777  		"Expiration.",
	 778  		"http://www.host.test",
	 779  		[]string{
	 780  			"a=1",
	 781  			"b=2; max-age=3",
	 782  			"c=3; " + expiresIn(3),
	 783  			"d=4; max-age=5",
	 784  			"e=5; " + expiresIn(5),
	 785  			"f=6; max-age=100",
	 786  		},
	 787  		"a=1 b=2 c=3 d=4 e=5 f=6", // executed at t0 + 1001 ms
	 788  		[]query{
	 789  			{"http://www.host.test", "a=1 b=2 c=3 d=4 e=5 f=6"}, // t0 + 2002 ms
	 790  			{"http://www.host.test", "a=1 d=4 e=5 f=6"},				 // t0 + 3003 ms
	 791  			{"http://www.host.test", "a=1 d=4 e=5 f=6"},				 // t0 + 4004 ms
	 792  			{"http://www.host.test", "a=1 f=6"},								 // t0 + 5005 ms
	 793  			{"http://www.host.test", "a=1 f=6"},								 // t0 + 6006 ms
	 794  		},
	 795  	}.run(t, jar)
	 796  }
	 797  
	 798  //
	 799  // Tests derived from Chromium's cookie_store_unittest.h.
	 800  //
	 801  
	 802  // See http://src.chromium.org/viewvc/chrome/trunk/src/net/cookies/cookie_store_unittest.h?revision=159685&content-type=text/plain
	 803  // Some of the original tests are in a bad condition (e.g.
	 804  // DomainWithTrailingDotTest) or are not RFC 6265 conforming (e.g.
	 805  // TestNonDottedAndTLD #1 and #6) and have not been ported.
	 806  
	 807  // chromiumBasicsTests contains fundamental tests. Each jarTest has to be
	 808  // performed on a fresh, empty Jar.
	 809  var chromiumBasicsTests = [...]jarTest{
	 810  	{
	 811  		"DomainWithTrailingDotTest.",
	 812  		"http://www.google.com/",
	 813  		[]string{
	 814  			"a=1; domain=.www.google.com.",
	 815  			"b=2; domain=.www.google.com.."},
	 816  		"",
	 817  		[]query{
	 818  			{"http://www.google.com", ""},
	 819  		},
	 820  	},
	 821  	{
	 822  		"ValidSubdomainTest #1.",
	 823  		"http://a.b.c.d.com",
	 824  		[]string{
	 825  			"a=1; domain=.a.b.c.d.com",
	 826  			"b=2; domain=.b.c.d.com",
	 827  			"c=3; domain=.c.d.com",
	 828  			"d=4; domain=.d.com"},
	 829  		"a=1 b=2 c=3 d=4",
	 830  		[]query{
	 831  			{"http://a.b.c.d.com", "a=1 b=2 c=3 d=4"},
	 832  			{"http://b.c.d.com", "b=2 c=3 d=4"},
	 833  			{"http://c.d.com", "c=3 d=4"},
	 834  			{"http://d.com", "d=4"},
	 835  		},
	 836  	},
	 837  	{
	 838  		"ValidSubdomainTest #2.",
	 839  		"http://a.b.c.d.com",
	 840  		[]string{
	 841  			"a=1; domain=.a.b.c.d.com",
	 842  			"b=2; domain=.b.c.d.com",
	 843  			"c=3; domain=.c.d.com",
	 844  			"d=4; domain=.d.com",
	 845  			"X=bcd; domain=.b.c.d.com",
	 846  			"X=cd; domain=.c.d.com"},
	 847  		"X=bcd X=cd a=1 b=2 c=3 d=4",
	 848  		[]query{
	 849  			{"http://b.c.d.com", "b=2 c=3 d=4 X=bcd X=cd"},
	 850  			{"http://c.d.com", "c=3 d=4 X=cd"},
	 851  		},
	 852  	},
	 853  	{
	 854  		"InvalidDomainTest #1.",
	 855  		"http://foo.bar.com",
	 856  		[]string{
	 857  			"a=1; domain=.yo.foo.bar.com",
	 858  			"b=2; domain=.foo.com",
	 859  			"c=3; domain=.bar.foo.com",
	 860  			"d=4; domain=.foo.bar.com.net",
	 861  			"e=5; domain=ar.com",
	 862  			"f=6; domain=.",
	 863  			"g=7; domain=/",
	 864  			"h=8; domain=http://foo.bar.com",
	 865  			"i=9; domain=..foo.bar.com",
	 866  			"j=10; domain=..bar.com",
	 867  			"k=11; domain=.foo.bar.com?blah",
	 868  			"l=12; domain=.foo.bar.com/blah",
	 869  			"m=12; domain=.foo.bar.com:80",
	 870  			"n=14; domain=.foo.bar.com:",
	 871  			"o=15; domain=.foo.bar.com#sup",
	 872  		},
	 873  		"", // Jar is empty.
	 874  		[]query{{"http://foo.bar.com", ""}},
	 875  	},
	 876  	{
	 877  		"InvalidDomainTest #2.",
	 878  		"http://foo.com.com",
	 879  		[]string{"a=1; domain=.foo.com.com.com"},
	 880  		"",
	 881  		[]query{{"http://foo.bar.com", ""}},
	 882  	},
	 883  	{
	 884  		"DomainWithoutLeadingDotTest #1.",
	 885  		"http://manage.hosted.filefront.com",
	 886  		[]string{"a=1; domain=filefront.com"},
	 887  		"a=1",
	 888  		[]query{{"http://www.filefront.com", "a=1"}},
	 889  	},
	 890  	{
	 891  		"DomainWithoutLeadingDotTest #2.",
	 892  		"http://www.google.com",
	 893  		[]string{"a=1; domain=www.google.com"},
	 894  		"a=1",
	 895  		[]query{
	 896  			{"http://www.google.com", "a=1"},
	 897  			{"http://sub.www.google.com", "a=1"},
	 898  			{"http://something-else.com", ""},
	 899  		},
	 900  	},
	 901  	{
	 902  		"CaseInsensitiveDomainTest.",
	 903  		"http://www.google.com",
	 904  		[]string{
	 905  			"a=1; domain=.GOOGLE.COM",
	 906  			"b=2; domain=.www.gOOgLE.coM"},
	 907  		"a=1 b=2",
	 908  		[]query{{"http://www.google.com", "a=1 b=2"}},
	 909  	},
	 910  	{
	 911  		"TestIpAddress #1.",
	 912  		"http://1.2.3.4/foo",
	 913  		[]string{"a=1; path=/"},
	 914  		"a=1",
	 915  		[]query{{"http://1.2.3.4/foo", "a=1"}},
	 916  	},
	 917  	{
	 918  		"TestIpAddress #2.",
	 919  		"http://1.2.3.4/foo",
	 920  		[]string{
	 921  			"a=1; domain=.1.2.3.4",
	 922  			"b=2; domain=.3.4"},
	 923  		"",
	 924  		[]query{{"http://1.2.3.4/foo", ""}},
	 925  	},
	 926  	{
	 927  		"TestIpAddress #3.",
	 928  		"http://1.2.3.4/foo",
	 929  		[]string{"a=1; domain=1.2.3.4"},
	 930  		"",
	 931  		[]query{{"http://1.2.3.4/foo", ""}},
	 932  	},
	 933  	{
	 934  		"TestNonDottedAndTLD #2.",
	 935  		"http://com./index.html",
	 936  		[]string{"a=1"},
	 937  		"a=1",
	 938  		[]query{
	 939  			{"http://com./index.html", "a=1"},
	 940  			{"http://no-cookies.com./index.html", ""},
	 941  		},
	 942  	},
	 943  	{
	 944  		"TestNonDottedAndTLD #3.",
	 945  		"http://a.b",
	 946  		[]string{
	 947  			"a=1; domain=.b",
	 948  			"b=2; domain=b"},
	 949  		"",
	 950  		[]query{{"http://bar.foo", ""}},
	 951  	},
	 952  	{
	 953  		"TestNonDottedAndTLD #4.",
	 954  		"http://google.com",
	 955  		[]string{
	 956  			"a=1; domain=.com",
	 957  			"b=2; domain=com"},
	 958  		"",
	 959  		[]query{{"http://google.com", ""}},
	 960  	},
	 961  	{
	 962  		"TestNonDottedAndTLD #5.",
	 963  		"http://google.co.uk",
	 964  		[]string{
	 965  			"a=1; domain=.co.uk",
	 966  			"b=2; domain=.uk"},
	 967  		"",
	 968  		[]query{
	 969  			{"http://google.co.uk", ""},
	 970  			{"http://else.co.com", ""},
	 971  			{"http://else.uk", ""},
	 972  		},
	 973  	},
	 974  	{
	 975  		"TestHostEndsWithDot.",
	 976  		"http://www.google.com",
	 977  		[]string{
	 978  			"a=1",
	 979  			"b=2; domain=.www.google.com."},
	 980  		"a=1",
	 981  		[]query{{"http://www.google.com", "a=1"}},
	 982  	},
	 983  	{
	 984  		"PathTest",
	 985  		"http://www.google.izzle",
	 986  		[]string{"a=1; path=/wee"},
	 987  		"a=1",
	 988  		[]query{
	 989  			{"http://www.google.izzle/wee", "a=1"},
	 990  			{"http://www.google.izzle/wee/", "a=1"},
	 991  			{"http://www.google.izzle/wee/war", "a=1"},
	 992  			{"http://www.google.izzle/wee/war/more/more", "a=1"},
	 993  			{"http://www.google.izzle/weehee", ""},
	 994  			{"http://www.google.izzle/", ""},
	 995  		},
	 996  	},
	 997  }
	 998  
	 999  func TestChromiumBasics(t *testing.T) {
	1000  	for _, test := range chromiumBasicsTests {
	1001  		jar := newTestJar()
	1002  		test.run(t, jar)
	1003  	}
	1004  }
	1005  
	1006  // chromiumDomainTests contains jarTests which must be executed all on the
	1007  // same Jar.
	1008  var chromiumDomainTests = [...]jarTest{
	1009  	{
	1010  		"Fill #1.",
	1011  		"http://www.google.izzle",
	1012  		[]string{"A=B"},
	1013  		"A=B",
	1014  		[]query{{"http://www.google.izzle", "A=B"}},
	1015  	},
	1016  	{
	1017  		"Fill #2.",
	1018  		"http://www.google.izzle",
	1019  		[]string{"C=D; domain=.google.izzle"},
	1020  		"A=B C=D",
	1021  		[]query{{"http://www.google.izzle", "A=B C=D"}},
	1022  	},
	1023  	{
	1024  		"Verify A is a host cookie and not accessible from subdomain.",
	1025  		"http://unused.nil",
	1026  		[]string{},
	1027  		"A=B C=D",
	1028  		[]query{{"http://foo.www.google.izzle", "C=D"}},
	1029  	},
	1030  	{
	1031  		"Verify domain cookies are found on proper domain.",
	1032  		"http://www.google.izzle",
	1033  		[]string{"E=F; domain=.www.google.izzle"},
	1034  		"A=B C=D E=F",
	1035  		[]query{{"http://www.google.izzle", "A=B C=D E=F"}},
	1036  	},
	1037  	{
	1038  		"Leading dots in domain attributes are optional.",
	1039  		"http://www.google.izzle",
	1040  		[]string{"G=H; domain=www.google.izzle"},
	1041  		"A=B C=D E=F G=H",
	1042  		[]query{{"http://www.google.izzle", "A=B C=D E=F G=H"}},
	1043  	},
	1044  	{
	1045  		"Verify domain enforcement works #1.",
	1046  		"http://www.google.izzle",
	1047  		[]string{"K=L; domain=.bar.www.google.izzle"},
	1048  		"A=B C=D E=F G=H",
	1049  		[]query{{"http://bar.www.google.izzle", "C=D E=F G=H"}},
	1050  	},
	1051  	{
	1052  		"Verify domain enforcement works #2.",
	1053  		"http://unused.nil",
	1054  		[]string{},
	1055  		"A=B C=D E=F G=H",
	1056  		[]query{{"http://www.google.izzle", "A=B C=D E=F G=H"}},
	1057  	},
	1058  }
	1059  
	1060  func TestChromiumDomain(t *testing.T) {
	1061  	jar := newTestJar()
	1062  	for _, test := range chromiumDomainTests {
	1063  		test.run(t, jar)
	1064  	}
	1065  
	1066  }
	1067  
	1068  // chromiumDeletionTests must be performed all on the same Jar.
	1069  var chromiumDeletionTests = [...]jarTest{
	1070  	{
	1071  		"Create session cookie a1.",
	1072  		"http://www.google.com",
	1073  		[]string{"a=1"},
	1074  		"a=1",
	1075  		[]query{{"http://www.google.com", "a=1"}},
	1076  	},
	1077  	{
	1078  		"Delete sc a1 via MaxAge.",
	1079  		"http://www.google.com",
	1080  		[]string{"a=1; max-age=-1"},
	1081  		"",
	1082  		[]query{{"http://www.google.com", ""}},
	1083  	},
	1084  	{
	1085  		"Create session cookie b2.",
	1086  		"http://www.google.com",
	1087  		[]string{"b=2"},
	1088  		"b=2",
	1089  		[]query{{"http://www.google.com", "b=2"}},
	1090  	},
	1091  	{
	1092  		"Delete sc b2 via Expires.",
	1093  		"http://www.google.com",
	1094  		[]string{"b=2; " + expiresIn(-10)},
	1095  		"",
	1096  		[]query{{"http://www.google.com", ""}},
	1097  	},
	1098  	{
	1099  		"Create persistent cookie c3.",
	1100  		"http://www.google.com",
	1101  		[]string{"c=3; max-age=3600"},
	1102  		"c=3",
	1103  		[]query{{"http://www.google.com", "c=3"}},
	1104  	},
	1105  	{
	1106  		"Delete pc c3 via MaxAge.",
	1107  		"http://www.google.com",
	1108  		[]string{"c=3; max-age=-1"},
	1109  		"",
	1110  		[]query{{"http://www.google.com", ""}},
	1111  	},
	1112  	{
	1113  		"Create persistent cookie d4.",
	1114  		"http://www.google.com",
	1115  		[]string{"d=4; max-age=3600"},
	1116  		"d=4",
	1117  		[]query{{"http://www.google.com", "d=4"}},
	1118  	},
	1119  	{
	1120  		"Delete pc d4 via Expires.",
	1121  		"http://www.google.com",
	1122  		[]string{"d=4; " + expiresIn(-10)},
	1123  		"",
	1124  		[]query{{"http://www.google.com", ""}},
	1125  	},
	1126  }
	1127  
	1128  func TestChromiumDeletion(t *testing.T) {
	1129  	jar := newTestJar()
	1130  	for _, test := range chromiumDeletionTests {
	1131  		test.run(t, jar)
	1132  	}
	1133  }
	1134  
	1135  // domainHandlingTests tests and documents the rules for domain handling.
	1136  // Each test must be performed on an empty new Jar.
	1137  var domainHandlingTests = [...]jarTest{
	1138  	{
	1139  		"Host cookie",
	1140  		"http://www.host.test",
	1141  		[]string{"a=1"},
	1142  		"a=1",
	1143  		[]query{
	1144  			{"http://www.host.test", "a=1"},
	1145  			{"http://host.test", ""},
	1146  			{"http://bar.host.test", ""},
	1147  			{"http://foo.www.host.test", ""},
	1148  			{"http://other.test", ""},
	1149  			{"http://test", ""},
	1150  		},
	1151  	},
	1152  	{
	1153  		"Domain cookie #1",
	1154  		"http://www.host.test",
	1155  		[]string{"a=1; domain=host.test"},
	1156  		"a=1",
	1157  		[]query{
	1158  			{"http://www.host.test", "a=1"},
	1159  			{"http://host.test", "a=1"},
	1160  			{"http://bar.host.test", "a=1"},
	1161  			{"http://foo.www.host.test", "a=1"},
	1162  			{"http://other.test", ""},
	1163  			{"http://test", ""},
	1164  		},
	1165  	},
	1166  	{
	1167  		"Domain cookie #2",
	1168  		"http://www.host.test",
	1169  		[]string{"a=1; domain=.host.test"},
	1170  		"a=1",
	1171  		[]query{
	1172  			{"http://www.host.test", "a=1"},
	1173  			{"http://host.test", "a=1"},
	1174  			{"http://bar.host.test", "a=1"},
	1175  			{"http://foo.www.host.test", "a=1"},
	1176  			{"http://other.test", ""},
	1177  			{"http://test", ""},
	1178  		},
	1179  	},
	1180  	{
	1181  		"Host cookie on IDNA domain #1",
	1182  		"http://www.bücher.test",
	1183  		[]string{"a=1"},
	1184  		"a=1",
	1185  		[]query{
	1186  			{"http://www.bücher.test", "a=1"},
	1187  			{"http://www.xn--bcher-kva.test", "a=1"},
	1188  			{"http://bücher.test", ""},
	1189  			{"http://xn--bcher-kva.test", ""},
	1190  			{"http://bar.bücher.test", ""},
	1191  			{"http://bar.xn--bcher-kva.test", ""},
	1192  			{"http://foo.www.bücher.test", ""},
	1193  			{"http://foo.www.xn--bcher-kva.test", ""},
	1194  			{"http://other.test", ""},
	1195  			{"http://test", ""},
	1196  		},
	1197  	},
	1198  	{
	1199  		"Host cookie on IDNA domain #2",
	1200  		"http://www.xn--bcher-kva.test",
	1201  		[]string{"a=1"},
	1202  		"a=1",
	1203  		[]query{
	1204  			{"http://www.bücher.test", "a=1"},
	1205  			{"http://www.xn--bcher-kva.test", "a=1"},
	1206  			{"http://bücher.test", ""},
	1207  			{"http://xn--bcher-kva.test", ""},
	1208  			{"http://bar.bücher.test", ""},
	1209  			{"http://bar.xn--bcher-kva.test", ""},
	1210  			{"http://foo.www.bücher.test", ""},
	1211  			{"http://foo.www.xn--bcher-kva.test", ""},
	1212  			{"http://other.test", ""},
	1213  			{"http://test", ""},
	1214  		},
	1215  	},
	1216  	{
	1217  		"Domain cookie on IDNA domain #1",
	1218  		"http://www.bücher.test",
	1219  		[]string{"a=1; domain=xn--bcher-kva.test"},
	1220  		"a=1",
	1221  		[]query{
	1222  			{"http://www.bücher.test", "a=1"},
	1223  			{"http://www.xn--bcher-kva.test", "a=1"},
	1224  			{"http://bücher.test", "a=1"},
	1225  			{"http://xn--bcher-kva.test", "a=1"},
	1226  			{"http://bar.bücher.test", "a=1"},
	1227  			{"http://bar.xn--bcher-kva.test", "a=1"},
	1228  			{"http://foo.www.bücher.test", "a=1"},
	1229  			{"http://foo.www.xn--bcher-kva.test", "a=1"},
	1230  			{"http://other.test", ""},
	1231  			{"http://test", ""},
	1232  		},
	1233  	},
	1234  	{
	1235  		"Domain cookie on IDNA domain #2",
	1236  		"http://www.xn--bcher-kva.test",
	1237  		[]string{"a=1; domain=xn--bcher-kva.test"},
	1238  		"a=1",
	1239  		[]query{
	1240  			{"http://www.bücher.test", "a=1"},
	1241  			{"http://www.xn--bcher-kva.test", "a=1"},
	1242  			{"http://bücher.test", "a=1"},
	1243  			{"http://xn--bcher-kva.test", "a=1"},
	1244  			{"http://bar.bücher.test", "a=1"},
	1245  			{"http://bar.xn--bcher-kva.test", "a=1"},
	1246  			{"http://foo.www.bücher.test", "a=1"},
	1247  			{"http://foo.www.xn--bcher-kva.test", "a=1"},
	1248  			{"http://other.test", ""},
	1249  			{"http://test", ""},
	1250  		},
	1251  	},
	1252  	{
	1253  		"Host cookie on TLD.",
	1254  		"http://com",
	1255  		[]string{"a=1"},
	1256  		"a=1",
	1257  		[]query{
	1258  			{"http://com", "a=1"},
	1259  			{"http://any.com", ""},
	1260  			{"http://any.test", ""},
	1261  		},
	1262  	},
	1263  	{
	1264  		"Domain cookie on TLD becomes a host cookie.",
	1265  		"http://com",
	1266  		[]string{"a=1; domain=com"},
	1267  		"a=1",
	1268  		[]query{
	1269  			{"http://com", "a=1"},
	1270  			{"http://any.com", ""},
	1271  			{"http://any.test", ""},
	1272  		},
	1273  	},
	1274  	{
	1275  		"Host cookie on public suffix.",
	1276  		"http://co.uk",
	1277  		[]string{"a=1"},
	1278  		"a=1",
	1279  		[]query{
	1280  			{"http://co.uk", "a=1"},
	1281  			{"http://uk", ""},
	1282  			{"http://some.co.uk", ""},
	1283  			{"http://foo.some.co.uk", ""},
	1284  			{"http://any.uk", ""},
	1285  		},
	1286  	},
	1287  	{
	1288  		"Domain cookie on public suffix is ignored.",
	1289  		"http://some.co.uk",
	1290  		[]string{"a=1; domain=co.uk"},
	1291  		"",
	1292  		[]query{
	1293  			{"http://co.uk", ""},
	1294  			{"http://uk", ""},
	1295  			{"http://some.co.uk", ""},
	1296  			{"http://foo.some.co.uk", ""},
	1297  			{"http://any.uk", ""},
	1298  		},
	1299  	},
	1300  }
	1301  
	1302  func TestDomainHandling(t *testing.T) {
	1303  	for _, test := range domainHandlingTests {
	1304  		jar := newTestJar()
	1305  		test.run(t, jar)
	1306  	}
	1307  }
	1308  
	1309  func TestIssue19384(t *testing.T) {
	1310  	cookies := []*http.Cookie{{Name: "name", Value: "value"}}
	1311  	for _, host := range []string{"", ".", "..", "..."} {
	1312  		jar, _ := New(nil)
	1313  		u := &url.URL{Scheme: "http", Host: host, Path: "/"}
	1314  		if got := jar.Cookies(u); len(got) != 0 {
	1315  			t.Errorf("host %q, got %v", host, got)
	1316  		}
	1317  		jar.SetCookies(u, cookies)
	1318  		if got := jar.Cookies(u); len(got) != 1 || got[0].Value != "value" {
	1319  			t.Errorf("host %q, got %v", host, got)
	1320  		}
	1321  	}
	1322  }
	1323  

View as plain text