blob: 89ddaa4390aef694e5db8b15a6883f54a20b9dc3 [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
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
Thomas Wouters477c8d52006-05-27 19:21:47 +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
Thomas Woutersb2137042007-02-01 18:02:27 +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/")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000147 urllib2.urlopen, "http://www.python.invalid./")
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000148
Thomas Wouters477c8d52006-05-27 19:21:47 +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 = [
169 'ftp://www.python.org/pub/python/misc/sousa.au',
170 'ftp://www.python.org/pub/tmp/blat',
171 'ftp://gatekeeper.research.compaq.com/pub/DEC/SRC'
172 '/research-reports/00README-Legal-Rules-Regs',
173 ]
174 self._test_urls(urls, self._extra_handlers())
175
Thomas Wouters477c8d52006-05-27 19:21:47 +0000176 def test_file(self):
177 TESTFN = test_support.TESTFN
178 f = open(TESTFN, 'w')
179 try:
180 f.write('hi there\n')
181 f.close()
182 urls = [
183 'file:'+sanepathname2url(os.path.abspath(TESTFN)),
184
185 # XXX bug, should raise URLError
186 #('file://nonsensename/etc/passwd', None, urllib2.URLError)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000187 ('file://nonsensename/etc/passwd', None, (EnvironmentError, socket.error))
Thomas Wouters477c8d52006-05-27 19:21:47 +0000188 ]
189 self._test_urls(urls, self._extra_handlers())
190 finally:
191 os.remove(TESTFN)
192
193 def test_http(self):
194 urls = [
195 'http://www.espn.com/', # redirect
196 'http://www.python.org/Spanish/Inquistion/',
197 ('http://www.python.org/cgi-bin/faqw.py',
198 'query=pythonistas&querytype=simple&casefold=yes&req=search', None),
199 'http://www.python.org/',
200 ]
201 self._test_urls(urls, self._extra_handlers())
202
203 # XXX Following test depends on machine configurations that are internal
204 # to CNRI. Need to set up a public server with the right authentication
205 # configuration for test purposes.
206
207## def test_cnri(self):
208## if socket.gethostname() == 'bitdiddle':
209## localhost = 'bitdiddle.cnri.reston.va.us'
210## elif socket.gethostname() == 'bitdiddle.concentric.net':
211## localhost = 'localhost'
212## else:
213## localhost = None
214## if localhost is not None:
215## urls = [
216## 'file://%s/etc/passwd' % localhost,
217## 'http://%s/simple/' % localhost,
218## 'http://%s/digest/' % localhost,
219## 'http://%s/not/found.h' % localhost,
220## ]
221
222## bauth = HTTPBasicAuthHandler()
223## bauth.add_password('basic_test_realm', localhost, 'jhylton',
224## 'password')
225## dauth = HTTPDigestAuthHandler()
226## dauth.add_password('digest_test_realm', localhost, 'jhylton',
227## 'password')
228
229## self._test_urls(urls, self._extra_handlers()+[bauth, dauth])
230
231 def _test_urls(self, urls, handlers):
232 import socket
233 import time
234 import logging
235 debug = logging.getLogger("test_urllib2").debug
236
237 urllib2.install_opener(urllib2.build_opener(*handlers))
238
239 for url in urls:
240 if isinstance(url, tuple):
241 url, req, expected_err = url
242 else:
243 req = expected_err = None
244 debug(url)
245 try:
246 f = urllib2.urlopen(url, req)
Guido van Rossumb940e112007-01-10 16:19:56 +0000247 except (IOError, socket.error, OSError) as err:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000248 debug(err)
249 if expected_err:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000250 msg = ("Didn't get expected error(s) %s for %s %s, got %s" %
251 (expected_err, url, req, err))
252 self.assert_(isinstance(err, expected_err), msg)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000253 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000254 with test_support.transient_internet():
255 buf = f.read()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000256 f.close()
257 debug("read %d bytes" % len(buf))
258 debug("******** next url coming up...")
259 time.sleep(0.1)
260
261 def _extra_handlers(self):
262 handlers = []
263
Thomas Wouters477c8d52006-05-27 19:21:47 +0000264 cfh = urllib2.CacheFTPHandler()
265 cfh.setTimeout(1)
266 handlers.append(cfh)
267
268 return handlers
269
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000270class TimeoutTest(unittest.TestCase):
271 def test_http_basic(self):
272 u = urllib2.urlopen("http://www.python.org")
273 self.assertTrue(u.fp._sock.fp._sock.gettimeout() is None)
274
275 def test_http_NoneWithdefault(self):
276 prev = socket.getdefaulttimeout()
277 socket.setdefaulttimeout(60)
278 try:
279 u = urllib2.urlopen("http://www.python.org", timeout=None)
280 self.assertEqual(u.fp._sock.fp._sock.gettimeout(), 60)
281 finally:
282 socket.setdefaulttimeout(prev)
283
284 def test_http_Value(self):
285 u = urllib2.urlopen("http://www.python.org", timeout=120)
286 self.assertEqual(u.fp._sock.fp._sock.gettimeout(), 120)
287
288 def test_http_NoneNodefault(self):
289 u = urllib2.urlopen("http://www.python.org", timeout=None)
290 self.assertTrue(u.fp._sock.fp._sock.gettimeout() is None)
291
292 def test_ftp_basic(self):
293 u = urllib2.urlopen("ftp://ftp.mirror.nl/pub/mirror/gnu/")
294 self.assertTrue(u.fp.fp._sock.gettimeout() is None)
295
296 def test_ftp_NoneWithdefault(self):
297 prev = socket.getdefaulttimeout()
298 socket.setdefaulttimeout(60)
299 try:
300 u = urllib2.urlopen("ftp://ftp.mirror.nl/pub/mirror/gnu/", timeout=None)
301 self.assertEqual(u.fp.fp._sock.gettimeout(), 60)
302 finally:
303 socket.setdefaulttimeout(prev)
304
305 def test_ftp_NoneNodefault(self):
306 u = urllib2.urlopen("ftp://ftp.mirror.nl/pub/mirror/gnu/", timeout=None)
307 self.assertTrue(u.fp.fp._sock.gettimeout() is None)
308
309 def test_ftp_Value(self):
310 u = urllib2.urlopen("ftp://ftp.mirror.nl/pub/mirror/gnu/", timeout=60)
311 self.assertEqual(u.fp.fp._sock.gettimeout(), 60)
312
Thomas Wouters477c8d52006-05-27 19:21:47 +0000313
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000314def test_main():
315 test_support.requires("network")
Thomas Woutersb2137042007-02-01 18:02:27 +0000316 test_support.run_unittest(URLTimeoutTest,
317 urlopenNetworkTests,
318 AuthTests,
319 OtherNetworkTests,
320 CloseSocketTest,
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000321 TimeoutTest,
Thomas Woutersb2137042007-02-01 18:02:27 +0000322 )
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000323
324if __name__ == "__main__":
325 test_main()