Imported Upstream version 12.1.0
[contrib/python-twisted.git] / twisted / web / test / test_http_headers.py
1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 Tests for L{twisted.web.http_headers}.
6 """
7
8 import sys
9
10 from twisted.python.compat import set
11 from twisted.trial.unittest import TestCase
12 from twisted.web.http_headers import _DictHeaders, Headers
13
14
15 class HeadersTests(TestCase):
16     """
17     Tests for L{Headers}.
18     """
19     def test_initializer(self):
20         """
21         The header values passed to L{Headers.__init__} can be retrieved via
22         L{Headers.getRawHeaders}.
23         """
24         h = Headers({'Foo': ['bar']})
25         self.assertEqual(h.getRawHeaders('foo'), ['bar'])
26
27
28     def test_setRawHeaders(self):
29         """
30         L{Headers.setRawHeaders} sets the header values for the given
31         header name to the sequence of string values.
32         """
33         rawValue = ["value1", "value2"]
34         h = Headers()
35         h.setRawHeaders("test", rawValue)
36         self.assertTrue(h.hasHeader("test"))
37         self.assertTrue(h.hasHeader("Test"))
38         self.assertEqual(h.getRawHeaders("test"), rawValue)
39
40
41     def test_rawHeadersTypeChecking(self):
42         """
43         L{Headers.setRawHeaders} requires values to be of type list.
44         """
45         h = Headers()
46         self.assertRaises(TypeError, h.setRawHeaders, {'Foo': 'bar'})
47
48
49     def test_addRawHeader(self):
50         """
51         L{Headers.addRawHeader} adds a new value for a given header.
52         """
53         h = Headers()
54         h.addRawHeader("test", "lemur")
55         self.assertEqual(h.getRawHeaders("test"), ["lemur"])
56         h.addRawHeader("test", "panda")
57         self.assertEqual(h.getRawHeaders("test"), ["lemur", "panda"])
58
59
60     def test_getRawHeadersNoDefault(self):
61         """
62         L{Headers.getRawHeaders} returns C{None} if the header is not found and
63         no default is specified.
64         """
65         self.assertIdentical(Headers().getRawHeaders("test"), None)
66
67
68     def test_getRawHeadersDefaultValue(self):
69         """
70         L{Headers.getRawHeaders} returns the specified default value when no
71         header is found.
72         """
73         h = Headers()
74         default = object()
75         self.assertIdentical(h.getRawHeaders("test", default), default)
76
77
78     def test_getRawHeaders(self):
79         """
80         L{Headers.getRawHeaders} returns the values which have been set for a
81         given header.
82         """
83         h = Headers()
84         h.setRawHeaders("test", ["lemur"])
85         self.assertEqual(h.getRawHeaders("test"), ["lemur"])
86         self.assertEqual(h.getRawHeaders("Test"), ["lemur"])
87
88
89     def test_hasHeaderTrue(self):
90         """
91         Check that L{Headers.hasHeader} returns C{True} when the given header
92         is found.
93         """
94         h = Headers()
95         h.setRawHeaders("test", ["lemur"])
96         self.assertTrue(h.hasHeader("test"))
97         self.assertTrue(h.hasHeader("Test"))
98
99
100     def test_hasHeaderFalse(self):
101         """
102         L{Headers.hasHeader} returns C{False} when the given header is not
103         found.
104         """
105         self.assertFalse(Headers().hasHeader("test"))
106
107
108     def test_removeHeader(self):
109         """
110         Check that L{Headers.removeHeader} removes the given header.
111         """
112         h = Headers()
113
114         h.setRawHeaders("foo", ["lemur"])
115         self.assertTrue(h.hasHeader("foo"))
116         h.removeHeader("foo")
117         self.assertFalse(h.hasHeader("foo"))
118
119         h.setRawHeaders("bar", ["panda"])
120         self.assertTrue(h.hasHeader("bar"))
121         h.removeHeader("Bar")
122         self.assertFalse(h.hasHeader("bar"))
123
124
125     def test_removeHeaderDoesntExist(self):
126         """
127         L{Headers.removeHeader} is a no-operation when the specified header is
128         not found.
129         """
130         h = Headers()
131         h.removeHeader("test")
132         self.assertEqual(list(h.getAllRawHeaders()), [])
133
134
135     def test_canonicalNameCaps(self):
136         """
137         L{Headers._canonicalNameCaps} returns the canonical capitalization for
138         the given header.
139         """
140         h = Headers()
141         self.assertEqual(h._canonicalNameCaps("test"), "Test")
142         self.assertEqual(h._canonicalNameCaps("test-stuff"), "Test-Stuff")
143         self.assertEqual(h._canonicalNameCaps("content-md5"), "Content-MD5")
144         self.assertEqual(h._canonicalNameCaps("dnt"), "DNT")
145         self.assertEqual(h._canonicalNameCaps("etag"), "ETag")
146         self.assertEqual(h._canonicalNameCaps("p3p"), "P3P")
147         self.assertEqual(h._canonicalNameCaps("te"), "TE")
148         self.assertEqual(h._canonicalNameCaps("www-authenticate"),
149                           "WWW-Authenticate")
150         self.assertEqual(h._canonicalNameCaps("x-xss-protection"),
151                           "X-XSS-Protection")
152
153
154     def test_getAllRawHeaders(self):
155         """
156         L{Headers.getAllRawHeaders} returns an iterable of (k, v) pairs, where
157         C{k} is the canonicalized representation of the header name, and C{v}
158         is a sequence of values.
159         """
160         h = Headers()
161         h.setRawHeaders("test", ["lemurs"])
162         h.setRawHeaders("www-authenticate", ["basic aksljdlk="])
163
164         allHeaders = set([(k, tuple(v)) for k, v in h.getAllRawHeaders()])
165
166         self.assertEqual(allHeaders,
167                           set([("WWW-Authenticate", ("basic aksljdlk=",)),
168                                ("Test", ("lemurs",))]))
169
170
171     def test_headersComparison(self):
172         """
173         A L{Headers} instance compares equal to itself and to another
174         L{Headers} instance with the same values.
175         """
176         first = Headers()
177         first.setRawHeaders("foo", ["panda"])
178         second = Headers()
179         second.setRawHeaders("foo", ["panda"])
180         third = Headers()
181         third.setRawHeaders("foo", ["lemur", "panda"])
182         self.assertEqual(first, first)
183         self.assertEqual(first, second)
184         self.assertNotEqual(first, third)
185
186
187     def test_otherComparison(self):
188         """
189         An instance of L{Headers} does not compare equal to other unrelated
190         objects.
191         """
192         h = Headers()
193         self.assertNotEqual(h, ())
194         self.assertNotEqual(h, object())
195         self.assertNotEqual(h, "foo")
196
197
198     def test_repr(self):
199         """
200         The L{repr} of a L{Headers} instance shows the names and values of all
201         the headers it contains.
202         """
203         self.assertEqual(
204             repr(Headers({"foo": ["bar", "baz"]})),
205             "Headers({'foo': ['bar', 'baz']})")
206
207
208     def test_subclassRepr(self):
209         """
210         The L{repr} of an instance of a subclass of L{Headers} uses the name
211         of the subclass instead of the string C{"Headers"}.
212         """
213         class FunnyHeaders(Headers):
214             pass
215         self.assertEqual(
216             repr(FunnyHeaders({"foo": ["bar", "baz"]})),
217             "FunnyHeaders({'foo': ['bar', 'baz']})")
218
219
220     def test_copy(self):
221         """
222         L{Headers.copy} creates a new independant copy of an existing
223         L{Headers} instance, allowing future modifications without impacts
224         between the copies.
225         """
226         h = Headers()
227         h.setRawHeaders('test', ['foo'])
228         i = h.copy()
229         self.assertEqual(i.getRawHeaders('test'), ['foo'])
230         h.addRawHeader('test', 'bar')
231         self.assertEqual(i.getRawHeaders('test'), ['foo'])
232         i.addRawHeader('test', 'baz')
233         self.assertEqual(h.getRawHeaders('test'), ['foo', 'bar'])
234
235
236
237 class HeaderDictTests(TestCase):
238     """
239     Tests for the backwards compatible C{dict} interface for L{Headers}
240     provided by L{_DictHeaders}.
241     """
242     def headers(self, **kw):
243         """
244         Create a L{Headers} instance populated with the header name/values
245         specified by C{kw} and a L{_DictHeaders} wrapped around it and return
246         them both.
247         """
248         h = Headers()
249         for k, v in kw.iteritems():
250             h.setRawHeaders(k, v)
251         return h, _DictHeaders(h)
252
253
254     def test_getItem(self):
255         """
256         L{_DictHeaders.__getitem__} returns a single header for the given name.
257         """
258         headers, wrapper = self.headers(test=["lemur"])
259         self.assertEqual(wrapper["test"], "lemur")
260
261
262     def test_getItemMultiple(self):
263         """
264         L{_DictHeaders.__getitem__} returns only the last header value for a
265         given name.
266         """
267         headers, wrapper = self.headers(test=["lemur", "panda"])
268         self.assertEqual(wrapper["test"], "panda")
269
270
271     def test_getItemMissing(self):
272         """
273         L{_DictHeaders.__getitem__} raises L{KeyError} if called with a header
274         which is not present.
275         """
276         headers, wrapper = self.headers()
277         exc = self.assertRaises(KeyError, wrapper.__getitem__, "test")
278         self.assertEqual(exc.args, ("test",))
279
280
281     def test_iteration(self):
282         """
283         L{_DictHeaders.__iter__} returns an iterator the elements of which
284         are the lowercase name of each header present.
285         """
286         headers, wrapper = self.headers(foo=["lemur", "panda"], bar=["baz"])
287         self.assertEqual(set(list(wrapper)), set(["foo", "bar"]))
288
289
290     def test_length(self):
291         """
292         L{_DictHeaders.__len__} returns the number of headers present.
293         """
294         headers, wrapper = self.headers()
295         self.assertEqual(len(wrapper), 0)
296         headers.setRawHeaders("foo", ["bar"])
297         self.assertEqual(len(wrapper), 1)
298         headers.setRawHeaders("test", ["lemur", "panda"])
299         self.assertEqual(len(wrapper), 2)
300
301
302     def test_setItem(self):
303         """
304         L{_DictHeaders.__setitem__} sets a single header value for the given
305         name.
306         """
307         headers, wrapper = self.headers()
308         wrapper["test"] = "lemur"
309         self.assertEqual(headers.getRawHeaders("test"), ["lemur"])
310
311
312     def test_setItemOverwrites(self):
313         """
314         L{_DictHeaders.__setitem__} will replace any previous header values for
315         the given name.
316         """
317         headers, wrapper = self.headers(test=["lemur", "panda"])
318         wrapper["test"] = "lemur"
319         self.assertEqual(headers.getRawHeaders("test"), ["lemur"])
320
321
322     def test_delItem(self):
323         """
324         L{_DictHeaders.__delitem__} will remove the header values for the given
325         name.
326         """
327         headers, wrapper = self.headers(test=["lemur"])
328         del wrapper["test"]
329         self.assertFalse(headers.hasHeader("test"))
330
331
332     def test_delItemMissing(self):
333         """
334         L{_DictHeaders.__delitem__} will raise L{KeyError} if the given name is
335         not present.
336         """
337         headers, wrapper = self.headers()
338         exc = self.assertRaises(KeyError, wrapper.__delitem__, "test")
339         self.assertEqual(exc.args, ("test",))
340
341
342     def test_keys(self, _method='keys', _requireList=True):
343         """
344         L{_DictHeaders.keys} will return a list of all present header names.
345         """
346         headers, wrapper = self.headers(test=["lemur"], foo=["bar"])
347         keys = getattr(wrapper, _method)()
348         if _requireList:
349             self.assertIsInstance(keys, list)
350         self.assertEqual(set(keys), set(["foo", "test"]))
351
352
353     def test_iterkeys(self):
354         """
355         L{_DictHeaders.iterkeys} will return all present header names.
356         """
357         self.test_keys('iterkeys', False)
358
359
360     def test_values(self, _method='values', _requireList=True):
361         """
362         L{_DictHeaders.values} will return a list of all present header values,
363         returning only the last value for headers with more than one.
364         """
365         headers, wrapper = self.headers(foo=["lemur"], bar=["marmot", "panda"])
366         values = getattr(wrapper, _method)()
367         if _requireList:
368             self.assertIsInstance(values, list)
369         self.assertEqual(set(values), set(["lemur", "panda"]))
370
371
372     def test_itervalues(self):
373         """
374         L{_DictHeaders.itervalues} will return all present header values,
375         returning only the last value for headers with more than one.
376         """
377         self.test_values('itervalues', False)
378
379
380     def test_items(self, _method='items', _requireList=True):
381         """
382         L{_DictHeaders.items} will return a list of all present header names
383         and values as tuples, returning only the last value for headers with
384         more than one.
385         """
386         headers, wrapper = self.headers(foo=["lemur"], bar=["marmot", "panda"])
387         items = getattr(wrapper, _method)()
388         if _requireList:
389             self.assertIsInstance(items, list)
390         self.assertEqual(set(items), set([("foo", "lemur"), ("bar", "panda")]))
391
392
393     def test_iteritems(self):
394         """
395         L{_DictHeaders.iteritems} will return all present header names and
396         values as tuples, returning only the last value for headers with more
397         than one.
398         """
399         self.test_items('iteritems', False)
400
401
402     def test_clear(self):
403         """
404         L{_DictHeaders.clear} will remove all headers.
405         """
406         headers, wrapper = self.headers(foo=["lemur"], bar=["panda"])
407         wrapper.clear()
408         self.assertEqual(list(headers.getAllRawHeaders()), [])
409
410
411     def test_copy(self):
412         """
413         L{_DictHeaders.copy} will return a C{dict} with all the same headers
414         and the last value for each.
415         """
416         headers, wrapper = self.headers(foo=["lemur", "panda"], bar=["marmot"])
417         duplicate = wrapper.copy()
418         self.assertEqual(duplicate, {"foo": "panda", "bar": "marmot"})
419
420
421     def test_get(self):
422         """
423         L{_DictHeaders.get} returns the last value for the given header name.
424         """
425         headers, wrapper = self.headers(foo=["lemur", "panda"])
426         self.assertEqual(wrapper.get("foo"), "panda")
427
428
429     def test_getMissing(self):
430         """
431         L{_DictHeaders.get} returns C{None} for a header which is not present.
432         """
433         headers, wrapper = self.headers()
434         self.assertIdentical(wrapper.get("foo"), None)
435
436
437     def test_getDefault(self):
438         """
439         L{_DictHeaders.get} returns the last value for the given header name
440         even when it is invoked with a default value.
441         """
442         headers, wrapper = self.headers(foo=["lemur"])
443         self.assertEqual(wrapper.get("foo", "bar"), "lemur")
444
445
446     def test_getDefaultMissing(self):
447         """
448         L{_DictHeaders.get} returns the default value specified if asked for a
449         header which is not present.
450         """
451         headers, wrapper = self.headers()
452         self.assertEqual(wrapper.get("foo", "bar"), "bar")
453
454
455     def test_has_key(self):
456         """
457         L{_DictHeaders.has_key} returns C{True} if the given header is present,
458         C{False} otherwise.
459         """
460         headers, wrapper = self.headers(foo=["lemur"])
461         self.assertTrue(wrapper.has_key("foo"))
462         self.assertFalse(wrapper.has_key("bar"))
463
464
465     def test_contains(self):
466         """
467         L{_DictHeaders.__contains__} returns C{True} if the given header is
468         present, C{False} otherwise.
469         """
470         headers, wrapper = self.headers(foo=["lemur"])
471         self.assertIn("foo", wrapper)
472         self.assertNotIn("bar", wrapper)
473
474
475     def test_pop(self):
476         """
477         L{_DictHeaders.pop} returns the last header value associated with the
478         given header name and removes the header.
479         """
480         headers, wrapper = self.headers(foo=["lemur", "panda"])
481         self.assertEqual(wrapper.pop("foo"), "panda")
482         self.assertIdentical(headers.getRawHeaders("foo"), None)
483
484
485     def test_popMissing(self):
486         """
487         L{_DictHeaders.pop} raises L{KeyError} if passed a header name which is
488         not present.
489         """
490         headers, wrapper = self.headers()
491         self.assertRaises(KeyError, wrapper.pop, "foo")
492
493
494     def test_popDefault(self):
495         """
496         L{_DictHeaders.pop} returns the last header value associated with the
497         given header name and removes the header, even if it is supplied with a
498         default value.
499         """
500         headers, wrapper = self.headers(foo=["lemur"])
501         self.assertEqual(wrapper.pop("foo", "bar"), "lemur")
502         self.assertIdentical(headers.getRawHeaders("foo"), None)
503
504
505     def test_popDefaultMissing(self):
506         """
507         L{_DictHeaders.pop} returns the default value is asked for a header
508         name which is not present.
509         """
510         headers, wrapper = self.headers(foo=["lemur"])
511         self.assertEqual(wrapper.pop("bar", "baz"), "baz")
512         self.assertEqual(headers.getRawHeaders("foo"), ["lemur"])
513
514
515     def test_popitem(self):
516         """
517         L{_DictHeaders.popitem} returns some header name/value pair.
518         """
519         headers, wrapper = self.headers(foo=["lemur", "panda"])
520         self.assertEqual(wrapper.popitem(), ("foo", "panda"))
521         self.assertIdentical(headers.getRawHeaders("foo"), None)
522
523
524     def test_popitemEmpty(self):
525         """
526         L{_DictHeaders.popitem} raises L{KeyError} if there are no headers
527         present.
528         """
529         headers, wrapper = self.headers()
530         self.assertRaises(KeyError, wrapper.popitem)
531
532
533     def test_update(self):
534         """
535         L{_DictHeaders.update} adds the header/value pairs in the C{dict} it is
536         passed, overriding any existing values for those headers.
537         """
538         headers, wrapper = self.headers(foo=["lemur"])
539         wrapper.update({"foo": "panda", "bar": "marmot"})
540         self.assertEqual(headers.getRawHeaders("foo"), ["panda"])
541         self.assertEqual(headers.getRawHeaders("bar"), ["marmot"])
542
543
544     def test_updateWithKeywords(self):
545         """
546         L{_DictHeaders.update} adds header names given as keyword arguments
547         with the keyword values as the header value.
548         """
549         headers, wrapper = self.headers(foo=["lemur"])
550         wrapper.update(foo="panda", bar="marmot")
551         self.assertEqual(headers.getRawHeaders("foo"), ["panda"])
552         self.assertEqual(headers.getRawHeaders("bar"), ["marmot"])
553
554     if sys.version_info < (2, 4):
555         test_updateWithKeywords.skip = (
556             "Python 2.3 does not support keyword arguments to dict.update.")
557
558
559     def test_setdefaultMissing(self):
560         """
561         If passed the name of a header which is not present,
562         L{_DictHeaders.setdefault} sets the value of the given header to the
563         specified default value and returns it.
564         """
565         headers, wrapper = self.headers(foo=["bar"])
566         self.assertEqual(wrapper.setdefault("baz", "quux"), "quux")
567         self.assertEqual(headers.getRawHeaders("foo"), ["bar"])
568         self.assertEqual(headers.getRawHeaders("baz"), ["quux"])
569
570
571     def test_setdefaultPresent(self):
572         """
573         If passed the name of a header which is present,
574         L{_DictHeaders.setdefault} makes no changes to the headers and
575         returns the last value already associated with that header.
576         """
577         headers, wrapper = self.headers(foo=["bar", "baz"])
578         self.assertEqual(wrapper.setdefault("foo", "quux"), "baz")
579         self.assertEqual(headers.getRawHeaders("foo"), ["bar", "baz"])
580
581
582     def test_setdefaultDefault(self):
583         """
584         If a value is not passed to L{_DictHeaders.setdefault}, C{None} is
585         used.
586         """
587         # This results in an invalid state for the headers, but maybe some
588         # application is doing this an intermediate step towards some other
589         # state.  Anyway, it was broken with the old implementation so it's
590         # broken with the new implementation.  Compatibility, for the win.
591         # -exarkun
592         headers, wrapper = self.headers()
593         self.assertIdentical(wrapper.setdefault("foo"), None)
594         self.assertEqual(headers.getRawHeaders("foo"), [None])
595
596
597     def test_dictComparison(self):
598         """
599         An instance of L{_DictHeaders} compares equal to a C{dict} which
600         contains the same header/value pairs.  For header names with multiple
601         values, the last value only is considered.
602         """
603         headers, wrapper = self.headers(foo=["lemur"], bar=["panda", "marmot"])
604         self.assertNotEqual(wrapper, {"foo": "lemur", "bar": "panda"})
605         self.assertEqual(wrapper, {"foo": "lemur", "bar": "marmot"})
606
607
608     def test_otherComparison(self):
609         """
610         An instance of L{_DictHeaders} does not compare equal to other
611         unrelated objects.
612         """
613         headers, wrapper = self.headers()
614         self.assertNotEqual(wrapper, ())
615         self.assertNotEqual(wrapper, object())
616         self.assertNotEqual(wrapper, "foo")