blob: c18e738f8987371e88baf72b7c01825a64fc4926 [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
Serhiy Storchakaa898abd2014-09-06 21:41:39 +03006import io
Brett Cannon74bfd702003-04-25 09:39:47 +00007import unittest
Brett Cannon74bfd702003-04-25 09:39:47 +00008import os
Senthil Kumarana99b7612011-04-14 12:54:35 +08009import sys
Brett Cannon74bfd702003-04-25 09:39:47 +000010import mimetools
Georg Brandl5a650a22005-08-26 08:51:34 +000011import tempfile
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
Serhiy Storchakaa898abd2014-09-06 21:41:39 +030025def fakehttp(fakedata):
26 class FakeSocket(io.BytesIO):
27
28 def sendall(self, data):
29 FakeHTTPConnection.buf = data
30
31 def makefile(self, *args, **kwds):
32 return self
33
34 def read(self, amt=None):
35 if self.closed:
36 return b""
37 return io.BytesIO.read(self, amt)
38
39 def readline(self, length=None):
40 if self.closed:
41 return b""
42 return io.BytesIO.readline(self, length)
43
44 class FakeHTTPConnection(httplib.HTTPConnection):
45
46 # buffer to store data for verification in urlopen tests.
47 buf = ""
48 fakesock = FakeSocket(fakedata)
49
50 def connect(self):
51 self.sock = self.fakesock
52
53 return FakeHTTPConnection
54
55
Senthil Kumaran87e58552011-11-01 02:44:45 +080056class FakeHTTPMixin(object):
57 def fakehttp(self, fakedata):
Senthil Kumaran87e58552011-11-01 02:44:45 +080058 assert httplib.HTTP._connection_class == httplib.HTTPConnection
Senthil Kumaranbcd833f2012-01-11 00:09:24 +080059
Serhiy Storchakaa898abd2014-09-06 21:41:39 +030060 httplib.HTTP._connection_class = fakehttp(fakedata)
Senthil Kumaran87e58552011-11-01 02:44:45 +080061
62 def unfakehttp(self):
63 httplib.HTTP._connection_class = httplib.HTTPConnection
64
65
Brett Cannon74bfd702003-04-25 09:39:47 +000066class urlopen_FileTests(unittest.TestCase):
67 """Test urlopen() opening a temporary file.
Jeremy Hylton6102e292000-08-31 15:48:10 +000068
Brett Cannon74bfd702003-04-25 09:39:47 +000069 Try to test as much functionality as possible so as to cut down on reliance
Andrew M. Kuchlingf1a2f9e2004-06-29 13:07:53 +000070 on connecting to the Net for testing.
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000071
Brett Cannon74bfd702003-04-25 09:39:47 +000072 """
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000073
Brett Cannon74bfd702003-04-25 09:39:47 +000074 def setUp(self):
75 """Setup of a temp file to use for testing"""
76 self.text = "test_urllib: %s\n" % self.__class__.__name__
Guido van Rossum51735b02003-04-25 15:01:05 +000077 FILE = file(test_support.TESTFN, 'wb')
Brett Cannon74bfd702003-04-25 09:39:47 +000078 try:
79 FILE.write(self.text)
80 finally:
81 FILE.close()
82 self.pathname = test_support.TESTFN
83 self.returned_obj = urllib.urlopen("file:%s" % self.pathname)
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000084
Brett Cannon74bfd702003-04-25 09:39:47 +000085 def tearDown(self):
86 """Shut down the open object"""
87 self.returned_obj.close()
Brett Cannon19691362003-04-29 05:08:06 +000088 os.remove(test_support.TESTFN)
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000089
Brett Cannon74bfd702003-04-25 09:39:47 +000090 def test_interface(self):
91 # Make sure object returned by urlopen() has the specified methods
92 for attr in ("read", "readline", "readlines", "fileno",
Georg Brandl9b0d46d2008-01-20 11:43:03 +000093 "close", "info", "geturl", "getcode", "__iter__"):
Benjamin Peterson5c8da862009-06-30 22:57:08 +000094 self.assertTrue(hasattr(self.returned_obj, attr),
Brett Cannon74bfd702003-04-25 09:39:47 +000095 "object returned by urlopen() lacks %s attribute" %
96 attr)
Skip Montanaroe78b92a2001-01-20 20:22:30 +000097
Brett Cannon74bfd702003-04-25 09:39:47 +000098 def test_read(self):
99 self.assertEqual(self.text, self.returned_obj.read())
Skip Montanaro080c9972001-01-28 21:12:22 +0000100
Brett Cannon74bfd702003-04-25 09:39:47 +0000101 def test_readline(self):
102 self.assertEqual(self.text, self.returned_obj.readline())
103 self.assertEqual('', self.returned_obj.readline(),
104 "calling readline() after exhausting the file did not"
105 " return an empty string")
Skip Montanaro080c9972001-01-28 21:12:22 +0000106
Brett Cannon74bfd702003-04-25 09:39:47 +0000107 def test_readlines(self):
108 lines_list = self.returned_obj.readlines()
109 self.assertEqual(len(lines_list), 1,
110 "readlines() returned the wrong number of lines")
111 self.assertEqual(lines_list[0], self.text,
112 "readlines() returned improper text")
Skip Montanaro080c9972001-01-28 21:12:22 +0000113
Brett Cannon74bfd702003-04-25 09:39:47 +0000114 def test_fileno(self):
115 file_num = self.returned_obj.fileno()
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000116 self.assertIsInstance(file_num, int, "fileno() did not return an int")
Brett Cannon74bfd702003-04-25 09:39:47 +0000117 self.assertEqual(os.read(file_num, len(self.text)), self.text,
118 "Reading on the file descriptor returned by fileno() "
119 "did not return the expected text")
Skip Montanaroe78b92a2001-01-20 20:22:30 +0000120
Brett Cannon74bfd702003-04-25 09:39:47 +0000121 def test_close(self):
122 # Test close() by calling it hear and then having it be called again
123 # by the tearDown() method for the test
124 self.returned_obj.close()
Skip Montanaro080c9972001-01-28 21:12:22 +0000125
Brett Cannon74bfd702003-04-25 09:39:47 +0000126 def test_info(self):
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000127 self.assertIsInstance(self.returned_obj.info(), mimetools.Message)
Skip Montanaroe78b92a2001-01-20 20:22:30 +0000128
Brett Cannon74bfd702003-04-25 09:39:47 +0000129 def test_geturl(self):
130 self.assertEqual(self.returned_obj.geturl(), self.pathname)
Skip Montanaro080c9972001-01-28 21:12:22 +0000131
Georg Brandl9b0d46d2008-01-20 11:43:03 +0000132 def test_getcode(self):
133 self.assertEqual(self.returned_obj.getcode(), None)
134
Brett Cannon74bfd702003-04-25 09:39:47 +0000135 def test_iter(self):
136 # Test iterator
137 # Don't need to count number of iterations since test would fail the
138 # instant it returned anything beyond the first line from the
139 # comparison
140 for line in self.returned_obj.__iter__():
141 self.assertEqual(line, self.text)
Skip Montanaro080c9972001-01-28 21:12:22 +0000142
Senthil Kumaran58c60622012-01-21 11:43:02 +0800143 def test_relativelocalfile(self):
144 self.assertRaises(ValueError,urllib.urlopen,'./' + self.pathname)
145
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000146class ProxyTests(unittest.TestCase):
147
148 def setUp(self):
Walter Dörwald4b965f62009-04-26 20:51:44 +0000149 # Records changes to env vars
150 self.env = test_support.EnvironmentVarGuard()
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000151 # Delete all proxy related env vars
Senthil Kumaran7a2ee0b2010-01-08 19:20:25 +0000152 for k in os.environ.keys():
Walter Dörwald4b965f62009-04-26 20:51:44 +0000153 if 'proxy' in k.lower():
Senthil Kumarandc61ec32009-10-01 01:50:13 +0000154 self.env.unset(k)
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000155
156 def tearDown(self):
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000157 # Restore all proxy related env vars
Walter Dörwald4b965f62009-04-26 20:51:44 +0000158 self.env.__exit__()
159 del self.env
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000160
161 def test_getproxies_environment_keep_no_proxies(self):
Walter Dörwald4b965f62009-04-26 20:51:44 +0000162 self.env.set('NO_PROXY', 'localhost')
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000163 proxies = urllib.getproxies_environment()
164 # getproxies_environment use lowered case truncated (no '_proxy') keys
Ezio Melotti2623a372010-11-21 13:34:58 +0000165 self.assertEqual('localhost', proxies['no'])
Senthil Kumaranb5bd4c82011-08-06 12:24:33 +0800166 # List of no_proxies with space.
Senthil Kumaranb31c87b2016-04-25 09:17:54 -0700167 self.env.set('NO_PROXY', 'localhost, anotherdomain.com, newdomain.com:1234')
Senthil Kumaranb5bd4c82011-08-06 12:24:33 +0800168 self.assertTrue(urllib.proxy_bypass_environment('anotherdomain.com'))
Senthil Kumaranb31c87b2016-04-25 09:17:54 -0700169 self.assertTrue(urllib.proxy_bypass_environment('anotherdomain.com:8888'))
170 self.assertTrue(urllib.proxy_bypass_environment('newdomain.com:1234'))
171
Martin Panter064ee4d2016-04-30 01:03:40 +0000172 def test_proxy_bypass_environment_host_match(self):
173 bypass = urllib.proxy_bypass_environment
174 self.env.set('NO_PROXY',
175 'localhost, anotherdomain.com, newdomain.com:1234')
176 self.assertTrue(bypass('localhost'))
177 self.assertTrue(bypass('LocalHost')) # MixedCase
178 self.assertTrue(bypass('LOCALHOST')) # UPPERCASE
179 self.assertTrue(bypass('newdomain.com:1234'))
180 self.assertTrue(bypass('anotherdomain.com:8888'))
181 self.assertTrue(bypass('www.newdomain.com:1234'))
182 self.assertFalse(bypass('prelocalhost'))
183 self.assertFalse(bypass('newdomain.com')) # no port
184 self.assertFalse(bypass('newdomain.com:1235')) # wrong port
Senthil Kumaranb31c87b2016-04-25 09:17:54 -0700185
186class ProxyTests_withOrderedEnv(unittest.TestCase):
187
188 def setUp(self):
189 # We need to test conditions, where variable order _is_ significant
190 self._saved_env = os.environ
191 # Monkey patch os.environ, start with empty fake environment
192 os.environ = collections.OrderedDict()
193
194 def tearDown(self):
195 os.environ = self._saved_env
196
197 def test_getproxies_environment_prefer_lowercase(self):
198 # Test lowercase preference with removal
199 os.environ['no_proxy'] = ''
200 os.environ['No_Proxy'] = 'localhost'
201 self.assertFalse(urllib.proxy_bypass_environment('localhost'))
202 self.assertFalse(urllib.proxy_bypass_environment('arbitrary'))
203 os.environ['http_proxy'] = ''
204 os.environ['HTTP_PROXY'] = 'http://somewhere:3128'
205 proxies = urllib.getproxies_environment()
206 self.assertEqual({}, proxies)
207 # Test lowercase preference of proxy bypass and correct matching including ports
208 os.environ['no_proxy'] = 'localhost, noproxy.com, my.proxy:1234'
209 os.environ['No_Proxy'] = 'xyz.com'
210 self.assertTrue(urllib.proxy_bypass_environment('localhost'))
211 self.assertTrue(urllib.proxy_bypass_environment('noproxy.com:5678'))
212 self.assertTrue(urllib.proxy_bypass_environment('my.proxy:1234'))
213 self.assertFalse(urllib.proxy_bypass_environment('my.proxy'))
214 self.assertFalse(urllib.proxy_bypass_environment('arbitrary'))
215 # Test lowercase preference with replacement
216 os.environ['http_proxy'] = 'http://somewhere:3128'
217 os.environ['Http_Proxy'] = 'http://somewhereelse:3128'
218 proxies = urllib.getproxies_environment()
219 self.assertEqual('http://somewhere:3128', proxies['http'])
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000220
221
Senthil Kumaran87e58552011-11-01 02:44:45 +0800222class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin):
Hye-Shik Chang39aef792004-06-05 13:30:56 +0000223 """Test urlopen() opening a fake http connection."""
224
Hye-Shik Chang39aef792004-06-05 13:30:56 +0000225 def test_read(self):
226 self.fakehttp('Hello!')
227 try:
228 fp = urllib.urlopen("http://python.org/")
229 self.assertEqual(fp.readline(), 'Hello!')
230 self.assertEqual(fp.readline(), '')
Georg Brandl9b0d46d2008-01-20 11:43:03 +0000231 self.assertEqual(fp.geturl(), 'http://python.org/')
232 self.assertEqual(fp.getcode(), 200)
Hye-Shik Chang39aef792004-06-05 13:30:56 +0000233 finally:
234 self.unfakehttp()
235
Senthil Kumaran49c44082011-04-13 07:31:45 +0800236 def test_url_fragment(self):
237 # Issue #11703: geturl() omits fragments in the original URL.
238 url = 'http://docs.python.org/library/urllib.html#OK'
239 self.fakehttp('Hello!')
240 try:
241 fp = urllib.urlopen(url)
242 self.assertEqual(fp.geturl(), url)
243 finally:
244 self.unfakehttp()
245
Kurt B. Kaiser0f7c25d2008-01-02 04:11:28 +0000246 def test_read_bogus(self):
Kurt B. Kaiser0a112322008-01-02 05:23:38 +0000247 # urlopen() should raise IOError for many error codes.
Kurt B. Kaiser0f7c25d2008-01-02 04:11:28 +0000248 self.fakehttp('''HTTP/1.1 401 Authentication Required
249Date: Wed, 02 Jan 2008 03:03:54 GMT
250Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e
251Connection: close
252Content-Type: text/html; charset=iso-8859-1
253''')
254 try:
255 self.assertRaises(IOError, urllib.urlopen, "http://python.org/")
256 finally:
257 self.unfakehttp()
258
guido@google.comf1509302011-03-28 13:47:01 -0700259 def test_invalid_redirect(self):
260 # urlopen() should raise IOError for many error codes.
261 self.fakehttp("""HTTP/1.1 302 Found
262Date: Wed, 02 Jan 2008 03:03:54 GMT
263Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e
264Location: file:README
265Connection: close
266Content-Type: text/html; charset=iso-8859-1
267""")
268 try:
Martin Panterade40972016-02-04 06:01:35 +0000269 msg = "Redirection to url 'file:"
270 with self.assertRaisesRegexp(IOError, msg):
271 urllib.urlopen("http://python.org/")
guido@google.comf1509302011-03-28 13:47:01 -0700272 finally:
273 self.unfakehttp()
274
Martin Panterade40972016-02-04 06:01:35 +0000275 def test_redirect_limit_independent(self):
276 # Ticket #12923: make sure independent requests each use their
277 # own retry limit.
278 for i in range(urllib.FancyURLopener().maxtries):
279 self.fakehttp(b'''HTTP/1.1 302 Found
280Location: file://guidocomputer.athome.com:/python/license
281Connection: close
282''')
283 try:
284 self.assertRaises(IOError, urllib.urlopen,
285 "http://something")
286 finally:
287 self.unfakehttp()
288
Georg Brandlf66b6032007-03-14 08:27:52 +0000289 def test_empty_socket(self):
Kurt B. Kaiser0a112322008-01-02 05:23:38 +0000290 # urlopen() raises IOError if the underlying socket does not send any
291 # data. (#1680230)
Georg Brandlf66b6032007-03-14 08:27:52 +0000292 self.fakehttp('')
293 try:
294 self.assertRaises(IOError, urllib.urlopen, 'http://something')
295 finally:
296 self.unfakehttp()
297
Senthil Kumaranf8d370e2012-10-27 03:48:40 -0700298 def test_missing_localfile(self):
299 self.assertRaises(IOError, urllib.urlopen,
300 'file://localhost/a/missing/file.py')
301 fd, tmp_file = tempfile.mkstemp()
302 tmp_fileurl = 'file://localhost/' + tmp_file.replace(os.path.sep, '/')
Senthil Kumarana085f002013-06-01 07:59:10 -0700303 self.assertTrue(os.path.exists(tmp_file))
Senthil Kumaranf8d370e2012-10-27 03:48:40 -0700304 try:
Senthil Kumaranf8d370e2012-10-27 03:48:40 -0700305 fp = urllib.urlopen(tmp_fileurl)
Senthil Kumarana085f002013-06-01 07:59:10 -0700306 fp.close()
Senthil Kumaranf8d370e2012-10-27 03:48:40 -0700307 finally:
308 os.close(fd)
Senthil Kumarana085f002013-06-01 07:59:10 -0700309 os.unlink(tmp_file)
Senthil Kumaranf8d370e2012-10-27 03:48:40 -0700310
311 self.assertFalse(os.path.exists(tmp_file))
312 self.assertRaises(IOError, urllib.urlopen, tmp_fileurl)
313
314 def test_ftp_nonexisting(self):
315 self.assertRaises(IOError, urllib.urlopen,
316 'ftp://localhost/not/existing/file.py')
317
318
Senthil Kumaranbcd833f2012-01-11 00:09:24 +0800319 def test_userpass_inurl(self):
320 self.fakehttp('Hello!')
321 try:
322 fakehttp_wrapper = httplib.HTTP._connection_class
323 fp = urllib.urlopen("http://user:pass@python.org/")
324 authorization = ("Authorization: Basic %s\r\n" %
325 b64encode('user:pass'))
326 # The authorization header must be in place
327 self.assertIn(authorization, fakehttp_wrapper.buf)
328 self.assertEqual(fp.readline(), "Hello!")
329 self.assertEqual(fp.readline(), "")
330 self.assertEqual(fp.geturl(), 'http://user:pass@python.org/')
331 self.assertEqual(fp.getcode(), 200)
332 finally:
333 self.unfakehttp()
334
335 def test_userpass_with_spaces_inurl(self):
336 self.fakehttp('Hello!')
337 try:
338 url = "http://a b:c d@python.org/"
339 fakehttp_wrapper = httplib.HTTP._connection_class
340 authorization = ("Authorization: Basic %s\r\n" %
341 b64encode('a b:c d'))
342 fp = urllib.urlopen(url)
343 # The authorization header must be in place
344 self.assertIn(authorization, fakehttp_wrapper.buf)
345 self.assertEqual(fp.readline(), "Hello!")
346 self.assertEqual(fp.readline(), "")
347 # the spaces are quoted in URL so no match
348 self.assertNotEqual(fp.geturl(), url)
349 self.assertEqual(fp.getcode(), 200)
350 finally:
351 self.unfakehttp()
352
353
Brett Cannon19691362003-04-29 05:08:06 +0000354class urlretrieve_FileTests(unittest.TestCase):
Brett Cannon74bfd702003-04-25 09:39:47 +0000355 """Test urllib.urlretrieve() on local files"""
Skip Montanaro080c9972001-01-28 21:12:22 +0000356
Brett Cannon19691362003-04-29 05:08:06 +0000357 def setUp(self):
Georg Brandl5a650a22005-08-26 08:51:34 +0000358 # Create a list of temporary files. Each item in the list is a file
359 # name (absolute path or relative to the current working directory).
360 # All files in this list will be deleted in the tearDown method. Note,
361 # this only helps to makes sure temporary files get deleted, but it
362 # does nothing about trying to close files that may still be open. It
363 # is the responsibility of the developer to properly close files even
364 # when exceptional conditions occur.
365 self.tempFiles = []
366
Brett Cannon19691362003-04-29 05:08:06 +0000367 # Create a temporary file.
Georg Brandl5a650a22005-08-26 08:51:34 +0000368 self.registerFileForCleanUp(test_support.TESTFN)
Brett Cannon19691362003-04-29 05:08:06 +0000369 self.text = 'testing urllib.urlretrieve'
Georg Brandl5a650a22005-08-26 08:51:34 +0000370 try:
371 FILE = file(test_support.TESTFN, 'wb')
372 FILE.write(self.text)
373 FILE.close()
374 finally:
375 try: FILE.close()
376 except: pass
Brett Cannon19691362003-04-29 05:08:06 +0000377
378 def tearDown(self):
Georg Brandl5a650a22005-08-26 08:51:34 +0000379 # Delete the temporary files.
380 for each in self.tempFiles:
381 try: os.remove(each)
382 except: pass
383
384 def constructLocalFileUrl(self, filePath):
385 return "file://%s" % urllib.pathname2url(os.path.abspath(filePath))
386
387 def createNewTempFile(self, data=""):
388 """Creates a new temporary file containing the specified data,
389 registers the file for deletion during the test fixture tear down, and
390 returns the absolute path of the file."""
391
392 newFd, newFilePath = tempfile.mkstemp()
393 try:
394 self.registerFileForCleanUp(newFilePath)
395 newFile = os.fdopen(newFd, "wb")
396 newFile.write(data)
397 newFile.close()
398 finally:
399 try: newFile.close()
400 except: pass
401 return newFilePath
402
403 def registerFileForCleanUp(self, fileName):
404 self.tempFiles.append(fileName)
Brett Cannon19691362003-04-29 05:08:06 +0000405
406 def test_basic(self):
407 # Make sure that a local file just gets its own location returned and
408 # a headers value is returned.
409 result = urllib.urlretrieve("file:%s" % test_support.TESTFN)
410 self.assertEqual(result[0], test_support.TESTFN)
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000411 self.assertIsInstance(result[1], mimetools.Message,
412 "did not get a mimetools.Message instance as "
413 "second returned value")
Brett Cannon19691362003-04-29 05:08:06 +0000414
415 def test_copy(self):
416 # Test that setting the filename argument works.
417 second_temp = "%s.2" % test_support.TESTFN
Georg Brandl5a650a22005-08-26 08:51:34 +0000418 self.registerFileForCleanUp(second_temp)
419 result = urllib.urlretrieve(self.constructLocalFileUrl(
420 test_support.TESTFN), second_temp)
Brett Cannon19691362003-04-29 05:08:06 +0000421 self.assertEqual(second_temp, result[0])
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000422 self.assertTrue(os.path.exists(second_temp), "copy of the file was not "
Brett Cannon19691362003-04-29 05:08:06 +0000423 "made")
424 FILE = file(second_temp, 'rb')
425 try:
426 text = FILE.read()
Brett Cannon19691362003-04-29 05:08:06 +0000427 FILE.close()
Georg Brandl5a650a22005-08-26 08:51:34 +0000428 finally:
429 try: FILE.close()
430 except: pass
Brett Cannon19691362003-04-29 05:08:06 +0000431 self.assertEqual(self.text, text)
432
433 def test_reporthook(self):
434 # Make sure that the reporthook works.
435 def hooktester(count, block_size, total_size, count_holder=[0]):
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000436 self.assertIsInstance(count, int)
437 self.assertIsInstance(block_size, int)
438 self.assertIsInstance(total_size, int)
Brett Cannon19691362003-04-29 05:08:06 +0000439 self.assertEqual(count, count_holder[0])
440 count_holder[0] = count_holder[0] + 1
441 second_temp = "%s.2" % test_support.TESTFN
Georg Brandl5a650a22005-08-26 08:51:34 +0000442 self.registerFileForCleanUp(second_temp)
443 urllib.urlretrieve(self.constructLocalFileUrl(test_support.TESTFN),
444 second_temp, hooktester)
445
446 def test_reporthook_0_bytes(self):
447 # Test on zero length file. Should call reporthook only 1 time.
448 report = []
449 def hooktester(count, block_size, total_size, _report=report):
450 _report.append((count, block_size, total_size))
451 srcFileName = self.createNewTempFile()
452 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
453 test_support.TESTFN, hooktester)
454 self.assertEqual(len(report), 1)
455 self.assertEqual(report[0][2], 0)
456
457 def test_reporthook_5_bytes(self):
458 # Test on 5 byte file. Should call reporthook only 2 times (once when
459 # the "network connection" is established and once when the block is
460 # read). Since the block size is 8192 bytes, only one block read is
461 # required to read the entire file.
462 report = []
463 def hooktester(count, block_size, total_size, _report=report):
464 _report.append((count, block_size, total_size))
465 srcFileName = self.createNewTempFile("x" * 5)
466 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
467 test_support.TESTFN, hooktester)
468 self.assertEqual(len(report), 2)
469 self.assertEqual(report[0][1], 8192)
470 self.assertEqual(report[0][2], 5)
471
472 def test_reporthook_8193_bytes(self):
473 # Test on 8193 byte file. Should call reporthook only 3 times (once
474 # when the "network connection" is established, once for the next 8192
475 # bytes, and once for the last byte).
476 report = []
477 def hooktester(count, block_size, total_size, _report=report):
478 _report.append((count, block_size, total_size))
479 srcFileName = self.createNewTempFile("x" * 8193)
480 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
481 test_support.TESTFN, hooktester)
482 self.assertEqual(len(report), 3)
483 self.assertEqual(report[0][1], 8192)
484 self.assertEqual(report[0][2], 8193)
Skip Montanaro080c9972001-01-28 21:12:22 +0000485
Senthil Kumaran87e58552011-11-01 02:44:45 +0800486
487class urlretrieve_HttpTests(unittest.TestCase, FakeHTTPMixin):
488 """Test urllib.urlretrieve() using fake http connections"""
489
490 def test_short_content_raises_ContentTooShortError(self):
491 self.fakehttp('''HTTP/1.1 200 OK
492Date: Wed, 02 Jan 2008 03:03:54 GMT
493Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e
494Connection: close
495Content-Length: 100
496Content-Type: text/html; charset=iso-8859-1
497
498FF
499''')
500
501 def _reporthook(par1, par2, par3):
502 pass
503
504 try:
505 self.assertRaises(urllib.ContentTooShortError, urllib.urlretrieve,
506 'http://example.com', reporthook=_reporthook)
507 finally:
508 self.unfakehttp()
509
510 def test_short_content_raises_ContentTooShortError_without_reporthook(self):
511 self.fakehttp('''HTTP/1.1 200 OK
512Date: Wed, 02 Jan 2008 03:03:54 GMT
513Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e
514Connection: close
515Content-Length: 100
516Content-Type: text/html; charset=iso-8859-1
517
518FF
519''')
520 try:
521 self.assertRaises(urllib.ContentTooShortError, urllib.urlretrieve, 'http://example.com/')
522 finally:
523 self.unfakehttp()
524
Brett Cannon74bfd702003-04-25 09:39:47 +0000525class QuotingTests(unittest.TestCase):
526 """Tests for urllib.quote() and urllib.quote_plus()
Tim Petersc2659cf2003-05-12 20:19:37 +0000527
Brett Cannon74bfd702003-04-25 09:39:47 +0000528 According to RFC 2396 ("Uniform Resource Identifiers), to escape a
529 character you write it as '%' + <2 character US-ASCII hex value>. The Python
530 code of ``'%' + hex(ord(<character>))[2:]`` escapes a character properly.
531 Case does not matter on the hex letters.
532
533 The various character sets specified are:
Tim Petersc2659cf2003-05-12 20:19:37 +0000534
Brett Cannon74bfd702003-04-25 09:39:47 +0000535 Reserved characters : ";/?:@&=+$,"
536 Have special meaning in URIs and must be escaped if not being used for
537 their special meaning
538 Data characters : letters, digits, and "-_.!~*'()"
539 Unreserved and do not need to be escaped; can be, though, if desired
540 Control characters : 0x00 - 0x1F, 0x7F
541 Have no use in URIs so must be escaped
542 space : 0x20
543 Must be escaped
544 Delimiters : '<>#%"'
545 Must be escaped
546 Unwise : "{}|\^[]`"
547 Must be escaped
Tim Petersc2659cf2003-05-12 20:19:37 +0000548
Brett Cannon74bfd702003-04-25 09:39:47 +0000549 """
550
551 def test_never_quote(self):
552 # Make sure quote() does not quote letters, digits, and "_,.-"
553 do_not_quote = '' .join(["ABCDEFGHIJKLMNOPQRSTUVWXYZ",
554 "abcdefghijklmnopqrstuvwxyz",
555 "0123456789",
556 "_.-"])
557 result = urllib.quote(do_not_quote)
558 self.assertEqual(do_not_quote, result,
559 "using quote(): %s != %s" % (do_not_quote, result))
560 result = urllib.quote_plus(do_not_quote)
561 self.assertEqual(do_not_quote, result,
562 "using quote_plus(): %s != %s" % (do_not_quote, result))
563
564 def test_default_safe(self):
565 # Test '/' is default value for 'safe' parameter
566 self.assertEqual(urllib.quote.func_defaults[0], '/')
567
568 def test_safe(self):
569 # Test setting 'safe' parameter does what it should do
570 quote_by_default = "<>"
571 result = urllib.quote(quote_by_default, safe=quote_by_default)
572 self.assertEqual(quote_by_default, result,
573 "using quote(): %s != %s" % (quote_by_default, result))
574 result = urllib.quote_plus(quote_by_default, safe=quote_by_default)
575 self.assertEqual(quote_by_default, result,
576 "using quote_plus(): %s != %s" %
577 (quote_by_default, result))
578
579 def test_default_quoting(self):
580 # Make sure all characters that should be quoted are by default sans
581 # space (separate test for that).
582 should_quote = [chr(num) for num in range(32)] # For 0x00 - 0x1F
583 should_quote.append('<>#%"{}|\^[]`')
584 should_quote.append(chr(127)) # For 0x7F
585 should_quote = ''.join(should_quote)
586 for char in should_quote:
587 result = urllib.quote(char)
588 self.assertEqual(hexescape(char), result,
589 "using quote(): %s should be escaped to %s, not %s" %
590 (char, hexescape(char), result))
591 result = urllib.quote_plus(char)
592 self.assertEqual(hexescape(char), result,
593 "using quote_plus(): "
Tim Petersc2659cf2003-05-12 20:19:37 +0000594 "%s should be escapes to %s, not %s" %
Brett Cannon74bfd702003-04-25 09:39:47 +0000595 (char, hexescape(char), result))
596 del should_quote
597 partial_quote = "ab[]cd"
598 expected = "ab%5B%5Dcd"
599 result = urllib.quote(partial_quote)
600 self.assertEqual(expected, result,
601 "using quote(): %s != %s" % (expected, result))
Senthil Kumaran0d4c34c2011-09-13 06:42:21 +0800602 result = urllib.quote_plus(partial_quote)
Brett Cannon74bfd702003-04-25 09:39:47 +0000603 self.assertEqual(expected, result,
604 "using quote_plus(): %s != %s" % (expected, result))
Senthil Kumaranc7743aa2010-07-19 17:35:50 +0000605 self.assertRaises(TypeError, urllib.quote, None)
Brett Cannon74bfd702003-04-25 09:39:47 +0000606
607 def test_quoting_space(self):
608 # Make sure quote() and quote_plus() handle spaces as specified in
609 # their unique way
610 result = urllib.quote(' ')
611 self.assertEqual(result, hexescape(' '),
612 "using quote(): %s != %s" % (result, hexescape(' ')))
613 result = urllib.quote_plus(' ')
614 self.assertEqual(result, '+',
615 "using quote_plus(): %s != +" % result)
616 given = "a b cd e f"
617 expect = given.replace(' ', hexescape(' '))
618 result = urllib.quote(given)
619 self.assertEqual(expect, result,
620 "using quote(): %s != %s" % (expect, result))
621 expect = given.replace(' ', '+')
622 result = urllib.quote_plus(given)
623 self.assertEqual(expect, result,
624 "using quote_plus(): %s != %s" % (expect, result))
625
Raymond Hettinger2bdec7b2005-09-10 14:30:09 +0000626 def test_quoting_plus(self):
627 self.assertEqual(urllib.quote_plus('alpha+beta gamma'),
628 'alpha%2Bbeta+gamma')
629 self.assertEqual(urllib.quote_plus('alpha+beta gamma', '+'),
630 'alpha+beta+gamma')
631
Brett Cannon74bfd702003-04-25 09:39:47 +0000632class UnquotingTests(unittest.TestCase):
633 """Tests for unquote() and unquote_plus()
Tim Petersc2659cf2003-05-12 20:19:37 +0000634
Brett Cannon74bfd702003-04-25 09:39:47 +0000635 See the doc string for quoting_Tests for details on quoting and such.
636
637 """
638
639 def test_unquoting(self):
640 # Make sure unquoting of all ASCII values works
641 escape_list = []
642 for num in range(128):
643 given = hexescape(chr(num))
644 expect = chr(num)
645 result = urllib.unquote(given)
646 self.assertEqual(expect, result,
647 "using unquote(): %s != %s" % (expect, result))
648 result = urllib.unquote_plus(given)
649 self.assertEqual(expect, result,
650 "using unquote_plus(): %s != %s" %
651 (expect, result))
652 escape_list.append(given)
653 escape_string = ''.join(escape_list)
654 del escape_list
655 result = urllib.unquote(escape_string)
656 self.assertEqual(result.count('%'), 1,
657 "using quote(): not all characters escaped; %s" %
658 result)
659 result = urllib.unquote(escape_string)
660 self.assertEqual(result.count('%'), 1,
661 "using unquote(): not all characters escaped: "
662 "%s" % result)
663
Senthil Kumaranf3e9b2a2010-03-18 12:14:15 +0000664 def test_unquoting_badpercent(self):
665 # Test unquoting on bad percent-escapes
666 given = '%xab'
667 expect = given
668 result = urllib.unquote(given)
669 self.assertEqual(expect, result, "using unquote(): %r != %r"
670 % (expect, result))
671 given = '%x'
672 expect = given
673 result = urllib.unquote(given)
674 self.assertEqual(expect, result, "using unquote(): %r != %r"
675 % (expect, result))
676 given = '%'
677 expect = given
678 result = urllib.unquote(given)
679 self.assertEqual(expect, result, "using unquote(): %r != %r"
680 % (expect, result))
681
682 def test_unquoting_mixed_case(self):
683 # Test unquoting on mixed-case hex digits in the percent-escapes
684 given = '%Ab%eA'
685 expect = '\xab\xea'
686 result = urllib.unquote(given)
687 self.assertEqual(expect, result, "using unquote(): %r != %r"
688 % (expect, result))
689
Brett Cannon74bfd702003-04-25 09:39:47 +0000690 def test_unquoting_parts(self):
691 # Make sure unquoting works when have non-quoted characters
692 # interspersed
693 given = 'ab%sd' % hexescape('c')
694 expect = "abcd"
695 result = urllib.unquote(given)
696 self.assertEqual(expect, result,
697 "using quote(): %s != %s" % (expect, result))
698 result = urllib.unquote_plus(given)
699 self.assertEqual(expect, result,
700 "using unquote_plus(): %s != %s" % (expect, result))
Tim Petersc2659cf2003-05-12 20:19:37 +0000701
Brett Cannon74bfd702003-04-25 09:39:47 +0000702 def test_unquoting_plus(self):
703 # Test difference between unquote() and unquote_plus()
704 given = "are+there+spaces..."
705 expect = given
706 result = urllib.unquote(given)
707 self.assertEqual(expect, result,
708 "using unquote(): %s != %s" % (expect, result))
709 expect = given.replace('+', ' ')
710 result = urllib.unquote_plus(given)
711 self.assertEqual(expect, result,
712 "using unquote_plus(): %s != %s" % (expect, result))
713
Raymond Hettinger4b0f20d2005-10-15 16:41:53 +0000714 def test_unquote_with_unicode(self):
715 r = urllib.unquote(u'br%C3%BCckner_sapporo_20050930.doc')
716 self.assertEqual(r, u'br\xc3\xbcckner_sapporo_20050930.doc')
717
Brett Cannon74bfd702003-04-25 09:39:47 +0000718class urlencode_Tests(unittest.TestCase):
719 """Tests for urlencode()"""
720
721 def help_inputtype(self, given, test_type):
722 """Helper method for testing different input types.
Tim Petersc2659cf2003-05-12 20:19:37 +0000723
Brett Cannon74bfd702003-04-25 09:39:47 +0000724 'given' must lead to only the pairs:
725 * 1st, 1
726 * 2nd, 2
727 * 3rd, 3
Tim Petersc2659cf2003-05-12 20:19:37 +0000728
Brett Cannon74bfd702003-04-25 09:39:47 +0000729 Test cannot assume anything about order. Docs make no guarantee and
730 have possible dictionary input.
Tim Petersc2659cf2003-05-12 20:19:37 +0000731
Brett Cannon74bfd702003-04-25 09:39:47 +0000732 """
733 expect_somewhere = ["1st=1", "2nd=2", "3rd=3"]
734 result = urllib.urlencode(given)
735 for expected in expect_somewhere:
Ezio Melottiaa980582010-01-23 23:04:36 +0000736 self.assertIn(expected, result,
Brett Cannon74bfd702003-04-25 09:39:47 +0000737 "testing %s: %s not found in %s" %
738 (test_type, expected, result))
739 self.assertEqual(result.count('&'), 2,
740 "testing %s: expected 2 '&'s; got %s" %
741 (test_type, result.count('&')))
742 amp_location = result.index('&')
743 on_amp_left = result[amp_location - 1]
744 on_amp_right = result[amp_location + 1]
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000745 self.assertTrue(on_amp_left.isdigit() and on_amp_right.isdigit(),
Brett Cannon74bfd702003-04-25 09:39:47 +0000746 "testing %s: '&' not located in proper place in %s" %
747 (test_type, result))
748 self.assertEqual(len(result), (5 * 3) + 2, #5 chars per thing and amps
749 "testing %s: "
750 "unexpected number of characters: %s != %s" %
751 (test_type, len(result), (5 * 3) + 2))
752
753 def test_using_mapping(self):
754 # Test passing in a mapping object as an argument.
755 self.help_inputtype({"1st":'1', "2nd":'2', "3rd":'3'},
756 "using dict as input type")
757
758 def test_using_sequence(self):
759 # Test passing in a sequence of two-item sequences as an argument.
760 self.help_inputtype([('1st', '1'), ('2nd', '2'), ('3rd', '3')],
761 "using sequence of two-item tuples as input")
762
763 def test_quoting(self):
764 # Make sure keys and values are quoted using quote_plus()
765 given = {"&":"="}
766 expect = "%s=%s" % (hexescape('&'), hexescape('='))
767 result = urllib.urlencode(given)
768 self.assertEqual(expect, result)
769 given = {"key name":"A bunch of pluses"}
770 expect = "key+name=A+bunch+of+pluses"
771 result = urllib.urlencode(given)
772 self.assertEqual(expect, result)
773
774 def test_doseq(self):
775 # Test that passing True for 'doseq' parameter works correctly
776 given = {'sequence':['1', '2', '3']}
777 expect = "sequence=%s" % urllib.quote_plus(str(['1', '2', '3']))
778 result = urllib.urlencode(given)
779 self.assertEqual(expect, result)
780 result = urllib.urlencode(given, True)
781 for value in given["sequence"]:
782 expect = "sequence=%s" % value
Ezio Melottiaa980582010-01-23 23:04:36 +0000783 self.assertIn(expect, result)
Brett Cannon74bfd702003-04-25 09:39:47 +0000784 self.assertEqual(result.count('&'), 2,
785 "Expected 2 '&'s, got %s" % result.count('&'))
786
787class Pathname_Tests(unittest.TestCase):
788 """Test pathname2url() and url2pathname()"""
789
790 def test_basic(self):
791 # Make sure simple tests pass
792 expected_path = os.path.join("parts", "of", "a", "path")
793 expected_url = "parts/of/a/path"
794 result = urllib.pathname2url(expected_path)
795 self.assertEqual(expected_url, result,
796 "pathname2url() failed; %s != %s" %
797 (result, expected_url))
798 result = urllib.url2pathname(expected_url)
799 self.assertEqual(expected_path, result,
800 "url2pathame() failed; %s != %s" %
801 (result, expected_path))
802
803 def test_quoting(self):
804 # Test automatic quoting and unquoting works for pathnam2url() and
805 # url2pathname() respectively
806 given = os.path.join("needs", "quot=ing", "here")
807 expect = "needs/%s/here" % urllib.quote("quot=ing")
808 result = urllib.pathname2url(given)
809 self.assertEqual(expect, result,
810 "pathname2url() failed; %s != %s" %
811 (expect, result))
812 expect = given
813 result = urllib.url2pathname(result)
814 self.assertEqual(expect, result,
815 "url2pathname() failed; %s != %s" %
816 (expect, result))
817 given = os.path.join("make sure", "using_quote")
818 expect = "%s/using_quote" % urllib.quote("make sure")
819 result = urllib.pathname2url(given)
820 self.assertEqual(expect, result,
821 "pathname2url() failed; %s != %s" %
822 (expect, result))
823 given = "make+sure/using_unquote"
824 expect = os.path.join("make+sure", "using_unquote")
825 result = urllib.url2pathname(given)
826 self.assertEqual(expect, result,
827 "url2pathname() failed; %s != %s" %
828 (expect, result))
Tim Petersc2659cf2003-05-12 20:19:37 +0000829
Senthil Kumarana99b7612011-04-14 12:54:35 +0800830 @unittest.skipUnless(sys.platform == 'win32',
831 'test specific to the nturl2path library')
832 def test_ntpath(self):
833 given = ('/C:/', '///C:/', '/C|//')
834 expect = 'C:\\'
835 for url in given:
836 result = urllib.url2pathname(url)
837 self.assertEqual(expect, result,
838 'nturl2path.url2pathname() failed; %s != %s' %
839 (expect, result))
840 given = '///C|/path'
841 expect = 'C:\\path'
842 result = urllib.url2pathname(given)
843 self.assertEqual(expect, result,
844 'nturl2path.url2pathname() failed; %s != %s' %
845 (expect, result))
846
Senthil Kumaran5e95e762009-03-30 21:51:50 +0000847class Utility_Tests(unittest.TestCase):
848 """Testcase to test the various utility functions in the urllib."""
Serhiy Storchakaf0b630b2015-03-02 16:31:57 +0200849 # In Python 3 this test class is moved to test_urlparse.
850
851 def test_splittype(self):
852 splittype = urllib.splittype
853 self.assertEqual(splittype('type:opaquestring'), ('type', 'opaquestring'))
854 self.assertEqual(splittype('opaquestring'), (None, 'opaquestring'))
855 self.assertEqual(splittype(':opaquestring'), (None, ':opaquestring'))
856 self.assertEqual(splittype('type:'), ('type', ''))
857 self.assertEqual(splittype('type:opaque:string'), ('type', 'opaque:string'))
858
859 def test_splithost(self):
860 splithost = urllib.splithost
861 self.assertEqual(splithost('//www.example.org:80/foo/bar/baz.html'),
862 ('www.example.org:80', '/foo/bar/baz.html'))
863 self.assertEqual(splithost('//www.example.org:80'),
864 ('www.example.org:80', ''))
865 self.assertEqual(splithost('/foo/bar/baz.html'),
866 (None, '/foo/bar/baz.html'))
867
868 def test_splituser(self):
869 splituser = urllib.splituser
870 self.assertEqual(splituser('User:Pass@www.python.org:080'),
871 ('User:Pass', 'www.python.org:080'))
872 self.assertEqual(splituser('@www.python.org:080'),
873 ('', 'www.python.org:080'))
874 self.assertEqual(splituser('www.python.org:080'),
875 (None, 'www.python.org:080'))
876 self.assertEqual(splituser('User:Pass@'),
877 ('User:Pass', ''))
878 self.assertEqual(splituser('User@example.com:Pass@www.python.org:080'),
879 ('User@example.com:Pass', 'www.python.org:080'))
Senthil Kumaran5e95e762009-03-30 21:51:50 +0000880
881 def test_splitpasswd(self):
Serhiy Storchakaf0b630b2015-03-02 16:31:57 +0200882 # Some of the password examples are not sensible, but it is added to
883 # confirming to RFC2617 and addressing issue4675.
884 splitpasswd = urllib.splitpasswd
885 self.assertEqual(splitpasswd('user:ab'), ('user', 'ab'))
886 self.assertEqual(splitpasswd('user:a\nb'), ('user', 'a\nb'))
887 self.assertEqual(splitpasswd('user:a\tb'), ('user', 'a\tb'))
888 self.assertEqual(splitpasswd('user:a\rb'), ('user', 'a\rb'))
889 self.assertEqual(splitpasswd('user:a\fb'), ('user', 'a\fb'))
890 self.assertEqual(splitpasswd('user:a\vb'), ('user', 'a\vb'))
891 self.assertEqual(splitpasswd('user:a:b'), ('user', 'a:b'))
892 self.assertEqual(splitpasswd('user:a b'), ('user', 'a b'))
893 self.assertEqual(splitpasswd('user 2:ab'), ('user 2', 'ab'))
894 self.assertEqual(splitpasswd('user+1:a+b'), ('user+1', 'a+b'))
895 self.assertEqual(splitpasswd('user:'), ('user', ''))
896 self.assertEqual(splitpasswd('user'), ('user', None))
897 self.assertEqual(splitpasswd(':ab'), ('', 'ab'))
Senthil Kumaran5e95e762009-03-30 21:51:50 +0000898
Serhiy Storchaka326b5ab2014-01-18 18:30:09 +0200899 def test_splitport(self):
900 splitport = urllib.splitport
901 self.assertEqual(splitport('parrot:88'), ('parrot', '88'))
902 self.assertEqual(splitport('parrot'), ('parrot', None))
903 self.assertEqual(splitport('parrot:'), ('parrot', None))
904 self.assertEqual(splitport('127.0.0.1'), ('127.0.0.1', None))
905 self.assertEqual(splitport('parrot:cheese'), ('parrot:cheese', None))
Serhiy Storchakaf0b630b2015-03-02 16:31:57 +0200906 self.assertEqual(splitport('[::1]:88'), ('[::1]', '88'))
907 self.assertEqual(splitport('[::1]'), ('[::1]', None))
908 self.assertEqual(splitport(':88'), ('', '88'))
Serhiy Storchaka326b5ab2014-01-18 18:30:09 +0200909
910 def test_splitnport(self):
911 splitnport = urllib.splitnport
912 self.assertEqual(splitnport('parrot:88'), ('parrot', 88))
913 self.assertEqual(splitnport('parrot'), ('parrot', -1))
914 self.assertEqual(splitnport('parrot', 55), ('parrot', 55))
915 self.assertEqual(splitnport('parrot:'), ('parrot', -1))
916 self.assertEqual(splitnport('parrot:', 55), ('parrot', 55))
917 self.assertEqual(splitnport('127.0.0.1'), ('127.0.0.1', -1))
918 self.assertEqual(splitnport('127.0.0.1', 55), ('127.0.0.1', 55))
919 self.assertEqual(splitnport('parrot:cheese'), ('parrot', None))
920 self.assertEqual(splitnport('parrot:cheese', 55), ('parrot', None))
921
Serhiy Storchakaf0b630b2015-03-02 16:31:57 +0200922 def test_splitquery(self):
923 # Normal cases are exercised by other tests; ensure that we also
924 # catch cases with no port specified (testcase ensuring coverage)
925 splitquery = urllib.splitquery
926 self.assertEqual(splitquery('http://python.org/fake?foo=bar'),
927 ('http://python.org/fake', 'foo=bar'))
928 self.assertEqual(splitquery('http://python.org/fake?foo=bar?'),
929 ('http://python.org/fake?foo=bar', ''))
930 self.assertEqual(splitquery('http://python.org/fake'),
931 ('http://python.org/fake', None))
932 self.assertEqual(splitquery('?foo=bar'), ('', 'foo=bar'))
933
934 def test_splittag(self):
935 splittag = urllib.splittag
936 self.assertEqual(splittag('http://example.com?foo=bar#baz'),
937 ('http://example.com?foo=bar', 'baz'))
938 self.assertEqual(splittag('http://example.com?foo=bar#'),
939 ('http://example.com?foo=bar', ''))
940 self.assertEqual(splittag('#baz'), ('', 'baz'))
941 self.assertEqual(splittag('http://example.com?foo=bar'),
942 ('http://example.com?foo=bar', None))
943 self.assertEqual(splittag('http://example.com?foo=bar#baz#boo'),
944 ('http://example.com?foo=bar#baz', 'boo'))
945
946 def test_splitattr(self):
947 splitattr = urllib.splitattr
948 self.assertEqual(splitattr('/path;attr1=value1;attr2=value2'),
949 ('/path', ['attr1=value1', 'attr2=value2']))
950 self.assertEqual(splitattr('/path;'), ('/path', ['']))
951 self.assertEqual(splitattr(';attr1=value1;attr2=value2'),
952 ('', ['attr1=value1', 'attr2=value2']))
953 self.assertEqual(splitattr('/path'), ('/path', []))
954
955 def test_splitvalue(self):
956 # Normal cases are exercised by other tests; test pathological cases
957 # with no key/value pairs. (testcase ensuring coverage)
958 splitvalue = urllib.splitvalue
959 self.assertEqual(splitvalue('foo=bar'), ('foo', 'bar'))
960 self.assertEqual(splitvalue('foo='), ('foo', ''))
961 self.assertEqual(splitvalue('=bar'), ('', 'bar'))
962 self.assertEqual(splitvalue('foobar'), ('foobar', None))
963 self.assertEqual(splitvalue('foo=bar=baz'), ('foo', 'bar=baz'))
964
965 def test_toBytes(self):
966 result = urllib.toBytes(u'http://www.python.org')
967 self.assertEqual(result, 'http://www.python.org')
968 self.assertRaises(UnicodeError, urllib.toBytes,
969 test_support.u(r'http://www.python.org/medi\u00e6val'))
970
971 def test_unwrap(self):
972 url = urllib.unwrap('<URL:type://host/path>')
973 self.assertEqual(url, 'type://host/path')
974
Senthil Kumaran5e95e762009-03-30 21:51:50 +0000975
Senthil Kumaran7c2867f2009-04-21 03:24:19 +0000976class URLopener_Tests(unittest.TestCase):
977 """Testcase to test the open method of URLopener class."""
978
979 def test_quoted_open(self):
980 class DummyURLopener(urllib.URLopener):
981 def open_spam(self, url):
982 return url
983
984 self.assertEqual(DummyURLopener().open(
985 'spam://example/ /'),'//example/%20/')
986
Senthil Kumaran18d5a692010-02-20 22:05:34 +0000987 # test the safe characters are not quoted by urlopen
988 self.assertEqual(DummyURLopener().open(
989 "spam://c:|windows%/:=&?~#+!$,;'@()*[]|/path/"),
990 "//c:|windows%/:=&?~#+!$,;'@()*[]|/path/")
991
Senthil Kumaran7c2867f2009-04-21 03:24:19 +0000992
Facundo Batistad9880d02007-05-25 04:20:22 +0000993# Just commented them out.
994# Can't really tell why keep failing in windows and sparc.
Ezio Melottic2077b02011-03-16 12:34:31 +0200995# Everywhere else they work ok, but on those machines, sometimes
Facundo Batistad9880d02007-05-25 04:20:22 +0000996# fail in one of the tests, sometimes in other. I have a linux, and
997# the tests go ok.
Ezio Melotti419e23c2013-08-17 16:56:09 +0300998# If anybody has one of the problematic environments, please help!
Facundo Batistad9880d02007-05-25 04:20:22 +0000999# . Facundo
1000#
1001# def server(evt):
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001002# import socket, time
Facundo Batistad9880d02007-05-25 04:20:22 +00001003# serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1004# serv.settimeout(3)
1005# serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
1006# serv.bind(("", 9093))
1007# serv.listen(5)
1008# try:
1009# conn, addr = serv.accept()
1010# conn.send("1 Hola mundo\n")
1011# cantdata = 0
1012# while cantdata < 13:
1013# data = conn.recv(13-cantdata)
1014# cantdata += len(data)
1015# time.sleep(.3)
1016# conn.send("2 No more lines\n")
1017# conn.close()
1018# except socket.timeout:
1019# pass
1020# finally:
1021# serv.close()
1022# evt.set()
1023#
1024# class FTPWrapperTests(unittest.TestCase):
1025#
1026# def setUp(self):
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001027# import ftplib, time, threading
Facundo Batistad9880d02007-05-25 04:20:22 +00001028# ftplib.FTP.port = 9093
1029# self.evt = threading.Event()
1030# threading.Thread(target=server, args=(self.evt,)).start()
1031# time.sleep(.1)
1032#
1033# def tearDown(self):
1034# self.evt.wait()
1035#
1036# def testBasic(self):
1037# # connects
1038# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001039# ftp.close()
Facundo Batistad9880d02007-05-25 04:20:22 +00001040#
1041# def testTimeoutNone(self):
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001042# # global default timeout is ignored
1043# import socket
Serhiy Storchaka528bed82014-02-08 14:49:55 +02001044# self.assertIsNone(socket.getdefaulttimeout())
Facundo Batistad9880d02007-05-25 04:20:22 +00001045# socket.setdefaulttimeout(30)
1046# try:
1047# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
1048# finally:
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001049# socket.setdefaulttimeout(None)
Facundo Batistad9880d02007-05-25 04:20:22 +00001050# self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001051# ftp.close()
Facundo Batistad9880d02007-05-25 04:20:22 +00001052#
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001053# def testTimeoutDefault(self):
1054# # global default timeout is used
1055# import socket
Serhiy Storchaka528bed82014-02-08 14:49:55 +02001056# self.assertIsNone(socket.getdefaulttimeout())
Facundo Batista4f1b1ed2008-05-29 16:39:26 +00001057# socket.setdefaulttimeout(30)
1058# try:
1059# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
1060# finally:
1061# socket.setdefaulttimeout(None)
1062# self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
1063# ftp.close()
1064#
1065# def testTimeoutValue(self):
1066# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [],
1067# timeout=30)
1068# self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
1069# ftp.close()
Facundo Batista711a54e2007-05-24 17:50:54 +00001070
Skip Montanaro080c9972001-01-28 21:12:22 +00001071
1072
Brett Cannon74bfd702003-04-25 09:39:47 +00001073def test_main():
Brett Cannon8bb8fa52008-07-02 01:57:08 +00001074 import warnings
Brett Cannon672237d2008-09-09 00:49:16 +00001075 with warnings.catch_warnings():
Brett Cannon8bb8fa52008-07-02 01:57:08 +00001076 warnings.filterwarnings('ignore', ".*urllib\.urlopen.*Python 3.0",
1077 DeprecationWarning)
1078 test_support.run_unittest(
1079 urlopen_FileTests,
1080 urlopen_HttpTests,
1081 urlretrieve_FileTests,
Senthil Kumaran87e58552011-11-01 02:44:45 +08001082 urlretrieve_HttpTests,
Benjamin Peterson2c7470d2008-09-21 21:27:51 +00001083 ProxyTests,
Brett Cannon8bb8fa52008-07-02 01:57:08 +00001084 QuotingTests,
1085 UnquotingTests,
1086 urlencode_Tests,
1087 Pathname_Tests,
Senthil Kumaran5e95e762009-03-30 21:51:50 +00001088 Utility_Tests,
Senthil Kumaran7c2867f2009-04-21 03:24:19 +00001089 URLopener_Tests,
Senthil Kumaranb31c87b2016-04-25 09:17:54 -07001090 ProxyTests,
1091 ProxyTests_withOrderedEnv,
Brett Cannon8bb8fa52008-07-02 01:57:08 +00001092 #FTPWrapperTests,
1093 )
Brett Cannon74bfd702003-04-25 09:39:47 +00001094
1095
1096
1097if __name__ == '__main__':
1098 test_main()