blob: 3329822256673b4e2ac8f419eecb7d5867be286d [file] [log] [blame]
Jeremy Hylton5d9c3032004-08-07 17:40:50 +00001#!/usr/bin/env python
2
3import unittest
4from test import test_support
Georg Brandl1b06a1d2006-05-03 05:15:10 +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
Neal Norwitz769d0ee2008-01-25 06:37:23 +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)
20 except urllib2.URLError, last_exc:
21 continue
22 except:
23 raise
24 raise last_exc
25
26
Jeremy Hylton5d9c3032004-08-07 17:40:50 +000027class URLTimeoutTest(unittest.TestCase):
28
29 TIMEOUT = 10.0
30
31 def setUp(self):
32 socket.setdefaulttimeout(self.TIMEOUT)
33
34 def tearDown(self):
35 socket.setdefaulttimeout(None)
36
37 def testURLread(self):
Neal Norwitz769d0ee2008-01-25 06:37:23 +000038 f = _urlopen_with_retry("http://www.python.org/")
Jeremy Hylton5d9c3032004-08-07 17:40:50 +000039 x = f.read()
40
Georg Brandlfa42bd72006-04-30 07:06:11 +000041
42class AuthTests(unittest.TestCase):
43 """Tests urllib2 authentication features."""
44
45## Disabled at the moment since there is no page under python.org which
46## could be used to HTTP authentication.
47#
48# def test_basic_auth(self):
49# import httplib
50#
51# test_url = "http://www.python.org/test/test_urllib2/basic_auth"
52# test_hostport = "www.python.org"
53# test_realm = 'Test Realm'
54# test_user = 'test.test_urllib2net'
55# test_password = 'blah'
56#
57# # failure
58# try:
Neal Norwitz769d0ee2008-01-25 06:37:23 +000059# _urlopen_with_retry(test_url)
Georg Brandlfa42bd72006-04-30 07:06:11 +000060# except urllib2.HTTPError, exc:
61# self.assertEqual(exc.code, 401)
62# else:
63# self.fail("urlopen() should have failed with 401")
64#
65# # success
66# auth_handler = urllib2.HTTPBasicAuthHandler()
67# auth_handler.add_password(test_realm, test_hostport,
68# test_user, test_password)
69# opener = urllib2.build_opener(auth_handler)
70# f = opener.open('http://localhost/')
Neal Norwitz769d0ee2008-01-25 06:37:23 +000071# response = _urlopen_with_retry("http://www.python.org/")
Georg Brandlfa42bd72006-04-30 07:06:11 +000072#
73# # The 'userinfo' URL component is deprecated by RFC 3986 for security
74# # reasons, let's not implement it! (it's already implemented for proxy
75# # specification strings (that is, URLs or authorities specifying a
76# # proxy), so we must keep that)
77# self.assertRaises(httplib.InvalidURL,
78# urllib2.urlopen, "http://evil:thing@example.com")
79
80
Georg Brandldd7b0522007-01-21 10:35:10 +000081class CloseSocketTest(unittest.TestCase):
82
83 def test_close(self):
84 import socket, httplib, gc
85
86 # calling .close() on urllib2's response objects should close the
87 # underlying socket
88
89 # delve deep into response to fetch socket._socketobject
Neal Norwitz769d0ee2008-01-25 06:37:23 +000090 response = _urlopen_with_retry("http://www.python.org/")
Georg Brandldd7b0522007-01-21 10:35:10 +000091 abused_fileobject = response.fp
92 self.assert_(abused_fileobject.__class__ is socket._fileobject)
93 httpresponse = abused_fileobject._sock
94 self.assert_(httpresponse.__class__ is httplib.HTTPResponse)
95 fileobject = httpresponse.fp
96 self.assert_(fileobject.__class__ is socket._fileobject)
97
98 self.assert_(not fileobject.closed)
99 response.close()
100 self.assert_(fileobject.closed)
101
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000102class urlopenNetworkTests(unittest.TestCase):
103 """Tests urllib2.urlopen using the network.
104
105 These tests are not exhaustive. Assuming that testing using files does a
106 good job overall of some of the basic interface features. There are no
107 tests exercising the optional 'data' and 'proxies' arguments. No tests
108 for transparent redirection have been written.
109
110 setUp is not used for always constructing a connection to
111 http://www.python.org/ since there a few tests that don't use that address
112 and making a connection is expensive enough to warrant minimizing unneeded
113 connections.
114
115 """
116
117 def test_basic(self):
118 # Simple test expected to pass.
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000119 open_url = _urlopen_with_retry("http://www.python.org/")
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000120 for attr in ("read", "close", "info", "geturl"):
121 self.assert_(hasattr(open_url, attr), "object returned from "
122 "urlopen lacks the %s attribute" % attr)
123 try:
124 self.assert_(open_url.read(), "calling 'read' failed")
125 finally:
126 open_url.close()
127
128 def test_info(self):
129 # Test 'info'.
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000130 open_url = _urlopen_with_retry("http://www.python.org/")
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000131 try:
132 info_obj = open_url.info()
133 finally:
134 open_url.close()
135 self.assert_(isinstance(info_obj, mimetools.Message),
136 "object returned by 'info' is not an instance of "
137 "mimetools.Message")
138 self.assertEqual(info_obj.getsubtype(), "html")
139
140 def test_geturl(self):
141 # Make sure same URL as opened is returned by geturl.
142 URL = "http://www.python.org/"
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000143 open_url = _urlopen_with_retry(URL)
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000144 try:
145 gotten_url = open_url.geturl()
146 finally:
147 open_url.close()
148 self.assertEqual(gotten_url, URL)
149
150 def test_bad_address(self):
151 # Make sure proper exception is raised when connecting to a bogus
152 # address.
153 self.assertRaises(IOError,
154 # SF patch 809915: In Sep 2003, VeriSign started
155 # highjacking invalid .com and .net addresses to
156 # boost traffic to their own site. This test
157 # started failing then. One hopes the .invalid
158 # domain will be spared to serve its defined
159 # purpose.
160 # urllib2.urlopen, "http://www.sadflkjsasadf.com/")
Neal Norwitza29fc292006-06-11 20:25:56 +0000161 urllib2.urlopen, "http://www.python.invalid./")
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000162
Georg Brandl1b06a1d2006-05-03 05:15:10 +0000163
164class OtherNetworkTests(unittest.TestCase):
165 def setUp(self):
166 if 0: # for debugging
167 import logging
168 logger = logging.getLogger("test_urllib2net")
169 logger.addHandler(logging.StreamHandler())
170
171 def test_range (self):
172 req = urllib2.Request("http://www.python.org",
173 headers={'Range': 'bytes=20-39'})
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000174 result = _urlopen_with_retry(req)
Georg Brandl1b06a1d2006-05-03 05:15:10 +0000175 data = result.read()
176 self.assertEqual(len(data), 20)
177
178 # XXX The rest of these tests aren't very good -- they don't check much.
179 # They do sometimes catch some major disasters, though.
180
181 def test_ftp(self):
182 urls = [
Gregory P. Smithe9fef692007-09-09 23:36:46 +0000183 'ftp://ftp.kernel.org/pub/linux/kernel/README',
184 'ftp://ftp.kernel.org/pub/linux/kernel/non-existant-file',
185 #'ftp://ftp.kernel.org/pub/leenox/kernel/test',
Georg Brandl1b06a1d2006-05-03 05:15:10 +0000186 'ftp://gatekeeper.research.compaq.com/pub/DEC/SRC'
187 '/research-reports/00README-Legal-Rules-Regs',
188 ]
189 self._test_urls(urls, self._extra_handlers())
190
Georg Brandl1b06a1d2006-05-03 05:15:10 +0000191 def test_file(self):
192 TESTFN = test_support.TESTFN
193 f = open(TESTFN, 'w')
194 try:
195 f.write('hi there\n')
196 f.close()
197 urls = [
198 'file:'+sanepathname2url(os.path.abspath(TESTFN)),
Gregory P. Smithe9fef692007-09-09 23:36:46 +0000199 ('file:///nonsensename/etc/passwd', None, urllib2.URLError),
Georg Brandl1b06a1d2006-05-03 05:15:10 +0000200 ]
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000201 self._test_urls(urls, self._extra_handlers(), urllib2.urlopen)
Georg Brandl1b06a1d2006-05-03 05:15:10 +0000202 finally:
203 os.remove(TESTFN)
204
205 def test_http(self):
206 urls = [
207 'http://www.espn.com/', # redirect
208 'http://www.python.org/Spanish/Inquistion/',
209 ('http://www.python.org/cgi-bin/faqw.py',
210 'query=pythonistas&querytype=simple&casefold=yes&req=search', None),
211 'http://www.python.org/',
212 ]
213 self._test_urls(urls, self._extra_handlers())
214
215 # XXX Following test depends on machine configurations that are internal
216 # to CNRI. Need to set up a public server with the right authentication
217 # configuration for test purposes.
218
219## def test_cnri(self):
220## if socket.gethostname() == 'bitdiddle':
221## localhost = 'bitdiddle.cnri.reston.va.us'
222## elif socket.gethostname() == 'bitdiddle.concentric.net':
223## localhost = 'localhost'
224## else:
225## localhost = None
226## if localhost is not None:
227## urls = [
228## 'file://%s/etc/passwd' % localhost,
229## 'http://%s/simple/' % localhost,
230## 'http://%s/digest/' % localhost,
231## 'http://%s/not/found.h' % localhost,
232## ]
233
234## bauth = HTTPBasicAuthHandler()
235## bauth.add_password('basic_test_realm', localhost, 'jhylton',
236## 'password')
237## dauth = HTTPDigestAuthHandler()
238## dauth.add_password('digest_test_realm', localhost, 'jhylton',
239## 'password')
240
241## self._test_urls(urls, self._extra_handlers()+[bauth, dauth])
242
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000243 def _test_urls(self, urls, handlers, urlopen=_urlopen_with_retry):
Georg Brandl1b06a1d2006-05-03 05:15:10 +0000244 import socket
245 import time
246 import logging
247 debug = logging.getLogger("test_urllib2").debug
248
249 urllib2.install_opener(urllib2.build_opener(*handlers))
250
251 for url in urls:
252 if isinstance(url, tuple):
253 url, req, expected_err = url
254 else:
255 req = expected_err = None
256 debug(url)
257 try:
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000258 f = urlopen(url, req)
Gregory P. Smithe9fef692007-09-09 23:36:46 +0000259 except EnvironmentError, err:
Georg Brandl1b06a1d2006-05-03 05:15:10 +0000260 debug(err)
261 if expected_err:
Gregory P. Smithe9fef692007-09-09 23:36:46 +0000262 msg = ("Didn't get expected error(s) %s for %s %s, got %s: %s" %
263 (expected_err, url, req, type(err), err))
Neal Norwitzf054aeb2006-06-11 20:42:02 +0000264 self.assert_(isinstance(err, expected_err), msg)
Georg Brandl1b06a1d2006-05-03 05:15:10 +0000265 else:
Brett Cannonea2835a2007-03-14 21:44:15 +0000266 with test_support.transient_internet():
267 buf = f.read()
Georg Brandl1b06a1d2006-05-03 05:15:10 +0000268 f.close()
269 debug("read %d bytes" % len(buf))
270 debug("******** next url coming up...")
271 time.sleep(0.1)
272
273 def _extra_handlers(self):
274 handlers = []
275
Georg Brandl1b06a1d2006-05-03 05:15:10 +0000276 cfh = urllib2.CacheFTPHandler()
277 cfh.setTimeout(1)
278 handlers.append(cfh)
279
280 return handlers
281
Facundo Batista10951d52007-06-06 17:15:23 +0000282class TimeoutTest(unittest.TestCase):
283 def test_http_basic(self):
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000284 u = _urlopen_with_retry("http://www.python.org")
Facundo Batista10951d52007-06-06 17:15:23 +0000285 self.assertTrue(u.fp._sock.fp._sock.gettimeout() is None)
286
287 def test_http_NoneWithdefault(self):
288 prev = socket.getdefaulttimeout()
289 socket.setdefaulttimeout(60)
290 try:
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000291 u = _urlopen_with_retry("http://www.python.org", timeout=None)
Facundo Batista10951d52007-06-06 17:15:23 +0000292 self.assertEqual(u.fp._sock.fp._sock.gettimeout(), 60)
293 finally:
294 socket.setdefaulttimeout(prev)
295
296 def test_http_Value(self):
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000297 u = _urlopen_with_retry("http://www.python.org", timeout=120)
Facundo Batista10951d52007-06-06 17:15:23 +0000298 self.assertEqual(u.fp._sock.fp._sock.gettimeout(), 120)
299
300 def test_http_NoneNodefault(self):
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000301 u = _urlopen_with_retry("http://www.python.org", timeout=None)
Facundo Batista10951d52007-06-06 17:15:23 +0000302 self.assertTrue(u.fp._sock.fp._sock.gettimeout() is None)
303
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000304 FTP_HOST = "ftp://ftp.mirror.nl/pub/mirror/gnu/"
305
Facundo Batista10951d52007-06-06 17:15:23 +0000306 def test_ftp_basic(self):
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000307 u = _urlopen_with_retry(self.FTP_HOST)
Facundo Batista10951d52007-06-06 17:15:23 +0000308 self.assertTrue(u.fp.fp._sock.gettimeout() is None)
309
310 def test_ftp_NoneWithdefault(self):
311 prev = socket.getdefaulttimeout()
312 socket.setdefaulttimeout(60)
313 try:
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000314 u = _urlopen_with_retry(self.FTP_HOST, timeout=None)
Facundo Batista10951d52007-06-06 17:15:23 +0000315 self.assertEqual(u.fp.fp._sock.gettimeout(), 60)
316 finally:
317 socket.setdefaulttimeout(prev)
318
319 def test_ftp_NoneNodefault(self):
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000320 u = _urlopen_with_retry(self.FTP_HOST, timeout=None)
Facundo Batista10951d52007-06-06 17:15:23 +0000321 self.assertTrue(u.fp.fp._sock.gettimeout() is None)
322
323 def test_ftp_Value(self):
Neal Norwitz769d0ee2008-01-25 06:37:23 +0000324 u = _urlopen_with_retry(self.FTP_HOST, timeout=60)
Facundo Batista10951d52007-06-06 17:15:23 +0000325 self.assertEqual(u.fp.fp._sock.gettimeout(), 60)
326
Georg Brandl1b06a1d2006-05-03 05:15:10 +0000327
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000328def test_main():
329 test_support.requires("network")
Georg Brandldd7b0522007-01-21 10:35:10 +0000330 test_support.run_unittest(URLTimeoutTest,
331 urlopenNetworkTests,
332 AuthTests,
333 OtherNetworkTests,
334 CloseSocketTest,
Facundo Batista10951d52007-06-06 17:15:23 +0000335 TimeoutTest,
Georg Brandldd7b0522007-01-21 10:35:10 +0000336 )
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000337
338if __name__ == "__main__":
339 test_main()