test_cookielib.py revision 3bff9d269c8fece4126c4698e67e79362b53bfd1
1# -*- coding: utf-8 -*- 2"""Tests for cookielib.py.""" 3 4import re, os, time 5from unittest import TestCase 6 7from test import test_support 8 9class DateTimeTests(TestCase): 10 11 def test_time2isoz(self): 12 from cookielib import time2isoz 13 14 base = 1019227000 15 day = 24*3600 16 self.assertEquals(time2isoz(base), "2002-04-19 14:36:40Z") 17 self.assertEquals(time2isoz(base+day), "2002-04-20 14:36:40Z") 18 self.assertEquals(time2isoz(base+2*day), "2002-04-21 14:36:40Z") 19 self.assertEquals(time2isoz(base+3*day), "2002-04-22 14:36:40Z") 20 21 az = time2isoz() 22 bz = time2isoz(500000) 23 for text in (az, bz): 24 self.assert_(re.search(r"^\d{4}-\d\d-\d\d \d\d:\d\d:\d\dZ$", text), 25 "bad time2isoz format: %s %s" % (az, bz)) 26 27 def test_http2time(self): 28 from cookielib import http2time 29 30 def parse_date(text): 31 return time.gmtime(http2time(text))[:6] 32 33 self.assertEquals(parse_date("01 Jan 2001"), (2001, 1, 1, 0, 0, 0.0)) 34 35 # this test will break around year 2070 36 self.assertEquals(parse_date("03-Feb-20"), (2020, 2, 3, 0, 0, 0.0)) 37 38 # this test will break around year 2048 39 self.assertEquals(parse_date("03-Feb-98"), (1998, 2, 3, 0, 0, 0.0)) 40 41 def test_http2time_formats(self): 42 from cookielib import http2time, time2isoz 43 44 # test http2time for supported dates. Test cases with 2 digit year 45 # will probably break in year 2044. 46 tests = [ 47 'Thu, 03 Feb 1994 00:00:00 GMT', # proposed new HTTP format 48 'Thursday, 03-Feb-94 00:00:00 GMT', # old rfc850 HTTP format 49 'Thursday, 03-Feb-1994 00:00:00 GMT', # broken rfc850 HTTP format 50 51 '03 Feb 1994 00:00:00 GMT', # HTTP format (no weekday) 52 '03-Feb-94 00:00:00 GMT', # old rfc850 (no weekday) 53 '03-Feb-1994 00:00:00 GMT', # broken rfc850 (no weekday) 54 '03-Feb-1994 00:00 GMT', # broken rfc850 (no weekday, no seconds) 55 '03-Feb-1994 00:00', # broken rfc850 (no weekday, no seconds, no tz) 56 57 '03-Feb-94', # old rfc850 HTTP format (no weekday, no time) 58 '03-Feb-1994', # broken rfc850 HTTP format (no weekday, no time) 59 '03 Feb 1994', # proposed new HTTP format (no weekday, no time) 60 61 # A few tests with extra space at various places 62 ' 03 Feb 1994 0:00 ', 63 ' 03-Feb-1994 ', 64 ] 65 66 test_t = 760233600 # assume broken POSIX counting of seconds 67 result = time2isoz(test_t) 68 expected = "1994-02-03 00:00:00Z" 69 self.assertEquals(result, expected, 70 "%s => '%s' (%s)" % (test_t, result, expected)) 71 72 for s in tests: 73 t = http2time(s) 74 t2 = http2time(s.lower()) 75 t3 = http2time(s.upper()) 76 77 self.assert_(t == t2 == t3 == test_t, 78 "'%s' => %s, %s, %s (%s)" % (s, t, t2, t3, test_t)) 79 80 def test_http2time_garbage(self): 81 from cookielib import http2time 82 83 for test in [ 84 '', 85 'Garbage', 86 'Mandag 16. September 1996', 87 '01-00-1980', 88 '01-13-1980', 89 '00-01-1980', 90 '32-01-1980', 91 '01-01-1980 25:00:00', 92 '01-01-1980 00:61:00', 93 '01-01-1980 00:00:62', 94 ]: 95 self.assert_(http2time(test) is None, 96 "http2time(%s) is not None\n" 97 "http2time(test) %s" % (test, http2time(test)) 98 ) 99 100 101class HeaderTests(TestCase): 102 def test_parse_ns_headers(self): 103 from cookielib import parse_ns_headers 104 105 # quotes should be stripped 106 expected = [[('foo', 'bar'), ('expires', 2209069412L), ('version', '0')]] 107 for hdr in [ 108 'foo=bar; expires=01 Jan 2040 22:23:32 GMT', 109 'foo=bar; expires="01 Jan 2040 22:23:32 GMT"', 110 ]: 111 self.assertEquals(parse_ns_headers([hdr]), expected) 112 113 def test_parse_ns_headers_special_names(self): 114 # names such as 'expires' are not special in first name=value pair 115 # of Set-Cookie: header 116 from cookielib import parse_ns_headers 117 118 # Cookie with name 'expires' 119 hdr = 'expires=01 Jan 2040 22:23:32 GMT' 120 expected = [[("expires", "01 Jan 2040 22:23:32 GMT"), ("version", "0")]] 121 self.assertEquals(parse_ns_headers([hdr]), expected) 122 123 def test_join_header_words(self): 124 from cookielib import join_header_words 125 126 joined = join_header_words([[("foo", None), ("bar", "baz")]]) 127 self.assertEquals(joined, "foo; bar=baz") 128 129 self.assertEquals(join_header_words([[]]), "") 130 131 def test_split_header_words(self): 132 from cookielib import split_header_words 133 134 tests = [ 135 ("foo", [[("foo", None)]]), 136 ("foo=bar", [[("foo", "bar")]]), 137 (" foo ", [[("foo", None)]]), 138 (" foo= ", [[("foo", "")]]), 139 (" foo=", [[("foo", "")]]), 140 (" foo= ; ", [[("foo", "")]]), 141 (" foo= ; bar= baz ", [[("foo", ""), ("bar", "baz")]]), 142 ("foo=bar bar=baz", [[("foo", "bar"), ("bar", "baz")]]), 143 # doesn't really matter if this next fails, but it works ATM 144 ("foo= bar=baz", [[("foo", "bar=baz")]]), 145 ("foo=bar;bar=baz", [[("foo", "bar"), ("bar", "baz")]]), 146 ('foo bar baz', [[("foo", None), ("bar", None), ("baz", None)]]), 147 ("a, b, c", [[("a", None)], [("b", None)], [("c", None)]]), 148 (r'foo; bar=baz, spam=, foo="\,\;\"", bar= ', 149 [[("foo", None), ("bar", "baz")], 150 [("spam", "")], [("foo", ',;"')], [("bar", "")]]), 151 ] 152 153 for arg, expect in tests: 154 try: 155 result = split_header_words([arg]) 156 except: 157 import traceback, StringIO 158 f = StringIO.StringIO() 159 traceback.print_exc(None, f) 160 result = "(error -- traceback follows)\n\n%s" % f.getvalue() 161 self.assertEquals(result, expect, """ 162When parsing: '%s' 163Expected: '%s' 164Got: '%s' 165""" % (arg, expect, result)) 166 167 def test_roundtrip(self): 168 from cookielib import split_header_words, join_header_words 169 170 tests = [ 171 ("foo", "foo"), 172 ("foo=bar", "foo=bar"), 173 (" foo ", "foo"), 174 ("foo=", 'foo=""'), 175 ("foo=bar bar=baz", "foo=bar; bar=baz"), 176 ("foo=bar;bar=baz", "foo=bar; bar=baz"), 177 ('foo bar baz', "foo; bar; baz"), 178 (r'foo="\"" bar="\\"', r'foo="\""; bar="\\"'), 179 ('foo,,,bar', 'foo, bar'), 180 ('foo=bar,bar=baz', 'foo=bar, bar=baz'), 181 182 ('text/html; charset=iso-8859-1', 183 'text/html; charset="iso-8859-1"'), 184 185 ('foo="bar"; port="80,81"; discard, bar=baz', 186 'foo=bar; port="80,81"; discard, bar=baz'), 187 188 (r'Basic realm="\"foo\\\\bar\""', 189 r'Basic; realm="\"foo\\\\bar\""') 190 ] 191 192 for arg, expect in tests: 193 input = split_header_words([arg]) 194 res = join_header_words(input) 195 self.assertEquals(res, expect, """ 196When parsing: '%s' 197Expected: '%s' 198Got: '%s' 199Input was: '%s' 200""" % (arg, expect, res, input)) 201 202 203class FakeResponse: 204 def __init__(self, headers=[], url=None): 205 """ 206 headers: list of RFC822-style 'Key: value' strings 207 """ 208 import mimetools, StringIO 209 f = StringIO.StringIO("\n".join(headers)) 210 self._headers = mimetools.Message(f) 211 self._url = url 212 def info(self): return self._headers 213 214def interact_2965(cookiejar, url, *set_cookie_hdrs): 215 return _interact(cookiejar, url, set_cookie_hdrs, "Set-Cookie2") 216 217def interact_netscape(cookiejar, url, *set_cookie_hdrs): 218 return _interact(cookiejar, url, set_cookie_hdrs, "Set-Cookie") 219 220def _interact(cookiejar, url, set_cookie_hdrs, hdr_name): 221 """Perform a single request / response cycle, returning Cookie: header.""" 222 from urllib2 import Request 223 req = Request(url) 224 cookiejar.add_cookie_header(req) 225 cookie_hdr = req.get_header("Cookie", "") 226 headers = [] 227 for hdr in set_cookie_hdrs: 228 headers.append("%s: %s" % (hdr_name, hdr)) 229 res = FakeResponse(headers, url) 230 cookiejar.extract_cookies(res, req) 231 return cookie_hdr 232 233 234class FileCookieJarTests(TestCase): 235 def test_lwp_valueless_cookie(self): 236 # cookies with no value should be saved and loaded consistently 237 from cookielib import LWPCookieJar 238 filename = test_support.TESTFN 239 c = LWPCookieJar() 240 interact_netscape(c, "http://www.acme.com/", 'boo') 241 self.assertEqual(c._cookies["www.acme.com"]["/"]["boo"].value, None) 242 try: 243 c.save(filename, ignore_discard=True) 244 c = LWPCookieJar() 245 c.load(filename, ignore_discard=True) 246 finally: 247 try: os.unlink(filename) 248 except OSError: pass 249 self.assertEqual(c._cookies["www.acme.com"]["/"]["boo"].value, None) 250 251 def test_bad_magic(self): 252 from cookielib import LWPCookieJar, MozillaCookieJar, LoadError 253 # IOErrors (eg. file doesn't exist) are allowed to propagate 254 filename = test_support.TESTFN 255 for cookiejar_class in LWPCookieJar, MozillaCookieJar: 256 c = cookiejar_class() 257 try: 258 c.load(filename="for this test to work, a file with this " 259 "filename should not exist") 260 except IOError, exc: 261 # exactly IOError, not LoadError 262 self.assertEqual(exc.__class__, IOError) 263 else: 264 self.fail("expected IOError for invalid filename") 265 # Invalid contents of cookies file (eg. bad magic string) 266 # causes a LoadError. 267 try: 268 f = open(filename, "w") 269 f.write("oops\n") 270 for cookiejar_class in LWPCookieJar, MozillaCookieJar: 271 c = cookiejar_class() 272 self.assertRaises(LoadError, c.load, filename) 273 finally: 274 try: os.unlink(filename) 275 except OSError: pass 276 277class CookieTests(TestCase): 278 # XXX 279 # Get rid of string comparisons where not actually testing str / repr. 280 # .clear() etc. 281 # IP addresses like 50 (single number, no dot) and domain-matching 282 # functions (and is_HDN)? See draft RFC 2965 errata. 283 # Strictness switches 284 # is_third_party() 285 # unverifiability / third-party blocking 286 # Netscape cookies work the same as RFC 2965 with regard to port. 287 # Set-Cookie with negative max age. 288 # If turn RFC 2965 handling off, Set-Cookie2 cookies should not clobber 289 # Set-Cookie cookies. 290 # Cookie2 should be sent if *any* cookies are not V1 (ie. V0 OR V2 etc.). 291 # Cookies (V1 and V0) with no expiry date should be set to be discarded. 292 # RFC 2965 Quoting: 293 # Should accept unquoted cookie-attribute values? check errata draft. 294 # Which are required on the way in and out? 295 # Should always return quoted cookie-attribute values? 296 # Proper testing of when RFC 2965 clobbers Netscape (waiting for errata). 297 # Path-match on return (same for V0 and V1). 298 # RFC 2965 acceptance and returning rules 299 # Set-Cookie2 without version attribute is rejected. 300 301 # Netscape peculiarities list from Ronald Tschalar. 302 # The first two still need tests, the rest are covered. 303## - Quoting: only quotes around the expires value are recognized as such 304## (and yes, some folks quote the expires value); quotes around any other 305## value are treated as part of the value. 306## - White space: white space around names and values is ignored 307## - Default path: if no path parameter is given, the path defaults to the 308## path in the request-uri up to, but not including, the last '/'. Note 309## that this is entirely different from what the spec says. 310## - Commas and other delimiters: Netscape just parses until the next ';'. 311## This means it will allow commas etc inside values (and yes, both 312## commas and equals are commonly appear in the cookie value). This also 313## means that if you fold multiple Set-Cookie header fields into one, 314## comma-separated list, it'll be a headache to parse (at least my head 315## starts hurting everytime I think of that code). 316## - Expires: You'll get all sorts of date formats in the expires, 317## including emtpy expires attributes ("expires="). Be as flexible as you 318## can, and certainly don't expect the weekday to be there; if you can't 319## parse it, just ignore it and pretend it's a session cookie. 320## - Domain-matching: Netscape uses the 2-dot rule for _all_ domains, not 321## just the 7 special TLD's listed in their spec. And folks rely on 322## that... 323 324 def test_domain_return_ok(self): 325 # test optimization: .domain_return_ok() should filter out most 326 # domains in the CookieJar before we try to access them (because that 327 # may require disk access -- in particular, with MSIECookieJar) 328 # This is only a rough check for performance reasons, so it's not too 329 # critical as long as it's sufficiently liberal. 330 import cookielib, urllib2 331 pol = cookielib.DefaultCookiePolicy() 332 for url, domain, ok in [ 333 ("http://foo.bar.com/", "blah.com", False), 334 ("http://foo.bar.com/", "rhubarb.blah.com", False), 335 ("http://foo.bar.com/", "rhubarb.foo.bar.com", False), 336 ("http://foo.bar.com/", ".foo.bar.com", True), 337 ("http://foo.bar.com/", "foo.bar.com", True), 338 ("http://foo.bar.com/", ".bar.com", True), 339 ("http://foo.bar.com/", "com", True), 340 ("http://foo.com/", "rhubarb.foo.com", False), 341 ("http://foo.com/", ".foo.com", True), 342 ("http://foo.com/", "foo.com", True), 343 ("http://foo.com/", "com", True), 344 ("http://foo/", "rhubarb.foo", False), 345 ("http://foo/", ".foo", True), 346 ("http://foo/", "foo", True), 347 ("http://foo/", "foo.local", True), 348 ("http://foo/", ".local", True), 349 ]: 350 request = urllib2.Request(url) 351 r = pol.domain_return_ok(domain, request) 352 if ok: self.assert_(r) 353 else: self.assert_(not r) 354 355 def test_missing_value(self): 356 from cookielib import MozillaCookieJar, lwp_cookie_str 357 358 # missing = sign in Cookie: header is regarded by Mozilla as a missing 359 # name, and by cookielib as a missing value 360 filename = test_support.TESTFN 361 c = MozillaCookieJar(filename) 362 interact_netscape(c, "http://www.acme.com/", 'eggs') 363 interact_netscape(c, "http://www.acme.com/", '"spam"; path=/foo/') 364 cookie = c._cookies["www.acme.com"]["/"]["eggs"] 365 self.assert_(cookie.value is None) 366 self.assertEquals(cookie.name, "eggs") 367 cookie = c._cookies["www.acme.com"]['/foo/']['"spam"'] 368 self.assert_(cookie.value is None) 369 self.assertEquals(cookie.name, '"spam"') 370 self.assertEquals(lwp_cookie_str(cookie), ( 371 r'"spam"; path="/foo/"; domain="www.acme.com"; ' 372 'path_spec; discard; version=0')) 373 old_str = repr(c) 374 c.save(ignore_expires=True, ignore_discard=True) 375 try: 376 c = MozillaCookieJar(filename) 377 c.revert(ignore_expires=True, ignore_discard=True) 378 finally: 379 os.unlink(c.filename) 380 # cookies unchanged apart from lost info re. whether path was specified 381 self.assertEquals( 382 repr(c), 383 re.sub("path_specified=%s" % True, "path_specified=%s" % False, 384 old_str) 385 ) 386 self.assertEquals(interact_netscape(c, "http://www.acme.com/foo/"), 387 '"spam"; eggs') 388 389 def test_rfc2109_handling(self): 390 # RFC 2109 cookies are handled as RFC 2965 or Netscape cookies, 391 # dependent on policy settings 392 from cookielib import CookieJar, DefaultCookiePolicy 393 394 for rfc2109_as_netscape, rfc2965, version in [ 395 # default according to rfc2965 if not explicitly specified 396 (None, False, 0), 397 (None, True, 1), 398 # explicit rfc2109_as_netscape 399 (False, False, None), # version None here means no cookie stored 400 (False, True, 1), 401 (True, False, 0), 402 (True, True, 0), 403 ]: 404 policy = DefaultCookiePolicy( 405 rfc2109_as_netscape=rfc2109_as_netscape, 406 rfc2965=rfc2965) 407 c = CookieJar(policy) 408 interact_netscape(c, "http://www.example.com/", "ni=ni; Version=1") 409 try: 410 cookie = c._cookies["www.example.com"]["/"]["ni"] 411 except KeyError: 412 self.assert_(version is None) # didn't expect a stored cookie 413 else: 414 self.assertEqual(cookie.version, version) 415 # 2965 cookies are unaffected 416 interact_2965(c, "http://www.example.com/", 417 "foo=bar; Version=1") 418 if rfc2965: 419 cookie2965 = c._cookies["www.example.com"]["/"]["foo"] 420 self.assertEqual(cookie2965.version, 1) 421 422 def test_ns_parser(self): 423 from cookielib import CookieJar, DEFAULT_HTTP_PORT 424 425 c = CookieJar() 426 interact_netscape(c, "http://www.acme.com/", 427 'spam=eggs; DoMain=.acme.com; port; blArgh="feep"') 428 interact_netscape(c, "http://www.acme.com/", 'ni=ni; port=80,8080') 429 interact_netscape(c, "http://www.acme.com:80/", 'nini=ni') 430 interact_netscape(c, "http://www.acme.com:80/", 'foo=bar; expires=') 431 interact_netscape(c, "http://www.acme.com:80/", 'spam=eggs; ' 432 'expires="Foo Bar 25 33:22:11 3022"') 433 434 cookie = c._cookies[".acme.com"]["/"]["spam"] 435 self.assertEquals(cookie.domain, ".acme.com") 436 self.assert_(cookie.domain_specified) 437 self.assertEquals(cookie.port, DEFAULT_HTTP_PORT) 438 self.assert_(not cookie.port_specified) 439 # case is preserved 440 self.assert_(cookie.has_nonstandard_attr("blArgh") and 441 not cookie.has_nonstandard_attr("blargh")) 442 443 cookie = c._cookies["www.acme.com"]["/"]["ni"] 444 self.assertEquals(cookie.domain, "www.acme.com") 445 self.assert_(not cookie.domain_specified) 446 self.assertEquals(cookie.port, "80,8080") 447 self.assert_(cookie.port_specified) 448 449 cookie = c._cookies["www.acme.com"]["/"]["nini"] 450 self.assert_(cookie.port is None) 451 self.assert_(not cookie.port_specified) 452 453 # invalid expires should not cause cookie to be dropped 454 foo = c._cookies["www.acme.com"]["/"]["foo"] 455 spam = c._cookies["www.acme.com"]["/"]["foo"] 456 self.assert_(foo.expires is None) 457 self.assert_(spam.expires is None) 458 459 def test_ns_parser_special_names(self): 460 # names such as 'expires' are not special in first name=value pair 461 # of Set-Cookie: header 462 from cookielib import CookieJar 463 464 c = CookieJar() 465 interact_netscape(c, "http://www.acme.com/", 'expires=eggs') 466 interact_netscape(c, "http://www.acme.com/", 'version=eggs; spam=eggs') 467 468 cookies = c._cookies["www.acme.com"]["/"] 469 self.assert_('expires' in cookies) 470 self.assert_('version' in cookies) 471 472 def test_expires(self): 473 from cookielib import time2netscape, CookieJar 474 475 # if expires is in future, keep cookie... 476 c = CookieJar() 477 future = time2netscape(time.time()+3600) 478 interact_netscape(c, "http://www.acme.com/", 'spam="bar"; expires=%s' % 479 future) 480 self.assertEquals(len(c), 1) 481 now = time2netscape(time.time()-1) 482 # ... and if in past or present, discard it 483 interact_netscape(c, "http://www.acme.com/", 'foo="eggs"; expires=%s' % 484 now) 485 h = interact_netscape(c, "http://www.acme.com/") 486 self.assertEquals(len(c), 1) 487 self.assert_('spam="bar"' in h and "foo" not in h) 488 489 # max-age takes precedence over expires, and zero max-age is request to 490 # delete both new cookie and any old matching cookie 491 interact_netscape(c, "http://www.acme.com/", 'eggs="bar"; expires=%s' % 492 future) 493 interact_netscape(c, "http://www.acme.com/", 'bar="bar"; expires=%s' % 494 future) 495 self.assertEquals(len(c), 3) 496 interact_netscape(c, "http://www.acme.com/", 'eggs="bar"; ' 497 'expires=%s; max-age=0' % future) 498 interact_netscape(c, "http://www.acme.com/", 'bar="bar"; ' 499 'max-age=0; expires=%s' % future) 500 h = interact_netscape(c, "http://www.acme.com/") 501 self.assertEquals(len(c), 1) 502 503 # test expiry at end of session for cookies with no expires attribute 504 interact_netscape(c, "http://www.rhubarb.net/", 'whum="fizz"') 505 self.assertEquals(len(c), 2) 506 c.clear_session_cookies() 507 self.assertEquals(len(c), 1) 508 self.assert_('spam="bar"' in h) 509 510 # XXX RFC 2965 expiry rules (some apply to V0 too) 511 512 def test_default_path(self): 513 from cookielib import CookieJar, DefaultCookiePolicy 514 515 # RFC 2965 516 pol = DefaultCookiePolicy(rfc2965=True) 517 518 c = CookieJar(pol) 519 interact_2965(c, "http://www.acme.com/", 'spam="bar"; Version="1"') 520 self.assert_("/" in c._cookies["www.acme.com"]) 521 522 c = CookieJar(pol) 523 interact_2965(c, "http://www.acme.com/blah", 'eggs="bar"; Version="1"') 524 self.assert_("/" in c._cookies["www.acme.com"]) 525 526 c = CookieJar(pol) 527 interact_2965(c, "http://www.acme.com/blah/rhubarb", 528 'eggs="bar"; Version="1"') 529 self.assert_("/blah/" in c._cookies["www.acme.com"]) 530 531 c = CookieJar(pol) 532 interact_2965(c, "http://www.acme.com/blah/rhubarb/", 533 'eggs="bar"; Version="1"') 534 self.assert_("/blah/rhubarb/" in c._cookies["www.acme.com"]) 535 536 # Netscape 537 538 c = CookieJar() 539 interact_netscape(c, "http://www.acme.com/", 'spam="bar"') 540 self.assert_("/" in c._cookies["www.acme.com"]) 541 542 c = CookieJar() 543 interact_netscape(c, "http://www.acme.com/blah", 'eggs="bar"') 544 self.assert_("/" in c._cookies["www.acme.com"]) 545 546 c = CookieJar() 547 interact_netscape(c, "http://www.acme.com/blah/rhubarb", 'eggs="bar"') 548 self.assert_("/blah" in c._cookies["www.acme.com"]) 549 550 c = CookieJar() 551 interact_netscape(c, "http://www.acme.com/blah/rhubarb/", 'eggs="bar"') 552 self.assert_("/blah/rhubarb" in c._cookies["www.acme.com"]) 553 554 def test_escape_path(self): 555 from cookielib import escape_path 556 cases = [ 557 # quoted safe 558 ("/foo%2f/bar", "/foo%2F/bar"), 559 ("/foo%2F/bar", "/foo%2F/bar"), 560 # quoted % 561 ("/foo%%/bar", "/foo%%/bar"), 562 # quoted unsafe 563 ("/fo%19o/bar", "/fo%19o/bar"), 564 ("/fo%7do/bar", "/fo%7Do/bar"), 565 # unquoted safe 566 ("/foo/bar&", "/foo/bar&"), 567 ("/foo//bar", "/foo//bar"), 568 ("\176/foo/bar", "\176/foo/bar"), 569 # unquoted unsafe 570 ("/foo\031/bar", "/foo%19/bar"), 571 ("/\175foo/bar", "/%7Dfoo/bar"), 572 # unicode 573 (u"/foo/bar\uabcd", "/foo/bar%EA%AF%8D"), # UTF-8 encoded 574 ] 575 for arg, result in cases: 576 self.assertEquals(escape_path(arg), result) 577 578 def test_request_path(self): 579 from urllib2 import Request 580 from cookielib import request_path 581 # with parameters 582 req = Request("http://www.example.com/rheum/rhaponicum;" 583 "foo=bar;sing=song?apples=pears&spam=eggs#ni") 584 self.assertEquals(request_path(req), "/rheum/rhaponicum;" 585 "foo=bar;sing=song?apples=pears&spam=eggs#ni") 586 # without parameters 587 req = Request("http://www.example.com/rheum/rhaponicum?" 588 "apples=pears&spam=eggs#ni") 589 self.assertEquals(request_path(req), "/rheum/rhaponicum?" 590 "apples=pears&spam=eggs#ni") 591 # missing final slash 592 req = Request("http://www.example.com") 593 self.assertEquals(request_path(req), "/") 594 595 def test_request_port(self): 596 from urllib2 import Request 597 from cookielib import request_port, DEFAULT_HTTP_PORT 598 req = Request("http://www.acme.com:1234/", 599 headers={"Host": "www.acme.com:4321"}) 600 self.assertEquals(request_port(req), "1234") 601 req = Request("http://www.acme.com/", 602 headers={"Host": "www.acme.com:4321"}) 603 self.assertEquals(request_port(req), DEFAULT_HTTP_PORT) 604 605 def test_request_host(self): 606 from urllib2 import Request 607 from cookielib import request_host 608 # this request is illegal (RFC2616, 14.2.3) 609 req = Request("http://1.1.1.1/", 610 headers={"Host": "www.acme.com:80"}) 611 # libwww-perl wants this response, but that seems wrong (RFC 2616, 612 # section 5.2, point 1., and RFC 2965 section 1, paragraph 3) 613 #self.assertEquals(request_host(req), "www.acme.com") 614 self.assertEquals(request_host(req), "1.1.1.1") 615 req = Request("http://www.acme.com/", 616 headers={"Host": "irrelevant.com"}) 617 self.assertEquals(request_host(req), "www.acme.com") 618 # not actually sure this one is valid Request object, so maybe should 619 # remove test for no host in url in request_host function? 620 req = Request("/resource.html", 621 headers={"Host": "www.acme.com"}) 622 self.assertEquals(request_host(req), "www.acme.com") 623 # port shouldn't be in request-host 624 req = Request("http://www.acme.com:2345/resource.html", 625 headers={"Host": "www.acme.com:5432"}) 626 self.assertEquals(request_host(req), "www.acme.com") 627 628 def test_is_HDN(self): 629 from cookielib import is_HDN 630 self.assert_(is_HDN("foo.bar.com")) 631 self.assert_(is_HDN("1foo2.3bar4.5com")) 632 self.assert_(not is_HDN("192.168.1.1")) 633 self.assert_(not is_HDN("")) 634 self.assert_(not is_HDN(".")) 635 self.assert_(not is_HDN(".foo.bar.com")) 636 self.assert_(not is_HDN("..foo")) 637 self.assert_(not is_HDN("foo.")) 638 639 def test_reach(self): 640 from cookielib import reach 641 self.assertEquals(reach("www.acme.com"), ".acme.com") 642 self.assertEquals(reach("acme.com"), "acme.com") 643 self.assertEquals(reach("acme.local"), ".local") 644 self.assertEquals(reach(".local"), ".local") 645 self.assertEquals(reach(".com"), ".com") 646 self.assertEquals(reach("."), ".") 647 self.assertEquals(reach(""), "") 648 self.assertEquals(reach("192.168.0.1"), "192.168.0.1") 649 650 def test_domain_match(self): 651 from cookielib import domain_match, user_domain_match 652 self.assert_(domain_match("192.168.1.1", "192.168.1.1")) 653 self.assert_(not domain_match("192.168.1.1", ".168.1.1")) 654 self.assert_(domain_match("x.y.com", "x.Y.com")) 655 self.assert_(domain_match("x.y.com", ".Y.com")) 656 self.assert_(not domain_match("x.y.com", "Y.com")) 657 self.assert_(domain_match("a.b.c.com", ".c.com")) 658 self.assert_(not domain_match(".c.com", "a.b.c.com")) 659 self.assert_(domain_match("example.local", ".local")) 660 self.assert_(not domain_match("blah.blah", "")) 661 self.assert_(not domain_match("", ".rhubarb.rhubarb")) 662 self.assert_(domain_match("", "")) 663 664 self.assert_(user_domain_match("acme.com", "acme.com")) 665 self.assert_(not user_domain_match("acme.com", ".acme.com")) 666 self.assert_(user_domain_match("rhubarb.acme.com", ".acme.com")) 667 self.assert_(user_domain_match("www.rhubarb.acme.com", ".acme.com")) 668 self.assert_(user_domain_match("x.y.com", "x.Y.com")) 669 self.assert_(user_domain_match("x.y.com", ".Y.com")) 670 self.assert_(not user_domain_match("x.y.com", "Y.com")) 671 self.assert_(user_domain_match("y.com", "Y.com")) 672 self.assert_(not user_domain_match(".y.com", "Y.com")) 673 self.assert_(user_domain_match(".y.com", ".Y.com")) 674 self.assert_(user_domain_match("x.y.com", ".com")) 675 self.assert_(not user_domain_match("x.y.com", "com")) 676 self.assert_(not user_domain_match("x.y.com", "m")) 677 self.assert_(not user_domain_match("x.y.com", ".m")) 678 self.assert_(not user_domain_match("x.y.com", "")) 679 self.assert_(not user_domain_match("x.y.com", ".")) 680 self.assert_(user_domain_match("192.168.1.1", "192.168.1.1")) 681 # not both HDNs, so must string-compare equal to match 682 self.assert_(not user_domain_match("192.168.1.1", ".168.1.1")) 683 self.assert_(not user_domain_match("192.168.1.1", ".")) 684 # empty string is a special case 685 self.assert_(not user_domain_match("192.168.1.1", "")) 686 687 def test_wrong_domain(self): 688 # Cookies whose effective request-host name does not domain-match the 689 # domain are rejected. 690 691 # XXX far from complete 692 from cookielib import CookieJar 693 c = CookieJar() 694 interact_2965(c, "http://www.nasty.com/", 695 'foo=bar; domain=friendly.org; Version="1"') 696 self.assertEquals(len(c), 0) 697 698 def test_strict_domain(self): 699 # Cookies whose domain is a country-code tld like .co.uk should 700 # not be set if CookiePolicy.strict_domain is true. 701 from cookielib import CookieJar, DefaultCookiePolicy 702 703 cp = DefaultCookiePolicy(strict_domain=True) 704 cj = CookieJar(policy=cp) 705 interact_netscape(cj, "http://example.co.uk/", 'no=problemo') 706 interact_netscape(cj, "http://example.co.uk/", 707 'okey=dokey; Domain=.example.co.uk') 708 self.assertEquals(len(cj), 2) 709 for pseudo_tld in [".co.uk", ".org.za", ".tx.us", ".name.us"]: 710 interact_netscape(cj, "http://example.%s/" % pseudo_tld, 711 'spam=eggs; Domain=.co.uk') 712 self.assertEquals(len(cj), 2) 713 714 def test_two_component_domain_ns(self): 715 # Netscape: .www.bar.com, www.bar.com, .bar.com, bar.com, no domain 716 # should all get accepted, as should .acme.com, acme.com and no domain 717 # for 2-component domains like acme.com. 718 from cookielib import CookieJar, DefaultCookiePolicy 719 720 c = CookieJar() 721 722 # two-component V0 domain is OK 723 interact_netscape(c, "http://foo.net/", 'ns=bar') 724 self.assertEquals(len(c), 1) 725 self.assertEquals(c._cookies["foo.net"]["/"]["ns"].value, "bar") 726 self.assertEquals(interact_netscape(c, "http://foo.net/"), "ns=bar") 727 # *will* be returned to any other domain (unlike RFC 2965)... 728 self.assertEquals(interact_netscape(c, "http://www.foo.net/"), 729 "ns=bar") 730 # ...unless requested otherwise 731 pol = DefaultCookiePolicy( 732 strict_ns_domain=DefaultCookiePolicy.DomainStrictNonDomain) 733 c.set_policy(pol) 734 self.assertEquals(interact_netscape(c, "http://www.foo.net/"), "") 735 736 # unlike RFC 2965, even explicit two-component domain is OK, 737 # because .foo.net matches foo.net 738 interact_netscape(c, "http://foo.net/foo/", 739 'spam1=eggs; domain=foo.net') 740 # even if starts with a dot -- in NS rules, .foo.net matches foo.net! 741 interact_netscape(c, "http://foo.net/foo/bar/", 742 'spam2=eggs; domain=.foo.net') 743 self.assertEquals(len(c), 3) 744 self.assertEquals(c._cookies[".foo.net"]["/foo"]["spam1"].value, 745 "eggs") 746 self.assertEquals(c._cookies[".foo.net"]["/foo/bar"]["spam2"].value, 747 "eggs") 748 self.assertEquals(interact_netscape(c, "http://foo.net/foo/bar/"), 749 "spam2=eggs; spam1=eggs; ns=bar") 750 751 # top-level domain is too general 752 interact_netscape(c, "http://foo.net/", 'nini="ni"; domain=.net') 753 self.assertEquals(len(c), 3) 754 755## # Netscape protocol doesn't allow non-special top level domains (such 756## # as co.uk) in the domain attribute unless there are at least three 757## # dots in it. 758 # Oh yes it does! Real implementations don't check this, and real 759 # cookies (of course) rely on that behaviour. 760 interact_netscape(c, "http://foo.co.uk", 'nasty=trick; domain=.co.uk') 761## self.assertEquals(len(c), 2) 762 self.assertEquals(len(c), 4) 763 764 def test_two_component_domain_rfc2965(self): 765 from cookielib import CookieJar, DefaultCookiePolicy 766 767 pol = DefaultCookiePolicy(rfc2965=True) 768 c = CookieJar(pol) 769 770 # two-component V1 domain is OK 771 interact_2965(c, "http://foo.net/", 'foo=bar; Version="1"') 772 self.assertEquals(len(c), 1) 773 self.assertEquals(c._cookies["foo.net"]["/"]["foo"].value, "bar") 774 self.assertEquals(interact_2965(c, "http://foo.net/"), 775 "$Version=1; foo=bar") 776 # won't be returned to any other domain (because domain was implied) 777 self.assertEquals(interact_2965(c, "http://www.foo.net/"), "") 778 779 # unless domain is given explicitly, because then it must be 780 # rewritten to start with a dot: foo.net --> .foo.net, which does 781 # not domain-match foo.net 782 interact_2965(c, "http://foo.net/foo", 783 'spam=eggs; domain=foo.net; path=/foo; Version="1"') 784 self.assertEquals(len(c), 1) 785 self.assertEquals(interact_2965(c, "http://foo.net/foo"), 786 "$Version=1; foo=bar") 787 788 # explicit foo.net from three-component domain www.foo.net *does* get 789 # set, because .foo.net domain-matches .foo.net 790 interact_2965(c, "http://www.foo.net/foo/", 791 'spam=eggs; domain=foo.net; Version="1"') 792 self.assertEquals(c._cookies[".foo.net"]["/foo/"]["spam"].value, 793 "eggs") 794 self.assertEquals(len(c), 2) 795 self.assertEquals(interact_2965(c, "http://foo.net/foo/"), 796 "$Version=1; foo=bar") 797 self.assertEquals(interact_2965(c, "http://www.foo.net/foo/"), 798 '$Version=1; spam=eggs; $Domain="foo.net"') 799 800 # top-level domain is too general 801 interact_2965(c, "http://foo.net/", 802 'ni="ni"; domain=".net"; Version="1"') 803 self.assertEquals(len(c), 2) 804 805 # RFC 2965 doesn't require blocking this 806 interact_2965(c, "http://foo.co.uk/", 807 'nasty=trick; domain=.co.uk; Version="1"') 808 self.assertEquals(len(c), 3) 809 810 def test_domain_allow(self): 811 from cookielib import CookieJar, DefaultCookiePolicy 812 from urllib2 import Request 813 814 c = CookieJar(policy=DefaultCookiePolicy( 815 blocked_domains=["acme.com"], 816 allowed_domains=["www.acme.com"])) 817 818 req = Request("http://acme.com/") 819 headers = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/"] 820 res = FakeResponse(headers, "http://acme.com/") 821 c.extract_cookies(res, req) 822 self.assertEquals(len(c), 0) 823 824 req = Request("http://www.acme.com/") 825 res = FakeResponse(headers, "http://www.acme.com/") 826 c.extract_cookies(res, req) 827 self.assertEquals(len(c), 1) 828 829 req = Request("http://www.coyote.com/") 830 res = FakeResponse(headers, "http://www.coyote.com/") 831 c.extract_cookies(res, req) 832 self.assertEquals(len(c), 1) 833 834 # set a cookie with non-allowed domain... 835 req = Request("http://www.coyote.com/") 836 res = FakeResponse(headers, "http://www.coyote.com/") 837 cookies = c.make_cookies(res, req) 838 c.set_cookie(cookies[0]) 839 self.assertEquals(len(c), 2) 840 # ... and check is doesn't get returned 841 c.add_cookie_header(req) 842 self.assert_(not req.has_header("Cookie")) 843 844 def test_domain_block(self): 845 from cookielib import CookieJar, DefaultCookiePolicy 846 from urllib2 import Request 847 848 pol = DefaultCookiePolicy( 849 rfc2965=True, blocked_domains=[".acme.com"]) 850 c = CookieJar(policy=pol) 851 headers = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/"] 852 853 req = Request("http://www.acme.com/") 854 res = FakeResponse(headers, "http://www.acme.com/") 855 c.extract_cookies(res, req) 856 self.assertEquals(len(c), 0) 857 858 p = pol.set_blocked_domains(["acme.com"]) 859 c.extract_cookies(res, req) 860 self.assertEquals(len(c), 1) 861 862 c.clear() 863 req = Request("http://www.roadrunner.net/") 864 res = FakeResponse(headers, "http://www.roadrunner.net/") 865 c.extract_cookies(res, req) 866 self.assertEquals(len(c), 1) 867 req = Request("http://www.roadrunner.net/") 868 c.add_cookie_header(req) 869 self.assert_((req.has_header("Cookie") and 870 req.has_header("Cookie2"))) 871 872 c.clear() 873 pol.set_blocked_domains([".acme.com"]) 874 c.extract_cookies(res, req) 875 self.assertEquals(len(c), 1) 876 877 # set a cookie with blocked domain... 878 req = Request("http://www.acme.com/") 879 res = FakeResponse(headers, "http://www.acme.com/") 880 cookies = c.make_cookies(res, req) 881 c.set_cookie(cookies[0]) 882 self.assertEquals(len(c), 2) 883 # ... and check is doesn't get returned 884 c.add_cookie_header(req) 885 self.assert_(not req.has_header("Cookie")) 886 887 def test_secure(self): 888 from cookielib import CookieJar, DefaultCookiePolicy 889 890 for ns in True, False: 891 for whitespace in " ", "": 892 c = CookieJar() 893 if ns: 894 pol = DefaultCookiePolicy(rfc2965=False) 895 int = interact_netscape 896 vs = "" 897 else: 898 pol = DefaultCookiePolicy(rfc2965=True) 899 int = interact_2965 900 vs = "; Version=1" 901 c.set_policy(pol) 902 url = "http://www.acme.com/" 903 int(c, url, "foo1=bar%s%s" % (vs, whitespace)) 904 int(c, url, "foo2=bar%s; secure%s" % (vs, whitespace)) 905 self.assert_( 906 not c._cookies["www.acme.com"]["/"]["foo1"].secure, 907 "non-secure cookie registered secure") 908 self.assert_( 909 c._cookies["www.acme.com"]["/"]["foo2"].secure, 910 "secure cookie registered non-secure") 911 912 def test_quote_cookie_value(self): 913 from cookielib import CookieJar, DefaultCookiePolicy 914 c = CookieJar(policy=DefaultCookiePolicy(rfc2965=True)) 915 interact_2965(c, "http://www.acme.com/", r'foo=\b"a"r; Version=1') 916 h = interact_2965(c, "http://www.acme.com/") 917 self.assertEquals(h, r'$Version=1; foo=\\b\"a\"r') 918 919 def test_missing_final_slash(self): 920 # Missing slash from request URL's abs_path should be assumed present. 921 from cookielib import CookieJar, DefaultCookiePolicy 922 from urllib2 import Request 923 url = "http://www.acme.com" 924 c = CookieJar(DefaultCookiePolicy(rfc2965=True)) 925 interact_2965(c, url, "foo=bar; Version=1") 926 req = Request(url) 927 self.assertEquals(len(c), 1) 928 c.add_cookie_header(req) 929 self.assert_(req.has_header("Cookie")) 930 931 def test_domain_mirror(self): 932 from cookielib import CookieJar, DefaultCookiePolicy 933 934 pol = DefaultCookiePolicy(rfc2965=True) 935 936 c = CookieJar(pol) 937 url = "http://foo.bar.com/" 938 interact_2965(c, url, "spam=eggs; Version=1") 939 h = interact_2965(c, url) 940 self.assert_("Domain" not in h, 941 "absent domain returned with domain present") 942 943 c = CookieJar(pol) 944 url = "http://foo.bar.com/" 945 interact_2965(c, url, 'spam=eggs; Version=1; Domain=.bar.com') 946 h = interact_2965(c, url) 947 self.assert_('$Domain=".bar.com"' in h, "domain not returned") 948 949 c = CookieJar(pol) 950 url = "http://foo.bar.com/" 951 # note missing initial dot in Domain 952 interact_2965(c, url, 'spam=eggs; Version=1; Domain=bar.com') 953 h = interact_2965(c, url) 954 self.assert_('$Domain="bar.com"' in h, "domain not returned") 955 956 def test_path_mirror(self): 957 from cookielib import CookieJar, DefaultCookiePolicy 958 959 pol = DefaultCookiePolicy(rfc2965=True) 960 961 c = CookieJar(pol) 962 url = "http://foo.bar.com/" 963 interact_2965(c, url, "spam=eggs; Version=1") 964 h = interact_2965(c, url) 965 self.assert_("Path" not in h, 966 "absent path returned with path present") 967 968 c = CookieJar(pol) 969 url = "http://foo.bar.com/" 970 interact_2965(c, url, 'spam=eggs; Version=1; Path=/') 971 h = interact_2965(c, url) 972 self.assert_('$Path="/"' in h, "path not returned") 973 974 def test_port_mirror(self): 975 from cookielib import CookieJar, DefaultCookiePolicy 976 977 pol = DefaultCookiePolicy(rfc2965=True) 978 979 c = CookieJar(pol) 980 url = "http://foo.bar.com/" 981 interact_2965(c, url, "spam=eggs; Version=1") 982 h = interact_2965(c, url) 983 self.assert_("Port" not in h, 984 "absent port returned with port present") 985 986 c = CookieJar(pol) 987 url = "http://foo.bar.com/" 988 interact_2965(c, url, "spam=eggs; Version=1; Port") 989 h = interact_2965(c, url) 990 self.assert_(re.search("\$Port([^=]|$)", h), 991 "port with no value not returned with no value") 992 993 c = CookieJar(pol) 994 url = "http://foo.bar.com/" 995 interact_2965(c, url, 'spam=eggs; Version=1; Port="80"') 996 h = interact_2965(c, url) 997 self.assert_('$Port="80"' in h, 998 "port with single value not returned with single value") 999 1000 c = CookieJar(pol) 1001 url = "http://foo.bar.com/" 1002 interact_2965(c, url, 'spam=eggs; Version=1; Port="80,8080"') 1003 h = interact_2965(c, url) 1004 self.assert_('$Port="80,8080"' in h, 1005 "port with multiple values not returned with multiple " 1006 "values") 1007 1008 def test_no_return_comment(self): 1009 from cookielib import CookieJar, DefaultCookiePolicy 1010 1011 c = CookieJar(DefaultCookiePolicy(rfc2965=True)) 1012 url = "http://foo.bar.com/" 1013 interact_2965(c, url, 'spam=eggs; Version=1; ' 1014 'Comment="does anybody read these?"; ' 1015 'CommentURL="http://foo.bar.net/comment.html"') 1016 h = interact_2965(c, url) 1017 self.assert_( 1018 "Comment" not in h, 1019 "Comment or CommentURL cookie-attributes returned to server") 1020 1021 def test_Cookie_iterator(self): 1022 from cookielib import CookieJar, Cookie, DefaultCookiePolicy 1023 1024 cs = CookieJar(DefaultCookiePolicy(rfc2965=True)) 1025 # add some random cookies 1026 interact_2965(cs, "http://blah.spam.org/", 'foo=eggs; Version=1; ' 1027 'Comment="does anybody read these?"; ' 1028 'CommentURL="http://foo.bar.net/comment.html"') 1029 interact_netscape(cs, "http://www.acme.com/blah/", "spam=bar; secure") 1030 interact_2965(cs, "http://www.acme.com/blah/", 1031 "foo=bar; secure; Version=1") 1032 interact_2965(cs, "http://www.acme.com/blah/", 1033 "foo=bar; path=/; Version=1") 1034 interact_2965(cs, "http://www.sol.no", 1035 r'bang=wallop; version=1; domain=".sol.no"; ' 1036 r'port="90,100, 80,8080"; ' 1037 r'max-age=100; Comment = "Just kidding! (\"|\\\\) "') 1038 1039 versions = [1, 1, 1, 0, 1] 1040 names = ["bang", "foo", "foo", "spam", "foo"] 1041 domains = [".sol.no", "blah.spam.org", "www.acme.com", 1042 "www.acme.com", "www.acme.com"] 1043 paths = ["/", "/", "/", "/blah", "/blah/"] 1044 1045 for i in range(4): 1046 i = 0 1047 for c in cs: 1048 self.assert_(isinstance(c, Cookie)) 1049 self.assertEquals(c.version, versions[i]) 1050 self.assertEquals(c.name, names[i]) 1051 self.assertEquals(c.domain, domains[i]) 1052 self.assertEquals(c.path, paths[i]) 1053 i = i + 1 1054 1055 def test_parse_ns_headers(self): 1056 from cookielib import parse_ns_headers 1057 1058 # missing domain value (invalid cookie) 1059 self.assertEquals( 1060 parse_ns_headers(["foo=bar; path=/; domain"]), 1061 [[("foo", "bar"), 1062 ("path", "/"), ("domain", None), ("version", "0")]] 1063 ) 1064 # invalid expires value 1065 self.assertEquals( 1066 parse_ns_headers(["foo=bar; expires=Foo Bar 12 33:22:11 2000"]), 1067 [[("foo", "bar"), ("expires", None), ("version", "0")]] 1068 ) 1069 # missing cookie value (valid cookie) 1070 self.assertEquals( 1071 parse_ns_headers(["foo"]), 1072 [[("foo", None), ("version", "0")]] 1073 ) 1074 # shouldn't add version if header is empty 1075 self.assertEquals(parse_ns_headers([""]), []) 1076 1077 def test_bad_cookie_header(self): 1078 1079 def cookiejar_from_cookie_headers(headers): 1080 from cookielib import CookieJar 1081 from urllib2 import Request 1082 c = CookieJar() 1083 req = Request("http://www.example.com/") 1084 r = FakeResponse(headers, "http://www.example.com/") 1085 c.extract_cookies(r, req) 1086 return c 1087 1088 # none of these bad headers should cause an exception to be raised 1089 for headers in [ 1090 ["Set-Cookie: "], # actually, nothing wrong with this 1091 ["Set-Cookie2: "], # ditto 1092 # missing domain value 1093 ["Set-Cookie2: a=foo; path=/; Version=1; domain"], 1094 # bad max-age 1095 ["Set-Cookie: b=foo; max-age=oops"], 1096 ]: 1097 c = cookiejar_from_cookie_headers(headers) 1098 # these bad cookies shouldn't be set 1099 self.assertEquals(len(c), 0) 1100 1101 # cookie with invalid expires is treated as session cookie 1102 headers = ["Set-Cookie: c=foo; expires=Foo Bar 12 33:22:11 2000"] 1103 c = cookiejar_from_cookie_headers(headers) 1104 cookie = c._cookies["www.example.com"]["/"]["c"] 1105 self.assert_(cookie.expires is None) 1106 1107 1108class LWPCookieTests(TestCase): 1109 # Tests taken from libwww-perl, with a few modifications and additions. 1110 1111 def test_netscape_example_1(self): 1112 from cookielib import CookieJar, DefaultCookiePolicy 1113 from urllib2 import Request 1114 1115 #------------------------------------------------------------------- 1116 # First we check that it works for the original example at 1117 # http://www.netscape.com/newsref/std/cookie_spec.html 1118 1119 # Client requests a document, and receives in the response: 1120 # 1121 # Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT 1122 # 1123 # When client requests a URL in path "/" on this server, it sends: 1124 # 1125 # Cookie: CUSTOMER=WILE_E_COYOTE 1126 # 1127 # Client requests a document, and receives in the response: 1128 # 1129 # Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/ 1130 # 1131 # When client requests a URL in path "/" on this server, it sends: 1132 # 1133 # Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001 1134 # 1135 # Client receives: 1136 # 1137 # Set-Cookie: SHIPPING=FEDEX; path=/fo 1138 # 1139 # When client requests a URL in path "/" on this server, it sends: 1140 # 1141 # Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001 1142 # 1143 # When client requests a URL in path "/foo" on this server, it sends: 1144 # 1145 # Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001; SHIPPING=FEDEX 1146 # 1147 # The last Cookie is buggy, because both specifications say that the 1148 # most specific cookie must be sent first. SHIPPING=FEDEX is the 1149 # most specific and should thus be first. 1150 1151 year_plus_one = time.localtime()[0] + 1 1152 1153 headers = [] 1154 1155 c = CookieJar(DefaultCookiePolicy(rfc2965 = True)) 1156 1157 #req = Request("http://1.1.1.1/", 1158 # headers={"Host": "www.acme.com:80"}) 1159 req = Request("http://www.acme.com:80/", 1160 headers={"Host": "www.acme.com:80"}) 1161 1162 headers.append( 1163 "Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/ ; " 1164 "expires=Wednesday, 09-Nov-%d 23:12:40 GMT" % year_plus_one) 1165 res = FakeResponse(headers, "http://www.acme.com/") 1166 c.extract_cookies(res, req) 1167 1168 req = Request("http://www.acme.com/") 1169 c.add_cookie_header(req) 1170 1171 self.assertEqual(req.get_header("Cookie"), "CUSTOMER=WILE_E_COYOTE") 1172 self.assertEqual(req.get_header("Cookie2"), '$Version="1"') 1173 1174 headers.append("Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/") 1175 res = FakeResponse(headers, "http://www.acme.com/") 1176 c.extract_cookies(res, req) 1177 1178 req = Request("http://www.acme.com/foo/bar") 1179 c.add_cookie_header(req) 1180 1181 h = req.get_header("Cookie") 1182 self.assert_("PART_NUMBER=ROCKET_LAUNCHER_0001" in h and 1183 "CUSTOMER=WILE_E_COYOTE" in h) 1184 1185 headers.append('Set-Cookie: SHIPPING=FEDEX; path=/foo') 1186 res = FakeResponse(headers, "http://www.acme.com") 1187 c.extract_cookies(res, req) 1188 1189 req = Request("http://www.acme.com/") 1190 c.add_cookie_header(req) 1191 1192 h = req.get_header("Cookie") 1193 self.assert_("PART_NUMBER=ROCKET_LAUNCHER_0001" in h and 1194 "CUSTOMER=WILE_E_COYOTE" in h and 1195 "SHIPPING=FEDEX" not in h) 1196 1197 req = Request("http://www.acme.com/foo/") 1198 c.add_cookie_header(req) 1199 1200 h = req.get_header("Cookie") 1201 self.assert_(("PART_NUMBER=ROCKET_LAUNCHER_0001" in h and 1202 "CUSTOMER=WILE_E_COYOTE" in h and 1203 h.startswith("SHIPPING=FEDEX;"))) 1204 1205 def test_netscape_example_2(self): 1206 from cookielib import CookieJar 1207 from urllib2 import Request 1208 1209 # Second Example transaction sequence: 1210 # 1211 # Assume all mappings from above have been cleared. 1212 # 1213 # Client receives: 1214 # 1215 # Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/ 1216 # 1217 # When client requests a URL in path "/" on this server, it sends: 1218 # 1219 # Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001 1220 # 1221 # Client receives: 1222 # 1223 # Set-Cookie: PART_NUMBER=RIDING_ROCKET_0023; path=/ammo 1224 # 1225 # When client requests a URL in path "/ammo" on this server, it sends: 1226 # 1227 # Cookie: PART_NUMBER=RIDING_ROCKET_0023; PART_NUMBER=ROCKET_LAUNCHER_0001 1228 # 1229 # NOTE: There are two name/value pairs named "PART_NUMBER" due to 1230 # the inheritance of the "/" mapping in addition to the "/ammo" mapping. 1231 1232 c = CookieJar() 1233 headers = [] 1234 1235 req = Request("http://www.acme.com/") 1236 headers.append("Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/") 1237 res = FakeResponse(headers, "http://www.acme.com/") 1238 1239 c.extract_cookies(res, req) 1240 1241 req = Request("http://www.acme.com/") 1242 c.add_cookie_header(req) 1243 1244 self.assertEquals(req.get_header("Cookie"), 1245 "PART_NUMBER=ROCKET_LAUNCHER_0001") 1246 1247 headers.append( 1248 "Set-Cookie: PART_NUMBER=RIDING_ROCKET_0023; path=/ammo") 1249 res = FakeResponse(headers, "http://www.acme.com/") 1250 c.extract_cookies(res, req) 1251 1252 req = Request("http://www.acme.com/ammo") 1253 c.add_cookie_header(req) 1254 1255 self.assert_(re.search(r"PART_NUMBER=RIDING_ROCKET_0023;\s*" 1256 "PART_NUMBER=ROCKET_LAUNCHER_0001", 1257 req.get_header("Cookie"))) 1258 1259 def test_ietf_example_1(self): 1260 from cookielib import CookieJar, DefaultCookiePolicy 1261 #------------------------------------------------------------------- 1262 # Then we test with the examples from draft-ietf-http-state-man-mec-03.txt 1263 # 1264 # 5. EXAMPLES 1265 1266 c = CookieJar(DefaultCookiePolicy(rfc2965=True)) 1267 1268 # 1269 # 5.1 Example 1 1270 # 1271 # Most detail of request and response headers has been omitted. Assume 1272 # the user agent has no stored cookies. 1273 # 1274 # 1. User Agent -> Server 1275 # 1276 # POST /acme/login HTTP/1.1 1277 # [form data] 1278 # 1279 # User identifies self via a form. 1280 # 1281 # 2. Server -> User Agent 1282 # 1283 # HTTP/1.1 200 OK 1284 # Set-Cookie2: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme" 1285 # 1286 # Cookie reflects user's identity. 1287 1288 cookie = interact_2965( 1289 c, 'http://www.acme.com/acme/login', 1290 'Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"') 1291 self.assert_(not cookie) 1292 1293 # 1294 # 3. User Agent -> Server 1295 # 1296 # POST /acme/pickitem HTTP/1.1 1297 # Cookie: $Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme" 1298 # [form data] 1299 # 1300 # User selects an item for ``shopping basket.'' 1301 # 1302 # 4. Server -> User Agent 1303 # 1304 # HTTP/1.1 200 OK 1305 # Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1"; 1306 # Path="/acme" 1307 # 1308 # Shopping basket contains an item. 1309 1310 cookie = interact_2965(c, 'http://www.acme.com/acme/pickitem', 1311 'Part_Number="Rocket_Launcher_0001"; ' 1312 'Version="1"; Path="/acme"'); 1313 self.assert_(re.search( 1314 r'^\$Version="?1"?; Customer="?WILE_E_COYOTE"?; \$Path="/acme"$', 1315 cookie)) 1316 1317 # 1318 # 5. User Agent -> Server 1319 # 1320 # POST /acme/shipping HTTP/1.1 1321 # Cookie: $Version="1"; 1322 # Customer="WILE_E_COYOTE"; $Path="/acme"; 1323 # Part_Number="Rocket_Launcher_0001"; $Path="/acme" 1324 # [form data] 1325 # 1326 # User selects shipping method from form. 1327 # 1328 # 6. Server -> User Agent 1329 # 1330 # HTTP/1.1 200 OK 1331 # Set-Cookie2: Shipping="FedEx"; Version="1"; Path="/acme" 1332 # 1333 # New cookie reflects shipping method. 1334 1335 cookie = interact_2965(c, "http://www.acme.com/acme/shipping", 1336 'Shipping="FedEx"; Version="1"; Path="/acme"') 1337 1338 self.assert_(re.search(r'^\$Version="?1"?;', cookie)) 1339 self.assert_(re.search(r'Part_Number="?Rocket_Launcher_0001"?;' 1340 '\s*\$Path="\/acme"', cookie)) 1341 self.assert_(re.search(r'Customer="?WILE_E_COYOTE"?;\s*\$Path="\/acme"', 1342 cookie)) 1343 1344 # 1345 # 7. User Agent -> Server 1346 # 1347 # POST /acme/process HTTP/1.1 1348 # Cookie: $Version="1"; 1349 # Customer="WILE_E_COYOTE"; $Path="/acme"; 1350 # Part_Number="Rocket_Launcher_0001"; $Path="/acme"; 1351 # Shipping="FedEx"; $Path="/acme" 1352 # [form data] 1353 # 1354 # User chooses to process order. 1355 # 1356 # 8. Server -> User Agent 1357 # 1358 # HTTP/1.1 200 OK 1359 # 1360 # Transaction is complete. 1361 1362 cookie = interact_2965(c, "http://www.acme.com/acme/process") 1363 self.assert_( 1364 re.search(r'Shipping="?FedEx"?;\s*\$Path="\/acme"', cookie) and 1365 "WILE_E_COYOTE" in cookie) 1366 1367 # 1368 # The user agent makes a series of requests on the origin server, after 1369 # each of which it receives a new cookie. All the cookies have the same 1370 # Path attribute and (default) domain. Because the request URLs all have 1371 # /acme as a prefix, and that matches the Path attribute, each request 1372 # contains all the cookies received so far. 1373 1374 def test_ietf_example_2(self): 1375 from cookielib import CookieJar, DefaultCookiePolicy 1376 1377 # 5.2 Example 2 1378 # 1379 # This example illustrates the effect of the Path attribute. All detail 1380 # of request and response headers has been omitted. Assume the user agent 1381 # has no stored cookies. 1382 1383 c = CookieJar(DefaultCookiePolicy(rfc2965=True)) 1384 1385 # Imagine the user agent has received, in response to earlier requests, 1386 # the response headers 1387 # 1388 # Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1"; 1389 # Path="/acme" 1390 # 1391 # and 1392 # 1393 # Set-Cookie2: Part_Number="Riding_Rocket_0023"; Version="1"; 1394 # Path="/acme/ammo" 1395 1396 interact_2965( 1397 c, "http://www.acme.com/acme/ammo/specific", 1398 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"', 1399 'Part_Number="Riding_Rocket_0023"; Version="1"; Path="/acme/ammo"') 1400 1401 # A subsequent request by the user agent to the (same) server for URLs of 1402 # the form /acme/ammo/... would include the following request header: 1403 # 1404 # Cookie: $Version="1"; 1405 # Part_Number="Riding_Rocket_0023"; $Path="/acme/ammo"; 1406 # Part_Number="Rocket_Launcher_0001"; $Path="/acme" 1407 # 1408 # Note that the NAME=VALUE pair for the cookie with the more specific Path 1409 # attribute, /acme/ammo, comes before the one with the less specific Path 1410 # attribute, /acme. Further note that the same cookie name appears more 1411 # than once. 1412 1413 cookie = interact_2965(c, "http://www.acme.com/acme/ammo/...") 1414 self.assert_( 1415 re.search(r"Riding_Rocket_0023.*Rocket_Launcher_0001", cookie)) 1416 1417 # A subsequent request by the user agent to the (same) server for a URL of 1418 # the form /acme/parts/ would include the following request header: 1419 # 1420 # Cookie: $Version="1"; Part_Number="Rocket_Launcher_0001"; $Path="/acme" 1421 # 1422 # Here, the second cookie's Path attribute /acme/ammo is not a prefix of 1423 # the request URL, /acme/parts/, so the cookie does not get forwarded to 1424 # the server. 1425 1426 cookie = interact_2965(c, "http://www.acme.com/acme/parts/") 1427 self.assert_("Rocket_Launcher_0001" in cookie and 1428 "Riding_Rocket_0023" not in cookie) 1429 1430 def test_rejection(self): 1431 # Test rejection of Set-Cookie2 responses based on domain, path, port. 1432 from cookielib import DefaultCookiePolicy, LWPCookieJar 1433 1434 pol = DefaultCookiePolicy(rfc2965=True) 1435 1436 c = LWPCookieJar(policy=pol) 1437 1438 max_age = "max-age=3600" 1439 1440 # illegal domain (no embedded dots) 1441 cookie = interact_2965(c, "http://www.acme.com", 1442 'foo=bar; domain=".com"; version=1') 1443 self.assert_(not c) 1444 1445 # legal domain 1446 cookie = interact_2965(c, "http://www.acme.com", 1447 'ping=pong; domain="acme.com"; version=1') 1448 self.assertEquals(len(c), 1) 1449 1450 # illegal domain (host prefix "www.a" contains a dot) 1451 cookie = interact_2965(c, "http://www.a.acme.com", 1452 'whiz=bang; domain="acme.com"; version=1') 1453 self.assertEquals(len(c), 1) 1454 1455 # legal domain 1456 cookie = interact_2965(c, "http://www.a.acme.com", 1457 'wow=flutter; domain=".a.acme.com"; version=1') 1458 self.assertEquals(len(c), 2) 1459 1460 # can't partially match an IP-address 1461 cookie = interact_2965(c, "http://125.125.125.125", 1462 'zzzz=ping; domain="125.125.125"; version=1') 1463 self.assertEquals(len(c), 2) 1464 1465 # illegal path (must be prefix of request path) 1466 cookie = interact_2965(c, "http://www.sol.no", 1467 'blah=rhubarb; domain=".sol.no"; path="/foo"; ' 1468 'version=1') 1469 self.assertEquals(len(c), 2) 1470 1471 # legal path 1472 cookie = interact_2965(c, "http://www.sol.no/foo/bar", 1473 'bing=bong; domain=".sol.no"; path="/foo"; ' 1474 'version=1') 1475 self.assertEquals(len(c), 3) 1476 1477 # illegal port (request-port not in list) 1478 cookie = interact_2965(c, "http://www.sol.no", 1479 'whiz=ffft; domain=".sol.no"; port="90,100"; ' 1480 'version=1') 1481 self.assertEquals(len(c), 3) 1482 1483 # legal port 1484 cookie = interact_2965( 1485 c, "http://www.sol.no", 1486 r'bang=wallop; version=1; domain=".sol.no"; ' 1487 r'port="90,100, 80,8080"; ' 1488 r'max-age=100; Comment = "Just kidding! (\"|\\\\) "') 1489 self.assertEquals(len(c), 4) 1490 1491 # port attribute without any value (current port) 1492 cookie = interact_2965(c, "http://www.sol.no", 1493 'foo9=bar; version=1; domain=".sol.no"; port; ' 1494 'max-age=100;') 1495 self.assertEquals(len(c), 5) 1496 1497 # encoded path 1498 # LWP has this test, but unescaping allowed path characters seems 1499 # like a bad idea, so I think this should fail: 1500## cookie = interact_2965(c, "http://www.sol.no/foo/", 1501## r'foo8=bar; version=1; path="/%66oo"') 1502 # but this is OK, because '<' is not an allowed HTTP URL path 1503 # character: 1504 cookie = interact_2965(c, "http://www.sol.no/<oo/", 1505 r'foo8=bar; version=1; path="/%3coo"') 1506 self.assertEquals(len(c), 6) 1507 1508 # save and restore 1509 filename = test_support.TESTFN 1510 1511 try: 1512 c.save(filename, ignore_discard=True) 1513 old = repr(c) 1514 1515 c = LWPCookieJar(policy=pol) 1516 c.load(filename, ignore_discard=True) 1517 finally: 1518 try: os.unlink(filename) 1519 except OSError: pass 1520 1521 self.assertEquals(old, repr(c)) 1522 1523 def test_url_encoding(self): 1524 # Try some URL encodings of the PATHs. 1525 # (the behaviour here has changed from libwww-perl) 1526 from cookielib import CookieJar, DefaultCookiePolicy 1527 1528 c = CookieJar(DefaultCookiePolicy(rfc2965=True)) 1529 interact_2965(c, "http://www.acme.com/foo%2f%25/%3c%3c%0Anew%E5/%E5", 1530 "foo = bar; version = 1") 1531 1532 cookie = interact_2965( 1533 c, "http://www.acme.com/foo%2f%25/<<%0anewå/æøå", 1534 'bar=baz; path="/foo/"; version=1'); 1535 version_re = re.compile(r'^\$version=\"?1\"?', re.I) 1536 self.assert_("foo=bar" in cookie and version_re.search(cookie)) 1537 1538 cookie = interact_2965( 1539 c, "http://www.acme.com/foo/%25/<<%0anewå/æøå") 1540 self.assert_(not cookie) 1541 1542 # unicode URL doesn't raise exception 1543 cookie = interact_2965(c, u"http://www.acme.com/\xfc") 1544 1545 def test_mozilla(self): 1546 # Save / load Mozilla/Netscape cookie file format. 1547 from cookielib import MozillaCookieJar, DefaultCookiePolicy 1548 1549 year_plus_one = time.localtime()[0] + 1 1550 1551 filename = test_support.TESTFN 1552 1553 c = MozillaCookieJar(filename, 1554 policy=DefaultCookiePolicy(rfc2965=True)) 1555 interact_2965(c, "http://www.acme.com/", 1556 "foo1=bar; max-age=100; Version=1") 1557 interact_2965(c, "http://www.acme.com/", 1558 'foo2=bar; port="80"; max-age=100; Discard; Version=1') 1559 interact_2965(c, "http://www.acme.com/", "foo3=bar; secure; Version=1") 1560 1561 expires = "expires=09-Nov-%d 23:12:40 GMT" % (year_plus_one,) 1562 interact_netscape(c, "http://www.foo.com/", 1563 "fooa=bar; %s" % expires) 1564 interact_netscape(c, "http://www.foo.com/", 1565 "foob=bar; Domain=.foo.com; %s" % expires) 1566 interact_netscape(c, "http://www.foo.com/", 1567 "fooc=bar; Domain=www.foo.com; %s" % expires) 1568 1569 def save_and_restore(cj, ignore_discard): 1570 try: 1571 cj.save(ignore_discard=ignore_discard) 1572 new_c = MozillaCookieJar(filename, 1573 DefaultCookiePolicy(rfc2965=True)) 1574 new_c.load(ignore_discard=ignore_discard) 1575 finally: 1576 try: os.unlink(filename) 1577 except OSError: pass 1578 return new_c 1579 1580 new_c = save_and_restore(c, True) 1581 self.assertEquals(len(new_c), 6) # none discarded 1582 self.assert_("name='foo1', value='bar'" in repr(new_c)) 1583 1584 new_c = save_and_restore(c, False) 1585 self.assertEquals(len(new_c), 4) # 2 of them discarded on save 1586 self.assert_("name='foo1', value='bar'" in repr(new_c)) 1587 1588 def test_netscape_misc(self): 1589 # Some additional Netscape cookies tests. 1590 from cookielib import CookieJar 1591 from urllib2 import Request 1592 1593 c = CookieJar() 1594 headers = [] 1595 req = Request("http://foo.bar.acme.com/foo") 1596 1597 # Netscape allows a host part that contains dots 1598 headers.append("Set-Cookie: Customer=WILE_E_COYOTE; domain=.acme.com") 1599 res = FakeResponse(headers, "http://www.acme.com/foo") 1600 c.extract_cookies(res, req) 1601 1602 # and that the domain is the same as the host without adding a leading 1603 # dot to the domain. Should not quote even if strange chars are used 1604 # in the cookie value. 1605 headers.append("Set-Cookie: PART_NUMBER=3,4; domain=foo.bar.acme.com") 1606 res = FakeResponse(headers, "http://www.acme.com/foo") 1607 c.extract_cookies(res, req) 1608 1609 req = Request("http://foo.bar.acme.com/foo") 1610 c.add_cookie_header(req) 1611 self.assert_( 1612 "PART_NUMBER=3,4" in req.get_header("Cookie") and 1613 "Customer=WILE_E_COYOTE" in req.get_header("Cookie")) 1614 1615 def test_intranet_domains_2965(self): 1616 # Test handling of local intranet hostnames without a dot. 1617 from cookielib import CookieJar, DefaultCookiePolicy 1618 1619 c = CookieJar(DefaultCookiePolicy(rfc2965=True)) 1620 interact_2965(c, "http://example/", 1621 "foo1=bar; PORT; Discard; Version=1;") 1622 cookie = interact_2965(c, "http://example/", 1623 'foo2=bar; domain=".local"; Version=1') 1624 self.assert_("foo1=bar" in cookie) 1625 1626 interact_2965(c, "http://example/", 'foo3=bar; Version=1') 1627 cookie = interact_2965(c, "http://example/") 1628 self.assert_("foo2=bar" in cookie and len(c) == 3) 1629 1630 def test_intranet_domains_ns(self): 1631 from cookielib import CookieJar, DefaultCookiePolicy 1632 1633 c = CookieJar(DefaultCookiePolicy(rfc2965 = False)) 1634 interact_netscape(c, "http://example/", "foo1=bar") 1635 cookie = interact_netscape(c, "http://example/", 1636 'foo2=bar; domain=.local') 1637 self.assertEquals(len(c), 2) 1638 self.assert_("foo1=bar" in cookie) 1639 1640 cookie = interact_netscape(c, "http://example/") 1641 self.assert_("foo2=bar" in cookie) 1642 self.assertEquals(len(c), 2) 1643 1644 def test_empty_path(self): 1645 from cookielib import CookieJar, DefaultCookiePolicy 1646 from urllib2 import Request 1647 1648 # Test for empty path 1649 # Broken web-server ORION/1.3.38 returns to the client response like 1650 # 1651 # Set-Cookie: JSESSIONID=ABCDERANDOM123; Path= 1652 # 1653 # ie. with Path set to nothing. 1654 # In this case, extract_cookies() must set cookie to / (root) 1655 c = CookieJar(DefaultCookiePolicy(rfc2965 = True)) 1656 headers = [] 1657 1658 req = Request("http://www.ants.com/") 1659 headers.append("Set-Cookie: JSESSIONID=ABCDERANDOM123; Path=") 1660 res = FakeResponse(headers, "http://www.ants.com/") 1661 c.extract_cookies(res, req) 1662 1663 req = Request("http://www.ants.com/") 1664 c.add_cookie_header(req) 1665 1666 self.assertEquals(req.get_header("Cookie"), 1667 "JSESSIONID=ABCDERANDOM123") 1668 self.assertEquals(req.get_header("Cookie2"), '$Version="1"') 1669 1670 # missing path in the request URI 1671 req = Request("http://www.ants.com:8080") 1672 c.add_cookie_header(req) 1673 1674 self.assertEquals(req.get_header("Cookie"), 1675 "JSESSIONID=ABCDERANDOM123") 1676 self.assertEquals(req.get_header("Cookie2"), '$Version="1"') 1677 1678 def test_session_cookies(self): 1679 from cookielib import CookieJar 1680 from urllib2 import Request 1681 1682 year_plus_one = time.localtime()[0] + 1 1683 1684 # Check session cookies are deleted properly by 1685 # CookieJar.clear_session_cookies method 1686 1687 req = Request('http://www.perlmeister.com/scripts') 1688 headers = [] 1689 headers.append("Set-Cookie: s1=session;Path=/scripts") 1690 headers.append("Set-Cookie: p1=perm; Domain=.perlmeister.com;" 1691 "Path=/;expires=Fri, 02-Feb-%d 23:24:20 GMT" % 1692 year_plus_one) 1693 headers.append("Set-Cookie: p2=perm;Path=/;expires=Fri, " 1694 "02-Feb-%d 23:24:20 GMT" % year_plus_one) 1695 headers.append("Set-Cookie: s2=session;Path=/scripts;" 1696 "Domain=.perlmeister.com") 1697 headers.append('Set-Cookie2: s3=session;Version=1;Discard;Path="/"') 1698 res = FakeResponse(headers, 'http://www.perlmeister.com/scripts') 1699 1700 c = CookieJar() 1701 c.extract_cookies(res, req) 1702 # How many session/permanent cookies do we have? 1703 counter = {"session_after": 0, 1704 "perm_after": 0, 1705 "session_before": 0, 1706 "perm_before": 0} 1707 for cookie in c: 1708 key = "%s_before" % cookie.value 1709 counter[key] = counter[key] + 1 1710 c.clear_session_cookies() 1711 # How many now? 1712 for cookie in c: 1713 key = "%s_after" % cookie.value 1714 counter[key] = counter[key] + 1 1715 1716 self.assert_(not ( 1717 # a permanent cookie got lost accidently 1718 counter["perm_after"] != counter["perm_before"] or 1719 # a session cookie hasn't been cleared 1720 counter["session_after"] != 0 or 1721 # we didn't have session cookies in the first place 1722 counter["session_before"] == 0)) 1723 1724 1725def test_main(verbose=None): 1726 from test import test_sets 1727 test_support.run_unittest( 1728 DateTimeTests, 1729 HeaderTests, 1730 CookieTests, 1731 FileCookieJarTests, 1732 LWPCookieTests, 1733 ) 1734 1735if __name__ == "__main__": 1736 test_main(verbose=True) 1737