blob: 02d69cfabc76d22f13998301e352756b738b24c7 [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
Jeremy Hyltonec0c5082007-08-03 21:03:02 +000078 httpresponse = abused_fileobject.raw
Thomas Woutersb2137042007-02-01 18:02:27 +000079 self.assert_(httpresponse.__class__ is httplib.HTTPResponse)
80 fileobject = httpresponse.fp
Thomas Woutersb2137042007-02-01 18:02:27 +000081
82 self.assert_(not fileobject.closed)
83 response.close()
84 self.assert_(fileobject.closed)
85
Jeremy Hylton5d9c3032004-08-07 17:40:50 +000086class urlopenNetworkTests(unittest.TestCase):
87 """Tests urllib2.urlopen using the network.
88
89 These tests are not exhaustive. Assuming that testing using files does a
90 good job overall of some of the basic interface features. There are no
91 tests exercising the optional 'data' and 'proxies' arguments. No tests
92 for transparent redirection have been written.
93
94 setUp is not used for always constructing a connection to
95 http://www.python.org/ since there a few tests that don't use that address
96 and making a connection is expensive enough to warrant minimizing unneeded
97 connections.
98
99 """
100
101 def test_basic(self):
102 # Simple test expected to pass.
103 open_url = urllib2.urlopen("http://www.python.org/")
104 for attr in ("read", "close", "info", "geturl"):
105 self.assert_(hasattr(open_url, attr), "object returned from "
106 "urlopen lacks the %s attribute" % attr)
107 try:
108 self.assert_(open_url.read(), "calling 'read' failed")
109 finally:
110 open_url.close()
111
112 def test_info(self):
113 # Test 'info'.
114 open_url = urllib2.urlopen("http://www.python.org/")
115 try:
116 info_obj = open_url.info()
117 finally:
118 open_url.close()
119 self.assert_(isinstance(info_obj, mimetools.Message),
120 "object returned by 'info' is not an instance of "
121 "mimetools.Message")
122 self.assertEqual(info_obj.getsubtype(), "html")
123
124 def test_geturl(self):
125 # Make sure same URL as opened is returned by geturl.
126 URL = "http://www.python.org/"
127 open_url = urllib2.urlopen(URL)
128 try:
129 gotten_url = open_url.geturl()
130 finally:
131 open_url.close()
132 self.assertEqual(gotten_url, URL)
133
134 def test_bad_address(self):
135 # Make sure proper exception is raised when connecting to a bogus
136 # address.
137 self.assertRaises(IOError,
138 # SF patch 809915: In Sep 2003, VeriSign started
139 # highjacking invalid .com and .net addresses to
140 # boost traffic to their own site. This test
141 # started failing then. One hopes the .invalid
142 # domain will be spared to serve its defined
143 # purpose.
144 # urllib2.urlopen, "http://www.sadflkjsasadf.com/")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000145 urllib2.urlopen, "http://www.python.invalid./")
Jeremy Hylton5d9c3032004-08-07 17:40:50 +0000146
Thomas Wouters477c8d52006-05-27 19:21:47 +0000147
148class OtherNetworkTests(unittest.TestCase):
149 def setUp(self):
150 if 0: # for debugging
151 import logging
152 logger = logging.getLogger("test_urllib2net")
153 logger.addHandler(logging.StreamHandler())
154
155 def test_range (self):
156 req = urllib2.Request("http://www.python.org",
157 headers={'Range': 'bytes=20-39'})
158 result = urllib2.urlopen(req)
159 data = result.read()
160 self.assertEqual(len(data), 20)
161
162 # XXX The rest of these tests aren't very good -- they don't check much.
163 # They do sometimes catch some major disasters, though.
164
165 def test_ftp(self):
166 urls = [
167 'ftp://www.python.org/pub/python/misc/sousa.au',
168 'ftp://www.python.org/pub/tmp/blat',
169 'ftp://gatekeeper.research.compaq.com/pub/DEC/SRC'
170 '/research-reports/00README-Legal-Rules-Regs',
171 ]
172 self._test_urls(urls, self._extra_handlers())
173
Thomas Wouters477c8d52006-05-27 19:21:47 +0000174 def test_file(self):
175 TESTFN = test_support.TESTFN
176 f = open(TESTFN, 'w')
177 try:
178 f.write('hi there\n')
179 f.close()
180 urls = [
181 'file:'+sanepathname2url(os.path.abspath(TESTFN)),
182
183 # XXX bug, should raise URLError
184 #('file://nonsensename/etc/passwd', None, urllib2.URLError)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000185 ('file://nonsensename/etc/passwd', None, (EnvironmentError, socket.error))
Thomas Wouters477c8d52006-05-27 19:21:47 +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)
Guido van Rossumb940e112007-01-10 16:19:56 +0000245 except (IOError, socket.error, OSError) as err:
Thomas Wouters477c8d52006-05-27 19:21:47 +0000246 debug(err)
247 if expected_err:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000248 msg = ("Didn't get expected error(s) %s for %s %s, got %s" %
249 (expected_err, url, req, err))
250 self.assert_(isinstance(err, expected_err), msg)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000251 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000252 with test_support.transient_internet():
253 buf = f.read()
Thomas Wouters477c8d52006-05-27 19:21:47 +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
Thomas Wouters477c8d52006-05-27 19:21:47 +0000262 cfh = urllib2.CacheFTPHandler()
263 cfh.setTimeout(1)
264 handlers.append(cfh)
265
266 return handlers
267
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000268class TimeoutTest(unittest.TestCase):
269 def test_http_basic(self):
270 u = urllib2.urlopen("http://www.python.org")
Jeremy Hyltoncf2f4192007-08-03 20:31:38 +0000271 self.assertTrue(u.fp.raw.fp._sock.gettimeout() is None)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000272
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)
Jeremy Hyltoncf2f4192007-08-03 20:31:38 +0000278 self.assertTrue(u.fp.raw.fp._sock.gettimeout(), 60)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000279 finally:
280 socket.setdefaulttimeout(prev)
281
282 def test_http_Value(self):
283 u = urllib2.urlopen("http://www.python.org", timeout=120)
Jeremy Hyltoncf2f4192007-08-03 20:31:38 +0000284 self.assertEqual(u.fp.raw.fp._sock.gettimeout(), 120)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000285
286 def test_http_NoneNodefault(self):
287 u = urllib2.urlopen("http://www.python.org", timeout=None)
Jeremy Hyltoncf2f4192007-08-03 20:31:38 +0000288 self.assertTrue(u.fp.raw.fp._sock.gettimeout() is None)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000289
290 def test_ftp_basic(self):
291 u = urllib2.urlopen("ftp://ftp.mirror.nl/pub/mirror/gnu/")
Jeremy Hyltoncf2f4192007-08-03 20:31:38 +0000292 self.assertTrue(u.fp.fp.raw._sock.gettimeout() is None)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000293
294 def test_ftp_NoneWithdefault(self):
295 prev = socket.getdefaulttimeout()
296 socket.setdefaulttimeout(60)
297 try:
Jeremy Hyltoncf2f4192007-08-03 20:31:38 +0000298 u = urllib2.urlopen("ftp://ftp.mirror.nl/pub/mirror/gnu/",
299 timeout=None)
300 self.assertEqual(u.fp.fp.raw._sock.gettimeout(), 60)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000301 finally:
302 socket.setdefaulttimeout(prev)
303
304 def test_ftp_NoneNodefault(self):
Jeremy Hyltoncf2f4192007-08-03 20:31:38 +0000305 u = urllib2.urlopen("ftp://ftp.mirror.nl/pub/mirror/gnu/",
306 timeout=None)
307 self.assertTrue(u.fp.fp.raw._sock.gettimeout() is None)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000308
309 def test_ftp_Value(self):
310 u = urllib2.urlopen("ftp://ftp.mirror.nl/pub/mirror/gnu/", timeout=60)
Jeremy Hyltoncf2f4192007-08-03 20:31:38 +0000311 self.assertEqual(u.fp.fp.raw._sock.gettimeout(), 60)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000312
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()