blob: 4851742aff3cfb6e5d4d1b0de0925905f2076a9e [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
Jeremy Hylton6102e292000-08-31 15:48:10 +000011
Brett Cannon74bfd702003-04-25 09:39:47 +000012def hexescape(char):
13 """Escape char as RFC 2396 specifies"""
14 hex_repr = hex(ord(char))[2:].upper()
15 if len(hex_repr) == 1:
16 hex_repr = "0%s" % hex_repr
17 return "%" + hex_repr
Jeremy Hylton6102e292000-08-31 15:48:10 +000018
Brett Cannon74bfd702003-04-25 09:39:47 +000019class urlopen_FileTests(unittest.TestCase):
20 """Test urlopen() opening a temporary file.
Jeremy Hylton6102e292000-08-31 15:48:10 +000021
Brett Cannon74bfd702003-04-25 09:39:47 +000022 Try to test as much functionality as possible so as to cut down on reliance
Andrew M. Kuchlingf1a2f9e2004-06-29 13:07:53 +000023 on connecting to the Net for testing.
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000024
Brett Cannon74bfd702003-04-25 09:39:47 +000025 """
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000026
Brett Cannon74bfd702003-04-25 09:39:47 +000027 def setUp(self):
28 """Setup of a temp file to use for testing"""
29 self.text = "test_urllib: %s\n" % self.__class__.__name__
Neal Norwitzce2ab352007-03-20 06:13:25 +000030 test_support.unlink(test_support.TESTFN)
Guido van Rossum51735b02003-04-25 15:01:05 +000031 FILE = file(test_support.TESTFN, 'wb')
Brett Cannon74bfd702003-04-25 09:39:47 +000032 try:
33 FILE.write(self.text)
34 finally:
35 FILE.close()
36 self.pathname = test_support.TESTFN
37 self.returned_obj = urllib.urlopen("file:%s" % self.pathname)
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000038
Brett Cannon74bfd702003-04-25 09:39:47 +000039 def tearDown(self):
40 """Shut down the open object"""
41 self.returned_obj.close()
Brett Cannon19691362003-04-29 05:08:06 +000042 os.remove(test_support.TESTFN)
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000043
Brett Cannon74bfd702003-04-25 09:39:47 +000044 def test_interface(self):
45 # Make sure object returned by urlopen() has the specified methods
46 for attr in ("read", "readline", "readlines", "fileno",
47 "close", "info", "geturl", "__iter__"):
48 self.assert_(hasattr(self.returned_obj, attr),
49 "object returned by urlopen() lacks %s attribute" %
50 attr)
Skip Montanaroe78b92a2001-01-20 20:22:30 +000051
Brett Cannon74bfd702003-04-25 09:39:47 +000052 def test_read(self):
53 self.assertEqual(self.text, self.returned_obj.read())
Skip Montanaro080c9972001-01-28 21:12:22 +000054
Brett Cannon74bfd702003-04-25 09:39:47 +000055 def test_readline(self):
56 self.assertEqual(self.text, self.returned_obj.readline())
57 self.assertEqual('', self.returned_obj.readline(),
58 "calling readline() after exhausting the file did not"
59 " return an empty string")
Skip Montanaro080c9972001-01-28 21:12:22 +000060
Brett Cannon74bfd702003-04-25 09:39:47 +000061 def test_readlines(self):
62 lines_list = self.returned_obj.readlines()
63 self.assertEqual(len(lines_list), 1,
64 "readlines() returned the wrong number of lines")
65 self.assertEqual(lines_list[0], self.text,
66 "readlines() returned improper text")
Skip Montanaro080c9972001-01-28 21:12:22 +000067
Brett Cannon74bfd702003-04-25 09:39:47 +000068 def test_fileno(self):
69 file_num = self.returned_obj.fileno()
70 self.assert_(isinstance(file_num, int),
71 "fileno() did not return an int")
72 self.assertEqual(os.read(file_num, len(self.text)), self.text,
73 "Reading on the file descriptor returned by fileno() "
74 "did not return the expected text")
Skip Montanaroe78b92a2001-01-20 20:22:30 +000075
Brett Cannon74bfd702003-04-25 09:39:47 +000076 def test_close(self):
77 # Test close() by calling it hear and then having it be called again
78 # by the tearDown() method for the test
79 self.returned_obj.close()
Skip Montanaro080c9972001-01-28 21:12:22 +000080
Brett Cannon74bfd702003-04-25 09:39:47 +000081 def test_info(self):
82 self.assert_(isinstance(self.returned_obj.info(), mimetools.Message))
Skip Montanaroe78b92a2001-01-20 20:22:30 +000083
Brett Cannon74bfd702003-04-25 09:39:47 +000084 def test_geturl(self):
85 self.assertEqual(self.returned_obj.geturl(), self.pathname)
Skip Montanaro080c9972001-01-28 21:12:22 +000086
Brett Cannon74bfd702003-04-25 09:39:47 +000087 def test_iter(self):
88 # Test iterator
89 # Don't need to count number of iterations since test would fail the
90 # instant it returned anything beyond the first line from the
91 # comparison
92 for line in self.returned_obj.__iter__():
93 self.assertEqual(line, self.text)
Skip Montanaro080c9972001-01-28 21:12:22 +000094
Hye-Shik Chang39aef792004-06-05 13:30:56 +000095class urlopen_HttpTests(unittest.TestCase):
96 """Test urlopen() opening a fake http connection."""
97
98 def fakehttp(self, fakedata):
99 class FakeSocket(StringIO.StringIO):
100 def sendall(self, str): pass
101 def makefile(self, mode, name): return self
102 def read(self, amt=None):
103 if self.closed: return ''
104 return StringIO.StringIO.read(self, amt)
105 def readline(self, length=None):
106 if self.closed: return ''
107 return StringIO.StringIO.readline(self, length)
108 class FakeHTTPConnection(httplib.HTTPConnection):
109 def connect(self):
110 self.sock = FakeSocket(fakedata)
111 assert httplib.HTTP._connection_class == httplib.HTTPConnection
112 httplib.HTTP._connection_class = FakeHTTPConnection
113
114 def unfakehttp(self):
115 httplib.HTTP._connection_class = httplib.HTTPConnection
116
117 def test_read(self):
118 self.fakehttp('Hello!')
119 try:
120 fp = urllib.urlopen("http://python.org/")
121 self.assertEqual(fp.readline(), 'Hello!')
122 self.assertEqual(fp.readline(), '')
123 finally:
124 self.unfakehttp()
125
Georg Brandlf66b6032007-03-14 08:27:52 +0000126 def test_empty_socket(self):
127 """urlopen() raises IOError if the underlying socket does not send any
128 data. (#1680230) """
129 self.fakehttp('')
130 try:
131 self.assertRaises(IOError, urllib.urlopen, 'http://something')
132 finally:
133 self.unfakehttp()
134
Brett Cannon19691362003-04-29 05:08:06 +0000135class urlretrieve_FileTests(unittest.TestCase):
Brett Cannon74bfd702003-04-25 09:39:47 +0000136 """Test urllib.urlretrieve() on local files"""
Skip Montanaro080c9972001-01-28 21:12:22 +0000137
Brett Cannon19691362003-04-29 05:08:06 +0000138 def setUp(self):
Georg Brandl5a650a22005-08-26 08:51:34 +0000139 # Create a list of temporary files. Each item in the list is a file
140 # name (absolute path or relative to the current working directory).
141 # All files in this list will be deleted in the tearDown method. Note,
142 # this only helps to makes sure temporary files get deleted, but it
143 # does nothing about trying to close files that may still be open. It
144 # is the responsibility of the developer to properly close files even
145 # when exceptional conditions occur.
146 self.tempFiles = []
147
Brett Cannon19691362003-04-29 05:08:06 +0000148 # Create a temporary file.
Georg Brandl5a650a22005-08-26 08:51:34 +0000149 self.registerFileForCleanUp(test_support.TESTFN)
Brett Cannon19691362003-04-29 05:08:06 +0000150 self.text = 'testing urllib.urlretrieve'
Georg Brandl5a650a22005-08-26 08:51:34 +0000151 try:
152 FILE = file(test_support.TESTFN, 'wb')
153 FILE.write(self.text)
154 FILE.close()
155 finally:
156 try: FILE.close()
157 except: pass
Brett Cannon19691362003-04-29 05:08:06 +0000158
159 def tearDown(self):
Georg Brandl5a650a22005-08-26 08:51:34 +0000160 # Delete the temporary files.
161 for each in self.tempFiles:
162 try: os.remove(each)
163 except: pass
164
165 def constructLocalFileUrl(self, filePath):
166 return "file://%s" % urllib.pathname2url(os.path.abspath(filePath))
167
168 def createNewTempFile(self, data=""):
169 """Creates a new temporary file containing the specified data,
170 registers the file for deletion during the test fixture tear down, and
171 returns the absolute path of the file."""
172
173 newFd, newFilePath = tempfile.mkstemp()
174 try:
175 self.registerFileForCleanUp(newFilePath)
176 newFile = os.fdopen(newFd, "wb")
177 newFile.write(data)
178 newFile.close()
179 finally:
180 try: newFile.close()
181 except: pass
182 return newFilePath
183
184 def registerFileForCleanUp(self, fileName):
185 self.tempFiles.append(fileName)
Brett Cannon19691362003-04-29 05:08:06 +0000186
187 def test_basic(self):
188 # Make sure that a local file just gets its own location returned and
189 # a headers value is returned.
190 result = urllib.urlretrieve("file:%s" % test_support.TESTFN)
191 self.assertEqual(result[0], test_support.TESTFN)
192 self.assert_(isinstance(result[1], mimetools.Message),
193 "did not get a mimetools.Message instance as second "
194 "returned value")
195
196 def test_copy(self):
197 # Test that setting the filename argument works.
198 second_temp = "%s.2" % test_support.TESTFN
Neal Norwitzce2ab352007-03-20 06:13:25 +0000199 test_support.unlink(second_temp)
Georg Brandl5a650a22005-08-26 08:51:34 +0000200 self.registerFileForCleanUp(second_temp)
201 result = urllib.urlretrieve(self.constructLocalFileUrl(
202 test_support.TESTFN), second_temp)
Brett Cannon19691362003-04-29 05:08:06 +0000203 self.assertEqual(second_temp, result[0])
204 self.assert_(os.path.exists(second_temp), "copy of the file was not "
205 "made")
206 FILE = file(second_temp, 'rb')
207 try:
208 text = FILE.read()
Brett Cannon19691362003-04-29 05:08:06 +0000209 FILE.close()
Georg Brandl5a650a22005-08-26 08:51:34 +0000210 finally:
211 try: FILE.close()
212 except: pass
Brett Cannon19691362003-04-29 05:08:06 +0000213 self.assertEqual(self.text, text)
214
215 def test_reporthook(self):
216 # Make sure that the reporthook works.
217 def hooktester(count, block_size, total_size, count_holder=[0]):
218 self.assert_(isinstance(count, int))
219 self.assert_(isinstance(block_size, int))
220 self.assert_(isinstance(total_size, int))
221 self.assertEqual(count, count_holder[0])
222 count_holder[0] = count_holder[0] + 1
223 second_temp = "%s.2" % test_support.TESTFN
Neal Norwitzce2ab352007-03-20 06:13:25 +0000224 test_support.unlink(second_temp)
Georg Brandl5a650a22005-08-26 08:51:34 +0000225 self.registerFileForCleanUp(second_temp)
226 urllib.urlretrieve(self.constructLocalFileUrl(test_support.TESTFN),
227 second_temp, hooktester)
228
229 def test_reporthook_0_bytes(self):
230 # Test on zero length file. Should call reporthook only 1 time.
231 report = []
232 def hooktester(count, block_size, total_size, _report=report):
233 _report.append((count, block_size, total_size))
234 srcFileName = self.createNewTempFile()
235 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
236 test_support.TESTFN, hooktester)
237 self.assertEqual(len(report), 1)
238 self.assertEqual(report[0][2], 0)
239
240 def test_reporthook_5_bytes(self):
241 # Test on 5 byte file. Should call reporthook only 2 times (once when
242 # the "network connection" is established and once when the block is
243 # read). Since the block size is 8192 bytes, only one block read is
244 # required to read the entire file.
245 report = []
246 def hooktester(count, block_size, total_size, _report=report):
247 _report.append((count, block_size, total_size))
248 srcFileName = self.createNewTempFile("x" * 5)
249 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
250 test_support.TESTFN, hooktester)
251 self.assertEqual(len(report), 2)
252 self.assertEqual(report[0][1], 8192)
253 self.assertEqual(report[0][2], 5)
254
255 def test_reporthook_8193_bytes(self):
256 # Test on 8193 byte file. Should call reporthook only 3 times (once
257 # when the "network connection" is established, once for the next 8192
258 # bytes, and once for the last byte).
259 report = []
260 def hooktester(count, block_size, total_size, _report=report):
261 _report.append((count, block_size, total_size))
262 srcFileName = self.createNewTempFile("x" * 8193)
263 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
264 test_support.TESTFN, hooktester)
265 self.assertEqual(len(report), 3)
266 self.assertEqual(report[0][1], 8192)
267 self.assertEqual(report[0][2], 8193)
Skip Montanaro080c9972001-01-28 21:12:22 +0000268
Brett Cannon74bfd702003-04-25 09:39:47 +0000269class QuotingTests(unittest.TestCase):
270 """Tests for urllib.quote() and urllib.quote_plus()
Tim Petersc2659cf2003-05-12 20:19:37 +0000271
Brett Cannon74bfd702003-04-25 09:39:47 +0000272 According to RFC 2396 ("Uniform Resource Identifiers), to escape a
273 character you write it as '%' + <2 character US-ASCII hex value>. The Python
274 code of ``'%' + hex(ord(<character>))[2:]`` escapes a character properly.
275 Case does not matter on the hex letters.
276
277 The various character sets specified are:
Tim Petersc2659cf2003-05-12 20:19:37 +0000278
Brett Cannon74bfd702003-04-25 09:39:47 +0000279 Reserved characters : ";/?:@&=+$,"
280 Have special meaning in URIs and must be escaped if not being used for
281 their special meaning
282 Data characters : letters, digits, and "-_.!~*'()"
283 Unreserved and do not need to be escaped; can be, though, if desired
284 Control characters : 0x00 - 0x1F, 0x7F
285 Have no use in URIs so must be escaped
286 space : 0x20
287 Must be escaped
288 Delimiters : '<>#%"'
289 Must be escaped
290 Unwise : "{}|\^[]`"
291 Must be escaped
Tim Petersc2659cf2003-05-12 20:19:37 +0000292
Brett Cannon74bfd702003-04-25 09:39:47 +0000293 """
294
295 def test_never_quote(self):
296 # Make sure quote() does not quote letters, digits, and "_,.-"
297 do_not_quote = '' .join(["ABCDEFGHIJKLMNOPQRSTUVWXYZ",
298 "abcdefghijklmnopqrstuvwxyz",
299 "0123456789",
300 "_.-"])
301 result = urllib.quote(do_not_quote)
302 self.assertEqual(do_not_quote, result,
303 "using quote(): %s != %s" % (do_not_quote, result))
304 result = urllib.quote_plus(do_not_quote)
305 self.assertEqual(do_not_quote, result,
306 "using quote_plus(): %s != %s" % (do_not_quote, result))
307
308 def test_default_safe(self):
309 # Test '/' is default value for 'safe' parameter
310 self.assertEqual(urllib.quote.func_defaults[0], '/')
311
312 def test_safe(self):
313 # Test setting 'safe' parameter does what it should do
314 quote_by_default = "<>"
315 result = urllib.quote(quote_by_default, safe=quote_by_default)
316 self.assertEqual(quote_by_default, result,
317 "using quote(): %s != %s" % (quote_by_default, result))
318 result = urllib.quote_plus(quote_by_default, safe=quote_by_default)
319 self.assertEqual(quote_by_default, result,
320 "using quote_plus(): %s != %s" %
321 (quote_by_default, result))
322
323 def test_default_quoting(self):
324 # Make sure all characters that should be quoted are by default sans
325 # space (separate test for that).
326 should_quote = [chr(num) for num in range(32)] # For 0x00 - 0x1F
327 should_quote.append('<>#%"{}|\^[]`')
328 should_quote.append(chr(127)) # For 0x7F
329 should_quote = ''.join(should_quote)
330 for char in should_quote:
331 result = urllib.quote(char)
332 self.assertEqual(hexescape(char), result,
333 "using quote(): %s should be escaped to %s, not %s" %
334 (char, hexescape(char), result))
335 result = urllib.quote_plus(char)
336 self.assertEqual(hexescape(char), result,
337 "using quote_plus(): "
Tim Petersc2659cf2003-05-12 20:19:37 +0000338 "%s should be escapes to %s, not %s" %
Brett Cannon74bfd702003-04-25 09:39:47 +0000339 (char, hexescape(char), result))
340 del should_quote
341 partial_quote = "ab[]cd"
342 expected = "ab%5B%5Dcd"
343 result = urllib.quote(partial_quote)
344 self.assertEqual(expected, result,
345 "using quote(): %s != %s" % (expected, result))
346 self.assertEqual(expected, result,
347 "using quote_plus(): %s != %s" % (expected, result))
348
349 def test_quoting_space(self):
350 # Make sure quote() and quote_plus() handle spaces as specified in
351 # their unique way
352 result = urllib.quote(' ')
353 self.assertEqual(result, hexescape(' '),
354 "using quote(): %s != %s" % (result, hexescape(' ')))
355 result = urllib.quote_plus(' ')
356 self.assertEqual(result, '+',
357 "using quote_plus(): %s != +" % result)
358 given = "a b cd e f"
359 expect = given.replace(' ', hexescape(' '))
360 result = urllib.quote(given)
361 self.assertEqual(expect, result,
362 "using quote(): %s != %s" % (expect, result))
363 expect = given.replace(' ', '+')
364 result = urllib.quote_plus(given)
365 self.assertEqual(expect, result,
366 "using quote_plus(): %s != %s" % (expect, result))
367
Raymond Hettinger2bdec7b2005-09-10 14:30:09 +0000368 def test_quoting_plus(self):
369 self.assertEqual(urllib.quote_plus('alpha+beta gamma'),
370 'alpha%2Bbeta+gamma')
371 self.assertEqual(urllib.quote_plus('alpha+beta gamma', '+'),
372 'alpha+beta+gamma')
373
Brett Cannon74bfd702003-04-25 09:39:47 +0000374class UnquotingTests(unittest.TestCase):
375 """Tests for unquote() and unquote_plus()
Tim Petersc2659cf2003-05-12 20:19:37 +0000376
Brett Cannon74bfd702003-04-25 09:39:47 +0000377 See the doc string for quoting_Tests for details on quoting and such.
378
379 """
380
381 def test_unquoting(self):
382 # Make sure unquoting of all ASCII values works
383 escape_list = []
384 for num in range(128):
385 given = hexescape(chr(num))
386 expect = chr(num)
387 result = urllib.unquote(given)
388 self.assertEqual(expect, result,
389 "using unquote(): %s != %s" % (expect, result))
390 result = urllib.unquote_plus(given)
391 self.assertEqual(expect, result,
392 "using unquote_plus(): %s != %s" %
393 (expect, result))
394 escape_list.append(given)
395 escape_string = ''.join(escape_list)
396 del escape_list
397 result = urllib.unquote(escape_string)
398 self.assertEqual(result.count('%'), 1,
399 "using quote(): not all characters escaped; %s" %
400 result)
401 result = urllib.unquote(escape_string)
402 self.assertEqual(result.count('%'), 1,
403 "using unquote(): not all characters escaped: "
404 "%s" % result)
405
406 def test_unquoting_parts(self):
407 # Make sure unquoting works when have non-quoted characters
408 # interspersed
409 given = 'ab%sd' % hexescape('c')
410 expect = "abcd"
411 result = urllib.unquote(given)
412 self.assertEqual(expect, result,
413 "using quote(): %s != %s" % (expect, result))
414 result = urllib.unquote_plus(given)
415 self.assertEqual(expect, result,
416 "using unquote_plus(): %s != %s" % (expect, result))
Tim Petersc2659cf2003-05-12 20:19:37 +0000417
Brett Cannon74bfd702003-04-25 09:39:47 +0000418 def test_unquoting_plus(self):
419 # Test difference between unquote() and unquote_plus()
420 given = "are+there+spaces..."
421 expect = given
422 result = urllib.unquote(given)
423 self.assertEqual(expect, result,
424 "using unquote(): %s != %s" % (expect, result))
425 expect = given.replace('+', ' ')
426 result = urllib.unquote_plus(given)
427 self.assertEqual(expect, result,
428 "using unquote_plus(): %s != %s" % (expect, result))
429
Raymond Hettinger4b0f20d2005-10-15 16:41:53 +0000430 def test_unquote_with_unicode(self):
431 r = urllib.unquote(u'br%C3%BCckner_sapporo_20050930.doc')
432 self.assertEqual(r, u'br\xc3\xbcckner_sapporo_20050930.doc')
433
Brett Cannon74bfd702003-04-25 09:39:47 +0000434class urlencode_Tests(unittest.TestCase):
435 """Tests for urlencode()"""
436
437 def help_inputtype(self, given, test_type):
438 """Helper method for testing different input types.
Tim Petersc2659cf2003-05-12 20:19:37 +0000439
Brett Cannon74bfd702003-04-25 09:39:47 +0000440 'given' must lead to only the pairs:
441 * 1st, 1
442 * 2nd, 2
443 * 3rd, 3
Tim Petersc2659cf2003-05-12 20:19:37 +0000444
Brett Cannon74bfd702003-04-25 09:39:47 +0000445 Test cannot assume anything about order. Docs make no guarantee and
446 have possible dictionary input.
Tim Petersc2659cf2003-05-12 20:19:37 +0000447
Brett Cannon74bfd702003-04-25 09:39:47 +0000448 """
449 expect_somewhere = ["1st=1", "2nd=2", "3rd=3"]
450 result = urllib.urlencode(given)
451 for expected in expect_somewhere:
452 self.assert_(expected in result,
453 "testing %s: %s not found in %s" %
454 (test_type, expected, result))
455 self.assertEqual(result.count('&'), 2,
456 "testing %s: expected 2 '&'s; got %s" %
457 (test_type, result.count('&')))
458 amp_location = result.index('&')
459 on_amp_left = result[amp_location - 1]
460 on_amp_right = result[amp_location + 1]
461 self.assert_(on_amp_left.isdigit() and on_amp_right.isdigit(),
462 "testing %s: '&' not located in proper place in %s" %
463 (test_type, result))
464 self.assertEqual(len(result), (5 * 3) + 2, #5 chars per thing and amps
465 "testing %s: "
466 "unexpected number of characters: %s != %s" %
467 (test_type, len(result), (5 * 3) + 2))
468
469 def test_using_mapping(self):
470 # Test passing in a mapping object as an argument.
471 self.help_inputtype({"1st":'1', "2nd":'2', "3rd":'3'},
472 "using dict as input type")
473
474 def test_using_sequence(self):
475 # Test passing in a sequence of two-item sequences as an argument.
476 self.help_inputtype([('1st', '1'), ('2nd', '2'), ('3rd', '3')],
477 "using sequence of two-item tuples as input")
478
479 def test_quoting(self):
480 # Make sure keys and values are quoted using quote_plus()
481 given = {"&":"="}
482 expect = "%s=%s" % (hexescape('&'), hexescape('='))
483 result = urllib.urlencode(given)
484 self.assertEqual(expect, result)
485 given = {"key name":"A bunch of pluses"}
486 expect = "key+name=A+bunch+of+pluses"
487 result = urllib.urlencode(given)
488 self.assertEqual(expect, result)
489
490 def test_doseq(self):
491 # Test that passing True for 'doseq' parameter works correctly
492 given = {'sequence':['1', '2', '3']}
493 expect = "sequence=%s" % urllib.quote_plus(str(['1', '2', '3']))
494 result = urllib.urlencode(given)
495 self.assertEqual(expect, result)
496 result = urllib.urlencode(given, True)
497 for value in given["sequence"]:
498 expect = "sequence=%s" % value
499 self.assert_(expect in result,
500 "%s not found in %s" % (expect, result))
501 self.assertEqual(result.count('&'), 2,
502 "Expected 2 '&'s, got %s" % result.count('&'))
503
504class Pathname_Tests(unittest.TestCase):
505 """Test pathname2url() and url2pathname()"""
506
507 def test_basic(self):
508 # Make sure simple tests pass
509 expected_path = os.path.join("parts", "of", "a", "path")
510 expected_url = "parts/of/a/path"
511 result = urllib.pathname2url(expected_path)
512 self.assertEqual(expected_url, result,
513 "pathname2url() failed; %s != %s" %
514 (result, expected_url))
515 result = urllib.url2pathname(expected_url)
516 self.assertEqual(expected_path, result,
517 "url2pathame() failed; %s != %s" %
518 (result, expected_path))
519
520 def test_quoting(self):
521 # Test automatic quoting and unquoting works for pathnam2url() and
522 # url2pathname() respectively
523 given = os.path.join("needs", "quot=ing", "here")
524 expect = "needs/%s/here" % urllib.quote("quot=ing")
525 result = urllib.pathname2url(given)
526 self.assertEqual(expect, result,
527 "pathname2url() failed; %s != %s" %
528 (expect, result))
529 expect = given
530 result = urllib.url2pathname(result)
531 self.assertEqual(expect, result,
532 "url2pathname() failed; %s != %s" %
533 (expect, result))
534 given = os.path.join("make sure", "using_quote")
535 expect = "%s/using_quote" % urllib.quote("make sure")
536 result = urllib.pathname2url(given)
537 self.assertEqual(expect, result,
538 "pathname2url() failed; %s != %s" %
539 (expect, result))
540 given = "make+sure/using_unquote"
541 expect = os.path.join("make+sure", "using_unquote")
542 result = urllib.url2pathname(given)
543 self.assertEqual(expect, result,
544 "url2pathname() failed; %s != %s" %
545 (expect, result))
Tim Petersc2659cf2003-05-12 20:19:37 +0000546
Skip Montanaro080c9972001-01-28 21:12:22 +0000547
548
Brett Cannon74bfd702003-04-25 09:39:47 +0000549def test_main():
Walter Dörwald21d3a322003-05-01 17:45:56 +0000550 test_support.run_unittest(
551 urlopen_FileTests,
Hye-Shik Chang39aef792004-06-05 13:30:56 +0000552 urlopen_HttpTests,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000553 urlretrieve_FileTests,
554 QuotingTests,
555 UnquotingTests,
556 urlencode_Tests,
557 Pathname_Tests
558 )
Brett Cannon74bfd702003-04-25 09:39:47 +0000559
560
561
562if __name__ == '__main__':
563 test_main()