1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
5 Tests for L{twisted.web.http_headers}.
10 from twisted.python.compat import set
11 from twisted.trial.unittest import TestCase
12 from twisted.web.http_headers import _DictHeaders, Headers
15 class HeadersTests(TestCase):
19 def test_initializer(self):
21 The header values passed to L{Headers.__init__} can be retrieved via
22 L{Headers.getRawHeaders}.
24 h = Headers({'Foo': ['bar']})
25 self.assertEqual(h.getRawHeaders('foo'), ['bar'])
28 def test_setRawHeaders(self):
30 L{Headers.setRawHeaders} sets the header values for the given
31 header name to the sequence of string values.
33 rawValue = ["value1", "value2"]
35 h.setRawHeaders("test", rawValue)
36 self.assertTrue(h.hasHeader("test"))
37 self.assertTrue(h.hasHeader("Test"))
38 self.assertEqual(h.getRawHeaders("test"), rawValue)
41 def test_rawHeadersTypeChecking(self):
43 L{Headers.setRawHeaders} requires values to be of type list.
46 self.assertRaises(TypeError, h.setRawHeaders, {'Foo': 'bar'})
49 def test_addRawHeader(self):
51 L{Headers.addRawHeader} adds a new value for a given header.
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"])
60 def test_getRawHeadersNoDefault(self):
62 L{Headers.getRawHeaders} returns C{None} if the header is not found and
63 no default is specified.
65 self.assertIdentical(Headers().getRawHeaders("test"), None)
68 def test_getRawHeadersDefaultValue(self):
70 L{Headers.getRawHeaders} returns the specified default value when no
75 self.assertIdentical(h.getRawHeaders("test", default), default)
78 def test_getRawHeaders(self):
80 L{Headers.getRawHeaders} returns the values which have been set for a
84 h.setRawHeaders("test", ["lemur"])
85 self.assertEqual(h.getRawHeaders("test"), ["lemur"])
86 self.assertEqual(h.getRawHeaders("Test"), ["lemur"])
89 def test_hasHeaderTrue(self):
91 Check that L{Headers.hasHeader} returns C{True} when the given header
95 h.setRawHeaders("test", ["lemur"])
96 self.assertTrue(h.hasHeader("test"))
97 self.assertTrue(h.hasHeader("Test"))
100 def test_hasHeaderFalse(self):
102 L{Headers.hasHeader} returns C{False} when the given header is not
105 self.assertFalse(Headers().hasHeader("test"))
108 def test_removeHeader(self):
110 Check that L{Headers.removeHeader} removes the given header.
114 h.setRawHeaders("foo", ["lemur"])
115 self.assertTrue(h.hasHeader("foo"))
116 h.removeHeader("foo")
117 self.assertFalse(h.hasHeader("foo"))
119 h.setRawHeaders("bar", ["panda"])
120 self.assertTrue(h.hasHeader("bar"))
121 h.removeHeader("Bar")
122 self.assertFalse(h.hasHeader("bar"))
125 def test_removeHeaderDoesntExist(self):
127 L{Headers.removeHeader} is a no-operation when the specified header is
131 h.removeHeader("test")
132 self.assertEqual(list(h.getAllRawHeaders()), [])
135 def test_canonicalNameCaps(self):
137 L{Headers._canonicalNameCaps} returns the canonical capitalization for
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"),
150 self.assertEqual(h._canonicalNameCaps("x-xss-protection"),
154 def test_getAllRawHeaders(self):
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.
161 h.setRawHeaders("test", ["lemurs"])
162 h.setRawHeaders("www-authenticate", ["basic aksljdlk="])
164 allHeaders = set([(k, tuple(v)) for k, v in h.getAllRawHeaders()])
166 self.assertEqual(allHeaders,
167 set([("WWW-Authenticate", ("basic aksljdlk=",)),
168 ("Test", ("lemurs",))]))
171 def test_headersComparison(self):
173 A L{Headers} instance compares equal to itself and to another
174 L{Headers} instance with the same values.
177 first.setRawHeaders("foo", ["panda"])
179 second.setRawHeaders("foo", ["panda"])
181 third.setRawHeaders("foo", ["lemur", "panda"])
182 self.assertEqual(first, first)
183 self.assertEqual(first, second)
184 self.assertNotEqual(first, third)
187 def test_otherComparison(self):
189 An instance of L{Headers} does not compare equal to other unrelated
193 self.assertNotEqual(h, ())
194 self.assertNotEqual(h, object())
195 self.assertNotEqual(h, "foo")
200 The L{repr} of a L{Headers} instance shows the names and values of all
201 the headers it contains.
204 repr(Headers({"foo": ["bar", "baz"]})),
205 "Headers({'foo': ['bar', 'baz']})")
208 def test_subclassRepr(self):
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"}.
213 class FunnyHeaders(Headers):
216 repr(FunnyHeaders({"foo": ["bar", "baz"]})),
217 "FunnyHeaders({'foo': ['bar', 'baz']})")
222 L{Headers.copy} creates a new independant copy of an existing
223 L{Headers} instance, allowing future modifications without impacts
227 h.setRawHeaders('test', ['foo'])
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'])
237 class HeaderDictTests(TestCase):
239 Tests for the backwards compatible C{dict} interface for L{Headers}
240 provided by L{_DictHeaders}.
242 def headers(self, **kw):
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
249 for k, v in kw.iteritems():
250 h.setRawHeaders(k, v)
251 return h, _DictHeaders(h)
254 def test_getItem(self):
256 L{_DictHeaders.__getitem__} returns a single header for the given name.
258 headers, wrapper = self.headers(test=["lemur"])
259 self.assertEqual(wrapper["test"], "lemur")
262 def test_getItemMultiple(self):
264 L{_DictHeaders.__getitem__} returns only the last header value for a
267 headers, wrapper = self.headers(test=["lemur", "panda"])
268 self.assertEqual(wrapper["test"], "panda")
271 def test_getItemMissing(self):
273 L{_DictHeaders.__getitem__} raises L{KeyError} if called with a header
274 which is not present.
276 headers, wrapper = self.headers()
277 exc = self.assertRaises(KeyError, wrapper.__getitem__, "test")
278 self.assertEqual(exc.args, ("test",))
281 def test_iteration(self):
283 L{_DictHeaders.__iter__} returns an iterator the elements of which
284 are the lowercase name of each header present.
286 headers, wrapper = self.headers(foo=["lemur", "panda"], bar=["baz"])
287 self.assertEqual(set(list(wrapper)), set(["foo", "bar"]))
290 def test_length(self):
292 L{_DictHeaders.__len__} returns the number of headers present.
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)
302 def test_setItem(self):
304 L{_DictHeaders.__setitem__} sets a single header value for the given
307 headers, wrapper = self.headers()
308 wrapper["test"] = "lemur"
309 self.assertEqual(headers.getRawHeaders("test"), ["lemur"])
312 def test_setItemOverwrites(self):
314 L{_DictHeaders.__setitem__} will replace any previous header values for
317 headers, wrapper = self.headers(test=["lemur", "panda"])
318 wrapper["test"] = "lemur"
319 self.assertEqual(headers.getRawHeaders("test"), ["lemur"])
322 def test_delItem(self):
324 L{_DictHeaders.__delitem__} will remove the header values for the given
327 headers, wrapper = self.headers(test=["lemur"])
329 self.assertFalse(headers.hasHeader("test"))
332 def test_delItemMissing(self):
334 L{_DictHeaders.__delitem__} will raise L{KeyError} if the given name is
337 headers, wrapper = self.headers()
338 exc = self.assertRaises(KeyError, wrapper.__delitem__, "test")
339 self.assertEqual(exc.args, ("test",))
342 def test_keys(self, _method='keys', _requireList=True):
344 L{_DictHeaders.keys} will return a list of all present header names.
346 headers, wrapper = self.headers(test=["lemur"], foo=["bar"])
347 keys = getattr(wrapper, _method)()
349 self.assertIsInstance(keys, list)
350 self.assertEqual(set(keys), set(["foo", "test"]))
353 def test_iterkeys(self):
355 L{_DictHeaders.iterkeys} will return all present header names.
357 self.test_keys('iterkeys', False)
360 def test_values(self, _method='values', _requireList=True):
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.
365 headers, wrapper = self.headers(foo=["lemur"], bar=["marmot", "panda"])
366 values = getattr(wrapper, _method)()
368 self.assertIsInstance(values, list)
369 self.assertEqual(set(values), set(["lemur", "panda"]))
372 def test_itervalues(self):
374 L{_DictHeaders.itervalues} will return all present header values,
375 returning only the last value for headers with more than one.
377 self.test_values('itervalues', False)
380 def test_items(self, _method='items', _requireList=True):
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
386 headers, wrapper = self.headers(foo=["lemur"], bar=["marmot", "panda"])
387 items = getattr(wrapper, _method)()
389 self.assertIsInstance(items, list)
390 self.assertEqual(set(items), set([("foo", "lemur"), ("bar", "panda")]))
393 def test_iteritems(self):
395 L{_DictHeaders.iteritems} will return all present header names and
396 values as tuples, returning only the last value for headers with more
399 self.test_items('iteritems', False)
402 def test_clear(self):
404 L{_DictHeaders.clear} will remove all headers.
406 headers, wrapper = self.headers(foo=["lemur"], bar=["panda"])
408 self.assertEqual(list(headers.getAllRawHeaders()), [])
413 L{_DictHeaders.copy} will return a C{dict} with all the same headers
414 and the last value for each.
416 headers, wrapper = self.headers(foo=["lemur", "panda"], bar=["marmot"])
417 duplicate = wrapper.copy()
418 self.assertEqual(duplicate, {"foo": "panda", "bar": "marmot"})
423 L{_DictHeaders.get} returns the last value for the given header name.
425 headers, wrapper = self.headers(foo=["lemur", "panda"])
426 self.assertEqual(wrapper.get("foo"), "panda")
429 def test_getMissing(self):
431 L{_DictHeaders.get} returns C{None} for a header which is not present.
433 headers, wrapper = self.headers()
434 self.assertIdentical(wrapper.get("foo"), None)
437 def test_getDefault(self):
439 L{_DictHeaders.get} returns the last value for the given header name
440 even when it is invoked with a default value.
442 headers, wrapper = self.headers(foo=["lemur"])
443 self.assertEqual(wrapper.get("foo", "bar"), "lemur")
446 def test_getDefaultMissing(self):
448 L{_DictHeaders.get} returns the default value specified if asked for a
449 header which is not present.
451 headers, wrapper = self.headers()
452 self.assertEqual(wrapper.get("foo", "bar"), "bar")
455 def test_has_key(self):
457 L{_DictHeaders.has_key} returns C{True} if the given header is present,
460 headers, wrapper = self.headers(foo=["lemur"])
461 self.assertTrue(wrapper.has_key("foo"))
462 self.assertFalse(wrapper.has_key("bar"))
465 def test_contains(self):
467 L{_DictHeaders.__contains__} returns C{True} if the given header is
468 present, C{False} otherwise.
470 headers, wrapper = self.headers(foo=["lemur"])
471 self.assertIn("foo", wrapper)
472 self.assertNotIn("bar", wrapper)
477 L{_DictHeaders.pop} returns the last header value associated with the
478 given header name and removes the header.
480 headers, wrapper = self.headers(foo=["lemur", "panda"])
481 self.assertEqual(wrapper.pop("foo"), "panda")
482 self.assertIdentical(headers.getRawHeaders("foo"), None)
485 def test_popMissing(self):
487 L{_DictHeaders.pop} raises L{KeyError} if passed a header name which is
490 headers, wrapper = self.headers()
491 self.assertRaises(KeyError, wrapper.pop, "foo")
494 def test_popDefault(self):
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
500 headers, wrapper = self.headers(foo=["lemur"])
501 self.assertEqual(wrapper.pop("foo", "bar"), "lemur")
502 self.assertIdentical(headers.getRawHeaders("foo"), None)
505 def test_popDefaultMissing(self):
507 L{_DictHeaders.pop} returns the default value is asked for a header
508 name which is not present.
510 headers, wrapper = self.headers(foo=["lemur"])
511 self.assertEqual(wrapper.pop("bar", "baz"), "baz")
512 self.assertEqual(headers.getRawHeaders("foo"), ["lemur"])
515 def test_popitem(self):
517 L{_DictHeaders.popitem} returns some header name/value pair.
519 headers, wrapper = self.headers(foo=["lemur", "panda"])
520 self.assertEqual(wrapper.popitem(), ("foo", "panda"))
521 self.assertIdentical(headers.getRawHeaders("foo"), None)
524 def test_popitemEmpty(self):
526 L{_DictHeaders.popitem} raises L{KeyError} if there are no headers
529 headers, wrapper = self.headers()
530 self.assertRaises(KeyError, wrapper.popitem)
533 def test_update(self):
535 L{_DictHeaders.update} adds the header/value pairs in the C{dict} it is
536 passed, overriding any existing values for those headers.
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"])
544 def test_updateWithKeywords(self):
546 L{_DictHeaders.update} adds header names given as keyword arguments
547 with the keyword values as the header value.
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"])
554 if sys.version_info < (2, 4):
555 test_updateWithKeywords.skip = (
556 "Python 2.3 does not support keyword arguments to dict.update.")
559 def test_setdefaultMissing(self):
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.
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"])
571 def test_setdefaultPresent(self):
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.
577 headers, wrapper = self.headers(foo=["bar", "baz"])
578 self.assertEqual(wrapper.setdefault("foo", "quux"), "baz")
579 self.assertEqual(headers.getRawHeaders("foo"), ["bar", "baz"])
582 def test_setdefaultDefault(self):
584 If a value is not passed to L{_DictHeaders.setdefault}, C{None} is
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.
592 headers, wrapper = self.headers()
593 self.assertIdentical(wrapper.setdefault("foo"), None)
594 self.assertEqual(headers.getRawHeaders("foo"), [None])
597 def test_dictComparison(self):
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.
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"})
608 def test_otherComparison(self):
610 An instance of L{_DictHeaders} does not compare equal to other
613 headers, wrapper = self.headers()
614 self.assertNotEqual(wrapper, ())
615 self.assertNotEqual(wrapper, object())
616 self.assertNotEqual(wrapper, "foo")