from twisted.trial import unittest import random # Heh heh. Too Evil to pass up. ;) import __builtin__ __builtin__._http_headers_isBeingTested=True import http_headers del __builtin__._http_headers_isBeingTested class TokenizerTest(unittest.TestCase): """Test header list parsing functions.""" def testParse(self): parser = lambda val: list(http_headers.tokenize([val,])) Token = http_headers.Token tests = (('foo,bar', ['foo', Token(','), 'bar']), ('FOO,BAR', ['foo', Token(','), 'bar']), (' \t foo \t bar \t , \t baz ', ['foo', Token(' '), 'bar', Token(','), 'baz']), ('()<>@,;:\\/[]?={}', [Token('('), Token(')'), Token('<'), Token('>'), Token('@'), Token(','), Token(';'), Token(':'), Token('\\'), Token('/'), Token('['), Token(']'), Token('?'), Token('='), Token('{'), Token('}')]), (' "foo" ', ['foo']), ('"FOO(),\\"BAR,"', ['FOO(),"BAR,'])) raiseTests = ('"open quote', '"ending \\', "control character: \x127", "\x00", "\x1f") for test,result in tests: self.assertEquals(parser(test), result) for test in raiseTests: self.assertRaises(ValueError, parser, test) def testGenerate(self): pass def testRoundtrip(self): pass def parseHeader(name, val): head = http_headers.Headers(parsers=http_headers.DefaultHTTPParsers) head.setRawHeader(name,val) return head.getHeader(name) def generateHeader(name, val): head = http_headers.Headers(generators=http_headers.DefaultHTTPGenerators) head.setHeader(name, val) return head.getRawHeader(name) class HeaderParsingTestBase(unittest.TestCase): def runRoundtripTest(self, headername, table): for row in table: # parser parsed = parseHeader(headername, [row[0],]) self.assertEquals(parsed, row[1]) # generator self.assertEquals(generateHeader(headername, parsed), len(row) > 2 and [row[2],] or [row[0],]) class GeneralHeaderParsingTests(HeaderParsingTestBase): # def testCacheControl(self): # fail def testConnection(self): table = ( ("close", ['close',]), ("close, foo-bar", ['close', 'foo-bar']) ) self.runRoundtripTest("Connection", table) # def testDate(self): # fail # def testPragma(self): # fail # def testTrailer(self): # fail # def testTransferEncoding(self): # fail # def testUpgrade(self): # fail # def testVia(self): # fail # def testWarning(self): # fail class RequestHeaderParsingTests(HeaderParsingTestBase): #FIXME test ordering too. def testAccept(self): table = ( ("audio/*;q=0.2, audio/basic", {('audio', '*', ()): {'q': 0.2}, ('audio', 'basic', ()): {'q': 1.0}}), ("text/plain;q=0.5, text/html, text/x-dvi;q=0.8, text/x-c", {('text', 'plain', ()): {'q': 0.5}, ('text', 'html', ()): {'q': 1.0}, ('text', 'x-dvi', ()): {'q': 0.8}, ('text', 'x-c', ()): {'q': 1.0}}), ("text/*, text/html, text/html;level=1, */*", {('text', '*', ()): {'q': 1.0}, ('text', 'html', ()): {'q': 1.0}, ('text', 'html', (('level', '1'),)): {'q': 1.0}, ('*', '*', ()): {'q': 1.0}}), ("text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5", {('text', '*', ()): {'q': 0.3}, ('text', 'html', ()): {'q': 0.7}, ('text', 'html', (('level', '1'),)): {'q': 1.0}, ('text', 'html', (('level', '2'),)): {'q': 0.4}, ('*', '*', ()): {'q': 0.5}}), ) self.runRoundtripTest("Accept", table) def testAcceptCharset(self): table = ( ("iso-8859-5, unicode-1-1;q=0.8", {'iso-8859-5': 1.0, 'iso-8859-1': 1.0, 'unicode-1-1': 0.8}, "iso-8859-5, unicode-1-1;q=0.8, iso-8859-1"), ("iso-8859-1;q=0.7", {'iso-8859-1': 0.7}), ("*;q=.7", {'*': 0.7}, "*;q=0.7"), ("", {'iso-8859-1': 1.0}, "iso-8859-1"), # Yes this is an actual change -- we'll say that's okay. :) ) self.runRoundtripTest("Accept-Charset", table) def testAcceptEncoding(self): table = ( ("compress, gzip", {'compress': 1.0, 'gzip': 1.0, 'identity': 0.0001}), ("", {'identity': 0.0001}), ("*", {'*': 1}), ("compress;q=0.5, gzip;q=1.0", {'compress': 0.5, 'gzip': 1.0, 'identity': 0.0001}, "compress;q=0.5, gzip"), ("gzip;q=1.0, identity;q=0.5, *;q=0", {'gzip': 1.0, 'identity': 0.5, '*':0}, "gzip, identity;q=0.5, *;q=0"), ) self.runRoundtripTest("Accept-Encoding", table) def testAcceptLanguage(self): table = ( ("da, en-gb;q=0.8, en;q=0.7", {'da': 1.0, 'en-gb': 0.8, 'en': 0.7}), ("*", {'*': 1}), ) self.runRoundtripTest("Accept-Language", table) # def testAuthorization(self): # fail def testExpect(self): table = ( ("100-continue", {"100-continue":(True,)}), ('foobar=twiddle', {'foobar':('twiddle',)}), ("foo=bar;a=b;c", {'foo':('bar',('a', 'b'), ('c', True))}) ) self.runRoundtripTest("Expect", table) # def testFrom(self): # fail # def testHost(self): # fail def testIfModifiedSince(self): # Don't need major tests since the datetime parser has its own test self.runRoundtripTest("If-Modified-Since", (("Sun, 09 Sep 2001 01:46:40 GMT", 1000000000),)) # def testIfNoneMatch(self): # fail # def testIfRange(self): # fail def testIfUnmodifiedSince(self): self.runRoundtripTest("If-Unmodified-Since", (("Sun, 09 Sep 2001 01:46:40 GMT", 1000000000),)) pass def testMaxForwards(self): self.runRoundtripTest("Max-Forwards", (("15", 15),)) # def testProxyAuthorize(self): # fail def testRange(self): table = ( ("bytes=0-499", ('bytes', [(0,499),])), ("bytes=500-999", ('bytes', [(500,999),])), ("bytes=-500",('bytes', [(None,500),])), ("bytes=9500-",('bytes', [(9500, None),])), ("bytes=0-0,-1", ('bytes', [(0,0),(None,1)])), ) self.runRoundtripTest("Range", table) # def testReferer(self): # fail # def testTE(self): # fail # def testUserAgent(self): # fail class EntityHeaderParsingTests(HeaderParsingTestBase): def testAllow(self): # Allow is a silly case-sensitive header unlike all the rest table = ( ("GET", ['GET', ]), ("GET, HEAD, PUT", ['GET', 'HEAD', 'PUT']), ) self.runRoundtripTest("Allow", table) def testContentEncoding(self): table = ( ("gzip", ['gzip',]), ) self.runRoundtripTest("Content-Encoding", table) def testContentLanguage(self): table = ( ("da", ['da',]), ("mi, en", ['mi', 'en']), ) self.runRoundtripTest("Content-Encoding", table) # def testContentLength(self): # fail # def testContentLocation(self): # fail # def testContentMD5(self): # fail # def testContentRange(self): # fail # def testContentType(self): # fail # def testExpires(self): # fail # def testLastModified(self): # fail class DateTimeTest(unittest.TestCase): """Test date parsing functions.""" def testParse(self): timeNum = 784111777 timeStrs = ('Sun, 06 Nov 1994 08:49:37 GMT', 'Sunday, 06-Nov-94 08:49:37 GMT', 'Sun Nov 6 08:49:37 1994') for timeStr in timeStrs: self.assertEquals(http_headers.parseDateTime(timeStr), timeNum) def testGenerate(self): self.assertEquals(http_headers.generateDateTime(784111777), 'Sun, 06 Nov 1994 08:49:37 GMT') def testRoundtrip(self): for i in range(2000): time = random.randint(0, 2000000000) timestr = http_headers.generateDateTime(time) time2 = http_headers.parseDateTime(timestr) self.assertEquals(time, time2)