blob: 36214767bdad3775ea76976b0aa8001d9781b922 [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__
Guido van Rossum51735b02003-04-25 15:01:05 +000030 FILE = file(test_support.TESTFN, 'wb')
Brett Cannon74bfd702003-04-25 09:39:47 +000031 try:
32 FILE.write(self.text)
33 finally:
34 FILE.close()
35 self.pathname = test_support.TESTFN
36 self.returned_obj = urllib.urlopen("file:%s" % self.pathname)
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000037
Brett Cannon74bfd702003-04-25 09:39:47 +000038 def tearDown(self):
39 """Shut down the open object"""
40 self.returned_obj.close()
Brett Cannon19691362003-04-29 05:08:06 +000041 os.remove(test_support.TESTFN)
Jeremy Hylton7ae51bf2000-09-14 16:59:07 +000042
Brett Cannon74bfd702003-04-25 09:39:47 +000043 def test_interface(self):
44 # Make sure object returned by urlopen() has the specified methods
45 for attr in ("read", "readline", "readlines", "fileno",
46 "close", "info", "geturl", "__iter__"):
47 self.assert_(hasattr(self.returned_obj, attr),
48 "object returned by urlopen() lacks %s attribute" %
49 attr)
Skip Montanaroe78b92a2001-01-20 20:22:30 +000050
Brett Cannon74bfd702003-04-25 09:39:47 +000051 def test_read(self):
52 self.assertEqual(self.text, self.returned_obj.read())
Skip Montanaro080c9972001-01-28 21:12:22 +000053
Brett Cannon74bfd702003-04-25 09:39:47 +000054 def test_readline(self):
55 self.assertEqual(self.text, self.returned_obj.readline())
56 self.assertEqual('', self.returned_obj.readline(),
57 "calling readline() after exhausting the file did not"
58 " return an empty string")
Skip Montanaro080c9972001-01-28 21:12:22 +000059
Brett Cannon74bfd702003-04-25 09:39:47 +000060 def test_readlines(self):
61 lines_list = self.returned_obj.readlines()
62 self.assertEqual(len(lines_list), 1,
63 "readlines() returned the wrong number of lines")
64 self.assertEqual(lines_list[0], self.text,
65 "readlines() returned improper text")
Skip Montanaro080c9972001-01-28 21:12:22 +000066
Brett Cannon74bfd702003-04-25 09:39:47 +000067 def test_fileno(self):
68 file_num = self.returned_obj.fileno()
69 self.assert_(isinstance(file_num, int),
70 "fileno() did not return an int")
71 self.assertEqual(os.read(file_num, len(self.text)), self.text,
72 "Reading on the file descriptor returned by fileno() "
73 "did not return the expected text")
Skip Montanaroe78b92a2001-01-20 20:22:30 +000074
Brett Cannon74bfd702003-04-25 09:39:47 +000075 def test_close(self):
76 # Test close() by calling it hear and then having it be called again
77 # by the tearDown() method for the test
78 self.returned_obj.close()
Skip Montanaro080c9972001-01-28 21:12:22 +000079
Brett Cannon74bfd702003-04-25 09:39:47 +000080 def test_info(self):
81 self.assert_(isinstance(self.returned_obj.info(), mimetools.Message))
Skip Montanaroe78b92a2001-01-20 20:22:30 +000082
Brett Cannon74bfd702003-04-25 09:39:47 +000083 def test_geturl(self):
84 self.assertEqual(self.returned_obj.geturl(), self.pathname)
Skip Montanaro080c9972001-01-28 21:12:22 +000085
Brett Cannon74bfd702003-04-25 09:39:47 +000086 def test_iter(self):
87 # Test iterator
88 # Don't need to count number of iterations since test would fail the
89 # instant it returned anything beyond the first line from the
90 # comparison
91 for line in self.returned_obj.__iter__():
92 self.assertEqual(line, self.text)
Skip Montanaro080c9972001-01-28 21:12:22 +000093
Hye-Shik Chang39aef792004-06-05 13:30:56 +000094class urlopen_HttpTests(unittest.TestCase):
95 """Test urlopen() opening a fake http connection."""
96
97 def fakehttp(self, fakedata):
98 class FakeSocket(StringIO.StringIO):
99 def sendall(self, str): pass
100 def makefile(self, mode, name): return self
101 def read(self, amt=None):
102 if self.closed: return ''
103 return StringIO.StringIO.read(self, amt)
104 def readline(self, length=None):
105 if self.closed: return ''
106 return StringIO.StringIO.readline(self, length)
107 class FakeHTTPConnection(httplib.HTTPConnection):
108 def connect(self):
109 self.sock = FakeSocket(fakedata)
110 assert httplib.HTTP._connection_class == httplib.HTTPConnection
111 httplib.HTTP._connection_class = FakeHTTPConnection
112
113 def unfakehttp(self):
114 httplib.HTTP._connection_class = httplib.HTTPConnection
115
116 def test_read(self):
117 self.fakehttp('Hello!')
118 try:
119 fp = urllib.urlopen("http://python.org/")
120 self.assertEqual(fp.readline(), 'Hello!')
121 self.assertEqual(fp.readline(), '')
122 finally:
123 self.unfakehttp()
124
Brett Cannon19691362003-04-29 05:08:06 +0000125class urlretrieve_FileTests(unittest.TestCase):
Brett Cannon74bfd702003-04-25 09:39:47 +0000126 """Test urllib.urlretrieve() on local files"""
Skip Montanaro080c9972001-01-28 21:12:22 +0000127
Brett Cannon19691362003-04-29 05:08:06 +0000128 def setUp(self):
Georg Brandl5a650a22005-08-26 08:51:34 +0000129 # Create a list of temporary files. Each item in the list is a file
130 # name (absolute path or relative to the current working directory).
131 # All files in this list will be deleted in the tearDown method. Note,
132 # this only helps to makes sure temporary files get deleted, but it
133 # does nothing about trying to close files that may still be open. It
134 # is the responsibility of the developer to properly close files even
135 # when exceptional conditions occur.
136 self.tempFiles = []
137
Brett Cannon19691362003-04-29 05:08:06 +0000138 # Create a temporary file.
Georg Brandl5a650a22005-08-26 08:51:34 +0000139 self.registerFileForCleanUp(test_support.TESTFN)
Brett Cannon19691362003-04-29 05:08:06 +0000140 self.text = 'testing urllib.urlretrieve'
Georg Brandl5a650a22005-08-26 08:51:34 +0000141 try:
142 FILE = file(test_support.TESTFN, 'wb')
143 FILE.write(self.text)
144 FILE.close()
145 finally:
146 try: FILE.close()
147 except: pass
Brett Cannon19691362003-04-29 05:08:06 +0000148
149 def tearDown(self):
Georg Brandl5a650a22005-08-26 08:51:34 +0000150 # Delete the temporary files.
151 for each in self.tempFiles:
152 try: os.remove(each)
153 except: pass
154
155 def constructLocalFileUrl(self, filePath):
156 return "file://%s" % urllib.pathname2url(os.path.abspath(filePath))
157
158 def createNewTempFile(self, data=""):
159 """Creates a new temporary file containing the specified data,
160 registers the file for deletion during the test fixture tear down, and
161 returns the absolute path of the file."""
162
163 newFd, newFilePath = tempfile.mkstemp()
164 try:
165 self.registerFileForCleanUp(newFilePath)
166 newFile = os.fdopen(newFd, "wb")
167 newFile.write(data)
168 newFile.close()
169 finally:
170 try: newFile.close()
171 except: pass
172 return newFilePath
173
174 def registerFileForCleanUp(self, fileName):
175 self.tempFiles.append(fileName)
Brett Cannon19691362003-04-29 05:08:06 +0000176
177 def test_basic(self):
178 # Make sure that a local file just gets its own location returned and
179 # a headers value is returned.
180 result = urllib.urlretrieve("file:%s" % test_support.TESTFN)
181 self.assertEqual(result[0], test_support.TESTFN)
182 self.assert_(isinstance(result[1], mimetools.Message),
183 "did not get a mimetools.Message instance as second "
184 "returned value")
185
186 def test_copy(self):
187 # Test that setting the filename argument works.
188 second_temp = "%s.2" % test_support.TESTFN
Georg Brandl5a650a22005-08-26 08:51:34 +0000189 self.registerFileForCleanUp(second_temp)
190 result = urllib.urlretrieve(self.constructLocalFileUrl(
191 test_support.TESTFN), second_temp)
Brett Cannon19691362003-04-29 05:08:06 +0000192 self.assertEqual(second_temp, result[0])
193 self.assert_(os.path.exists(second_temp), "copy of the file was not "
194 "made")
195 FILE = file(second_temp, 'rb')
196 try:
197 text = FILE.read()
Brett Cannon19691362003-04-29 05:08:06 +0000198 FILE.close()
Georg Brandl5a650a22005-08-26 08:51:34 +0000199 finally:
200 try: FILE.close()
201 except: pass
Brett Cannon19691362003-04-29 05:08:06 +0000202 self.assertEqual(self.text, text)
203
204 def test_reporthook(self):
205 # Make sure that the reporthook works.
206 def hooktester(count, block_size, total_size, count_holder=[0]):
207 self.assert_(isinstance(count, int))
208 self.assert_(isinstance(block_size, int))
209 self.assert_(isinstance(total_size, int))
210 self.assertEqual(count, count_holder[0])
211 count_holder[0] = count_holder[0] + 1
212 second_temp = "%s.2" % test_support.TESTFN
Georg Brandl5a650a22005-08-26 08:51:34 +0000213 self.registerFileForCleanUp(second_temp)
214 urllib.urlretrieve(self.constructLocalFileUrl(test_support.TESTFN),
215 second_temp, hooktester)
216
217 def test_reporthook_0_bytes(self):
218 # Test on zero length file. Should call reporthook only 1 time.
219 report = []
220 def hooktester(count, block_size, total_size, _report=report):
221 _report.append((count, block_size, total_size))
222 srcFileName = self.createNewTempFile()
223 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
224 test_support.TESTFN, hooktester)
225 self.assertEqual(len(report), 1)
226 self.assertEqual(report[0][2], 0)
227
228 def test_reporthook_5_bytes(self):
229 # Test on 5 byte file. Should call reporthook only 2 times (once when
230 # the "network connection" is established and once when the block is
231 # read). Since the block size is 8192 bytes, only one block read is
232 # required to read the entire file.
233 report = []
234 def hooktester(count, block_size, total_size, _report=report):
235 _report.append((count, block_size, total_size))
236 srcFileName = self.createNewTempFile("x" * 5)
237 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
238 test_support.TESTFN, hooktester)
239 self.assertEqual(len(report), 2)
240 self.assertEqual(report[0][1], 8192)
241 self.assertEqual(report[0][2], 5)
242
243 def test_reporthook_8193_bytes(self):
244 # Test on 8193 byte file. Should call reporthook only 3 times (once
245 # when the "network connection" is established, once for the next 8192
246 # bytes, and once for the last byte).
247 report = []
248 def hooktester(count, block_size, total_size, _report=report):
249 _report.append((count, block_size, total_size))
250 srcFileName = self.createNewTempFile("x" * 8193)
251 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
252 test_support.TESTFN, hooktester)
253 self.assertEqual(len(report), 3)
254 self.assertEqual(report[0][1], 8192)
255 self.assertEqual(report[0][2], 8193)
Skip Montanaro080c9972001-01-28 21:12:22 +0000256
Brett Cannon74bfd702003-04-25 09:39:47 +0000257class QuotingTests(unittest.TestCase):
258 """Tests for urllib.quote() and urllib.quote_plus()
Tim Petersc2659cf2003-05-12 20:19:37 +0000259
Brett Cannon74bfd702003-04-25 09:39:47 +0000260 According to RFC 2396 ("Uniform Resource Identifiers), to escape a
261 character you write it as '%' + <2 character US-ASCII hex value>. The Python
262 code of ``'%' + hex(ord(<character>))[2:]`` escapes a character properly.
263 Case does not matter on the hex letters.
264
265 The various character sets specified are:
Tim Petersc2659cf2003-05-12 20:19:37 +0000266
Brett Cannon74bfd702003-04-25 09:39:47 +0000267 Reserved characters : ";/?:@&=+$,"
268 Have special meaning in URIs and must be escaped if not being used for
269 their special meaning
270 Data characters : letters, digits, and "-_.!~*'()"
271 Unreserved and do not need to be escaped; can be, though, if desired
272 Control characters : 0x00 - 0x1F, 0x7F
273 Have no use in URIs so must be escaped
274 space : 0x20
275 Must be escaped
276 Delimiters : '<>#%"'
277 Must be escaped
278 Unwise : "{}|\^[]`"
279 Must be escaped
Tim Petersc2659cf2003-05-12 20:19:37 +0000280
Brett Cannon74bfd702003-04-25 09:39:47 +0000281 """
282
283 def test_never_quote(self):
284 # Make sure quote() does not quote letters, digits, and "_,.-"
285 do_not_quote = '' .join(["ABCDEFGHIJKLMNOPQRSTUVWXYZ",
286 "abcdefghijklmnopqrstuvwxyz",
287 "0123456789",
288 "_.-"])
289 result = urllib.quote(do_not_quote)
290 self.assertEqual(do_not_quote, result,
291 "using quote(): %s != %s" % (do_not_quote, result))
292 result = urllib.quote_plus(do_not_quote)
293 self.assertEqual(do_not_quote, result,
294 "using quote_plus(): %s != %s" % (do_not_quote, result))
295
296 def test_default_safe(self):
297 # Test '/' is default value for 'safe' parameter
298 self.assertEqual(urllib.quote.func_defaults[0], '/')
299
300 def test_safe(self):
301 # Test setting 'safe' parameter does what it should do
302 quote_by_default = "<>"
303 result = urllib.quote(quote_by_default, safe=quote_by_default)
304 self.assertEqual(quote_by_default, result,
305 "using quote(): %s != %s" % (quote_by_default, result))
306 result = urllib.quote_plus(quote_by_default, safe=quote_by_default)
307 self.assertEqual(quote_by_default, result,
308 "using quote_plus(): %s != %s" %
309 (quote_by_default, result))
310
311 def test_default_quoting(self):
312 # Make sure all characters that should be quoted are by default sans
313 # space (separate test for that).
314 should_quote = [chr(num) for num in range(32)] # For 0x00 - 0x1F
315 should_quote.append('<>#%"{}|\^[]`')
316 should_quote.append(chr(127)) # For 0x7F
317 should_quote = ''.join(should_quote)
318 for char in should_quote:
319 result = urllib.quote(char)
320 self.assertEqual(hexescape(char), result,
321 "using quote(): %s should be escaped to %s, not %s" %
322 (char, hexescape(char), result))
323 result = urllib.quote_plus(char)
324 self.assertEqual(hexescape(char), result,
325 "using quote_plus(): "
Tim Petersc2659cf2003-05-12 20:19:37 +0000326 "%s should be escapes to %s, not %s" %
Brett Cannon74bfd702003-04-25 09:39:47 +0000327 (char, hexescape(char), result))
328 del should_quote
329 partial_quote = "ab[]cd"
330 expected = "ab%5B%5Dcd"
331 result = urllib.quote(partial_quote)
332 self.assertEqual(expected, result,
333 "using quote(): %s != %s" % (expected, result))
334 self.assertEqual(expected, result,
335 "using quote_plus(): %s != %s" % (expected, result))
336
337 def test_quoting_space(self):
338 # Make sure quote() and quote_plus() handle spaces as specified in
339 # their unique way
340 result = urllib.quote(' ')
341 self.assertEqual(result, hexescape(' '),
342 "using quote(): %s != %s" % (result, hexescape(' ')))
343 result = urllib.quote_plus(' ')
344 self.assertEqual(result, '+',
345 "using quote_plus(): %s != +" % result)
346 given = "a b cd e f"
347 expect = given.replace(' ', hexescape(' '))
348 result = urllib.quote(given)
349 self.assertEqual(expect, result,
350 "using quote(): %s != %s" % (expect, result))
351 expect = given.replace(' ', '+')
352 result = urllib.quote_plus(given)
353 self.assertEqual(expect, result,
354 "using quote_plus(): %s != %s" % (expect, result))
355
356class UnquotingTests(unittest.TestCase):
357 """Tests for unquote() and unquote_plus()
Tim Petersc2659cf2003-05-12 20:19:37 +0000358
Brett Cannon74bfd702003-04-25 09:39:47 +0000359 See the doc string for quoting_Tests for details on quoting and such.
360
361 """
362
363 def test_unquoting(self):
364 # Make sure unquoting of all ASCII values works
365 escape_list = []
366 for num in range(128):
367 given = hexescape(chr(num))
368 expect = chr(num)
369 result = urllib.unquote(given)
370 self.assertEqual(expect, result,
371 "using unquote(): %s != %s" % (expect, result))
372 result = urllib.unquote_plus(given)
373 self.assertEqual(expect, result,
374 "using unquote_plus(): %s != %s" %
375 (expect, result))
376 escape_list.append(given)
377 escape_string = ''.join(escape_list)
378 del escape_list
379 result = urllib.unquote(escape_string)
380 self.assertEqual(result.count('%'), 1,
381 "using quote(): not all characters escaped; %s" %
382 result)
383 result = urllib.unquote(escape_string)
384 self.assertEqual(result.count('%'), 1,
385 "using unquote(): not all characters escaped: "
386 "%s" % result)
387
388 def test_unquoting_parts(self):
389 # Make sure unquoting works when have non-quoted characters
390 # interspersed
391 given = 'ab%sd' % hexescape('c')
392 expect = "abcd"
393 result = urllib.unquote(given)
394 self.assertEqual(expect, result,
395 "using quote(): %s != %s" % (expect, result))
396 result = urllib.unquote_plus(given)
397 self.assertEqual(expect, result,
398 "using unquote_plus(): %s != %s" % (expect, result))
Tim Petersc2659cf2003-05-12 20:19:37 +0000399
Brett Cannon74bfd702003-04-25 09:39:47 +0000400 def test_unquoting_plus(self):
401 # Test difference between unquote() and unquote_plus()
402 given = "are+there+spaces..."
403 expect = given
404 result = urllib.unquote(given)
405 self.assertEqual(expect, result,
406 "using unquote(): %s != %s" % (expect, result))
407 expect = given.replace('+', ' ')
408 result = urllib.unquote_plus(given)
409 self.assertEqual(expect, result,
410 "using unquote_plus(): %s != %s" % (expect, result))
411
412class urlencode_Tests(unittest.TestCase):
413 """Tests for urlencode()"""
414
415 def help_inputtype(self, given, test_type):
416 """Helper method for testing different input types.
Tim Petersc2659cf2003-05-12 20:19:37 +0000417
Brett Cannon74bfd702003-04-25 09:39:47 +0000418 'given' must lead to only the pairs:
419 * 1st, 1
420 * 2nd, 2
421 * 3rd, 3
Tim Petersc2659cf2003-05-12 20:19:37 +0000422
Brett Cannon74bfd702003-04-25 09:39:47 +0000423 Test cannot assume anything about order. Docs make no guarantee and
424 have possible dictionary input.
Tim Petersc2659cf2003-05-12 20:19:37 +0000425
Brett Cannon74bfd702003-04-25 09:39:47 +0000426 """
427 expect_somewhere = ["1st=1", "2nd=2", "3rd=3"]
428 result = urllib.urlencode(given)
429 for expected in expect_somewhere:
430 self.assert_(expected in result,
431 "testing %s: %s not found in %s" %
432 (test_type, expected, result))
433 self.assertEqual(result.count('&'), 2,
434 "testing %s: expected 2 '&'s; got %s" %
435 (test_type, result.count('&')))
436 amp_location = result.index('&')
437 on_amp_left = result[amp_location - 1]
438 on_amp_right = result[amp_location + 1]
439 self.assert_(on_amp_left.isdigit() and on_amp_right.isdigit(),
440 "testing %s: '&' not located in proper place in %s" %
441 (test_type, result))
442 self.assertEqual(len(result), (5 * 3) + 2, #5 chars per thing and amps
443 "testing %s: "
444 "unexpected number of characters: %s != %s" %
445 (test_type, len(result), (5 * 3) + 2))
446
447 def test_using_mapping(self):
448 # Test passing in a mapping object as an argument.
449 self.help_inputtype({"1st":'1', "2nd":'2', "3rd":'3'},
450 "using dict as input type")
451
452 def test_using_sequence(self):
453 # Test passing in a sequence of two-item sequences as an argument.
454 self.help_inputtype([('1st', '1'), ('2nd', '2'), ('3rd', '3')],
455 "using sequence of two-item tuples as input")
456
457 def test_quoting(self):
458 # Make sure keys and values are quoted using quote_plus()
459 given = {"&":"="}
460 expect = "%s=%s" % (hexescape('&'), hexescape('='))
461 result = urllib.urlencode(given)
462 self.assertEqual(expect, result)
463 given = {"key name":"A bunch of pluses"}
464 expect = "key+name=A+bunch+of+pluses"
465 result = urllib.urlencode(given)
466 self.assertEqual(expect, result)
467
468 def test_doseq(self):
469 # Test that passing True for 'doseq' parameter works correctly
470 given = {'sequence':['1', '2', '3']}
471 expect = "sequence=%s" % urllib.quote_plus(str(['1', '2', '3']))
472 result = urllib.urlencode(given)
473 self.assertEqual(expect, result)
474 result = urllib.urlencode(given, True)
475 for value in given["sequence"]:
476 expect = "sequence=%s" % value
477 self.assert_(expect in result,
478 "%s not found in %s" % (expect, result))
479 self.assertEqual(result.count('&'), 2,
480 "Expected 2 '&'s, got %s" % result.count('&'))
481
482class Pathname_Tests(unittest.TestCase):
483 """Test pathname2url() and url2pathname()"""
484
485 def test_basic(self):
486 # Make sure simple tests pass
487 expected_path = os.path.join("parts", "of", "a", "path")
488 expected_url = "parts/of/a/path"
489 result = urllib.pathname2url(expected_path)
490 self.assertEqual(expected_url, result,
491 "pathname2url() failed; %s != %s" %
492 (result, expected_url))
493 result = urllib.url2pathname(expected_url)
494 self.assertEqual(expected_path, result,
495 "url2pathame() failed; %s != %s" %
496 (result, expected_path))
497
498 def test_quoting(self):
499 # Test automatic quoting and unquoting works for pathnam2url() and
500 # url2pathname() respectively
501 given = os.path.join("needs", "quot=ing", "here")
502 expect = "needs/%s/here" % urllib.quote("quot=ing")
503 result = urllib.pathname2url(given)
504 self.assertEqual(expect, result,
505 "pathname2url() failed; %s != %s" %
506 (expect, result))
507 expect = given
508 result = urllib.url2pathname(result)
509 self.assertEqual(expect, result,
510 "url2pathname() failed; %s != %s" %
511 (expect, result))
512 given = os.path.join("make sure", "using_quote")
513 expect = "%s/using_quote" % urllib.quote("make sure")
514 result = urllib.pathname2url(given)
515 self.assertEqual(expect, result,
516 "pathname2url() failed; %s != %s" %
517 (expect, result))
518 given = "make+sure/using_unquote"
519 expect = os.path.join("make+sure", "using_unquote")
520 result = urllib.url2pathname(given)
521 self.assertEqual(expect, result,
522 "url2pathname() failed; %s != %s" %
523 (expect, result))
Tim Petersc2659cf2003-05-12 20:19:37 +0000524
Skip Montanaro080c9972001-01-28 21:12:22 +0000525
526
Brett Cannon74bfd702003-04-25 09:39:47 +0000527def test_main():
Walter Dörwald21d3a322003-05-01 17:45:56 +0000528 test_support.run_unittest(
529 urlopen_FileTests,
Hye-Shik Chang39aef792004-06-05 13:30:56 +0000530 urlopen_HttpTests,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000531 urlretrieve_FileTests,
532 QuotingTests,
533 UnquotingTests,
534 urlencode_Tests,
535 Pathname_Tests
536 )
Brett Cannon74bfd702003-04-25 09:39:47 +0000537
538
539
540if __name__ == '__main__':
541 test_main()