blob: 1cfbe742e4657c2843cc8d44dec4748f2f18305b [file] [log] [blame]
Georg Brandl24420152008-05-26 16:32:26 +00001# Simple test suite for http/cookies.py
Andrew M. Kuchlingcdec8c72000-08-19 15:21:12 +00002
Brett Cannond3791ed2010-03-20 21:51:10 +00003from test.support import run_unittest, run_doctest, check_warnings
Thomas Wouters89f507f2006-12-13 04:49:30 +00004import unittest
Georg Brandl24420152008-05-26 16:32:26 +00005from http import cookies
Andrew M. Kuchlingcdec8c72000-08-19 15:21:12 +00006
Andrew M. Kuchling44644322002-12-29 16:45:06 +00007import warnings
Andrew M. Kuchling44644322002-12-29 16:45:06 +00008
Thomas Wouters89f507f2006-12-13 04:49:30 +00009class CookieTests(unittest.TestCase):
Brett Cannond3791ed2010-03-20 21:51:10 +000010
11 def setUp(self):
12 self._warnings_manager = check_warnings()
13 self._warnings_manager.__enter__()
14 warnings.filterwarnings("ignore", ".* class is insecure.*",
15 DeprecationWarning)
16
17 def tearDown(self):
18 self._warnings_manager.__exit__(None, None, None)
19
Thomas Wouters89f507f2006-12-13 04:49:30 +000020 def test_basic(self):
21 cases = [
Georg Brandl76e155a2010-07-31 21:04:00 +000022 {'data': 'chips=ahoy; vienna=finger',
23 'dict': {'chips':'ahoy', 'vienna':'finger'},
24 'repr': "<SimpleCookie: chips='ahoy' vienna='finger'>",
25 'output': 'Set-Cookie: chips=ahoy\nSet-Cookie: vienna=finger'},
Andrew M. Kuchlingcdec8c72000-08-19 15:21:12 +000026
Georg Brandl76e155a2010-07-31 21:04:00 +000027 {'data': 'keebler="E=mc2; L=\\"Loves\\"; fudge=\\012;"',
28 'dict': {'keebler' : 'E=mc2; L="Loves"; fudge=\012;'},
29 'repr': '''<SimpleCookie: keebler='E=mc2; L="Loves"; fudge=\\n;'>''',
30 'output': 'Set-Cookie: keebler="E=mc2; L=\\"Loves\\"; fudge=\\012;"'},
Andrew M. Kuchling8b94b1c2001-02-21 01:17:54 +000031
Thomas Wouters89f507f2006-12-13 04:49:30 +000032 # Check illegal cookies that have an '=' char in an unquoted value
Georg Brandl76e155a2010-07-31 21:04:00 +000033 {'data': 'keebler=E=mc2',
34 'dict': {'keebler' : 'E=mc2'},
35 'repr': "<SimpleCookie: keebler='E=mc2'>",
36 'output': 'Set-Cookie: keebler=E=mc2'},
Senthil Kumaran3a441c12012-04-22 09:19:04 +080037
38 # Cookies with ':' character in their name. Though not mentioned in
39 # RFC, servers / browsers allow it.
40
41 {'data': 'key:term=value:term',
42 'dict': {'key:term' : 'value:term'},
43 'repr': "<SimpleCookie: key:term='value:term'>",
44 'output': 'Set-Cookie: key:term=value:term'},
45
Thomas Wouters89f507f2006-12-13 04:49:30 +000046 ]
Andrew M. Kuchlingcdec8c72000-08-19 15:21:12 +000047
Thomas Wouters89f507f2006-12-13 04:49:30 +000048 for case in cases:
Georg Brandl24420152008-05-26 16:32:26 +000049 C = cookies.SimpleCookie()
Thomas Wouters89f507f2006-12-13 04:49:30 +000050 C.load(case['data'])
51 self.assertEqual(repr(C), case['repr'])
52 self.assertEqual(C.output(sep='\n'), case['output'])
Guido van Rossumcc2b0162007-02-11 06:12:03 +000053 for k, v in sorted(case['dict'].items()):
Thomas Wouters89f507f2006-12-13 04:49:30 +000054 self.assertEqual(C[k].value, v)
Andrew M. Kuchlingcdec8c72000-08-19 15:21:12 +000055
Thomas Wouters89f507f2006-12-13 04:49:30 +000056 def test_load(self):
Georg Brandl24420152008-05-26 16:32:26 +000057 C = cookies.SimpleCookie()
Thomas Wouters89f507f2006-12-13 04:49:30 +000058 C.load('Customer="WILE_E_COYOTE"; Version=1; Path=/acme')
Andrew M. Kuchlingcdec8c72000-08-19 15:21:12 +000059
Thomas Wouters89f507f2006-12-13 04:49:30 +000060 self.assertEqual(C['Customer'].value, 'WILE_E_COYOTE')
61 self.assertEqual(C['Customer']['version'], '1')
62 self.assertEqual(C['Customer']['path'], '/acme')
Moshe Zadka514a1022000-08-19 15:57:33 +000063
Thomas Wouters89f507f2006-12-13 04:49:30 +000064 self.assertEqual(C.output(['path']),
65 'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme')
Senthil Kumaran3e2ea792009-04-02 03:02:03 +000066 self.assertEqual(C.js_output(), r"""
Thomas Wouters89f507f2006-12-13 04:49:30 +000067 <script type="text/javascript">
68 <!-- begin hiding
Senthil Kumaran3e2ea792009-04-02 03:02:03 +000069 document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1";
Thomas Wouters89f507f2006-12-13 04:49:30 +000070 // end hiding -->
71 </script>
72 """)
Senthil Kumaran3e2ea792009-04-02 03:02:03 +000073 self.assertEqual(C.js_output(['path']), r"""
Thomas Wouters89f507f2006-12-13 04:49:30 +000074 <script type="text/javascript">
75 <!-- begin hiding
Senthil Kumaran3e2ea792009-04-02 03:02:03 +000076 document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme";
Thomas Wouters89f507f2006-12-13 04:49:30 +000077 // end hiding -->
78 </script>
79 """)
Moshe Zadka514a1022000-08-19 15:57:33 +000080
R. David Murraye05ca2a2010-12-28 18:54:13 +000081 def test_extended_encode(self):
82 # Issue 9824: some browsers don't follow the standard; we now
83 # encode , and ; to keep them from tripping up.
84 C = cookies.SimpleCookie()
85 C['val'] = "some,funky;stuff"
86 self.assertEqual(C.output(['val']),
87 'Set-Cookie: val="some\\054funky\\073stuff"')
88
Georg Brandl76e155a2010-07-31 21:04:00 +000089 def test_special_attrs(self):
90 # 'expires'
91 C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"')
92 C['Customer']['expires'] = 0
93 # can't test exact output, it always depends on current date/time
94 self.assertTrue(C.output().endswith('GMT'))
95
Georg Brandlb16e38b2010-08-01 09:06:34 +000096 # loading 'expires'
97 C = cookies.SimpleCookie()
Senthil Kumaran00c2ec22012-05-20 12:05:16 +080098 C.load('Customer="W"; expires=Wed, 01 Jan 2010 00:00:00 GMT')
Georg Brandlb16e38b2010-08-01 09:06:34 +000099 self.assertEqual(C['Customer']['expires'],
Senthil Kumaran00c2ec22012-05-20 12:05:16 +0800100 'Wed, 01 Jan 2010 00:00:00 GMT')
Georg Brandlb16e38b2010-08-01 09:06:34 +0000101 C = cookies.SimpleCookie()
Senthil Kumaran00c2ec22012-05-20 12:05:16 +0800102 C.load('Customer="W"; expires=Wed, 01 Jan 98 00:00:00 GMT')
Georg Brandlb16e38b2010-08-01 09:06:34 +0000103 self.assertEqual(C['Customer']['expires'],
Senthil Kumaran00c2ec22012-05-20 12:05:16 +0800104 'Wed, 01 Jan 98 00:00:00 GMT')
Georg Brandlb16e38b2010-08-01 09:06:34 +0000105
Georg Brandl76e155a2010-07-31 21:04:00 +0000106 # 'max-age'
107 C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"')
108 C['Customer']['max-age'] = 10
109 self.assertEqual(C.output(),
110 'Set-Cookie: Customer="WILE_E_COYOTE"; Max-Age=10')
111
R David Murraycd0f74b2013-08-25 11:09:02 -0400112 def test_set_secure_httponly_attrs(self):
Georg Brandl76e155a2010-07-31 21:04:00 +0000113 C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"')
114 C['Customer']['secure'] = True
115 C['Customer']['httponly'] = True
116 self.assertEqual(C.output(),
117 'Set-Cookie: Customer="WILE_E_COYOTE"; httponly; secure')
118
R David Murraycd0f74b2013-08-25 11:09:02 -0400119 def test_secure_httponly_false_if_not_present(self):
120 C = cookies.SimpleCookie()
121 C.load('eggs=scrambled; Path=/bacon')
122 self.assertFalse(C['eggs']['httponly'])
123 self.assertFalse(C['eggs']['secure'])
124
125 def test_secure_httponly_true_if_present(self):
126 # Issue 16611
127 C = cookies.SimpleCookie()
128 C.load('eggs=scrambled; httponly; secure; Path=/bacon')
129 self.assertTrue(C['eggs']['httponly'])
130 self.assertTrue(C['eggs']['secure'])
131
132 def test_secure_httponly_true_if_have_value(self):
133 # This isn't really valid, but demonstrates what the current code
134 # is expected to do in this case.
135 C = cookies.SimpleCookie()
136 C.load('eggs=scrambled; httponly=foo; secure=bar; Path=/bacon')
137 self.assertTrue(C['eggs']['httponly'])
138 self.assertTrue(C['eggs']['secure'])
139 # Here is what it actually does; don't depend on this behavior. These
140 # checks are testing backward compatibility for issue 16611.
141 self.assertEqual(C['eggs']['httponly'], 'foo')
142 self.assertEqual(C['eggs']['secure'], 'bar')
143
144 def test_bad_attrs(self):
145 # issue 16611: make sure we don't break backward compatibility.
146 C = cookies.SimpleCookie()
147 C.load('cookie=with; invalid; version; second=cookie;')
148 self.assertEqual(C.output(),
149 'Set-Cookie: cookie=with\r\nSet-Cookie: second=cookie')
150
151 def test_extra_spaces(self):
152 C = cookies.SimpleCookie()
153 C.load('eggs = scrambled ; secure ; path = bar ; foo=foo ')
154 self.assertEqual(C.output(),
155 'Set-Cookie: eggs=scrambled; Path=bar; secure\r\nSet-Cookie: foo=foo')
156
Thomas Wouters89f507f2006-12-13 04:49:30 +0000157 def test_quoted_meta(self):
158 # Try cookie with quoted meta-data
Georg Brandl24420152008-05-26 16:32:26 +0000159 C = cookies.SimpleCookie()
Thomas Wouters89f507f2006-12-13 04:49:30 +0000160 C.load('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"')
161 self.assertEqual(C['Customer'].value, 'WILE_E_COYOTE')
162 self.assertEqual(C['Customer']['version'], '1')
163 self.assertEqual(C['Customer']['path'], '/acme')
Tim Peterseb26f952001-04-06 21:20:58 +0000164
Georg Brandl76e155a2010-07-31 21:04:00 +0000165 self.assertEqual(C.output(['path']),
166 'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme')
167 self.assertEqual(C.js_output(), r"""
168 <script type="text/javascript">
169 <!-- begin hiding
170 document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1";
171 // end hiding -->
172 </script>
173 """)
174 self.assertEqual(C.js_output(['path']), r"""
175 <script type="text/javascript">
176 <!-- begin hiding
177 document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme";
178 // end hiding -->
179 </script>
180 """)
181
182class MorselTests(unittest.TestCase):
183 """Tests for the Morsel object."""
184
185 def test_reserved_keys(self):
186 M = cookies.Morsel()
187 # tests valid and invalid reserved keys for Morsels
188 for i in M._reserved:
189 # Test that all valid keys are reported as reserved and set them
190 self.assertTrue(M.isReservedKey(i))
191 M[i] = '%s_value' % i
192 for i in M._reserved:
193 # Test that valid key values come out fine
194 self.assertEqual(M[i], '%s_value' % i)
195 for i in "the holy hand grenade".split():
196 # Test that invalid keys raise CookieError
197 self.assertRaises(cookies.CookieError,
198 M.__setitem__, i, '%s_value' % i)
199
200 def test_setter(self):
201 M = cookies.Morsel()
202 # tests the .set method to set keys and their values
203 for i in M._reserved:
204 # Makes sure that all reserved keys can't be set this way
205 self.assertRaises(cookies.CookieError,
206 M.set, i, '%s_value' % i, '%s_value' % i)
207 for i in "thou cast _the- !holy! ^hand| +*grenade~".split():
208 # Try typical use case. Setting decent values.
209 # Check output and js_output.
210 M['path'] = '/foo' # Try a reserved key as well
211 M.set(i, "%s_val" % i, "%s_coded_val" % i)
212 self.assertEqual(
213 M.output(),
214 "Set-Cookie: %s=%s; Path=/foo" % (i, "%s_coded_val" % i))
215 expected_js_output = """
216 <script type="text/javascript">
217 <!-- begin hiding
218 document.cookie = "%s=%s; Path=/foo";
219 // end hiding -->
220 </script>
221 """ % (i, "%s_coded_val" % i)
222 self.assertEqual(M.js_output(), expected_js_output)
223 for i in ["foo bar", "foo@bar"]:
224 # Try some illegal characters
225 self.assertRaises(cookies.CookieError,
226 M.set, i, '%s_value' % i, '%s_value' % i)
227
228
Thomas Wouters89f507f2006-12-13 04:49:30 +0000229def test_main():
Georg Brandl76e155a2010-07-31 21:04:00 +0000230 run_unittest(CookieTests, MorselTests)
Georg Brandl24420152008-05-26 16:32:26 +0000231 run_doctest(cookies)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000232
233if __name__ == '__main__':
234 test_main()