blob: e94fc22324051f81c424b44c4d1a2fc3add41ddc [file] [log] [blame]
Brett Cannon74bfd702003-04-25 09:39:47 +00001"""Regresssion tests for urllib"""
2
Jeremy Hylton6102e292000-08-31 15:48:10 +00003import urllib
Hye-Shik Chang39aef792004-06-05 13:30:56 +00004import httplib
Brett Cannon74bfd702003-04-25 09:39:47 +00005import unittest
6from test import test_support
7import os
8import mimetools
Georg Brandl5a650a22005-08-26 08:51:34 +00009import tempfile
Hye-Shik Chang39aef792004-06-05 13:30:56 +000010import StringIO
Guido van Rossume7ba4952007-06-06 23:52:48 +000011import ftplib
12import threading
13import socket
14import time
Jeremy Hylton6102e292000-08-31 15:48:10 +000015
Brett Cannon74bfd702003-04-25 09:39:47 +000016def hexescape(char):
17 """Escape char as RFC 2396 specifies"""
18 hex_repr = hex(ord(char))[2:].upper()
19 if len(hex_repr) == 1:
20 hex_repr = "0%s" % hex_repr
21 return "%" + hex_repr
Jeremy Hylton6102e292000-08-31 15:48:10 +000022
Brett Cannon74bfd702003-04-25 09:39:47 +000023class urlopen_FileTests(unittest.TestCase):
24 """Test urlopen() opening a temporary file.
Jeremy Hylton6102e292000-08-31 15:48:10 +000025
Brett Cannon74bfd702003-04-25 09:39:47 +000026 Try to test as much functionality as possible so as to cut down on reliance
Andrew M. Kuchlingf1a2f9e2004-06-29 13:07:53 +000027 on connecting to the Net for testing.
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000028
Brett Cannon74bfd702003-04-25 09:39:47 +000029 """
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000030
Brett Cannon74bfd702003-04-25 09:39:47 +000031 def setUp(self):
32 """Setup of a temp file to use for testing"""
Guido van Rossuma0982942007-07-10 08:30:03 +000033 self.text = bytes("test_urllib: %s\n" % self.__class__.__name__)
Alex Martelli01c77c62006-08-24 02:58:11 +000034 FILE = open(test_support.TESTFN, 'wb')
Brett Cannon74bfd702003-04-25 09:39:47 +000035 try:
36 FILE.write(self.text)
37 finally:
38 FILE.close()
39 self.pathname = test_support.TESTFN
40 self.returned_obj = urllib.urlopen("file:%s" % self.pathname)
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000041
Brett Cannon74bfd702003-04-25 09:39:47 +000042 def tearDown(self):
43 """Shut down the open object"""
44 self.returned_obj.close()
Brett Cannon19691362003-04-29 05:08:06 +000045 os.remove(test_support.TESTFN)
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000046
Brett Cannon74bfd702003-04-25 09:39:47 +000047 def test_interface(self):
48 # Make sure object returned by urlopen() has the specified methods
49 for attr in ("read", "readline", "readlines", "fileno",
50 "close", "info", "geturl", "__iter__"):
51 self.assert_(hasattr(self.returned_obj, attr),
52 "object returned by urlopen() lacks %s attribute" %
53 attr)
Skip Montanaroe78b92a2001-01-20 20:22:30 +000054
Brett Cannon74bfd702003-04-25 09:39:47 +000055 def test_read(self):
56 self.assertEqual(self.text, self.returned_obj.read())
Skip Montanaro080c9972001-01-28 21:12:22 +000057
Brett Cannon74bfd702003-04-25 09:39:47 +000058 def test_readline(self):
59 self.assertEqual(self.text, self.returned_obj.readline())
Guido van Rossuma0982942007-07-10 08:30:03 +000060 self.assertEqual(b'', self.returned_obj.readline(),
Brett Cannon74bfd702003-04-25 09:39:47 +000061 "calling readline() after exhausting the file did not"
62 " return an empty string")
Skip Montanaro080c9972001-01-28 21:12:22 +000063
Brett Cannon74bfd702003-04-25 09:39:47 +000064 def test_readlines(self):
65 lines_list = self.returned_obj.readlines()
66 self.assertEqual(len(lines_list), 1,
67 "readlines() returned the wrong number of lines")
68 self.assertEqual(lines_list[0], self.text,
69 "readlines() returned improper text")
Skip Montanaro080c9972001-01-28 21:12:22 +000070
Brett Cannon74bfd702003-04-25 09:39:47 +000071 def test_fileno(self):
72 file_num = self.returned_obj.fileno()
73 self.assert_(isinstance(file_num, int),
74 "fileno() did not return an int")
75 self.assertEqual(os.read(file_num, len(self.text)), self.text,
76 "Reading on the file descriptor returned by fileno() "
77 "did not return the expected text")
Skip Montanaroe78b92a2001-01-20 20:22:30 +000078
Brett Cannon74bfd702003-04-25 09:39:47 +000079 def test_close(self):
80 # Test close() by calling it hear and then having it be called again
81 # by the tearDown() method for the test
82 self.returned_obj.close()
Skip Montanaro080c9972001-01-28 21:12:22 +000083
Brett Cannon74bfd702003-04-25 09:39:47 +000084 def test_info(self):
85 self.assert_(isinstance(self.returned_obj.info(), mimetools.Message))
Skip Montanaroe78b92a2001-01-20 20:22:30 +000086
Brett Cannon74bfd702003-04-25 09:39:47 +000087 def test_geturl(self):
88 self.assertEqual(self.returned_obj.geturl(), self.pathname)
Skip Montanaro080c9972001-01-28 21:12:22 +000089
Brett Cannon74bfd702003-04-25 09:39:47 +000090 def test_iter(self):
91 # Test iterator
92 # Don't need to count number of iterations since test would fail the
93 # instant it returned anything beyond the first line from the
94 # comparison
95 for line in self.returned_obj.__iter__():
96 self.assertEqual(line, self.text)
Skip Montanaro080c9972001-01-28 21:12:22 +000097
Hye-Shik Chang39aef792004-06-05 13:30:56 +000098class urlopen_HttpTests(unittest.TestCase):
99 """Test urlopen() opening a fake http connection."""
100
101 def fakehttp(self, fakedata):
102 class FakeSocket(StringIO.StringIO):
103 def sendall(self, str): pass
104 def makefile(self, mode, name): return self
105 def read(self, amt=None):
106 if self.closed: return ''
107 return StringIO.StringIO.read(self, amt)
108 def readline(self, length=None):
109 if self.closed: return ''
110 return StringIO.StringIO.readline(self, length)
111 class FakeHTTPConnection(httplib.HTTPConnection):
112 def connect(self):
113 self.sock = FakeSocket(fakedata)
114 assert httplib.HTTP._connection_class == httplib.HTTPConnection
115 httplib.HTTP._connection_class = FakeHTTPConnection
116
117 def unfakehttp(self):
118 httplib.HTTP._connection_class = httplib.HTTPConnection
119
120 def test_read(self):
121 self.fakehttp('Hello!')
122 try:
123 fp = urllib.urlopen("http://python.org/")
124 self.assertEqual(fp.readline(), 'Hello!')
125 self.assertEqual(fp.readline(), '')
126 finally:
127 self.unfakehttp()
128
Guido van Rossumd8faa362007-04-27 19:54:29 +0000129 def test_empty_socket(self):
130 """urlopen() raises IOError if the underlying socket does not send any
131 data. (#1680230) """
132 self.fakehttp('')
133 try:
134 self.assertRaises(IOError, urllib.urlopen, 'http://something')
135 finally:
136 self.unfakehttp()
137
Brett Cannon19691362003-04-29 05:08:06 +0000138class urlretrieve_FileTests(unittest.TestCase):
Brett Cannon74bfd702003-04-25 09:39:47 +0000139 """Test urllib.urlretrieve() on local files"""
Skip Montanaro080c9972001-01-28 21:12:22 +0000140
Brett Cannon19691362003-04-29 05:08:06 +0000141 def setUp(self):
Georg Brandl5a650a22005-08-26 08:51:34 +0000142 # Create a list of temporary files. Each item in the list is a file
143 # name (absolute path or relative to the current working directory).
144 # All files in this list will be deleted in the tearDown method. Note,
145 # this only helps to makes sure temporary files get deleted, but it
146 # does nothing about trying to close files that may still be open. It
147 # is the responsibility of the developer to properly close files even
148 # when exceptional conditions occur.
149 self.tempFiles = []
150
Brett Cannon19691362003-04-29 05:08:06 +0000151 # Create a temporary file.
Georg Brandl5a650a22005-08-26 08:51:34 +0000152 self.registerFileForCleanUp(test_support.TESTFN)
Guido van Rossuma0982942007-07-10 08:30:03 +0000153 self.text = b'testing urllib.urlretrieve'
Georg Brandl5a650a22005-08-26 08:51:34 +0000154 try:
Alex Martelli01c77c62006-08-24 02:58:11 +0000155 FILE = open(test_support.TESTFN, 'wb')
Georg Brandl5a650a22005-08-26 08:51:34 +0000156 FILE.write(self.text)
157 FILE.close()
158 finally:
159 try: FILE.close()
160 except: pass
Brett Cannon19691362003-04-29 05:08:06 +0000161
162 def tearDown(self):
Georg Brandl5a650a22005-08-26 08:51:34 +0000163 # Delete the temporary files.
164 for each in self.tempFiles:
165 try: os.remove(each)
166 except: pass
167
168 def constructLocalFileUrl(self, filePath):
169 return "file://%s" % urllib.pathname2url(os.path.abspath(filePath))
170
171 def createNewTempFile(self, data=""):
172 """Creates a new temporary file containing the specified data,
173 registers the file for deletion during the test fixture tear down, and
174 returns the absolute path of the file."""
175
176 newFd, newFilePath = tempfile.mkstemp()
177 try:
178 self.registerFileForCleanUp(newFilePath)
179 newFile = os.fdopen(newFd, "wb")
180 newFile.write(data)
181 newFile.close()
182 finally:
183 try: newFile.close()
184 except: pass
185 return newFilePath
186
187 def registerFileForCleanUp(self, fileName):
188 self.tempFiles.append(fileName)
Brett Cannon19691362003-04-29 05:08:06 +0000189
190 def test_basic(self):
191 # Make sure that a local file just gets its own location returned and
192 # a headers value is returned.
193 result = urllib.urlretrieve("file:%s" % test_support.TESTFN)
194 self.assertEqual(result[0], test_support.TESTFN)
195 self.assert_(isinstance(result[1], mimetools.Message),
196 "did not get a mimetools.Message instance as second "
197 "returned value")
198
199 def test_copy(self):
200 # Test that setting the filename argument works.
201 second_temp = "%s.2" % test_support.TESTFN
Georg Brandl5a650a22005-08-26 08:51:34 +0000202 self.registerFileForCleanUp(second_temp)
203 result = urllib.urlretrieve(self.constructLocalFileUrl(
204 test_support.TESTFN), second_temp)
Brett Cannon19691362003-04-29 05:08:06 +0000205 self.assertEqual(second_temp, result[0])
206 self.assert_(os.path.exists(second_temp), "copy of the file was not "
207 "made")
Alex Martelli01c77c62006-08-24 02:58:11 +0000208 FILE = open(second_temp, 'rb')
Brett Cannon19691362003-04-29 05:08:06 +0000209 try:
210 text = FILE.read()
Brett Cannon19691362003-04-29 05:08:06 +0000211 FILE.close()
Georg Brandl5a650a22005-08-26 08:51:34 +0000212 finally:
213 try: FILE.close()
214 except: pass
Brett Cannon19691362003-04-29 05:08:06 +0000215 self.assertEqual(self.text, text)
216
217 def test_reporthook(self):
218 # Make sure that the reporthook works.
219 def hooktester(count, block_size, total_size, count_holder=[0]):
220 self.assert_(isinstance(count, int))
221 self.assert_(isinstance(block_size, int))
222 self.assert_(isinstance(total_size, int))
223 self.assertEqual(count, count_holder[0])
224 count_holder[0] = count_holder[0] + 1
225 second_temp = "%s.2" % test_support.TESTFN
Georg Brandl5a650a22005-08-26 08:51:34 +0000226 self.registerFileForCleanUp(second_temp)
227 urllib.urlretrieve(self.constructLocalFileUrl(test_support.TESTFN),
228 second_temp, hooktester)
229
230 def test_reporthook_0_bytes(self):
231 # Test on zero length file. Should call reporthook only 1 time.
232 report = []
233 def hooktester(count, block_size, total_size, _report=report):
234 _report.append((count, block_size, total_size))
235 srcFileName = self.createNewTempFile()
236 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
237 test_support.TESTFN, hooktester)
238 self.assertEqual(len(report), 1)
239 self.assertEqual(report[0][2], 0)
240
241 def test_reporthook_5_bytes(self):
242 # Test on 5 byte file. Should call reporthook only 2 times (once when
243 # the "network connection" is established and once when the block is
244 # read). Since the block size is 8192 bytes, only one block read is
245 # required to read the entire file.
246 report = []
247 def hooktester(count, block_size, total_size, _report=report):
248 _report.append((count, block_size, total_size))
249 srcFileName = self.createNewTempFile("x" * 5)
250 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
251 test_support.TESTFN, hooktester)
252 self.assertEqual(len(report), 2)
253 self.assertEqual(report[0][1], 8192)
254 self.assertEqual(report[0][2], 5)
255
256 def test_reporthook_8193_bytes(self):
257 # Test on 8193 byte file. Should call reporthook only 3 times (once
258 # when the "network connection" is established, once for the next 8192
259 # bytes, and once for the last byte).
260 report = []
261 def hooktester(count, block_size, total_size, _report=report):
262 _report.append((count, block_size, total_size))
263 srcFileName = self.createNewTempFile("x" * 8193)
264 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
265 test_support.TESTFN, hooktester)
266 self.assertEqual(len(report), 3)
267 self.assertEqual(report[0][1], 8192)
268 self.assertEqual(report[0][2], 8193)
Skip Montanaro080c9972001-01-28 21:12:22 +0000269
Brett Cannon74bfd702003-04-25 09:39:47 +0000270class QuotingTests(unittest.TestCase):
271 """Tests for urllib.quote() and urllib.quote_plus()
Tim Petersc2659cf2003-05-12 20:19:37 +0000272
Brett Cannon74bfd702003-04-25 09:39:47 +0000273 According to RFC 2396 ("Uniform Resource Identifiers), to escape a
274 character you write it as '%' + <2 character US-ASCII hex value>. The Python
275 code of ``'%' + hex(ord(<character>))[2:]`` escapes a character properly.
276 Case does not matter on the hex letters.
277
278 The various character sets specified are:
Tim Petersc2659cf2003-05-12 20:19:37 +0000279
Brett Cannon74bfd702003-04-25 09:39:47 +0000280 Reserved characters : ";/?:@&=+$,"
281 Have special meaning in URIs and must be escaped if not being used for
282 their special meaning
283 Data characters : letters, digits, and "-_.!~*'()"
284 Unreserved and do not need to be escaped; can be, though, if desired
285 Control characters : 0x00 - 0x1F, 0x7F
286 Have no use in URIs so must be escaped
287 space : 0x20
288 Must be escaped
289 Delimiters : '<>#%"'
290 Must be escaped
291 Unwise : "{}|\^[]`"
292 Must be escaped
Tim Petersc2659cf2003-05-12 20:19:37 +0000293
Brett Cannon74bfd702003-04-25 09:39:47 +0000294 """
295
296 def test_never_quote(self):
297 # Make sure quote() does not quote letters, digits, and "_,.-"
298 do_not_quote = '' .join(["ABCDEFGHIJKLMNOPQRSTUVWXYZ",
299 "abcdefghijklmnopqrstuvwxyz",
300 "0123456789",
301 "_.-"])
302 result = urllib.quote(do_not_quote)
303 self.assertEqual(do_not_quote, result,
304 "using quote(): %s != %s" % (do_not_quote, result))
305 result = urllib.quote_plus(do_not_quote)
306 self.assertEqual(do_not_quote, result,
307 "using quote_plus(): %s != %s" % (do_not_quote, result))
308
309 def test_default_safe(self):
310 # Test '/' is default value for 'safe' parameter
Neal Norwitz221085d2007-02-25 20:55:47 +0000311 self.assertEqual(urllib.quote.__defaults__[0], '/')
Brett Cannon74bfd702003-04-25 09:39:47 +0000312
313 def test_safe(self):
314 # Test setting 'safe' parameter does what it should do
315 quote_by_default = "<>"
316 result = urllib.quote(quote_by_default, safe=quote_by_default)
317 self.assertEqual(quote_by_default, result,
318 "using quote(): %s != %s" % (quote_by_default, result))
319 result = urllib.quote_plus(quote_by_default, safe=quote_by_default)
320 self.assertEqual(quote_by_default, result,
321 "using quote_plus(): %s != %s" %
322 (quote_by_default, result))
323
324 def test_default_quoting(self):
325 # Make sure all characters that should be quoted are by default sans
326 # space (separate test for that).
327 should_quote = [chr(num) for num in range(32)] # For 0x00 - 0x1F
328 should_quote.append('<>#%"{}|\^[]`')
329 should_quote.append(chr(127)) # For 0x7F
330 should_quote = ''.join(should_quote)
331 for char in should_quote:
332 result = urllib.quote(char)
333 self.assertEqual(hexescape(char), result,
334 "using quote(): %s should be escaped to %s, not %s" %
335 (char, hexescape(char), result))
336 result = urllib.quote_plus(char)
337 self.assertEqual(hexescape(char), result,
338 "using quote_plus(): "
Tim Petersc2659cf2003-05-12 20:19:37 +0000339 "%s should be escapes to %s, not %s" %
Brett Cannon74bfd702003-04-25 09:39:47 +0000340 (char, hexescape(char), result))
341 del should_quote
342 partial_quote = "ab[]cd"
343 expected = "ab%5B%5Dcd"
344 result = urllib.quote(partial_quote)
345 self.assertEqual(expected, result,
346 "using quote(): %s != %s" % (expected, result))
347 self.assertEqual(expected, result,
348 "using quote_plus(): %s != %s" % (expected, result))
349
350 def test_quoting_space(self):
351 # Make sure quote() and quote_plus() handle spaces as specified in
352 # their unique way
353 result = urllib.quote(' ')
354 self.assertEqual(result, hexescape(' '),
355 "using quote(): %s != %s" % (result, hexescape(' ')))
356 result = urllib.quote_plus(' ')
357 self.assertEqual(result, '+',
358 "using quote_plus(): %s != +" % result)
359 given = "a b cd e f"
360 expect = given.replace(' ', hexescape(' '))
361 result = urllib.quote(given)
362 self.assertEqual(expect, result,
363 "using quote(): %s != %s" % (expect, result))
364 expect = given.replace(' ', '+')
365 result = urllib.quote_plus(given)
366 self.assertEqual(expect, result,
367 "using quote_plus(): %s != %s" % (expect, result))
368
Raymond Hettinger2bdec7b2005-09-10 14:30:09 +0000369 def test_quoting_plus(self):
370 self.assertEqual(urllib.quote_plus('alpha+beta gamma'),
371 'alpha%2Bbeta+gamma')
372 self.assertEqual(urllib.quote_plus('alpha+beta gamma', '+'),
373 'alpha+beta+gamma')
374
Brett Cannon74bfd702003-04-25 09:39:47 +0000375class UnquotingTests(unittest.TestCase):
376 """Tests for unquote() and unquote_plus()
Tim Petersc2659cf2003-05-12 20:19:37 +0000377
Brett Cannon74bfd702003-04-25 09:39:47 +0000378 See the doc string for quoting_Tests for details on quoting and such.
379
380 """
381
382 def test_unquoting(self):
383 # Make sure unquoting of all ASCII values works
384 escape_list = []
385 for num in range(128):
386 given = hexescape(chr(num))
387 expect = chr(num)
388 result = urllib.unquote(given)
389 self.assertEqual(expect, result,
390 "using unquote(): %s != %s" % (expect, result))
391 result = urllib.unquote_plus(given)
392 self.assertEqual(expect, result,
393 "using unquote_plus(): %s != %s" %
394 (expect, result))
395 escape_list.append(given)
396 escape_string = ''.join(escape_list)
397 del escape_list
398 result = urllib.unquote(escape_string)
399 self.assertEqual(result.count('%'), 1,
400 "using quote(): not all characters escaped; %s" %
401 result)
402 result = urllib.unquote(escape_string)
403 self.assertEqual(result.count('%'), 1,
404 "using unquote(): not all characters escaped: "
405 "%s" % result)
406
407 def test_unquoting_parts(self):
408 # Make sure unquoting works when have non-quoted characters
409 # interspersed
410 given = 'ab%sd' % hexescape('c')
411 expect = "abcd"
412 result = urllib.unquote(given)
413 self.assertEqual(expect, result,
414 "using quote(): %s != %s" % (expect, result))
415 result = urllib.unquote_plus(given)
416 self.assertEqual(expect, result,
417 "using unquote_plus(): %s != %s" % (expect, result))
Tim Petersc2659cf2003-05-12 20:19:37 +0000418
Brett Cannon74bfd702003-04-25 09:39:47 +0000419 def test_unquoting_plus(self):
420 # Test difference between unquote() and unquote_plus()
421 given = "are+there+spaces..."
422 expect = given
423 result = urllib.unquote(given)
424 self.assertEqual(expect, result,
425 "using unquote(): %s != %s" % (expect, result))
426 expect = given.replace('+', ' ')
427 result = urllib.unquote_plus(given)
428 self.assertEqual(expect, result,
429 "using unquote_plus(): %s != %s" % (expect, result))
430
Raymond Hettinger4b0f20d2005-10-15 16:41:53 +0000431 def test_unquote_with_unicode(self):
Guido van Rossumef87d6e2007-05-02 19:09:54 +0000432 r = urllib.unquote('br%C3%BCckner_sapporo_20050930.doc')
433 self.assertEqual(r, 'br\xc3\xbcckner_sapporo_20050930.doc')
Raymond Hettinger4b0f20d2005-10-15 16:41:53 +0000434
Brett Cannon74bfd702003-04-25 09:39:47 +0000435class urlencode_Tests(unittest.TestCase):
436 """Tests for urlencode()"""
437
438 def help_inputtype(self, given, test_type):
439 """Helper method for testing different input types.
Tim Petersc2659cf2003-05-12 20:19:37 +0000440
Brett Cannon74bfd702003-04-25 09:39:47 +0000441 'given' must lead to only the pairs:
442 * 1st, 1
443 * 2nd, 2
444 * 3rd, 3
Tim Petersc2659cf2003-05-12 20:19:37 +0000445
Brett Cannon74bfd702003-04-25 09:39:47 +0000446 Test cannot assume anything about order. Docs make no guarantee and
447 have possible dictionary input.
Tim Petersc2659cf2003-05-12 20:19:37 +0000448
Brett Cannon74bfd702003-04-25 09:39:47 +0000449 """
450 expect_somewhere = ["1st=1", "2nd=2", "3rd=3"]
451 result = urllib.urlencode(given)
452 for expected in expect_somewhere:
453 self.assert_(expected in result,
454 "testing %s: %s not found in %s" %
455 (test_type, expected, result))
456 self.assertEqual(result.count('&'), 2,
457 "testing %s: expected 2 '&'s; got %s" %
458 (test_type, result.count('&')))
459 amp_location = result.index('&')
460 on_amp_left = result[amp_location - 1]
461 on_amp_right = result[amp_location + 1]
462 self.assert_(on_amp_left.isdigit() and on_amp_right.isdigit(),
463 "testing %s: '&' not located in proper place in %s" %
464 (test_type, result))
465 self.assertEqual(len(result), (5 * 3) + 2, #5 chars per thing and amps
466 "testing %s: "
467 "unexpected number of characters: %s != %s" %
468 (test_type, len(result), (5 * 3) + 2))
469
470 def test_using_mapping(self):
471 # Test passing in a mapping object as an argument.
472 self.help_inputtype({"1st":'1', "2nd":'2', "3rd":'3'},
473 "using dict as input type")
474
475 def test_using_sequence(self):
476 # Test passing in a sequence of two-item sequences as an argument.
477 self.help_inputtype([('1st', '1'), ('2nd', '2'), ('3rd', '3')],
478 "using sequence of two-item tuples as input")
479
480 def test_quoting(self):
481 # Make sure keys and values are quoted using quote_plus()
482 given = {"&":"="}
483 expect = "%s=%s" % (hexescape('&'), hexescape('='))
484 result = urllib.urlencode(given)
485 self.assertEqual(expect, result)
486 given = {"key name":"A bunch of pluses"}
487 expect = "key+name=A+bunch+of+pluses"
488 result = urllib.urlencode(given)
489 self.assertEqual(expect, result)
490
491 def test_doseq(self):
492 # Test that passing True for 'doseq' parameter works correctly
493 given = {'sequence':['1', '2', '3']}
494 expect = "sequence=%s" % urllib.quote_plus(str(['1', '2', '3']))
495 result = urllib.urlencode(given)
496 self.assertEqual(expect, result)
497 result = urllib.urlencode(given, True)
498 for value in given["sequence"]:
499 expect = "sequence=%s" % value
500 self.assert_(expect in result,
501 "%s not found in %s" % (expect, result))
502 self.assertEqual(result.count('&'), 2,
503 "Expected 2 '&'s, got %s" % result.count('&'))
504
505class Pathname_Tests(unittest.TestCase):
506 """Test pathname2url() and url2pathname()"""
507
508 def test_basic(self):
509 # Make sure simple tests pass
510 expected_path = os.path.join("parts", "of", "a", "path")
511 expected_url = "parts/of/a/path"
512 result = urllib.pathname2url(expected_path)
513 self.assertEqual(expected_url, result,
514 "pathname2url() failed; %s != %s" %
515 (result, expected_url))
516 result = urllib.url2pathname(expected_url)
517 self.assertEqual(expected_path, result,
518 "url2pathame() failed; %s != %s" %
519 (result, expected_path))
520
521 def test_quoting(self):
522 # Test automatic quoting and unquoting works for pathnam2url() and
523 # url2pathname() respectively
524 given = os.path.join("needs", "quot=ing", "here")
525 expect = "needs/%s/here" % urllib.quote("quot=ing")
526 result = urllib.pathname2url(given)
527 self.assertEqual(expect, result,
528 "pathname2url() failed; %s != %s" %
529 (expect, result))
530 expect = given
531 result = urllib.url2pathname(result)
532 self.assertEqual(expect, result,
533 "url2pathname() failed; %s != %s" %
534 (expect, result))
535 given = os.path.join("make sure", "using_quote")
536 expect = "%s/using_quote" % urllib.quote("make sure")
537 result = urllib.pathname2url(given)
538 self.assertEqual(expect, result,
539 "pathname2url() failed; %s != %s" %
540 (expect, result))
541 given = "make+sure/using_unquote"
542 expect = os.path.join("make+sure", "using_unquote")
543 result = urllib.url2pathname(given)
544 self.assertEqual(expect, result,
545 "url2pathname() failed; %s != %s" %
546 (expect, result))
Tim Petersc2659cf2003-05-12 20:19:37 +0000547
Guido van Rossume7ba4952007-06-06 23:52:48 +0000548# Just commented them out.
549# Can't really tell why keep failing in windows and sparc.
550# Everywhere else they work ok, but on those machines, someteimes
551# fail in one of the tests, sometimes in other. I have a linux, and
552# the tests go ok.
553# If anybody has one of the problematic enviroments, please help!
554# . Facundo
555#
556# def server(evt):
557# serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
558# serv.settimeout(3)
559# serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
560# serv.bind(("", 9093))
561# serv.listen(5)
562# try:
563# conn, addr = serv.accept()
564# conn.send("1 Hola mundo\n")
565# cantdata = 0
566# while cantdata < 13:
567# data = conn.recv(13-cantdata)
568# cantdata += len(data)
569# time.sleep(.3)
570# conn.send("2 No more lines\n")
571# conn.close()
572# except socket.timeout:
573# pass
574# finally:
575# serv.close()
576# evt.set()
577#
578# class FTPWrapperTests(unittest.TestCase):
579#
580# def setUp(self):
581# ftplib.FTP.port = 9093
582# self.evt = threading.Event()
583# threading.Thread(target=server, args=(self.evt,)).start()
584# time.sleep(.1)
585#
586# def tearDown(self):
587# self.evt.wait()
588#
589# def testBasic(self):
590# # connects
591# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
592# ftp.ftp.sock.close()
593#
594# def testTimeoutDefault(self):
595# # default
596# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
597# self.assertTrue(ftp.ftp.sock.gettimeout() is None)
598# ftp.ftp.sock.close()
599#
600# def testTimeoutValue(self):
601# # a value
602# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [], timeout=30)
603# self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
604# ftp.ftp.sock.close()
605#
606# def testTimeoutNone(self):
607# # None, having other default
608# previous = socket.getdefaulttimeout()
609# socket.setdefaulttimeout(30)
610# try:
611# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
612# finally:
613# socket.setdefaulttimeout(previous)
614# self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
615# ftp.ftp.close()
616#
617
Skip Montanaro080c9972001-01-28 21:12:22 +0000618
619
Brett Cannon74bfd702003-04-25 09:39:47 +0000620def test_main():
Walter Dörwald21d3a322003-05-01 17:45:56 +0000621 test_support.run_unittest(
622 urlopen_FileTests,
Hye-Shik Chang39aef792004-06-05 13:30:56 +0000623 urlopen_HttpTests,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000624 urlretrieve_FileTests,
625 QuotingTests,
626 UnquotingTests,
627 urlencode_Tests,
Guido van Rossume7ba4952007-06-06 23:52:48 +0000628 Pathname_Tests,
629 #FTPWrapperTests,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000630 )
Brett Cannon74bfd702003-04-25 09:39:47 +0000631
632
633
634if __name__ == '__main__':
635 test_main()