blob: dc3d884194f30bf8dd1cfb95f90467e573bfdcb5 [file] [log] [blame]
Jeremy Hylton5d9c3032004-08-07 17:40:50 +00001#!/usr/bin/env python
2
3import unittest
4from test import test_support
Thomas Wouters477c8d52006-05-27 19:21:47 +00005from test.test_urllib2 import sanepathname2url
Jeremy Hylton5d9c3032004-08-07 17:40:50 +00006
7import socket
8import urllib2
9import sys
10import os
11import mimetools
12
Christian Heimes969fe572008-01-25 11:23:10 +000013
14def _urlopen_with_retry(host, *args, **kwargs):
15 # Connecting to remote hosts is flaky. Make it more robust
16 # by retrying the connection several times.
17 for i in range(3):
18 try:
19 return urllib2.urlopen(host, *args, **kwargs)
Neal Norwitz2f142582008-01-26 19:49:41 +000020 except urllib2.URLError as e:
21 last_exc = e
Christian Heimes969fe572008-01-25 11:23:10 +000022 continue
23 except:
24 raise
25 raise last_exc
26
27
Jeremy Hylton5d9c3032004-08-07 17:40:50 +000028class URLTimeoutTest(unittest.TestCase):
29
30 TIMEOUT = 10.0
31
32 def setUp(self):
33 socket.setdefaulttimeout(self.TIMEOUT)
34
35 def tearDown(self):
36 socket.setdefaulttimeout(None)
37
38 def testURLread(self):
Christian Heimes969fe572008-01-25 11:23:10 +000039 f = _urlopen_with_retry("http://www.python.org/")
Jeremy Hylton5d9c3032004-08-07 17:40:50 +000040 x = f.read()
41
Thomas Wouters477c8d52006-05-27 19:21:47 +000042
43class AuthTests(unittest.TestCase):
44 """Tests urllib2 authentication features."""
45
46## Disabled at the moment since there is no page under python.org which
47## could be used to HTTP authentication.
48#
49# def test_basic_auth(self):
50# import httplib
51#
52# test_url = "http://www.python.org/test/test_urllib2/basic_auth"
53# test_hostport = "www.python.org"
54# test_realm = 'Test Realm'
55# test_user = 'test.test_urllib2net'
56# test_password = 'blah'
57#
58# # failure
59# try:
Christian Heimes969fe572008-01-25 11:23:10 +000060# _urlopen_with_retry(test_url)
Thomas Wouters477c8d52006-05-27 19:21:47 +000061# except urllib2.HTTPError, exc:
62# self.assertEqual(exc.code, 401)
63# else:
64# self.fail("urlopen() should have failed with 401")
65#
66# # success
67# auth_handler = urllib2.HTTPBasicAuthHandler()
68# auth_handler.add_password(test_realm, test_hostport,
69# test_user, test_password)
70# opener = urllib2.build_opener(auth_handler)
71# f = opener.open('http://localhost/')
Christian Heimes969fe572008-01-25 11:23:10 +000072# response = _urlopen_with_retry("http://www.python.org/")
Thomas Wouters477c8d52006-05-27 19:21:47 +000073#
74# # The 'userinfo' URL component is deprecated by RFC 3986 for security
75# # reasons, let's not implement it! (it's already implemented for proxy
76# # specification strings (that is, URLs or authorities specifying a
77# # proxy), so we must keep that)
78# self.assertRaises(httplib.InvalidURL,
79# urllib2.urlopen, "http://evil:thing@example.com")
80
81
Thomas Woutersb2137042007-02-01 18:02:27 +000082class CloseSocketTest(unittest.TestCase):
83
84 def test_close(self):
85 import socket, httplib, gc
86
87 # calling .close() on urllib2's response objects should close the
88 # underlying socket
89
90 # delve deep into response to fetch socket._socketobject
Christian Heimes969fe572008-01-25 11:23:10 +000091 response = _urlopen_with_retry("http://www.python.org/")
Thomas Woutersb2137042007-02-01 18:02:27 +000092 abused_fileobject = response.fp
Jeremy Hyltonec0c5082007-08-03 21:03:02 +000093 httpresponse = abused_fileobject.raw
Thomas Woutersb2137042007-02-01 18:02:27 +000094 self.assert_(httpresponse.__class__ is httplib.HTTPResponse)
95 fileobject = httpresponse.fp
Thomas Woutersb2137042007-02-01 18:02:27 +000096
97 self.assert_(not fileobject.closed)
98 response.close()
99 self.assert_(fileobject.closed)
100
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000101class urlopenNetworkTests(unittest.TestCase):
102 """Tests urllib2.urlopen using the network.
103
104 These tests are not exhaustive. Assuming that testing using files does a
105 good job overall of some of the basic interface features. There are no
106 tests exercising the optional 'data' and 'proxies' arguments. No tests
107 for transparent redirection have been written.
108
109 setUp is not used for always constructing a connection to
110 http://www.python.org/ since there a few tests that don't use that address
111 and making a connection is expensive enough to warrant minimizing unneeded
112 connections.
113
114 """
115
116 def test_basic(self):
117 # Simple test expected to pass.
Christian Heimes969fe572008-01-25 11:23:10 +0000118 open_url = _urlopen_with_retry("http://www.python.org/")
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000119 for attr in ("read", "close", "info", "geturl"):
120 self.assert_(hasattr(open_url, attr), "object returned from "
121 "urlopen lacks the %s attribute" % attr)
122 try:
123 self.assert_(open_url.read(), "calling 'read' failed")
124 finally:
125 open_url.close()
126
127 def test_info(self):
128 # Test 'info'.
Christian Heimes969fe572008-01-25 11:23:10 +0000129 open_url = _urlopen_with_retry("http://www.python.org/")
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000130 try:
131 info_obj = open_url.info()
132 finally:
133 open_url.close()
134 self.assert_(isinstance(info_obj, mimetools.Message),
135 "object returned by 'info' is not an instance of "
136 "mimetools.Message")
137 self.assertEqual(info_obj.getsubtype(), "html")
138
139 def test_geturl(self):
140 # Make sure same URL as opened is returned by geturl.
141 URL = "http://www.python.org/"
Christian Heimes969fe572008-01-25 11:23:10 +0000142 open_url = _urlopen_with_retry(URL)
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000143 try:
144 gotten_url = open_url.geturl()
145 finally:
146 open_url.close()
147 self.assertEqual(gotten_url, URL)
148
149 def test_bad_address(self):
150 # Make sure proper exception is raised when connecting to a bogus
151 # address.
152 self.assertRaises(IOError,
153 # SF patch 809915: In Sep 2003, VeriSign started
154 # highjacking invalid .com and .net addresses to
155 # boost traffic to their own site. This test
156 # started failing then. One hopes the .invalid
157 # domain will be spared to serve its defined
158 # purpose.
159 # urllib2.urlopen, "http://www.sadflkjsasadf.com/")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000160 urllib2.urlopen, "http://www.python.invalid./")
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000161
Thomas Wouters477c8d52006-05-27 19:21:47 +0000162
163class OtherNetworkTests(unittest.TestCase):
164 def setUp(self):
165 if 0: # for debugging
166 import logging
167 logger = logging.getLogger("test_urllib2net")
168 logger.addHandler(logging.StreamHandler())
169
170 def test_range (self):
171 req = urllib2.Request("http://www.python.org",
172 headers={'Range': 'bytes=20-39'})
Christian Heimes969fe572008-01-25 11:23:10 +0000173 result = _urlopen_with_retry(req)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000174 data = result.read()
175 self.assertEqual(len(data), 20)
176
177 # XXX The rest of these tests aren't very good -- they don't check much.
178 # They do sometimes catch some major disasters, though.
179
180 def test_ftp(self):
181 urls = [
Gregory P. Smithc111d9f2007-09-09 23:55:55 +0000182 'ftp://ftp.kernel.org/pub/linux/kernel/README',
183 'ftp://ftp.kernel.org/pub/linux/kernel/non-existant-file',
184 #'ftp://ftp.kernel.org/pub/leenox/kernel/test',
Thomas Wouters477c8d52006-05-27 19:21:47 +0000185 'ftp://gatekeeper.research.compaq.com/pub/DEC/SRC'
186 '/research-reports/00README-Legal-Rules-Regs',
187 ]
188 self._test_urls(urls, self._extra_handlers())
189
Thomas Wouters477c8d52006-05-27 19:21:47 +0000190 def test_file(self):
191 TESTFN = test_support.TESTFN
192 f = open(TESTFN, 'w')
193 try:
194 f.write('hi there\n')
195 f.close()
196 urls = [
197 'file:'+sanepathname2url(os.path.abspath(TESTFN)),
Gregory P. Smithc111d9f2007-09-09 23:55:55 +0000198 ('file:///nonsensename/etc/passwd', None, urllib2.URLError),
Thomas Wouters477c8d52006-05-27 19:21:47 +0000199 ]
Christian Heimes969fe572008-01-25 11:23:10 +0000200 self._test_urls(urls, self._extra_handlers(), urllib2.urlopen)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000201 finally:
202 os.remove(TESTFN)
203
204 def test_http(self):
205 urls = [
206 'http://www.espn.com/', # redirect
207 'http://www.python.org/Spanish/Inquistion/',
208 ('http://www.python.org/cgi-bin/faqw.py',
209 'query=pythonistas&querytype=simple&casefold=yes&req=search', None),
210 'http://www.python.org/',
211 ]
212 self._test_urls(urls, self._extra_handlers())
213
214 # XXX Following test depends on machine configurations that are internal
215 # to CNRI. Need to set up a public server with the right authentication
216 # configuration for test purposes.
217
218## def test_cnri(self):
219## if socket.gethostname() == 'bitdiddle':
220## localhost = 'bitdiddle.cnri.reston.va.us'
221## elif socket.gethostname() == 'bitdiddle.concentric.net':
222## localhost = 'localhost'
223## else:
224## localhost = None
225## if localhost is not None:
226## urls = [
227## 'file://%s/etc/passwd' % localhost,
228## 'http://%s/simple/' % localhost,
229## 'http://%s/digest/' % localhost,
230## 'http://%s/not/found.h' % localhost,
231## ]
232
233## bauth = HTTPBasicAuthHandler()
234## bauth.add_password('basic_test_realm', localhost, 'jhylton',
235## 'password')
236## dauth = HTTPDigestAuthHandler()
237## dauth.add_password('digest_test_realm', localhost, 'jhylton',
238## 'password')
239
240## self._test_urls(urls, self._extra_handlers()+[bauth, dauth])
241
Christian Heimes969fe572008-01-25 11:23:10 +0000242 def _test_urls(self, urls, handlers, urlopen=_urlopen_with_retry):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000243 import socket
244 import time
245 import logging
246 debug = logging.getLogger("test_urllib2").debug
247
248 urllib2.install_opener(urllib2.build_opener(*handlers))
249
250 for url in urls:
251 if isinstance(url, tuple):
252 url, req, expected_err = url
253 else:
254 req = expected_err = None
255 debug(url)
256 try:
Christian Heimes969fe572008-01-25 11:23:10 +0000257 f = urlopen(url, req)
Gregory P. Smithc111d9f2007-09-09 23:55:55 +0000258 except EnvironmentError as err:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000259 debug(err)
260 if expected_err:
Gregory P. Smithc111d9f2007-09-09 23:55:55 +0000261 msg = ("Didn't get expected error(s) %s for %s %s, got %s: %s" %
262 (expected_err, url, req, type(err), err))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000263 self.assert_(isinstance(err, expected_err), msg)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000264 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000265 with test_support.transient_internet():
266 buf = f.read()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000267 f.close()
268 debug("read %d bytes" % len(buf))
269 debug("******** next url coming up...")
270 time.sleep(0.1)
271
272 def _extra_handlers(self):
273 handlers = []
274
Thomas Wouters477c8d52006-05-27 19:21:47 +0000275 cfh = urllib2.CacheFTPHandler()
276 cfh.setTimeout(1)
277 handlers.append(cfh)
278
279 return handlers
280
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000281class TimeoutTest(unittest.TestCase):
282 def test_http_basic(self):
Christian Heimes969fe572008-01-25 11:23:10 +0000283 u = _urlopen_with_retry("http://www.python.org")
Jeremy Hyltoncf2f4192007-08-03 20:31:38 +0000284 self.assertTrue(u.fp.raw.fp._sock.gettimeout() is None)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000285
286 def test_http_NoneWithdefault(self):
287 prev = socket.getdefaulttimeout()
288 socket.setdefaulttimeout(60)
289 try:
Christian Heimes969fe572008-01-25 11:23:10 +0000290 u = _urlopen_with_retry("http://www.python.org", timeout=None)
Jeremy Hyltoncf2f4192007-08-03 20:31:38 +0000291 self.assertTrue(u.fp.raw.fp._sock.gettimeout(), 60)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000292 finally:
293 socket.setdefaulttimeout(prev)
294
295 def test_http_Value(self):
Christian Heimes969fe572008-01-25 11:23:10 +0000296 u = _urlopen_with_retry("http://www.python.org", timeout=120)
Jeremy Hyltoncf2f4192007-08-03 20:31:38 +0000297 self.assertEqual(u.fp.raw.fp._sock.gettimeout(), 120)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000298
299 def test_http_NoneNodefault(self):
Christian Heimes969fe572008-01-25 11:23:10 +0000300 u = _urlopen_with_retry("http://www.python.org", timeout=None)
Jeremy Hyltoncf2f4192007-08-03 20:31:38 +0000301 self.assertTrue(u.fp.raw.fp._sock.gettimeout() is None)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000302
Christian Heimes969fe572008-01-25 11:23:10 +0000303 FTP_HOST = "ftp://ftp.mirror.nl/pub/mirror/gnu/"
304
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000305 def test_ftp_basic(self):
Christian Heimes969fe572008-01-25 11:23:10 +0000306 u = _urlopen_with_retry(self.FTP_HOST)
Jeremy Hyltoncf2f4192007-08-03 20:31:38 +0000307 self.assertTrue(u.fp.fp.raw._sock.gettimeout() is None)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000308
309 def test_ftp_NoneWithdefault(self):
310 prev = socket.getdefaulttimeout()
311 socket.setdefaulttimeout(60)
312 try:
Christian Heimes969fe572008-01-25 11:23:10 +0000313 u = _urlopen_with_retry(self.FTP_HOST, timeout=None)
Neal Norwitz2f142582008-01-26 19:49:41 +0000314 self.assertEqual(u.fp.fp.raw._sock.gettimeout(), 60)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000315 finally:
316 socket.setdefaulttimeout(prev)
317
318 def test_ftp_NoneNodefault(self):
Christian Heimes969fe572008-01-25 11:23:10 +0000319 u = _urlopen_with_retry(self.FTP_HOST, timeout=None)
Neal Norwitz2f142582008-01-26 19:49:41 +0000320 self.assertTrue(u.fp.fp.raw._sock.gettimeout() is None)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000321
322 def test_ftp_Value(self):
Christian Heimes969fe572008-01-25 11:23:10 +0000323 u = _urlopen_with_retry(self.FTP_HOST, timeout=60)
Jeremy Hyltoncf2f4192007-08-03 20:31:38 +0000324 self.assertEqual(u.fp.fp.raw._sock.gettimeout(), 60)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000325
Thomas Wouters477c8d52006-05-27 19:21:47 +0000326
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000327def test_main():
328 test_support.requires("network")
Thomas Woutersb2137042007-02-01 18:02:27 +0000329 test_support.run_unittest(URLTimeoutTest,
330 urlopenNetworkTests,
331 AuthTests,
332 OtherNetworkTests,
333 CloseSocketTest,
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000334 TimeoutTest,
Thomas Woutersb2137042007-02-01 18:02:27 +0000335 )
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000336
337if __name__ == "__main__":
338 test_main()