blob: 2708728e801bd3f39f800895bec7ecc19d11cac5 [file] [log] [blame]
Senthil Kumaranaa5f49e2010-10-03 18:26:07 +00001import httplib
Antoine Pitrou72481782009-09-29 17:48:18 +00002import array
Jeremy Hylton79fa2b62001-04-13 14:57:44 +00003import httplib
4import StringIO
Facundo Batista07c78be2007-03-23 18:54:07 +00005import socket
Victor Stinner2c6aee92010-07-24 02:46:16 +00006import errno
Jeremy Hylton121d34a2003-07-08 12:36:58 +00007
Gregory P. Smith9d325212010-01-03 02:06:07 +00008import unittest
9TestCase = unittest.TestCase
Jeremy Hylton2c178252004-08-07 16:28:14 +000010
11from test import test_support
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000012
Trent Nelsone41b0062008-04-08 23:47:30 +000013HOST = test_support.HOST
14
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000015class FakeSocket:
Jeremy Hylton121d34a2003-07-08 12:36:58 +000016 def __init__(self, text, fileclass=StringIO.StringIO):
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000017 self.text = text
Jeremy Hylton121d34a2003-07-08 12:36:58 +000018 self.fileclass = fileclass
Martin v. Löwis040a9272006-11-12 10:32:47 +000019 self.data = ''
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000020
Jeremy Hylton2c178252004-08-07 16:28:14 +000021 def sendall(self, data):
Antoine Pitrou72481782009-09-29 17:48:18 +000022 self.data += ''.join(data)
Jeremy Hylton2c178252004-08-07 16:28:14 +000023
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000024 def makefile(self, mode, bufsize=None):
25 if mode != 'r' and mode != 'rb':
Neal Norwitz28bb5722002-04-01 19:00:50 +000026 raise httplib.UnimplementedFileMode()
Jeremy Hylton121d34a2003-07-08 12:36:58 +000027 return self.fileclass(self.text)
28
Victor Stinner2c6aee92010-07-24 02:46:16 +000029class EPipeSocket(FakeSocket):
30
31 def __init__(self, text, pipe_trigger):
32 # When sendall() is called with pipe_trigger, raise EPIPE.
33 FakeSocket.__init__(self, text)
34 self.pipe_trigger = pipe_trigger
35
36 def sendall(self, data):
37 if self.pipe_trigger in data:
38 raise socket.error(errno.EPIPE, "gotcha")
39 self.data += data
40
41 def close(self):
42 pass
43
Jeremy Hylton121d34a2003-07-08 12:36:58 +000044class NoEOFStringIO(StringIO.StringIO):
45 """Like StringIO, but raises AssertionError on EOF.
46
47 This is used below to test that httplib doesn't try to read
48 more from the underlying file than it should.
49 """
50 def read(self, n=-1):
51 data = StringIO.StringIO.read(self, n)
52 if data == '':
53 raise AssertionError('caller tried to read past EOF')
54 return data
55
56 def readline(self, length=None):
57 data = StringIO.StringIO.readline(self, length)
58 if data == '':
59 raise AssertionError('caller tried to read past EOF')
60 return data
Jeremy Hylton79fa2b62001-04-13 14:57:44 +000061
Jeremy Hylton2c178252004-08-07 16:28:14 +000062
63class HeaderTests(TestCase):
64 def test_auto_headers(self):
65 # Some headers are added automatically, but should not be added by
66 # .request() if they are explicitly set.
67
Jeremy Hylton2c178252004-08-07 16:28:14 +000068 class HeaderCountingBuffer(list):
69 def __init__(self):
70 self.count = {}
71 def append(self, item):
72 kv = item.split(':')
73 if len(kv) > 1:
74 # item is a 'Key: Value' header string
75 lcKey = kv[0].lower()
76 self.count.setdefault(lcKey, 0)
77 self.count[lcKey] += 1
78 list.append(self, item)
79
80 for explicit_header in True, False:
81 for header in 'Content-length', 'Host', 'Accept-encoding':
82 conn = httplib.HTTPConnection('example.com')
83 conn.sock = FakeSocket('blahblahblah')
84 conn._buffer = HeaderCountingBuffer()
85
86 body = 'spamspamspam'
87 headers = {}
88 if explicit_header:
89 headers[header] = str(len(body))
90 conn.request('POST', '/', body, headers)
91 self.assertEqual(conn._buffer.count[header.lower()], 1)
92
Senthil Kumaranaa5f49e2010-10-03 18:26:07 +000093 def test_putheader(self):
94 conn = httplib.HTTPConnection('example.com')
95 conn.sock = FakeSocket(None)
96 conn.putrequest('GET','/')
97 conn.putheader('Content-length',42)
98 self.assertTrue('Content-length: 42' in conn._buffer)
99
Senthil Kumaran501bfd82010-11-14 03:31:52 +0000100 def test_ipv6host_header(self):
101 # Default host header on IPv6 transaction should wrapped by [] if
102 # its actual IPv6 address
103 expected = 'GET /foo HTTP/1.1\r\nHost: [2001::]:81\r\n' \
104 'Accept-Encoding: identity\r\n\r\n'
105 conn = httplib.HTTPConnection('[2001::]:81')
106 sock = FakeSocket('')
107 conn.sock = sock
108 conn.request('GET', '/foo')
109 self.assertTrue(sock.data.startswith(expected))
110
111 expected = 'GET /foo HTTP/1.1\r\nHost: [2001:102A::]\r\n' \
112 'Accept-Encoding: identity\r\n\r\n'
113 conn = httplib.HTTPConnection('[2001:102A::]')
114 sock = FakeSocket('')
115 conn.sock = sock
116 conn.request('GET', '/foo')
117 self.assertTrue(sock.data.startswith(expected))
118
119
Georg Brandl71a20892006-10-29 20:24:01 +0000120class BasicTest(TestCase):
121 def test_status_lines(self):
122 # Test HTTP status lines
Jeremy Hylton79fa2b62001-04-13 14:57:44 +0000123
Georg Brandl71a20892006-10-29 20:24:01 +0000124 body = "HTTP/1.1 200 Ok\r\n\r\nText"
125 sock = FakeSocket(body)
126 resp = httplib.HTTPResponse(sock)
Jeremy Hyltonba603192003-01-23 18:02:20 +0000127 resp.begin()
Georg Brandl71a20892006-10-29 20:24:01 +0000128 self.assertEqual(resp.read(), 'Text')
Facundo Batista70665902007-10-18 03:16:03 +0000129 self.assertTrue(resp.isclosed())
Jeremy Hyltonba603192003-01-23 18:02:20 +0000130
Georg Brandl71a20892006-10-29 20:24:01 +0000131 body = "HTTP/1.1 400.100 Not Ok\r\n\r\nText"
132 sock = FakeSocket(body)
133 resp = httplib.HTTPResponse(sock)
134 self.assertRaises(httplib.BadStatusLine, resp.begin)
Jeremy Hyltonba603192003-01-23 18:02:20 +0000135
Dirkjan Ochtmanebc73dc2010-02-24 04:49:00 +0000136 def test_bad_status_repr(self):
137 exc = httplib.BadStatusLine('')
Ezio Melotti2623a372010-11-21 13:34:58 +0000138 self.assertEqual(repr(exc), '''BadStatusLine("\'\'",)''')
Dirkjan Ochtmanebc73dc2010-02-24 04:49:00 +0000139
Facundo Batista70665902007-10-18 03:16:03 +0000140 def test_partial_reads(self):
141 # if we have a lenght, the system knows when to close itself
142 # same behaviour than when we read the whole thing with read()
143 body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText"
144 sock = FakeSocket(body)
145 resp = httplib.HTTPResponse(sock)
146 resp.begin()
147 self.assertEqual(resp.read(2), 'Te')
148 self.assertFalse(resp.isclosed())
149 self.assertEqual(resp.read(2), 'xt')
150 self.assertTrue(resp.isclosed())
151
Georg Brandl71a20892006-10-29 20:24:01 +0000152 def test_host_port(self):
153 # Check invalid host_port
Jeremy Hyltonba603192003-01-23 18:02:20 +0000154
Georg Brandl71a20892006-10-29 20:24:01 +0000155 for hp in ("www.python.org:abc", "www.python.org:"):
156 self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp)
157
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000158 for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b",
159 8000),
Georg Brandl71a20892006-10-29 20:24:01 +0000160 ("www.python.org:80", "www.python.org", 80),
161 ("www.python.org", "www.python.org", 80),
162 ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 80)):
Martin v. Löwis74a249e2004-09-14 21:45:36 +0000163 http = httplib.HTTP(hp)
Georg Brandl71a20892006-10-29 20:24:01 +0000164 c = http._conn
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000165 if h != c.host:
166 self.fail("Host incorrectly parsed: %s != %s" % (h, c.host))
167 if p != c.port:
168 self.fail("Port incorrectly parsed: %s != %s" % (p, c.host))
Skip Montanaro10e6e0e2004-09-14 16:32:02 +0000169
Georg Brandl71a20892006-10-29 20:24:01 +0000170 def test_response_headers(self):
171 # test response with multiple message headers with the same field name.
172 text = ('HTTP/1.1 200 OK\r\n'
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000173 'Set-Cookie: Customer="WILE_E_COYOTE";'
174 ' Version="1"; Path="/acme"\r\n'
Georg Brandl71a20892006-10-29 20:24:01 +0000175 'Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";'
176 ' Path="/acme"\r\n'
177 '\r\n'
178 'No body\r\n')
179 hdr = ('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"'
180 ', '
181 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"')
182 s = FakeSocket(text)
183 r = httplib.HTTPResponse(s)
184 r.begin()
185 cookies = r.getheader("Set-Cookie")
186 if cookies != hdr:
187 self.fail("multiple headers not combined properly")
Jeremy Hyltonba603192003-01-23 18:02:20 +0000188
Georg Brandl71a20892006-10-29 20:24:01 +0000189 def test_read_head(self):
190 # Test that the library doesn't attempt to read any data
191 # from a HEAD request. (Tickles SF bug #622042.)
192 sock = FakeSocket(
193 'HTTP/1.1 200 OK\r\n'
194 'Content-Length: 14432\r\n'
195 '\r\n',
196 NoEOFStringIO)
197 resp = httplib.HTTPResponse(sock, method="HEAD")
198 resp.begin()
199 if resp.read() != "":
200 self.fail("Did not expect response from HEAD request")
Jeremy Hyltonc1b2cb92003-05-05 16:13:58 +0000201
Martin v. Löwis040a9272006-11-12 10:32:47 +0000202 def test_send_file(self):
203 expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \
204 'Accept-Encoding: identity\r\nContent-Length:'
205
206 body = open(__file__, 'rb')
207 conn = httplib.HTTPConnection('example.com')
208 sock = FakeSocket(body)
209 conn.sock = sock
210 conn.request('GET', '/foo', body)
211 self.assertTrue(sock.data.startswith(expected))
Jeremy Hylton2c178252004-08-07 16:28:14 +0000212
Antoine Pitrou72481782009-09-29 17:48:18 +0000213 def test_send(self):
214 expected = 'this is a test this is only a test'
215 conn = httplib.HTTPConnection('example.com')
216 sock = FakeSocket(None)
217 conn.sock = sock
218 conn.send(expected)
Ezio Melotti2623a372010-11-21 13:34:58 +0000219 self.assertEqual(expected, sock.data)
Antoine Pitrou72481782009-09-29 17:48:18 +0000220 sock.data = ''
221 conn.send(array.array('c', expected))
Ezio Melotti2623a372010-11-21 13:34:58 +0000222 self.assertEqual(expected, sock.data)
Antoine Pitrou72481782009-09-29 17:48:18 +0000223 sock.data = ''
224 conn.send(StringIO.StringIO(expected))
Ezio Melotti2623a372010-11-21 13:34:58 +0000225 self.assertEqual(expected, sock.data)
Antoine Pitrou72481782009-09-29 17:48:18 +0000226
Georg Brandl23635032008-02-24 00:03:22 +0000227 def test_chunked(self):
228 chunked_start = (
229 'HTTP/1.1 200 OK\r\n'
230 'Transfer-Encoding: chunked\r\n\r\n'
231 'a\r\n'
232 'hello worl\r\n'
233 '1\r\n'
234 'd\r\n'
235 )
236 sock = FakeSocket(chunked_start + '0\r\n')
237 resp = httplib.HTTPResponse(sock, method="GET")
238 resp.begin()
Ezio Melotti2623a372010-11-21 13:34:58 +0000239 self.assertEqual(resp.read(), 'hello world')
Georg Brandl23635032008-02-24 00:03:22 +0000240 resp.close()
241
242 for x in ('', 'foo\r\n'):
243 sock = FakeSocket(chunked_start + x)
244 resp = httplib.HTTPResponse(sock, method="GET")
245 resp.begin()
246 try:
247 resp.read()
248 except httplib.IncompleteRead, i:
Ezio Melotti2623a372010-11-21 13:34:58 +0000249 self.assertEqual(i.partial, 'hello world')
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000250 self.assertEqual(repr(i),'IncompleteRead(11 bytes read)')
251 self.assertEqual(str(i),'IncompleteRead(11 bytes read)')
Georg Brandl23635032008-02-24 00:03:22 +0000252 else:
253 self.fail('IncompleteRead expected')
254 finally:
255 resp.close()
256
Senthil Kumaraned9204342010-04-28 17:20:43 +0000257 def test_chunked_head(self):
258 chunked_start = (
259 'HTTP/1.1 200 OK\r\n'
260 'Transfer-Encoding: chunked\r\n\r\n'
261 'a\r\n'
262 'hello world\r\n'
263 '1\r\n'
264 'd\r\n'
265 )
266 sock = FakeSocket(chunked_start + '0\r\n')
267 resp = httplib.HTTPResponse(sock, method="HEAD")
268 resp.begin()
Ezio Melotti2623a372010-11-21 13:34:58 +0000269 self.assertEqual(resp.read(), '')
270 self.assertEqual(resp.status, 200)
271 self.assertEqual(resp.reason, 'OK')
Senthil Kumaranfb695012010-06-04 17:17:09 +0000272 self.assertTrue(resp.isclosed())
Senthil Kumaraned9204342010-04-28 17:20:43 +0000273
Georg Brandl8c460d52008-02-24 00:14:24 +0000274 def test_negative_content_length(self):
Jeremy Hylton21d2e592008-11-29 00:09:16 +0000275 sock = FakeSocket('HTTP/1.1 200 OK\r\n'
276 'Content-Length: -1\r\n\r\nHello\r\n')
Georg Brandl8c460d52008-02-24 00:14:24 +0000277 resp = httplib.HTTPResponse(sock, method="GET")
278 resp.begin()
Ezio Melotti2623a372010-11-21 13:34:58 +0000279 self.assertEqual(resp.read(), 'Hello\r\n')
Georg Brandl8c460d52008-02-24 00:14:24 +0000280 resp.close()
281
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000282 def test_incomplete_read(self):
283 sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello\r\n')
284 resp = httplib.HTTPResponse(sock, method="GET")
285 resp.begin()
286 try:
287 resp.read()
288 except httplib.IncompleteRead as i:
Ezio Melotti2623a372010-11-21 13:34:58 +0000289 self.assertEqual(i.partial, 'Hello\r\n')
Benjamin Peterson7d49bba2009-03-02 22:41:42 +0000290 self.assertEqual(repr(i),
291 "IncompleteRead(7 bytes read, 3 more expected)")
292 self.assertEqual(str(i),
293 "IncompleteRead(7 bytes read, 3 more expected)")
294 else:
295 self.fail('IncompleteRead expected')
296 finally:
297 resp.close()
298
Victor Stinner2c6aee92010-07-24 02:46:16 +0000299 def test_epipe(self):
300 sock = EPipeSocket(
301 "HTTP/1.0 401 Authorization Required\r\n"
302 "Content-type: text/html\r\n"
303 "WWW-Authenticate: Basic realm=\"example\"\r\n",
304 b"Content-Length")
305 conn = httplib.HTTPConnection("example.com")
306 conn.sock = sock
307 self.assertRaises(socket.error,
308 lambda: conn.request("PUT", "/url", "body"))
309 resp = conn.getresponse()
310 self.assertEqual(401, resp.status)
311 self.assertEqual("Basic realm=\"example\"",
312 resp.getheader("www-authenticate"))
313
Senthil Kumarand389cb52010-09-21 01:38:15 +0000314 def test_filenoattr(self):
315 # Just test the fileno attribute in the HTTPResponse Object.
316 body = "HTTP/1.1 200 Ok\r\n\r\nText"
317 sock = FakeSocket(body)
318 resp = httplib.HTTPResponse(sock)
319 self.assertTrue(hasattr(resp,'fileno'),
320 'HTTPResponse should expose a fileno attribute')
Georg Brandl23635032008-02-24 00:03:22 +0000321
Antoine Pitroud7b6ac62010-12-18 18:18:21 +0000322 # Test lines overflowing the max line size (_MAXLINE in http.client)
323
324 def test_overflowing_status_line(self):
325 self.skipTest("disabled for HTTP 0.9 support")
326 body = "HTTP/1.1 200 Ok" + "k" * 65536 + "\r\n"
327 resp = httplib.HTTPResponse(FakeSocket(body))
328 self.assertRaises((httplib.LineTooLong, httplib.BadStatusLine), resp.begin)
329
330 def test_overflowing_header_line(self):
331 body = (
332 'HTTP/1.1 200 OK\r\n'
333 'X-Foo: bar' + 'r' * 65536 + '\r\n\r\n'
334 )
335 resp = httplib.HTTPResponse(FakeSocket(body))
336 self.assertRaises(httplib.LineTooLong, resp.begin)
337
338 def test_overflowing_chunked_line(self):
339 body = (
340 'HTTP/1.1 200 OK\r\n'
341 'Transfer-Encoding: chunked\r\n\r\n'
342 + '0' * 65536 + 'a\r\n'
343 'hello world\r\n'
344 '0\r\n'
345 )
346 resp = httplib.HTTPResponse(FakeSocket(body))
347 resp.begin()
348 self.assertRaises(httplib.LineTooLong, resp.read)
349
350
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000351class OfflineTest(TestCase):
352 def test_responses(self):
Ezio Melotti2623a372010-11-21 13:34:58 +0000353 self.assertEqual(httplib.responses[httplib.NOT_FOUND], "Not Found")
Georg Brandl4cbd1e32006-02-17 22:01:08 +0000354
Gregory P. Smith9d325212010-01-03 02:06:07 +0000355
356class SourceAddressTest(TestCase):
357 def setUp(self):
358 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
359 self.port = test_support.bind_port(self.serv)
360 self.source_port = test_support.find_unused_port()
361 self.serv.listen(5)
362 self.conn = None
363
364 def tearDown(self):
365 if self.conn:
366 self.conn.close()
367 self.conn = None
368 self.serv.close()
369 self.serv = None
370
371 def testHTTPConnectionSourceAddress(self):
372 self.conn = httplib.HTTPConnection(HOST, self.port,
373 source_address=('', self.source_port))
374 self.conn.connect()
375 self.assertEqual(self.conn.sock.getsockname()[1], self.source_port)
376
377 @unittest.skipIf(not hasattr(httplib, 'HTTPSConnection'),
378 'httplib.HTTPSConnection not defined')
379 def testHTTPSConnectionSourceAddress(self):
380 self.conn = httplib.HTTPSConnection(HOST, self.port,
381 source_address=('', self.source_port))
382 # We don't test anything here other the constructor not barfing as
383 # this code doesn't deal with setting up an active running SSL server
384 # for an ssl_wrapped connect() to actually return from.
385
386
Facundo Batista07c78be2007-03-23 18:54:07 +0000387class TimeoutTest(TestCase):
Trent Nelsone41b0062008-04-08 23:47:30 +0000388 PORT = None
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000389
Facundo Batista07c78be2007-03-23 18:54:07 +0000390 def setUp(self):
391 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000392 TimeoutTest.PORT = test_support.bind_port(self.serv)
Facundo Batistaf1966292007-03-25 03:20:05 +0000393 self.serv.listen(5)
Facundo Batista07c78be2007-03-23 18:54:07 +0000394
395 def tearDown(self):
396 self.serv.close()
397 self.serv = None
398
399 def testTimeoutAttribute(self):
400 '''This will prove that the timeout gets through
401 HTTPConnection and into the socket.
402 '''
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000403 # default -- use global socket timeout
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000404 self.assertTrue(socket.getdefaulttimeout() is None)
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000405 socket.setdefaulttimeout(30)
406 try:
407 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT)
408 httpConn.connect()
409 finally:
410 socket.setdefaulttimeout(None)
Facundo Batista14553b02007-03-23 20:23:08 +0000411 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000412 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000413
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000414 # no timeout -- do not use global socket default
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000415 self.assertTrue(socket.getdefaulttimeout() is None)
Facundo Batista14553b02007-03-23 20:23:08 +0000416 socket.setdefaulttimeout(30)
417 try:
Trent Nelson6c4a7c62008-04-09 00:34:53 +0000418 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT,
419 timeout=None)
Facundo Batista14553b02007-03-23 20:23:08 +0000420 httpConn.connect()
421 finally:
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000422 socket.setdefaulttimeout(None)
423 self.assertEqual(httpConn.sock.gettimeout(), None)
424 httpConn.close()
425
426 # a value
427 httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, timeout=30)
428 httpConn.connect()
Facundo Batista14553b02007-03-23 20:23:08 +0000429 self.assertEqual(httpConn.sock.gettimeout(), 30)
Facundo Batistaf1966292007-03-25 03:20:05 +0000430 httpConn.close()
Facundo Batista07c78be2007-03-23 18:54:07 +0000431
432
Facundo Batista70f996b2007-05-21 17:32:32 +0000433class HTTPSTimeoutTest(TestCase):
434# XXX Here should be tests for HTTPS, there isn't any right now!
435
436 def test_attributes(self):
437 # simple test to check it's storing it
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000438 if hasattr(httplib, 'HTTPSConnection'):
Trent Nelsone41b0062008-04-08 23:47:30 +0000439 h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30)
Thomas Wouters628e3bb2007-08-30 22:35:31 +0000440 self.assertEqual(h.timeout, 30)
Facundo Batista70f996b2007-05-21 17:32:32 +0000441
Jeremy Hylton2c178252004-08-07 16:28:14 +0000442def test_main(verbose=None):
Trent Nelsone41b0062008-04-08 23:47:30 +0000443 test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
Gregory P. Smith9d325212010-01-03 02:06:07 +0000444 HTTPSTimeoutTest, SourceAddressTest)
Jeremy Hylton2c178252004-08-07 16:28:14 +0000445
Georg Brandl71a20892006-10-29 20:24:01 +0000446if __name__ == '__main__':
447 test_main()