ยปCore Development>Code coverage>Lib/test/test_http_cookies.py

Python code coverage for Lib/test/test_http_cookies.py

#countcontent
1n/a# Simple test suite for http/cookies.py
2n/a
3n/aimport copy
4n/afrom test.support import run_unittest, run_doctest, check_warnings
5n/aimport unittest
6n/afrom http import cookies
7n/aimport pickle
8n/aimport warnings
9n/a
10n/aclass CookieTests(unittest.TestCase):
11n/a
12n/a def test_basic(self):
13n/a cases = [
14n/a {'data': 'chips=ahoy; vienna=finger',
15n/a 'dict': {'chips':'ahoy', 'vienna':'finger'},
16n/a 'repr': "<SimpleCookie: chips='ahoy' vienna='finger'>",
17n/a 'output': 'Set-Cookie: chips=ahoy\nSet-Cookie: vienna=finger'},
18n/a
19n/a {'data': 'keebler="E=mc2; L=\\"Loves\\"; fudge=\\012;"',
20n/a 'dict': {'keebler' : 'E=mc2; L="Loves"; fudge=\012;'},
21n/a 'repr': '''<SimpleCookie: keebler='E=mc2; L="Loves"; fudge=\\n;'>''',
22n/a 'output': 'Set-Cookie: keebler="E=mc2; L=\\"Loves\\"; fudge=\\012;"'},
23n/a
24n/a # Check illegal cookies that have an '=' char in an unquoted value
25n/a {'data': 'keebler=E=mc2',
26n/a 'dict': {'keebler' : 'E=mc2'},
27n/a 'repr': "<SimpleCookie: keebler='E=mc2'>",
28n/a 'output': 'Set-Cookie: keebler=E=mc2'},
29n/a
30n/a # Cookies with ':' character in their name. Though not mentioned in
31n/a # RFC, servers / browsers allow it.
32n/a
33n/a {'data': 'key:term=value:term',
34n/a 'dict': {'key:term' : 'value:term'},
35n/a 'repr': "<SimpleCookie: key:term='value:term'>",
36n/a 'output': 'Set-Cookie: key:term=value:term'},
37n/a
38n/a # issue22931 - Adding '[' and ']' as valid characters in cookie
39n/a # values as defined in RFC 6265
40n/a {
41n/a 'data': 'a=b; c=[; d=r; f=h',
42n/a 'dict': {'a':'b', 'c':'[', 'd':'r', 'f':'h'},
43n/a 'repr': "<SimpleCookie: a='b' c='[' d='r' f='h'>",
44n/a 'output': '\n'.join((
45n/a 'Set-Cookie: a=b',
46n/a 'Set-Cookie: c=[',
47n/a 'Set-Cookie: d=r',
48n/a 'Set-Cookie: f=h'
49n/a ))
50n/a }
51n/a ]
52n/a
53n/a for case in cases:
54n/a C = cookies.SimpleCookie()
55n/a C.load(case['data'])
56n/a self.assertEqual(repr(C), case['repr'])
57n/a self.assertEqual(C.output(sep='\n'), case['output'])
58n/a for k, v in sorted(case['dict'].items()):
59n/a self.assertEqual(C[k].value, v)
60n/a
61n/a def test_load(self):
62n/a C = cookies.SimpleCookie()
63n/a C.load('Customer="WILE_E_COYOTE"; Version=1; Path=/acme')
64n/a
65n/a self.assertEqual(C['Customer'].value, 'WILE_E_COYOTE')
66n/a self.assertEqual(C['Customer']['version'], '1')
67n/a self.assertEqual(C['Customer']['path'], '/acme')
68n/a
69n/a self.assertEqual(C.output(['path']),
70n/a 'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme')
71n/a self.assertEqual(C.js_output(), r"""
72n/a <script type="text/javascript">
73n/a <!-- begin hiding
74n/a document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1";
75n/a // end hiding -->
76n/a </script>
77n/a """)
78n/a self.assertEqual(C.js_output(['path']), r"""
79n/a <script type="text/javascript">
80n/a <!-- begin hiding
81n/a document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme";
82n/a // end hiding -->
83n/a </script>
84n/a """)
85n/a
86n/a def test_extended_encode(self):
87n/a # Issue 9824: some browsers don't follow the standard; we now
88n/a # encode , and ; to keep them from tripping up.
89n/a C = cookies.SimpleCookie()
90n/a C['val'] = "some,funky;stuff"
91n/a self.assertEqual(C.output(['val']),
92n/a 'Set-Cookie: val="some\\054funky\\073stuff"')
93n/a
94n/a def test_special_attrs(self):
95n/a # 'expires'
96n/a C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"')
97n/a C['Customer']['expires'] = 0
98n/a # can't test exact output, it always depends on current date/time
99n/a self.assertTrue(C.output().endswith('GMT'))
100n/a
101n/a # loading 'expires'
102n/a C = cookies.SimpleCookie()
103n/a C.load('Customer="W"; expires=Wed, 01 Jan 2010 00:00:00 GMT')
104n/a self.assertEqual(C['Customer']['expires'],
105n/a 'Wed, 01 Jan 2010 00:00:00 GMT')
106n/a C = cookies.SimpleCookie()
107n/a C.load('Customer="W"; expires=Wed, 01 Jan 98 00:00:00 GMT')
108n/a self.assertEqual(C['Customer']['expires'],
109n/a 'Wed, 01 Jan 98 00:00:00 GMT')
110n/a
111n/a # 'max-age'
112n/a C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"')
113n/a C['Customer']['max-age'] = 10
114n/a self.assertEqual(C.output(),
115n/a 'Set-Cookie: Customer="WILE_E_COYOTE"; Max-Age=10')
116n/a
117n/a def test_set_secure_httponly_attrs(self):
118n/a C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"')
119n/a C['Customer']['secure'] = True
120n/a C['Customer']['httponly'] = True
121n/a self.assertEqual(C.output(),
122n/a 'Set-Cookie: Customer="WILE_E_COYOTE"; HttpOnly; Secure')
123n/a
124n/a def test_secure_httponly_false_if_not_present(self):
125n/a C = cookies.SimpleCookie()
126n/a C.load('eggs=scrambled; Path=/bacon')
127n/a self.assertFalse(C['eggs']['httponly'])
128n/a self.assertFalse(C['eggs']['secure'])
129n/a
130n/a def test_secure_httponly_true_if_present(self):
131n/a # Issue 16611
132n/a C = cookies.SimpleCookie()
133n/a C.load('eggs=scrambled; httponly; secure; Path=/bacon')
134n/a self.assertTrue(C['eggs']['httponly'])
135n/a self.assertTrue(C['eggs']['secure'])
136n/a
137n/a def test_secure_httponly_true_if_have_value(self):
138n/a # This isn't really valid, but demonstrates what the current code
139n/a # is expected to do in this case.
140n/a C = cookies.SimpleCookie()
141n/a C.load('eggs=scrambled; httponly=foo; secure=bar; Path=/bacon')
142n/a self.assertTrue(C['eggs']['httponly'])
143n/a self.assertTrue(C['eggs']['secure'])
144n/a # Here is what it actually does; don't depend on this behavior. These
145n/a # checks are testing backward compatibility for issue 16611.
146n/a self.assertEqual(C['eggs']['httponly'], 'foo')
147n/a self.assertEqual(C['eggs']['secure'], 'bar')
148n/a
149n/a def test_extra_spaces(self):
150n/a C = cookies.SimpleCookie()
151n/a C.load('eggs = scrambled ; secure ; path = bar ; foo=foo ')
152n/a self.assertEqual(C.output(),
153n/a 'Set-Cookie: eggs=scrambled; Path=bar; Secure\r\nSet-Cookie: foo=foo')
154n/a
155n/a def test_quoted_meta(self):
156n/a # Try cookie with quoted meta-data
157n/a C = cookies.SimpleCookie()
158n/a C.load('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"')
159n/a self.assertEqual(C['Customer'].value, 'WILE_E_COYOTE')
160n/a self.assertEqual(C['Customer']['version'], '1')
161n/a self.assertEqual(C['Customer']['path'], '/acme')
162n/a
163n/a self.assertEqual(C.output(['path']),
164n/a 'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme')
165n/a self.assertEqual(C.js_output(), r"""
166n/a <script type="text/javascript">
167n/a <!-- begin hiding
168n/a document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1";
169n/a // end hiding -->
170n/a </script>
171n/a """)
172n/a self.assertEqual(C.js_output(['path']), r"""
173n/a <script type="text/javascript">
174n/a <!-- begin hiding
175n/a document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme";
176n/a // end hiding -->
177n/a </script>
178n/a """)
179n/a
180n/a def test_invalid_cookies(self):
181n/a # Accepting these could be a security issue
182n/a C = cookies.SimpleCookie()
183n/a for s in (']foo=x', '[foo=x', 'blah]foo=x', 'blah[foo=x',
184n/a 'Set-Cookie: foo=bar', 'Set-Cookie: foo',
185n/a 'foo=bar; baz', 'baz; foo=bar',
186n/a 'secure;foo=bar', 'Version=1;foo=bar'):
187n/a C.load(s)
188n/a self.assertEqual(dict(C), {})
189n/a self.assertEqual(C.output(), '')
190n/a
191n/a def test_pickle(self):
192n/a rawdata = 'Customer="WILE_E_COYOTE"; Path=/acme; Version=1'
193n/a expected_output = 'Set-Cookie: %s' % rawdata
194n/a
195n/a C = cookies.SimpleCookie()
196n/a C.load(rawdata)
197n/a self.assertEqual(C.output(), expected_output)
198n/a
199n/a for proto in range(pickle.HIGHEST_PROTOCOL + 1):
200n/a with self.subTest(proto=proto):
201n/a C1 = pickle.loads(pickle.dumps(C, protocol=proto))
202n/a self.assertEqual(C1.output(), expected_output)
203n/a
204n/a def test_illegal_chars(self):
205n/a rawdata = "a=b; c,d=e"
206n/a C = cookies.SimpleCookie()
207n/a with self.assertRaises(cookies.CookieError):
208n/a C.load(rawdata)
209n/a
210n/a
211n/aclass MorselTests(unittest.TestCase):
212n/a """Tests for the Morsel object."""
213n/a
214n/a def test_defaults(self):
215n/a morsel = cookies.Morsel()
216n/a self.assertIsNone(morsel.key)
217n/a self.assertIsNone(morsel.value)
218n/a self.assertIsNone(morsel.coded_value)
219n/a self.assertEqual(morsel.keys(), cookies.Morsel._reserved.keys())
220n/a for key, val in morsel.items():
221n/a self.assertEqual(val, '', key)
222n/a
223n/a def test_reserved_keys(self):
224n/a M = cookies.Morsel()
225n/a # tests valid and invalid reserved keys for Morsels
226n/a for i in M._reserved:
227n/a # Test that all valid keys are reported as reserved and set them
228n/a self.assertTrue(M.isReservedKey(i))
229n/a M[i] = '%s_value' % i
230n/a for i in M._reserved:
231n/a # Test that valid key values come out fine
232n/a self.assertEqual(M[i], '%s_value' % i)
233n/a for i in "the holy hand grenade".split():
234n/a # Test that invalid keys raise CookieError
235n/a self.assertRaises(cookies.CookieError,
236n/a M.__setitem__, i, '%s_value' % i)
237n/a
238n/a def test_setter(self):
239n/a M = cookies.Morsel()
240n/a # tests the .set method to set keys and their values
241n/a for i in M._reserved:
242n/a # Makes sure that all reserved keys can't be set this way
243n/a self.assertRaises(cookies.CookieError,
244n/a M.set, i, '%s_value' % i, '%s_value' % i)
245n/a for i in "thou cast _the- !holy! ^hand| +*grenade~".split():
246n/a # Try typical use case. Setting decent values.
247n/a # Check output and js_output.
248n/a M['path'] = '/foo' # Try a reserved key as well
249n/a M.set(i, "%s_val" % i, "%s_coded_val" % i)
250n/a self.assertEqual(M.key, i)
251n/a self.assertEqual(M.value, "%s_val" % i)
252n/a self.assertEqual(M.coded_value, "%s_coded_val" % i)
253n/a self.assertEqual(
254n/a M.output(),
255n/a "Set-Cookie: %s=%s; Path=/foo" % (i, "%s_coded_val" % i))
256n/a expected_js_output = """
257n/a <script type="text/javascript">
258n/a <!-- begin hiding
259n/a document.cookie = "%s=%s; Path=/foo";
260n/a // end hiding -->
261n/a </script>
262n/a """ % (i, "%s_coded_val" % i)
263n/a self.assertEqual(M.js_output(), expected_js_output)
264n/a for i in ["foo bar", "foo@bar"]:
265n/a # Try some illegal characters
266n/a self.assertRaises(cookies.CookieError,
267n/a M.set, i, '%s_value' % i, '%s_value' % i)
268n/a
269n/a def test_set_properties(self):
270n/a morsel = cookies.Morsel()
271n/a with self.assertRaises(AttributeError):
272n/a morsel.key = ''
273n/a with self.assertRaises(AttributeError):
274n/a morsel.value = ''
275n/a with self.assertRaises(AttributeError):
276n/a morsel.coded_value = ''
277n/a
278n/a def test_eq(self):
279n/a base_case = ('key', 'value', '"value"')
280n/a attribs = {
281n/a 'path': '/',
282n/a 'comment': 'foo',
283n/a 'domain': 'example.com',
284n/a 'version': 2,
285n/a }
286n/a morsel_a = cookies.Morsel()
287n/a morsel_a.update(attribs)
288n/a morsel_a.set(*base_case)
289n/a morsel_b = cookies.Morsel()
290n/a morsel_b.update(attribs)
291n/a morsel_b.set(*base_case)
292n/a self.assertTrue(morsel_a == morsel_b)
293n/a self.assertFalse(morsel_a != morsel_b)
294n/a cases = (
295n/a ('key', 'value', 'mismatch'),
296n/a ('key', 'mismatch', '"value"'),
297n/a ('mismatch', 'value', '"value"'),
298n/a )
299n/a for case_b in cases:
300n/a with self.subTest(case_b):
301n/a morsel_b = cookies.Morsel()
302n/a morsel_b.update(attribs)
303n/a morsel_b.set(*case_b)
304n/a self.assertFalse(morsel_a == morsel_b)
305n/a self.assertTrue(morsel_a != morsel_b)
306n/a
307n/a morsel_b = cookies.Morsel()
308n/a morsel_b.update(attribs)
309n/a morsel_b.set(*base_case)
310n/a morsel_b['comment'] = 'bar'
311n/a self.assertFalse(morsel_a == morsel_b)
312n/a self.assertTrue(morsel_a != morsel_b)
313n/a
314n/a # test mismatched types
315n/a self.assertFalse(cookies.Morsel() == 1)
316n/a self.assertTrue(cookies.Morsel() != 1)
317n/a self.assertFalse(cookies.Morsel() == '')
318n/a self.assertTrue(cookies.Morsel() != '')
319n/a items = list(cookies.Morsel().items())
320n/a self.assertFalse(cookies.Morsel() == items)
321n/a self.assertTrue(cookies.Morsel() != items)
322n/a
323n/a # morsel/dict
324n/a morsel = cookies.Morsel()
325n/a morsel.set(*base_case)
326n/a morsel.update(attribs)
327n/a self.assertTrue(morsel == dict(morsel))
328n/a self.assertFalse(morsel != dict(morsel))
329n/a
330n/a def test_copy(self):
331n/a morsel_a = cookies.Morsel()
332n/a morsel_a.set('foo', 'bar', 'baz')
333n/a morsel_a.update({
334n/a 'version': 2,
335n/a 'comment': 'foo',
336n/a })
337n/a morsel_b = morsel_a.copy()
338n/a self.assertIsInstance(morsel_b, cookies.Morsel)
339n/a self.assertIsNot(morsel_a, morsel_b)
340n/a self.assertEqual(morsel_a, morsel_b)
341n/a
342n/a morsel_b = copy.copy(morsel_a)
343n/a self.assertIsInstance(morsel_b, cookies.Morsel)
344n/a self.assertIsNot(morsel_a, morsel_b)
345n/a self.assertEqual(morsel_a, morsel_b)
346n/a
347n/a def test_setitem(self):
348n/a morsel = cookies.Morsel()
349n/a morsel['expires'] = 0
350n/a self.assertEqual(morsel['expires'], 0)
351n/a morsel['Version'] = 2
352n/a self.assertEqual(morsel['version'], 2)
353n/a morsel['DOMAIN'] = 'example.com'
354n/a self.assertEqual(morsel['domain'], 'example.com')
355n/a
356n/a with self.assertRaises(cookies.CookieError):
357n/a morsel['invalid'] = 'value'
358n/a self.assertNotIn('invalid', morsel)
359n/a
360n/a def test_setdefault(self):
361n/a morsel = cookies.Morsel()
362n/a morsel.update({
363n/a 'domain': 'example.com',
364n/a 'version': 2,
365n/a })
366n/a # this shouldn't override the default value
367n/a self.assertEqual(morsel.setdefault('expires', 'value'), '')
368n/a self.assertEqual(morsel['expires'], '')
369n/a self.assertEqual(morsel.setdefault('Version', 1), 2)
370n/a self.assertEqual(morsel['version'], 2)
371n/a self.assertEqual(morsel.setdefault('DOMAIN', 'value'), 'example.com')
372n/a self.assertEqual(morsel['domain'], 'example.com')
373n/a
374n/a with self.assertRaises(cookies.CookieError):
375n/a morsel.setdefault('invalid', 'value')
376n/a self.assertNotIn('invalid', morsel)
377n/a
378n/a def test_update(self):
379n/a attribs = {'expires': 1, 'Version': 2, 'DOMAIN': 'example.com'}
380n/a # test dict update
381n/a morsel = cookies.Morsel()
382n/a morsel.update(attribs)
383n/a self.assertEqual(morsel['expires'], 1)
384n/a self.assertEqual(morsel['version'], 2)
385n/a self.assertEqual(morsel['domain'], 'example.com')
386n/a # test iterable update
387n/a morsel = cookies.Morsel()
388n/a morsel.update(list(attribs.items()))
389n/a self.assertEqual(morsel['expires'], 1)
390n/a self.assertEqual(morsel['version'], 2)
391n/a self.assertEqual(morsel['domain'], 'example.com')
392n/a # test iterator update
393n/a morsel = cookies.Morsel()
394n/a morsel.update((k, v) for k, v in attribs.items())
395n/a self.assertEqual(morsel['expires'], 1)
396n/a self.assertEqual(morsel['version'], 2)
397n/a self.assertEqual(morsel['domain'], 'example.com')
398n/a
399n/a with self.assertRaises(cookies.CookieError):
400n/a morsel.update({'invalid': 'value'})
401n/a self.assertNotIn('invalid', morsel)
402n/a self.assertRaises(TypeError, morsel.update)
403n/a self.assertRaises(TypeError, morsel.update, 0)
404n/a
405n/a def test_pickle(self):
406n/a morsel_a = cookies.Morsel()
407n/a morsel_a.set('foo', 'bar', 'baz')
408n/a morsel_a.update({
409n/a 'version': 2,
410n/a 'comment': 'foo',
411n/a })
412n/a for proto in range(pickle.HIGHEST_PROTOCOL + 1):
413n/a with self.subTest(proto=proto):
414n/a morsel_b = pickle.loads(pickle.dumps(morsel_a, proto))
415n/a self.assertIsInstance(morsel_b, cookies.Morsel)
416n/a self.assertEqual(morsel_b, morsel_a)
417n/a self.assertEqual(str(morsel_b), str(morsel_a))
418n/a
419n/a def test_repr(self):
420n/a morsel = cookies.Morsel()
421n/a self.assertEqual(repr(morsel), '<Morsel: None=None>')
422n/a self.assertEqual(str(morsel), 'Set-Cookie: None=None')
423n/a morsel.set('key', 'val', 'coded_val')
424n/a self.assertEqual(repr(morsel), '<Morsel: key=coded_val>')
425n/a self.assertEqual(str(morsel), 'Set-Cookie: key=coded_val')
426n/a morsel.update({
427n/a 'path': '/',
428n/a 'comment': 'foo',
429n/a 'domain': 'example.com',
430n/a 'max-age': 0,
431n/a 'secure': 0,
432n/a 'version': 1,
433n/a })
434n/a self.assertEqual(repr(morsel),
435n/a '<Morsel: key=coded_val; Comment=foo; Domain=example.com; '
436n/a 'Max-Age=0; Path=/; Version=1>')
437n/a self.assertEqual(str(morsel),
438n/a 'Set-Cookie: key=coded_val; Comment=foo; Domain=example.com; '
439n/a 'Max-Age=0; Path=/; Version=1')
440n/a morsel['secure'] = True
441n/a morsel['httponly'] = 1
442n/a self.assertEqual(repr(morsel),
443n/a '<Morsel: key=coded_val; Comment=foo; Domain=example.com; '
444n/a 'HttpOnly; Max-Age=0; Path=/; Secure; Version=1>')
445n/a self.assertEqual(str(morsel),
446n/a 'Set-Cookie: key=coded_val; Comment=foo; Domain=example.com; '
447n/a 'HttpOnly; Max-Age=0; Path=/; Secure; Version=1')
448n/a
449n/a morsel = cookies.Morsel()
450n/a morsel.set('key', 'val', 'coded_val')
451n/a morsel['expires'] = 0
452n/a self.assertRegex(repr(morsel),
453n/a r'<Morsel: key=coded_val; '
454n/a r'expires=\w+, \d+ \w+ \d+ \d+:\d+:\d+ \w+>')
455n/a self.assertRegex(str(morsel),
456n/a r'Set-Cookie: key=coded_val; '
457n/a r'expires=\w+, \d+ \w+ \d+ \d+:\d+:\d+ \w+')
458n/a
459n/adef test_main():
460n/a run_unittest(CookieTests, MorselTests)
461n/a run_doctest(cookies)
462n/a
463n/aif __name__ == '__main__':
464n/a test_main()