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