jar_test.go 33 KB

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