blob: 0a82cb7e35a476a80351b2e1ce2a10606b91f54b [file] [log] [blame]
Brett Cannon74bfd702003-04-25 09:39:47 +00001"""Regresssion tests for urllib"""
2
Senthil Kumaranb31c87b2016-04-25 09:17:54 -07003import collections
Jeremy Hylton6102e292000-08-31 15:48:10 +00004import urllib
Hye-Shik Chang39aef792004-06-05 13:30:56 +00005import httplib
Brett Cannon74bfd702003-04-25 09:39:47 +00006import unittest
Brett Cannon74bfd702003-04-25 09:39:47 +00007import os
Senthil Kumarana99b7612011-04-14 12:54:35 +08008import sys
Brett Cannon74bfd702003-04-25 09:39:47 +00009import mimetools
Georg Brandl5a650a22005-08-26 08:51:34 +000010import tempfile
Hye-Shik Chang39aef792004-06-05 13:30:56 +000011import StringIO
Jeremy Hylton6102e292000-08-31 15:48:10 +000012
Senthil Kumaranbcd833f2012-01-11 00:09:24 +080013from test import test_support
14from base64 import b64encode
15
16
Brett Cannon74bfd702003-04-25 09:39:47 +000017def hexescape(char):
18 """Escape char as RFC 2396 specifies"""
19 hex_repr = hex(ord(char))[2:].upper()
20 if len(hex_repr) == 1:
21 hex_repr = "0%s" % hex_repr
22 return "%" + hex_repr
Jeremy Hylton6102e292000-08-31 15:48:10 +000023
Senthil Kumaran87e58552011-11-01 02:44:45 +080024
25class FakeHTTPMixin(object):
26 def fakehttp(self, fakedata):
27 class FakeSocket(StringIO.StringIO):
28
Senthil Kumaranbcd833f2012-01-11 00:09:24 +080029 def sendall(self, data):
30 FakeHTTPConnection.buf = data
31
Senthil Kumaran87e58552011-11-01 02:44:45 +080032 def makefile(self, *args, **kwds):
33 return self
34
35 def read(self, amt=None):
36 if self.closed:
37 return ""
38 return StringIO.StringIO.read(self, amt)
39
40 def readline(self, length=None):
41 if self.closed:
42 return ""
43 return StringIO.StringIO.readline(self, length)
44
45 class FakeHTTPConnection(httplib.HTTPConnection):
Senthil Kumaranbcd833f2012-01-11 00:09:24 +080046
47 # buffer to store data for verification in urlopen tests.
48 buf = ""
49
Senthil Kumaran87e58552011-11-01 02:44:45 +080050 def connect(self):
51 self.sock = FakeSocket(fakedata)
Senthil Kumaranbcd833f2012-01-11 00:09:24 +080052
Senthil Kumaran87e58552011-11-01 02:44:45 +080053 assert httplib.HTTP._connection_class == httplib.HTTPConnection
Senthil Kumaranbcd833f2012-01-11 00:09:24 +080054
Senthil Kumaran87e58552011-11-01 02:44:45 +080055 httplib.HTTP._connection_class = FakeHTTPConnection
56
57 def unfakehttp(self):
58 httplib.HTTP._connection_class = httplib.HTTPConnection
59
60
Brett Cannon74bfd702003-04-25 09:39:47 +000061class urlopen_FileTests(unittest.TestCase):
62 """Test urlopen() opening a temporary file.
Jeremy Hylton6102e292000-08-31 15:48:10 +000063
Brett Cannon74bfd702003-04-25 09:39:47 +000064 Try to test as much functionality as possible so as to cut down on reliance
Andrew M. Kuchlingf1a2f9e2004-06-29 13:07:53 +000065 on connecting to the Net for testing.
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000066
Brett Cannon74bfd702003-04-25 09:39:47 +000067 """
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000068
Brett Cannon74bfd702003-04-25 09:39:47 +000069 def setUp(self):
70 """Setup of a temp file to use for testing"""
71 self.text = "test_urllib: %s\n" % self.__class__.__name__
Guido van Rossum51735b02003-04-25 15:01:05 +000072 FILE = file(test_support.TESTFN, 'wb')
Brett Cannon74bfd702003-04-25 09:39:47 +000073 try:
74 FILE.write(self.text)
75 finally:
76 FILE.close()
77 self.pathname = test_support.TESTFN
78 self.returned_obj = urllib.urlopen("file:%s" % self.pathname)
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000079
Brett Cannon74bfd702003-04-25 09:39:47 +000080 def tearDown(self):
81 """Shut down the open object"""
82 self.returned_obj.close()
Brett Cannon19691362003-04-29 05:08:06 +000083 os.remove(test_support.TESTFN)
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000084
Brett Cannon74bfd702003-04-25 09:39:47 +000085 def test_interface(self):
86 # Make sure object returned by urlopen() has the specified methods
87 for attr in ("read", "readline", "readlines", "fileno",
Georg Brandl9b0d46d2008-01-20 11:43:03 +000088 "close", "info", "geturl", "getcode", "__iter__"):
Benjamin Peterson5c8da862009-06-30 22:57:08 +000089 self.assertTrue(hasattr(self.returned_obj, attr),
Brett Cannon74bfd702003-04-25 09:39:47 +000090 "object returned by urlopen() lacks %s attribute" %
91 attr)
Skip Montanaroe78b92a2001-01-20 20:22:30 +000092
Brett Cannon74bfd702003-04-25 09:39:47 +000093 def test_read(self):
94 self.assertEqual(self.text, self.returned_obj.read())
Skip Montanaro080c9972001-01-28 21:12:22 +000095
Brett Cannon74bfd702003-04-25 09:39:47 +000096 def test_readline(self):
97 self.assertEqual(self.text, self.returned_obj.readline())
98 self.assertEqual('', self.returned_obj.readline(),
99 "calling readline() after exhausting the file did not"
100 " return an empty string")
Skip Montanaro080c9972001-01-28 21:12:22 +0000101
Brett Cannon74bfd702003-04-25 09:39:47 +0000102 def test_readlines(self):
103 lines_list = self.returned_obj.readlines()
104 self.assertEqual(len(lines_list), 1,
105 "readlines() returned the wrong number of lines")
106 self.assertEqual(lines_list[0], self.text,
107 "readlines() returned improper text")
Skip Montanaro080c9972001-01-28 21:12:22 +0000108
Brett Cannon74bfd702003-04-25 09:39:47 +0000109 def test_fileno(self):
110 file_num = self.returned_obj.fileno()
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000111 self.assertIsInstance(file_num, int, "fileno() did not return an int")
Brett Cannon74bfd702003-04-25 09:39:47 +0000112 self.assertEqual(os.read(file_num, len(self.text)), self.text,
113 "Reading on the file descriptor returned by fileno() "
114 "did not return the expected text")
Skip Montanaroe78b92a2001-01-20 20:22:30 +0000115
Brett Cannon74bfd702003-04-25 09:39:47 +0000116 def test_close(self):
117 # Test close() by calling it hear and then having it be called again
118 # by the tearDown() method for the test
119 self.returned_obj.close()
Skip Montanaro080c9972001-01-28 21:12:22 +0000120
Brett Cannon74bfd702003-04-25 09:39:47 +0000121 def test_info(self):
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000122 self.assertIsInstance(self.returned_obj.info(), mimetools.Message)
Skip Montanaroe78b92a2001-01-20 20:22:30 +0000123
Brett Cannon74bfd702003-04-25 09:39:47 +0000124 def test_geturl(self):
125 self.assertEqual(self.returned_obj.geturl(), self.pathname)
Skip Montanaro080c9972001-01-28 21:12:22 +0000126
Georg Brandl9b0d46d2008-01-20 11:43:03 +0000127 def test_getcode(self):
128 self.assertEqual(self.returned_obj.getcode(), None)
129
Brett Cannon74bfd702003-04-25 09:39:47 +0000130 def test_iter(self):
131 # Test iterator
132 # Don't need to count number of iterations since test would fail the
133 # instant it returned anything beyond the first line from the
134 # comparison
135 for line in self.returned_obj.__iter__():
136 self.assertEqual(line, self.text)
Skip Montanaro080c9972001-01-28 21:12:22 +0000137
Senthil Kumaran58c60622012-01-21 11:43:02 +0800138 def test_relativelocalfile(self):
139 self.assertRaises(ValueError,urllib.urlopen,'./' + self.pathname)
140
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000141class ProxyTests(unittest.TestCase):
142
143 def setUp(self):
Walter Dörwald4b965f62009-04-26 20:51:44 +0000144 # Records changes to env vars
145 self.env = test_support.EnvironmentVarGuard()
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000146 # Delete all proxy related env vars
Senthil Kumaran7a2ee0b2010-01-08 19:20:25 +0000147 for k in os.environ.keys():
Walter Dörwald4b965f62009-04-26 20:51:44 +0000148 if 'proxy' in k.lower():
Senthil Kumarandc61ec32009-10-01 01:50:13 +0000149 self.env.unset(k)
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000150
151 def tearDown(self):
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000152 # Restore all proxy related env vars
Walter Dörwald4b965f62009-04-26 20:51:44 +0000153 self.env.__exit__()
154 del self.env
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000155
156 def test_getproxies_environment_keep_no_proxies(self):
Walter Dörwald4b965f62009-04-26 20:51:44 +0000157 self.env.set('NO_PROXY', 'localhost')
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000158 proxies = urllib.getproxies_environment()
159 # getproxies_environment use lowered case truncated (no '_proxy') keys
Ezio Melotti2623a372010-11-21 13:34:58 +0000160 self.assertEqual('localhost', proxies['no'])
Senthil Kumaranb5bd4c82011-08-06 12:24:33 +0800161 # List of no_proxies with space.
Senthil Kumaranb31c87b2016-04-25 09:17:54 -0700162 self.env.set('NO_PROXY', 'localhost, anotherdomain.com, newdomain.com:1234')
Senthil Kumaranb5bd4c82011-08-06 12:24:33 +0800163 self.assertTrue(urllib.proxy_bypass_environment('anotherdomain.com'))
Senthil Kumaranb31c87b2016-04-25 09:17:54 -0700164 self.assertTrue(urllib.proxy_bypass_environment('anotherdomain.com:8888'))
165 self.assertTrue(urllib.proxy_bypass_environment('newdomain.com:1234'))
166
Martin Panter064ee4d2016-04-30 01:03:40 +0000167 def test_proxy_bypass_environment_host_match(self):
168 bypass = urllib.proxy_bypass_environment
169 self.env.set('NO_PROXY',
170 'localhost, anotherdomain.com, newdomain.com:1234')
171 self.assertTrue(bypass('localhost'))
172 self.assertTrue(bypass('LocalHost')) # MixedCase
173 self.assertTrue(bypass('LOCALHOST')) # UPPERCASE
174 self.assertTrue(bypass('newdomain.com:1234'))
175 self.assertTrue(bypass('anotherdomain.com:8888'))
176 self.assertTrue(bypass('www.newdomain.com:1234'))
177 self.assertFalse(bypass('prelocalhost'))
178 self.assertFalse(bypass('newdomain.com')) # no port
179 self.assertFalse(bypass('newdomain.com:1235')) # wrong port
Senthil Kumaranb31c87b2016-04-25 09:17:54 -0700180
181class ProxyTests_withOrderedEnv(unittest.TestCase):
182
183 def setUp(self):
184 # We need to test conditions, where variable order _is_ significant
185 self._saved_env = os.environ
186 # Monkey patch os.environ, start with empty fake environment
187 os.environ = collections.OrderedDict()
188
189 def tearDown(self):
190 os.environ = self._saved_env
191
192 def test_getproxies_environment_prefer_lowercase(self):
193 # Test lowercase preference with removal
194 os.environ['no_proxy'] = ''
195 os.environ['No_Proxy'] = 'localhost'
196 self.assertFalse(urllib.proxy_bypass_environment('localhost'))
197 self.assertFalse(urllib.proxy_bypass_environment('arbitrary'))
198 os.environ['http_proxy'] = ''
199 os.environ['HTTP_PROXY'] = 'http://somewhere:3128'
200 proxies = urllib.getproxies_environment()
201 self.assertEqual({}, proxies)
202 # Test lowercase preference of proxy bypass and correct matching including ports
203 os.environ['no_proxy'] = 'localhost, noproxy.com, my.proxy:1234'
204 os.environ['No_Proxy'] = 'xyz.com'
205 self.assertTrue(urllib.proxy_bypass_environment('localhost'))
206 self.assertTrue(urllib.proxy_bypass_environment('noproxy.com:5678'))
207 self.assertTrue(urllib.proxy_bypass_environment('my.proxy:1234'))
208 self.assertFalse(urllib.proxy_bypass_environment('my.proxy'))
209 self.assertFalse(urllib.proxy_bypass_environment('arbitrary'))
210 # Test lowercase preference with replacement
211 os.environ['http_proxy'] = 'http://somewhere:3128'
212 os.environ['Http_Proxy'] = 'http://somewhereelse:3128'
213 proxies = urllib.getproxies_environment()
214 self.assertEqual('http://somewhere:3128', proxies['http'])
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000215
216
Senthil Kumaran87e58552011-11-01 02:44:45 +0800217class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin):
Hye-Shik Chang39aef792004-06-05 13:30:56 +0000218 """Test urlopen() opening a fake http connection."""
219
Hye-Shik Chang39aef792004-06-05 13:30:56 +0000220 def test_read(self):
221 self.fakehttp('Hello!')
222 try:
223 fp = urllib.urlopen("http://python.org/")
224 self.assertEqual(fp.readline(), 'Hello!')
225 self.assertEqual(fp.readline(), '')
Georg Brandl9b0d46d2008-01-20 11:43:03 +0000226 self.assertEqual(fp.geturl(), 'http://python.org/')
227 self.assertEqual(fp.getcode(), 200)
Hye-Shik Chang39aef792004-06-05 13:30:56 +0000228 finally:
229 self.unfakehttp()
230
Senthil Kumaran49c44082011-04-13 07:31:45 +0800231 def test_url_fragment(self):
232 # Issue #11703: geturl() omits fragments in the original URL.
233 url = 'http://docs.python.org/library/urllib.html#OK'
234 self.fakehttp('Hello!')
235 try:
236 fp = urllib.urlopen(url)
237 self.assertEqual(fp.geturl(), url)
238 finally:
239 self.unfakehttp()
240
Kurt B. Kaiser0f7c25d2008-01-02 04:11:28 +0000241 def test_read_bogus(self):
Kurt B. Kaiser0a112322008-01-02 05:23:38 +0000242 # urlopen() should raise IOError for many error codes.
Kurt B. Kaiser0f7c25d2008-01-02 04:11:28 +0000243 self.fakehttp('''HTTP/1.1 401 Authentication Required
244Date: Wed, 02 Jan 2008 03:03:54 GMT
245Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e
246Connection: close
247Content-Type: text/html; charset=iso-8859-1
248''')
249 try:
250 self.assertRaises(IOError, urllib.urlopen, "http://python.org/")
251 finally:
252 self.unfakehttp()
253
guido@google.comf1509302011-03-28 13:47:01 -0700254 def test_invalid_redirect(self):
255 # urlopen() should raise IOError for many error codes.
256 self.fakehttp("""HTTP/1.1 302 Found
257Date: Wed, 02 Jan 2008 03:03:54 GMT
258Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e
259Location: file:README
260Connection: close
261Content-Type: text/html; charset=iso-8859-1
262""")
263 try:
Martin Panterade40972016-02-04 06:01:35 +0000264 msg = "Redirection to url 'file:"
265 with self.assertRaisesRegexp(IOError, msg):
266 urllib.urlopen("http://python.org/")
guido@google.comf1509302011-03-28 13:47:01 -0700267 finally:
268 self.unfakehttp()
269
Martin Panterade40972016-02-04 06:01:35 +0000270 def test_redirect_limit_independent(self):
271 # Ticket #12923: make sure independent requests each use their
272 # own retry limit.
273 for i in range(urllib.FancyURLopener().maxtries):
274 self.fakehttp(b'''HTTP/1.1 302 Found
275Location: file://guidocomputer.athome.com:/python/license
276Connection: close
277''')
278 try:
279 self.assertRaises(IOError, urllib.urlopen,
280 "http://something")
281 finally:
282 self.unfakehttp()
283
Georg Brandlf66b6032007-03-14 08:27:52 +0000284 def test_empty_socket(self):
Kurt B. Kaiser0a112322008-01-02 05:23:38 +0000285 # urlopen() raises IOError if the underlying socket does not send any
286 # data. (#1680230)
Georg Brandlf66b6032007-03-14 08:27:52 +0000287 self.fakehttp('')
288 try:
289 self.assertRaises(IOError, urllib.urlopen, 'http://something')
290 finally:
291 self.unfakehttp()
292
Senthil Kumaranf8d370e2012-10-27 03:48:40 -0700293 def test_missing_localfile(self):
294 self.assertRaises(IOError, urllib.urlopen,
295 'file://localhost/a/missing/file.py')
296 fd, tmp_file = tempfile.mkstemp()
297 tmp_fileurl = 'file://localhost/' + tmp_file.replace(os.path.sep, '/')
Senthil Kumarana085f002013-06-01 07:59:10 -0700298 self.assertTrue(os.path.exists(tmp_file))
Senthil Kumaranf8d370e2012-10-27 03:48:40 -0700299 try:
Senthil Kumaranf8d370e2012-10-27 03:48:40 -0700300 fp = urllib.urlopen(tmp_fileurl)
Senthil Kumarana085f002013-06-01 07:59:10 -0700301 fp.close()
Senthil Kumaranf8d370e2012-10-27 03:48:40 -0700302 finally:
303 os.close(fd)
Senthil Kumarana085f002013-06-01 07:59:10 -0700304 os.unlink(tmp_file)
Senthil Kumaranf8d370e2012-10-27 03:48:40 -0700305
306 self.assertFalse(os.path.exists(tmp_file))
307 self.assertRaises(IOError, urllib.urlopen, tmp_fileurl)
308
309 def test_ftp_nonexisting(self):
310 self.assertRaises(IOError, urllib.urlopen,
311 'ftp://localhost/not/existing/file.py')
312
313
Senthil Kumaranbcd833f2012-01-11 00:09:24 +0800314 def test_userpass_inurl(self):
315 self.fakehttp('Hello!')
316 try:
317 fakehttp_wrapper = httplib.HTTP._connection_class
318 fp = urllib.urlopen("http://user:pass@python.org/")
319 authorization = ("Authorization: Basic %s\r\n" %
320 b64encode('user:pass'))
321 # The authorization header must be in place
322 self.assertIn(authorization, fakehttp_wrapper.buf)
323 self.assertEqual(fp.readline(), "Hello!")
324 self.assertEqual(fp.readline(), "")
325 self.assertEqual(fp.geturl(), 'http://user:pass@python.org/')
326 self.assertEqual(fp.getcode(), 200)
327 finally:
328 self.unfakehttp()
329
330 def test_userpass_with_spaces_inurl(self):
331 self.fakehttp('Hello!')
332 try:
333 url = "http://a b:c d@python.org/"
334 fakehttp_wrapper = httplib.HTTP._connection_class
335 authorization = ("Authorization: Basic %s\r\n" %
336 b64encode('a b:c d'))
337 fp = urllib.urlopen(url)
338 # The authorization header must be in place
339 self.assertIn(authorization, fakehttp_wrapper.buf)
340 self.assertEqual(fp.readline(), "Hello!")
341 self.assertEqual(fp.readline(), "")
342 # the spaces are quoted in URL so no match
343 self.assertNotEqual(fp.geturl(), url)
344 self.assertEqual(fp.getcode(), 200)
345 finally:
346 self.unfakehttp()
347
348
Brett Cannon19691362003-04-29 05:08:06 +0000349class urlretrieve_FileTests(unittest.TestCase):
Brett Cannon74bfd702003-04-25 09:39:47 +0000350 """Test urllib.urlretrieve() on local files"""
Skip Montanaro080c9972001-01-28 21:12:22 +0000351
Brett Cannon19691362003-04-29 05:08:06 +0000352 def setUp(self):
Georg Brandl5a650a22005-08-26 08:51:34 +0000353 # Create a list of temporary files. Each item in the list is a file
354 # name (absolute path or relative to the current working directory).
355 # All files in this list will be deleted in the tearDown method. Note,
356 # this only helps to makes sure temporary files get deleted, but it
357 # does nothing about trying to close files that may still be open. It
358 # is the responsibility of the developer to properly close files even
359 # when exceptional conditions occur.
360 self.tempFiles = []
361
Brett Cannon19691362003-04-29 05:08:06 +0000362 # Create a temporary file.
Georg Brandl5a650a22005-08-26 08:51:34 +0000363 self.registerFileForCleanUp(test_support.TESTFN)
Brett Cannon19691362003-04-29 05:08:06 +0000364 self.text = 'testing urllib.urlretrieve'
Georg Brandl5a650a22005-08-26 08:51:34 +0000365 try:
366 FILE = file(test_support.TESTFN, 'wb')
367 FILE.write(self.text)
368 FILE.close()
369 finally:
370 try: FILE.close()
371 except: pass
Brett Cannon19691362003-04-29 05:08:06 +0000372
373 def tearDown(self):
Georg Brandl5a650a22005-08-26 08:51:34 +0000374 # Delete the temporary files.
375 for each in self.tempFiles:
376 try: os.remove(each)
377 except: pass
378
379 def constructLocalFileUrl(self, filePath):
380 return "file://%s" % urllib.pathname2url(os.path.abspath(filePath))
381
382 def createNewTempFile(self, data=""):
383 """Creates a new temporary file containing the specified data,
384 registers the file for deletion during the test fixture tear down, and
385 returns the absolute path of the file."""
386
387 newFd, newFilePath = tempfile.mkstemp()
388 try:
389 self.registerFileForCleanUp(newFilePath)
390 newFile = os.fdopen(newFd, "wb")
391 newFile.write(data)
392 newFile.close()
393 finally:
394 try: newFile.close()
395 except: pass
396 return newFilePath
397
398 def registerFileForCleanUp(self, fileName):
399 self.tempFiles.append(fileName)
Brett Cannon19691362003-04-29 05:08:06 +0000400
401 def test_basic(self):
402 # Make sure that a local file just gets its own location returned and
403 # a headers value is returned.
404 result = urllib.urlretrieve("file:%s" % test_support.TESTFN)
405 self.assertEqual(result[0], test_support.TESTFN)
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000406 self.assertIsInstance(result[1], mimetools.Message,
407 "did not get a mimetools.Message instance as "
408 "second returned value")
Brett Cannon19691362003-04-29 05:08:06 +0000409
410 def test_copy(self):
411 # Test that setting the filename argument works.
412 second_temp = "%s.2" % test_support.TESTFN
Georg Brandl5a650a22005-08-26 08:51:34 +0000413 self.registerFileForCleanUp(second_temp)
414 result = urllib.urlretrieve(self.constructLocalFileUrl(
415 test_support.TESTFN), second_temp)
Brett Cannon19691362003-04-29 05:08:06 +0000416 self.assertEqual(second_temp, result[0])
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000417 self.assertTrue(os.path.exists(second_temp), "copy of the file was not "
Brett Cannon19691362003-04-29 05:08:06 +0000418 "made")
419 FILE = file(second_temp, 'rb')
420 try:
421 text = FILE.read()
Brett Cannon19691362003-04-29 05:08:06 +0000422 FILE.close()
Georg Brandl5a650a22005-08-26 08:51:34 +0000423 finally:
424 try: FILE.close()
425 except: pass
Brett Cannon19691362003-04-29 05:08:06 +0000426 self.assertEqual(self.text, text)
427
428 def test_reporthook(self):
429 # Make sure that the reporthook works.
430 def hooktester(count, block_size, total_size, count_holder=[0]):
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000431 self.assertIsInstance(count, int)
432 self.assertIsInstance(block_size, int)
433 self.assertIsInstance(total_size, int)
Brett Cannon19691362003-04-29 05:08:06 +0000434 self.assertEqual(count, count_holder[0])
435 count_holder[0] = count_holder[0] + 1
436 second_temp = "%s.2" % test_support.TESTFN
Georg Brandl5a650a22005-08-26 08:51:34 +0000437 self.registerFileForCleanUp(second_temp)
438 urllib.urlretrieve(self.constructLocalFileUrl(test_support.TESTFN),
439 second_temp, hooktester)
440
441 def test_reporthook_0_bytes(self):
442 # Test on zero length file. Should call reporthook only 1 time.
443 report = []
444 def hooktester(count, block_size, total_size, _report=report):
445 _report.append((count, block_size, total_size))
446 srcFileName = self.createNewTempFile()
447 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
448 test_support.TESTFN, hooktester)
449 self.assertEqual(len(report), 1)
450 self.assertEqual(report[0][2], 0)
451
452 def test_reporthook_5_bytes(self):
453 # Test on 5 byte file. Should call reporthook only 2 times (once when
454 # the "network connection" is established and once when the block is
455 # read). Since the block size is 8192 bytes, only one block read is
456 # required to read the entire file.
457 report = []
458 def hooktester(count, block_size, total_size, _report=report):
459 _report.append((count, block_size, total_size))
460 srcFileName = self.createNewTempFile("x" * 5)
461 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
462 test_support.TESTFN, hooktester)
463 self.assertEqual(len(report), 2)
464 self.assertEqual(report[0][1], 8192)
465 self.assertEqual(report[0][2], 5)
466
467 def test_reporthook_8193_bytes(self):
468 # Test on 8193 byte file. Should call reporthook only 3 times (once
469 # when the "network connection" is established, once for the next 8192
470 # bytes, and once for the last byte).
471 report = []
472 def hooktester(count, block_size, total_size, _report=report):
473 _report.append((count, block_size, total_size))
474 srcFileName = self.createNewTempFile("x" * 8193)
475 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
476 test_support.TESTFN, hooktester)
477 self.assertEqual(len(report), 3)
478 self.assertEqual(report[0][1], 8192)
479 self.assertEqual(report[0][2], 8193)
Skip Montanaro080c9972001-01-28 21:12:22 +0000480
Senthil Kumaran87e58552011-11-01 02:44:45 +0800481
482class urlretrieve_HttpTests(unittest.TestCase, FakeHTTPMixin):
483 """Test urllib.urlretrieve() using fake http connections"""
484
485 def test_short_content_raises_ContentTooShortError(self):
486 self.fakehttp('''HTTP/1.1 200 OK
487Date: Wed, 02 Jan 2008 03:03:54 GMT
488Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e
489Connection: close
490Content-Length: 100
491Content-Type: text/html; charset=iso-8859-1
492
493FF
494''')
495
496 def _reporthook(par1, par2, par3):
497 pass
498
499 try:
500 self.assertRaises(urllib.ContentTooShortError, urllib.urlretrieve,
501 'http://example.com', reporthook=_reporthook)
502 finally:
503 self.unfakehttp()
504
505 def test_short_content_raises_ContentTooShortError_without_reporthook(self):
506 self.fakehttp('''HTTP/1.1 200 OK
507Date: Wed, 02 Jan 2008 03:03:54 GMT
508Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e
509Connection: close
510Content-Length: 100
511Content-Type: text/html; charset=iso-8859-1
512
513FF
514''')
515 try:
516 self.assertRaises(urllib.ContentTooShortError, urllib.urlretrieve, 'http://example.com/')
517 finally:
518 self.unfakehttp()
519
Brett Cannon74bfd702003-04-25 09:39:47 +0000520class QuotingTests(unittest.TestCase):
521 """Tests for urllib.quote() and urllib.quote_plus()
Tim Petersc2659cf2003-05-12 20:19:37 +0000522
Brett Cannon74bfd702003-04-25 09:39:47 +0000523 According to RFC 2396 ("Uniform Resource Identifiers), to escape a
524 character you write it as '%' + <2 character US-ASCII hex value>. The Python
525 code of ``'%' + hex(ord(<character>))[2:]`` escapes a character properly.
526 Case does not matter on the hex letters.
527
528 The various character sets specified are:
Tim Petersc2659cf2003-05-12 20:19:37 +0000529
Brett Cannon74bfd702003-04-25 09:39:47 +0000530 Reserved characters : ";/?:@&=+$,"
531 Have special meaning in URIs and must be escaped if not being used for
532 their special meaning
533 Data characters : letters, digits, and "-_.!~*'()"
534 Unreserved and do not need to be escaped; can be, though, if desired
535 Control characters : 0x00 - 0x1F, 0x7F
536 Have no use in URIs so must be escaped
537 space : 0x20
538 Must be escaped
539 Delimiters : '<>#%"'
540 Must be escaped
541 Unwise : "{}|\^[]`"
542 Must be escaped
Tim Petersc2659cf2003-05-12 20:19:37 +0000543
Brett Cannon74bfd702003-04-25 09:39:47 +0000544 """
545
546 def test_never_quote(self):
547 # Make sure quote() does not quote letters, digits, and "_,.-"
548 do_not_quote = '' .join(["ABCDEFGHIJKLMNOPQRSTUVWXYZ",
549 "abcdefghijklmnopqrstuvwxyz",
550 "0123456789",
551 "_.-"])
552 result = urllib.quote(do_not_quote)
553 self.assertEqual(do_not_quote, result,
554 "using quote(): %s != %s" % (do_not_quote, result))
555 result = urllib.quote_plus(do_not_quote)
556 self.assertEqual(do_not_quote, result,
557 "using quote_plus(): %s != %s" % (do_not_quote, result))
558
559 def test_default_safe(self):
560 # Test '/' is default value for 'safe' parameter
561 self.assertEqual(urllib.quote.func_defaults[0], '/')
562
563 def test_safe(self):
564 # Test setting 'safe' parameter does what it should do
565 quote_by_default = "<>"
566 result = urllib.quote(quote_by_default, safe=quote_by_default)
567 self.assertEqual(quote_by_default, result,
568 "using quote(): %s != %s" % (quote_by_default, result))
569 result = urllib.quote_plus(quote_by_default, safe=quote_by_default)
570 self.assertEqual(quote_by_default, result,
571 "using quote_plus(): %s != %s" %
572 (quote_by_default, result))
573
574 def test_default_quoting(self):
575 # Make sure all characters that should be quoted are by default sans
576 # space (separate test for that).
577 should_quote = [chr(num) for num in range(32)] # For 0x00 - 0x1F
578 should_quote.append('<>#%"{}|\^[]`')
579 should_quote.append(chr(127)) # For 0x7F
580 should_quote = ''.join(should_quote)
581 for char in should_quote:
582 result = urllib.quote(char)
583 self.assertEqual(hexescape(char), result,
584 "using quote(): %s should be escaped to %s, not %s" %
585 (char, hexescape(char), result))
586 result = urllib.quote_plus(char)
587 self.assertEqual(hexescape(char), result,
588 "using quote_plus(): "
Tim Petersc2659cf2003-05-12 20:19:37 +0000589 "%s should be escapes to %s, not %s" %
Brett Cannon74bfd702003-04-25 09:39:47 +0000590 (char, hexescape(char), result))
591 del should_quote
592 partial_quote = "ab[]cd"
593 expected = "ab%5B%5Dcd"
594 result = urllib.quote(partial_quote)
595 self.assertEqual(expected, result,
596 "using quote(): %s != %s" % (expected, result))
Senthil Kumaran0d4c34c2011-09-13 06:42:21 +0800597 result = urllib.quote_plus(partial_quote)
Brett Cannon74bfd702003-04-25 09:39:47 +0000598 self.assertEqual(expected, result,
599 "using quote_plus(): %s != %s" % (expected, result))
Senthil Kumaranc7743aa2010-07-19 17:35:50 +0000600 self.assertRaises(TypeError, urllib.quote, None)
Brett Cannon74bfd702003-04-25 09:39:47 +0000601
602 def test_quoting_space(self):
603 # Make sure quote() and quote_plus() handle spaces as specified in
604 # their unique way
605 result = urllib.quote(' ')
606 self.assertEqual(result, hexescape(' '),
607 "using quote(): %s != %s" % (result, hexescape(' ')))
608 result = urllib.quote_plus(' ')
609 self.assertEqual(result, '+',
610 "using quote_plus(): %s != +" % result)
611 given = "a b cd e f"
612 expect = given.replace(' ', hexescape(' '))
613 result = urllib.quote(given)
614 self.assertEqual(expect, result,
615 "using quote(): %s != %s" % (expect, result))
616 expect = given.replace(' ', '+')
617 result = urllib.quote_plus(given)
618 self.assertEqual(expect, result,
619 "using quote_plus(): %s != %s" % (expect, result))
620
Raymond Hettinger2bdec7b2005-09-10 14:30:09 +0000621 def test_quoting_plus(self):
622 self.assertEqual(urllib.quote_plus('alpha+beta gamma'),
623 'alpha%2Bbeta+gamma')
624 self.assertEqual(urllib.quote_plus('alpha+beta gamma', '+'),
625 'alpha+beta+gamma')
626
Brett Cannon74bfd702003-04-25 09:39:47 +0000627class UnquotingTests(unittest.TestCase):
628 """Tests for unquote() and unquote_plus()
Tim Petersc2659cf2003-05-12 20:19:37 +0000629
Brett Cannon74bfd702003-04-25 09:39:47 +0000630 See the doc string for quoting_Tests for details on quoting and such.
631
632 """
633
634 def test_unquoting(self):
635 # Make sure unquoting of all ASCII values works
636 escape_list = []
637 for num in range(128):
638 given = hexescape(chr(num))
639 expect = chr(num)
640 result = urllib.unquote(given)
641 self.assertEqual(expect, result,
642 "using unquote(): %s != %s" % (expect, result))
643 result = urllib.unquote_plus(given)
644 self.assertEqual(expect, result,
645 "using unquote_plus(): %s != %s" %
646 (expect, result))
647 escape_list.append(given)
648 escape_string = ''.join(escape_list)
649 del escape_list
650 result = urllib.unquote(escape_string)
651 self.assertEqual(result.count('%'), 1,
652 "using quote(): not all characters escaped; %s" %
653 result)
654 result = urllib.unquote(escape_string)
655 self.assertEqual(result.count('%'), 1,
656 "using unquote(): not all characters escaped: "
657 "%s" % result)
658
Senthil Kumaranf3e9b2a2010-03-18 12:14:15 +0000659 def test_unquoting_badpercent(self):
660 # Test unquoting on bad percent-escapes
661 given = '%xab'
662 expect = given
663 result = urllib.unquote(given)
664 self.assertEqual(expect, result, "using unquote(): %r != %r"
665 % (expect, result))
666 given = '%x'
667 expect = given
668 result = urllib.unquote(given)
669 self.assertEqual(expect, result, "using unquote(): %r != %r"
670 % (expect, result))
671 given = '%'
672 expect = given
673 result = urllib.unquote(given)
674 self.assertEqual(expect, result, "using unquote(): %r != %r"
675 % (expect, result))
676
677 def test_unquoting_mixed_case(self):
678 # Test unquoting on mixed-case hex digits in the percent-escapes
679 given = '%Ab%eA'
680 expect = '\xab\xea'
681 result = urllib.unquote(given)
682 self.assertEqual(expect, result, "using unquote(): %r != %r"
683 % (expect, result))
684
Brett Cannon74bfd702003-04-25 09:39:47 +0000685 def test_unquoting_parts(self):
686 # Make sure unquoting works when have non-quoted characters
687 # interspersed
688 given = 'ab%sd' % hexescape('c')
689 expect = "abcd"
690 result = urllib.unquote(given)
691 self.assertEqual(expect, result,
692 "using quote(): %s != %s" % (expect, result))
693 result = urllib.unquote_plus(given)
694 self.assertEqual(expect, result,
695 "using unquote_plus(): %s != %s" % (expect, result))
Tim Petersc2659cf2003-05-12 20:19:37 +0000696
Brett Cannon74bfd702003-04-25 09:39:47 +0000697 def test_unquoting_plus(self):
698 # Test difference between unquote() and unquote_plus()
699 given = "are+there+spaces..."
700 expect = given
701 result = urllib.unquote(given)
702 self.assertEqual(expect, result,
703 "using unquote(): %s != %s" % (expect, result))
704 expect = given.replace('+', ' ')
705 result = urllib.unquote_plus(given)
706 self.assertEqual(expect, result,
707 "using unquote_plus(): %s != %s" % (expect, result))
708
Raymond Hettinger4b0f20d2005-10-15 16:41:53 +0000709 def test_unquote_with_unicode(self):
710 r = urllib.unquote(u'br%C3%BCckner_sapporo_20050930.doc')
711 self.assertEqual(r, u'br\xc3\xbcckner_sapporo_20050930.doc')
712
Brett Cannon74bfd702003-04-25 09:39:47 +0000713class urlencode_Tests(unittest.TestCase):
714 """Tests for urlencode()"""
715
716 def help_inputtype(self, given, test_type):
717 """Helper method for testing different input types.
Tim Petersc2659cf2003-05-12 20:19:37 +0000718
Brett Cannon74bfd702003-04-25 09:39:47 +0000719 'given' must lead to only the pairs:
720 * 1st, 1
721 * 2nd, 2
722 * 3rd, 3
Tim Petersc2659cf2003-05-12 20:19:37 +0000723
Brett Cannon74bfd702003-04-25 09:39:47 +0000724 Test cannot assume anything about order. Docs make no guarantee and
725 have possible dictionary input.
Tim Petersc2659cf2003-05-12 20:19:37 +0000726
Brett Cannon74bfd702003-04-25 09:39:47 +0000727 """
728 expect_somewhere = ["1st=1", "2nd=2", "3rd=3"]
729 result = urllib.urlencode(given)
730 for expected in expect_somewhere:
Ezio Melottiaa980582010-01-23 23:04:36 +0000731 self.assertIn(expected, result,
Brett Cannon74bfd702003-04-25 09:39:47 +0000732 "testing %s: %s not found in %s" %
733 (test_type, expected, result))
734 self.assertEqual(result.count('&'), 2,
735 "testing %s: expected 2 '&'s; got %s" %
736 (test_type, result.count('&')))
737 amp_location = result.index('&')
738 on_amp_left = result[amp_location - 1]
739 on_amp_right = result[amp_location + 1]
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000740 self.assertTrue(on_amp_left.isdigit() and on_amp_right.isdigit(),
Brett Cannon74bfd702003-04-25 09:39:47 +0000741 "testing %s: '&' not located in proper place in %s" %
742 (test_type, result))
743 self.assertEqual(len(result), (5 * 3) + 2, #5 chars per thing and amps
744 "testing %s: "
745 "unexpected number of characters: %s != %s" %
746 (test_type, len(result), (5 * 3) + 2))
747
748 def test_using_mapping(self):
749 # Test passing in a mapping object as an argument.
750 self.help_inputtype({"1st":'1', "2nd":'2', "3rd":'3'},
751 "using dict as input type")
752
753 def test_using_sequence(self):
754 # Test passing in a sequence of two-item sequences as an argument.
755 self.help_inputtype([('1st', '1'), ('2nd', '2'), ('3rd', '3')],
756 "using sequence of two-item tuples as input")
757
758 def test_quoting(self):
759 # Make sure keys and values are quoted using quote_plus()
760 given = {"&":"="}
761 expect = "%s=%s" % (hexescape('&'), hexescape('='))
762 result = urllib.urlencode(given)
763 self.assertEqual(expect, result)
764 given = {"key name":"A bunch of pluses"}
765 expect = "key+name=A+bunch+of+pluses"
766 result = urllib.urlencode(given)
767 self.assertEqual(expect, result)
768
769 def test_doseq(self):
770 # Test that passing True for 'doseq' parameter works correctly
771 given = {'sequence':['1', '2', '3']}
772 expect = "sequence=%s" % urllib.quote_plus(str(['1', '2', '3']))
773 result = urllib.urlencode(given)
774 self.assertEqual(expect, result)
775 result = urllib.urlencode(given, True)
776 for value in given["sequence"]:
777 expect = "sequence=%s" % value
Ezio Melottiaa980582010-01-23 23:04:36 +0000778 self.assertIn(expect, result)
Brett Cannon74bfd702003-04-25 09:39:47 +0000779 self.assertEqual(result.count('&'), 2,
780 "Expected 2 '&'s, got %s" % result.count('&'))
781
782class Pathname_Tests(unittest.TestCase):
783 """Test pathname2url() and url2pathname()"""
784
785 def test_basic(self):
786 # Make sure simple tests pass
787 expected_path = os.path.join("parts", "of", "a", "path")
788 expected_url = "parts/of/a/path"
789 result = urllib.pathname2url(expected_path)
790 self.assertEqual(expected_url, result,
791 "pathname2url() failed; %s != %s" %
792 (result, expected_url))
793 result = urllib.url2pathname(expected_url)
794 self.assertEqual(expected_path, result,
795 "url2pathame() failed; %s != %s" %
796 (result, expected_path))
797
798 def test_quoting(self):
799 # Test automatic quoting and unquoting works for pathnam2url() and
800 # url2pathname() respectively
801 given = os.path.join("needs", "quot=ing", "here")
802 expect = "needs/%s/here" % urllib.quote("quot=ing")
803 result = urllib.pathname2url(given)
804 self.assertEqual(expect, result,
805 "pathname2url() failed; %s != %s" %
806 (expect, result))
807 expect = given
808 result = urllib.url2pathname(result)
809 self.assertEqual(expect, result,
810 "url2pathname() failed; %s != %s" %
811 (expect, result))
812 given = os.path.join("make sure", "using_quote")
813 expect = "%s/using_quote" % urllib.quote("make sure")
814 result = urllib.pathname2url(given)
815 self.assertEqual(expect, result,
816 "pathname2url() failed; %s != %s" %
817 (expect, result))
818 given = "make+sure/using_unquote"
819 expect = os.path.join("make+sure", "using_unquote")
820 result = urllib.url2pathname(given)
821 self.assertEqual(expect, result,
822 "url2pathname() failed; %s != %s" %
823 (expect, result))
Tim Petersc2659cf2003-05-12 20:19:37 +0000824
Senthil Kumarana99b7612011-04-14 12:54:35 +0800825 @unittest.skipUnless(sys.platform == 'win32',
826 'test specific to the nturl2path library')
827 def test_ntpath(self):
828 given = ('/C:/', '///C:/', '/C|//')
829 expect = 'C:\\'
830 for url in given:
831 result = urllib.url2pathname(url)
832 self.assertEqual(expect, result,
833 'nturl2path.url2pathname() failed; %s != %s' %
834 (expect, result))
835 given = '///C|/path'
836 expect = 'C:\\path'
837 result = urllib.url2pathname(given)
838 self.assertEqual(expect, result,
839 'nturl2path.url2pathname() failed; %s != %s' %
840 (expect, result))
841
Senthil Kumaran5e95e762009-03-30 21:51:50 +0000842class Utility_Tests(unittest.TestCase):
843 """Testcase to test the various utility functions in the urllib."""
Serhiy Storchakaf0b630b2015-03-02 16:31:57 +0200844 # In Python 3 this test class is moved to test_urlparse.
845
846 def test_splittype(self):
847 splittype = urllib.splittype
848 self.assertEqual(splittype('type:opaquestring'), ('type', 'opaquestring'))
849 self.assertEqual(splittype('opaquestring'), (None, 'opaquestring'))
850 self.assertEqual(splittype(':opaquestring'), (None, ':opaquestring'))
851 self.assertEqual(splittype('type:'), ('type', ''))
852 self.assertEqual(splittype('type:opaque:string'), ('type', 'opaque:string'))
853
854 def test_splithost(self):
855 splithost = urllib.splithost
856 self.assertEqual(splithost('//www.example.org:80/foo/bar/baz.html'),
857 ('www.example.org:80', '/foo/bar/baz.html'))
858 self.assertEqual(splithost('//www.example.org:80'),
859 ('www.example.org:80', ''))
860 self.assertEqual(splithost('/foo/bar/baz.html'),
861 (None, '/foo/bar/baz.html'))
862
863 def test_splituser(self):
864 splituser = urllib.splituser
865 self.assertEqual(splituser('User:Pass@www.python.org:080'),
866 ('User:Pass', 'www.python.org:080'))
867 self.assertEqual(splituser('@www.python.org:080'),
868 ('', 'www.python.org:080'))
869 self.assertEqual(splituser('www.python.org:080'),
870 (None, 'www.python.org:080'))
871 self.assertEqual(splituser('User:Pass@'),
872 ('User:Pass', ''))
873 self.assertEqual(splituser('User@example.com:Pass@www.python.org:080'),
874 ('User@example.com:Pass', 'www.python.org:080'))
Senthil Kumaran5e95e762009-03-30 21:51:50 +0000875
876 def test_splitpasswd(self):
Serhiy Storchakaf0b630b2015-03-02 16:31:57 +0200877 # Some of the password examples are not sensible, but it is added to
878 # confirming to RFC2617 and addressing issue4675.
879 splitpasswd = urllib.splitpasswd
880 self.assertEqual(splitpasswd('user:ab'), ('user', 'ab'))
881 self.assertEqual(splitpasswd('user:a\nb'), ('user', 'a\nb'))
882 self.assertEqual(splitpasswd('user:a\tb'), ('user', 'a\tb'))
883 self.assertEqual(splitpasswd('user:a\rb'), ('user', 'a\rb'))
884 self.assertEqual(splitpasswd('user:a\fb'), ('user', 'a\fb'))
885 self.assertEqual(splitpasswd('user:a\vb'), ('user', 'a\vb'))
886 self.assertEqual(splitpasswd('user:a:b'), ('user', 'a:b'))
887 self.assertEqual(splitpasswd('user:a b'), ('user', 'a b'))
888 self.assertEqual(splitpasswd('user 2:ab'), ('user 2', 'ab'))
889 self.assertEqual(splitpasswd('user+1:a+b'), ('user+1', 'a+b'))
890 self.assertEqual(splitpasswd('user:'), ('user', ''))
891 self.assertEqual(splitpasswd('user'), ('user', None))
892 self.assertEqual(splitpasswd(':ab'), ('', 'ab'))
Senthil Kumaran5e95e762009-03-30 21:51:50 +0000893
Serhiy Storchaka326b5ab2014-01-18 18:30:09 +0200894 def test_splitport(self):
895 splitport = urllib.splitport
896 self.assertEqual(splitport('parrot:88'), ('parrot', '88'))
897 self.assertEqual(splitport('parrot'), ('parrot', None))
898 self.assertEqual(splitport('parrot:'), ('parrot', None))
899 self.assertEqual(splitport('127.0.0.1'), ('127.0.0.1', None))
900 self.assertEqual(splitport('parrot:cheese'), ('parrot:cheese', None))
Serhiy Storchakaf0b630b2015-03-02 16:31:57 +0200901 self.assertEqual(splitport('[::1]:88'), ('[::1]', '88'))
902 self.assertEqual(splitport('[::1]'), ('[::1]', None))
903 self.assertEqual(splitport(':88'), ('', '88'))
Serhiy Storchaka326b5ab2014-01-18 18:30:09 +0200904
905 def test_splitnport(self):
906 splitnport = urllib.splitnport
907 self.assertEqual(splitnport('parrot:88'), ('parrot', 88))
908 self.assertEqual(splitnport('parrot'), ('parrot', -1))
909 self.assertEqual(splitnport('parrot', 55), ('parrot', 55))
910 self.assertEqual(splitnport('parrot:'), ('parrot', -1))
911 self.assertEqual(splitnport('parrot:', 55), ('parrot', 55))
912 self.assertEqual(splitnport('127.0.0.1'), ('127.0.0.1', -1))
913 self.assertEqual(splitnport('127.0.0.1', 55), ('127.0.0.1', 55))
914 self.assertEqual(splitnport('parrot:cheese'), ('parrot', None))
915 self.assertEqual(splitnport('parrot:cheese', 55), ('parrot', None))
916
Serhiy Storchakaf0b630b2015-03-02 16:31:57 +0200917 def test_splitquery(self):
918 # Normal cases are exercised by other tests; ensure that we also
919 # catch cases with no port specified (testcase ensuring coverage)
920 splitquery = urllib.splitquery
921 self.assertEqual(splitquery('http://python.org/fake?foo=bar'),
922 ('http://python.org/fake', 'foo=bar'))
923 self.assertEqual(splitquery('http://python.org/fake?foo=bar?'),
924 ('http://python.org/fake?foo=bar', ''))
925 self.assertEqual(splitquery('http://python.org/fake'),
926 ('http://python.org/fake', None))
927 self.assertEqual(splitquery('?foo=bar'), ('', 'foo=bar'))
928
929 def test_splittag(self):
930 splittag = urllib.splittag
931 self.assertEqual(splittag('http://example.com?foo=bar#baz'),
932 ('http://example.com?foo=bar', 'baz'))
933 self.assertEqual(splittag('http://example.com?foo=bar#'),
934 ('http://example.com?foo=bar', ''))
935 self.assertEqual(splittag('#baz'), ('', 'baz'))
936 self.assertEqual(splittag('http://example.com?foo=bar'),
937 ('http://example.com?foo=bar', None))
938 self.assertEqual(splittag('http://example.com?foo=bar#baz#boo'),
939 ('http://example.com?foo=bar#baz', 'boo'))
940
941 def test_splitattr(self):
942 splitattr = urllib.splitattr
943 self.assertEqual(splitattr('/path;attr1=value1;attr2=value2'),
944 ('/path', ['attr1=value1', 'attr2=value2']))
945 self.assertEqual(splitattr('/path;'), ('/path', ['']))
946 self.assertEqual(splitattr(';attr1=value1;attr2=value2'),
947 ('', ['attr1=value1', 'attr2=value2']))
948 self.assertEqual(splitattr('/path'), ('/path', []))
949
950 def test_splitvalue(self):
951 # Normal cases are exercised by other tests; test pathological cases
952 # with no key/value pairs. (testcase ensuring coverage)
953 splitvalue = urllib.splitvalue
954 self.assertEqual(splitvalue('foo=bar'), ('foo', 'bar'))
955 self.assertEqual(splitvalue('foo='), ('foo', ''))
956 self.assertEqual(splitvalue('=bar'), ('', 'bar'))
957 self.assertEqual(splitvalue('foobar'), ('foobar', None))
958 self.assertEqual(splitvalue('foo=bar=baz'), ('foo', 'bar=baz'))
959
960 def test_toBytes(self):
961 result = urllib.toBytes(u'http://www.python.org')
962 self.assertEqual(result, 'http://www.python.org')
963 self.assertRaises(UnicodeError, urllib.toBytes,
964 test_support.u(r'http://www.python.org/medi\u00e6val'))
965
966 def test_unwrap(self):
967 url = urllib.unwrap('<URL:type://host/path>')
968 self.assertEqual(url, 'type://host/path')
969
Senthil Kumaran5e95e762009-03-30 21:51:50 +0000970
Senthil Kumaran7c2867f2009-04-21 03:24:19 +0000971class URLopener_Tests(unittest.TestCase):
972 """Testcase to test the open method of URLopener class."""
973
974 def test_quoted_open(self):
975 class DummyURLopener(urllib.URLopener):
976 def open_spam(self, url):
977 return url
978
979 self.assertEqual(DummyURLopener().open(
980 'spam://example/ /'),'//example/%20/')
981
Senthil Kumaran18d5a692010-02-20 22:05:34 +0000982 # test the safe characters are not quoted by urlopen
983 self.assertEqual(DummyURLopener().open(
984 "spam://c:|windows%/:=&?~#+!$,;'@()*[]|/path/"),
985 "//c:|windows%/:=&?~#+!$,;'@()*[]|/path/")
986
Senthil Kumaran7c2867f2009-04-21 03:24:19 +0000987
Facundo Batistad9880d02007-05-25 04:20:22 +0000988# Just commented them out.
989# Can't really tell why keep failing in windows and sparc.
Ezio Melottic2077b02011-03-16 12:34:31 +0200990# Everywhere else they work ok, but on those machines, sometimes
Facundo Batistad9880d02007-05-25 04:20:22 +0000991# fail in one of the tests, sometimes in other. I have a linux, and
992# the tests go ok.
Ezio Melotti419e23c2013-08-17 16:56:09 +0300993# If anybody has one of the problematic environments, please help!
Facundo Batistad9880d02007-05-25 04:20:22 +0000994# . Facundo
995#
996# def server(evt):
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000997# import socket, time
Facundo Batistad9880d02007-05-25 04:20:22 +0000998# serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
999# serv.settimeout(3)
1000# serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
1001# serv.bind(("", 9093))
1002# serv.listen(5)
1003# try:
1004# conn, addr = serv.accept()
1005# conn.send("1 Hola mundo\n")
1006# cantdata = 0
1007# while cantdata < 13:
1008# data = conn.recv(13-cantdata)
1009# cantdata += len(data)
1010# time.sleep(.3)
1011# conn.send("2 No more lines\n")
1012# conn.close()
1013# except socket.timeout:
1014# pass
1015# finally:
1016# serv.close()
1017# evt.set()
1018#
1019# class FTPWrapperTests(unittest.TestCase):
1020#
1021# def setUp(self):
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001022# import ftplib, time, threading
Facundo Batistad9880d02007-05-25 04:20:22 +00001023# ftplib.FTP.port = 9093
1024# self.evt = threading.Event()
1025# threading.Thread(target=server, args=(self.evt,)).start()
1026# time.sleep(.1)
1027#
1028# def tearDown(self):
1029# self.evt.wait()
1030#
1031# def testBasic(self):
1032# # connects
1033# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001034# ftp.close()
Facundo Batistad9880d02007-05-25 04:20:22 +00001035#
1036# def testTimeoutNone(self):
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001037# # global default timeout is ignored
1038# import socket
Serhiy Storchaka528bed82014-02-08 14:49:55 +02001039# self.assertIsNone(socket.getdefaulttimeout())
Facundo Batistad9880d02007-05-25 04:20:22 +00001040# socket.setdefaulttimeout(30)
1041# try:
1042# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
1043# finally:
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001044# socket.setdefaulttimeout(None)
Facundo Batistad9880d02007-05-25 04:20:22 +00001045# self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001046# ftp.close()
Facundo Batistad9880d02007-05-25 04:20:22 +00001047#
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001048# def testTimeoutDefault(self):
1049# # global default timeout is used
1050# import socket
Serhiy Storchaka528bed82014-02-08 14:49:55 +02001051# self.assertIsNone(socket.getdefaulttimeout())
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001052# socket.setdefaulttimeout(30)
1053# try:
1054# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
1055# finally:
1056# socket.setdefaulttimeout(None)
1057# self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
1058# ftp.close()
1059#
1060# def testTimeoutValue(self):
1061# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [],
1062# timeout=30)
1063# self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
1064# ftp.close()
Facundo Batista711a54e2007-05-24 17:50:54 +00001065
Skip Montanaro080c9972001-01-28 21:12:22 +00001066
1067
Brett Cannon74bfd702003-04-25 09:39:47 +00001068def test_main():
Brett Cannon8bb8fa52008-07-02 01:57:08 +00001069 import warnings
Brett Cannon672237d2008-09-09 00:49:16 +00001070 with warnings.catch_warnings():
Brett Cannon8bb8fa52008-07-02 01:57:08 +00001071 warnings.filterwarnings('ignore', ".*urllib\.urlopen.*Python 3.0",
1072 DeprecationWarning)
1073 test_support.run_unittest(
1074 urlopen_FileTests,
1075 urlopen_HttpTests,
1076 urlretrieve_FileTests,
Senthil Kumaran87e58552011-11-01 02:44:45 +08001077 urlretrieve_HttpTests,
Benjamin Peterson2c7470d2008-09-21 21:27:51 +00001078 ProxyTests,
Brett Cannon8bb8fa52008-07-02 01:57:08 +00001079 QuotingTests,
1080 UnquotingTests,
1081 urlencode_Tests,
1082 Pathname_Tests,
Senthil Kumaran5e95e762009-03-30 21:51:50 +00001083 Utility_Tests,
Senthil Kumaran7c2867f2009-04-21 03:24:19 +00001084 URLopener_Tests,
Senthil Kumaranb31c87b2016-04-25 09:17:54 -07001085 ProxyTests,
1086 ProxyTests_withOrderedEnv,
Brett Cannon8bb8fa52008-07-02 01:57:08 +00001087 #FTPWrapperTests,
1088 )
Brett Cannon74bfd702003-04-25 09:39:47 +00001089
1090
1091
1092if __name__ == '__main__':
1093 test_main()