blob: b78f30a136307228e5f397ea57178dbad14de28f [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",
Georg Brandl9b0d46d2008-01-20 11:43:03 +000046 "close", "info", "geturl", "getcode", "__iter__"):
Brett Cannon74bfd702003-04-25 09:39:47 +000047 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
Georg Brandl9b0d46d2008-01-20 11:43:03 +000086 def test_getcode(self):
87 self.assertEqual(self.returned_obj.getcode(), None)
88
Brett Cannon74bfd702003-04-25 09:39:47 +000089 def test_iter(self):
90 # Test iterator
91 # Don't need to count number of iterations since test would fail the
92 # instant it returned anything beyond the first line from the
93 # comparison
94 for line in self.returned_obj.__iter__():
95 self.assertEqual(line, self.text)
Skip Montanaro080c9972001-01-28 21:12:22 +000096
Benjamin Peterson2c7470d2008-09-21 21:27:51 +000097
98class ProxyTests(unittest.TestCase):
99
100 def setUp(self):
101 unittest.TestCase.setUp(self)
102 # Save all proxy related env vars
103 self._saved_environ = dict([(k, v) for k, v in os.environ.iteritems()
104 if k.lower().find('proxy') >= 0])
105 # Delete all proxy related env vars
106 for k in self._saved_environ:
107 del os.environ[k]
108
109 def tearDown(self):
110 unittest.TestCase.tearDown(self)
111 # Restore all proxy related env vars
112 for k, v in self._saved_environ:
113 os.environ[k] = v
114
115 def test_getproxies_environment_keep_no_proxies(self):
116 os.environ['NO_PROXY'] = 'localhost'
117 proxies = urllib.getproxies_environment()
118 # getproxies_environment use lowered case truncated (no '_proxy') keys
119 self.assertEquals('localhost', proxies['no'])
120
121
Hye-Shik Chang39aef792004-06-05 13:30:56 +0000122class urlopen_HttpTests(unittest.TestCase):
123 """Test urlopen() opening a fake http connection."""
124
125 def fakehttp(self, fakedata):
126 class FakeSocket(StringIO.StringIO):
127 def sendall(self, str): pass
128 def makefile(self, mode, name): return self
129 def read(self, amt=None):
130 if self.closed: return ''
131 return StringIO.StringIO.read(self, amt)
132 def readline(self, length=None):
133 if self.closed: return ''
134 return StringIO.StringIO.readline(self, length)
135 class FakeHTTPConnection(httplib.HTTPConnection):
136 def connect(self):
137 self.sock = FakeSocket(fakedata)
138 assert httplib.HTTP._connection_class == httplib.HTTPConnection
139 httplib.HTTP._connection_class = FakeHTTPConnection
140
141 def unfakehttp(self):
142 httplib.HTTP._connection_class = httplib.HTTPConnection
143
144 def test_read(self):
145 self.fakehttp('Hello!')
146 try:
147 fp = urllib.urlopen("http://python.org/")
148 self.assertEqual(fp.readline(), 'Hello!')
149 self.assertEqual(fp.readline(), '')
Georg Brandl9b0d46d2008-01-20 11:43:03 +0000150 self.assertEqual(fp.geturl(), 'http://python.org/')
151 self.assertEqual(fp.getcode(), 200)
Hye-Shik Chang39aef792004-06-05 13:30:56 +0000152 finally:
153 self.unfakehttp()
154
Kurt B. Kaiser0f7c25d2008-01-02 04:11:28 +0000155 def test_read_bogus(self):
Kurt B. Kaiser0a112322008-01-02 05:23:38 +0000156 # urlopen() should raise IOError for many error codes.
Kurt B. Kaiser0f7c25d2008-01-02 04:11:28 +0000157 self.fakehttp('''HTTP/1.1 401 Authentication Required
158Date: Wed, 02 Jan 2008 03:03:54 GMT
159Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e
160Connection: close
161Content-Type: text/html; charset=iso-8859-1
162''')
163 try:
164 self.assertRaises(IOError, urllib.urlopen, "http://python.org/")
165 finally:
166 self.unfakehttp()
167
Georg Brandlf66b6032007-03-14 08:27:52 +0000168 def test_empty_socket(self):
Kurt B. Kaiser0a112322008-01-02 05:23:38 +0000169 # urlopen() raises IOError if the underlying socket does not send any
170 # data. (#1680230)
Georg Brandlf66b6032007-03-14 08:27:52 +0000171 self.fakehttp('')
172 try:
173 self.assertRaises(IOError, urllib.urlopen, 'http://something')
174 finally:
175 self.unfakehttp()
176
Brett Cannon19691362003-04-29 05:08:06 +0000177class urlretrieve_FileTests(unittest.TestCase):
Brett Cannon74bfd702003-04-25 09:39:47 +0000178 """Test urllib.urlretrieve() on local files"""
Skip Montanaro080c9972001-01-28 21:12:22 +0000179
Brett Cannon19691362003-04-29 05:08:06 +0000180 def setUp(self):
Georg Brandl5a650a22005-08-26 08:51:34 +0000181 # Create a list of temporary files. Each item in the list is a file
182 # name (absolute path or relative to the current working directory).
183 # All files in this list will be deleted in the tearDown method. Note,
184 # this only helps to makes sure temporary files get deleted, but it
185 # does nothing about trying to close files that may still be open. It
186 # is the responsibility of the developer to properly close files even
187 # when exceptional conditions occur.
188 self.tempFiles = []
189
Brett Cannon19691362003-04-29 05:08:06 +0000190 # Create a temporary file.
Georg Brandl5a650a22005-08-26 08:51:34 +0000191 self.registerFileForCleanUp(test_support.TESTFN)
Brett Cannon19691362003-04-29 05:08:06 +0000192 self.text = 'testing urllib.urlretrieve'
Georg Brandl5a650a22005-08-26 08:51:34 +0000193 try:
194 FILE = file(test_support.TESTFN, 'wb')
195 FILE.write(self.text)
196 FILE.close()
197 finally:
198 try: FILE.close()
199 except: pass
Brett Cannon19691362003-04-29 05:08:06 +0000200
201 def tearDown(self):
Georg Brandl5a650a22005-08-26 08:51:34 +0000202 # Delete the temporary files.
203 for each in self.tempFiles:
204 try: os.remove(each)
205 except: pass
206
207 def constructLocalFileUrl(self, filePath):
208 return "file://%s" % urllib.pathname2url(os.path.abspath(filePath))
209
210 def createNewTempFile(self, data=""):
211 """Creates a new temporary file containing the specified data,
212 registers the file for deletion during the test fixture tear down, and
213 returns the absolute path of the file."""
214
215 newFd, newFilePath = tempfile.mkstemp()
216 try:
217 self.registerFileForCleanUp(newFilePath)
218 newFile = os.fdopen(newFd, "wb")
219 newFile.write(data)
220 newFile.close()
221 finally:
222 try: newFile.close()
223 except: pass
224 return newFilePath
225
226 def registerFileForCleanUp(self, fileName):
227 self.tempFiles.append(fileName)
Brett Cannon19691362003-04-29 05:08:06 +0000228
229 def test_basic(self):
230 # Make sure that a local file just gets its own location returned and
231 # a headers value is returned.
232 result = urllib.urlretrieve("file:%s" % test_support.TESTFN)
233 self.assertEqual(result[0], test_support.TESTFN)
234 self.assert_(isinstance(result[1], mimetools.Message),
235 "did not get a mimetools.Message instance as second "
236 "returned value")
237
238 def test_copy(self):
239 # Test that setting the filename argument works.
240 second_temp = "%s.2" % test_support.TESTFN
Georg Brandl5a650a22005-08-26 08:51:34 +0000241 self.registerFileForCleanUp(second_temp)
242 result = urllib.urlretrieve(self.constructLocalFileUrl(
243 test_support.TESTFN), second_temp)
Brett Cannon19691362003-04-29 05:08:06 +0000244 self.assertEqual(second_temp, result[0])
245 self.assert_(os.path.exists(second_temp), "copy of the file was not "
246 "made")
247 FILE = file(second_temp, 'rb')
248 try:
249 text = FILE.read()
Brett Cannon19691362003-04-29 05:08:06 +0000250 FILE.close()
Georg Brandl5a650a22005-08-26 08:51:34 +0000251 finally:
252 try: FILE.close()
253 except: pass
Brett Cannon19691362003-04-29 05:08:06 +0000254 self.assertEqual(self.text, text)
255
256 def test_reporthook(self):
257 # Make sure that the reporthook works.
258 def hooktester(count, block_size, total_size, count_holder=[0]):
259 self.assert_(isinstance(count, int))
260 self.assert_(isinstance(block_size, int))
261 self.assert_(isinstance(total_size, int))
262 self.assertEqual(count, count_holder[0])
263 count_holder[0] = count_holder[0] + 1
264 second_temp = "%s.2" % test_support.TESTFN
Georg Brandl5a650a22005-08-26 08:51:34 +0000265 self.registerFileForCleanUp(second_temp)
266 urllib.urlretrieve(self.constructLocalFileUrl(test_support.TESTFN),
267 second_temp, hooktester)
268
269 def test_reporthook_0_bytes(self):
270 # Test on zero length file. Should call reporthook only 1 time.
271 report = []
272 def hooktester(count, block_size, total_size, _report=report):
273 _report.append((count, block_size, total_size))
274 srcFileName = self.createNewTempFile()
275 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
276 test_support.TESTFN, hooktester)
277 self.assertEqual(len(report), 1)
278 self.assertEqual(report[0][2], 0)
279
280 def test_reporthook_5_bytes(self):
281 # Test on 5 byte file. Should call reporthook only 2 times (once when
282 # the "network connection" is established and once when the block is
283 # read). Since the block size is 8192 bytes, only one block read is
284 # required to read the entire file.
285 report = []
286 def hooktester(count, block_size, total_size, _report=report):
287 _report.append((count, block_size, total_size))
288 srcFileName = self.createNewTempFile("x" * 5)
289 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
290 test_support.TESTFN, hooktester)
291 self.assertEqual(len(report), 2)
292 self.assertEqual(report[0][1], 8192)
293 self.assertEqual(report[0][2], 5)
294
295 def test_reporthook_8193_bytes(self):
296 # Test on 8193 byte file. Should call reporthook only 3 times (once
297 # when the "network connection" is established, once for the next 8192
298 # bytes, and once for the last byte).
299 report = []
300 def hooktester(count, block_size, total_size, _report=report):
301 _report.append((count, block_size, total_size))
302 srcFileName = self.createNewTempFile("x" * 8193)
303 urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
304 test_support.TESTFN, hooktester)
305 self.assertEqual(len(report), 3)
306 self.assertEqual(report[0][1], 8192)
307 self.assertEqual(report[0][2], 8193)
Skip Montanaro080c9972001-01-28 21:12:22 +0000308
Brett Cannon74bfd702003-04-25 09:39:47 +0000309class QuotingTests(unittest.TestCase):
310 """Tests for urllib.quote() and urllib.quote_plus()
Tim Petersc2659cf2003-05-12 20:19:37 +0000311
Brett Cannon74bfd702003-04-25 09:39:47 +0000312 According to RFC 2396 ("Uniform Resource Identifiers), to escape a
313 character you write it as '%' + <2 character US-ASCII hex value>. The Python
314 code of ``'%' + hex(ord(<character>))[2:]`` escapes a character properly.
315 Case does not matter on the hex letters.
316
317 The various character sets specified are:
Tim Petersc2659cf2003-05-12 20:19:37 +0000318
Brett Cannon74bfd702003-04-25 09:39:47 +0000319 Reserved characters : ";/?:@&=+$,"
320 Have special meaning in URIs and must be escaped if not being used for
321 their special meaning
322 Data characters : letters, digits, and "-_.!~*'()"
323 Unreserved and do not need to be escaped; can be, though, if desired
324 Control characters : 0x00 - 0x1F, 0x7F
325 Have no use in URIs so must be escaped
326 space : 0x20
327 Must be escaped
328 Delimiters : '<>#%"'
329 Must be escaped
330 Unwise : "{}|\^[]`"
331 Must be escaped
Tim Petersc2659cf2003-05-12 20:19:37 +0000332
Brett Cannon74bfd702003-04-25 09:39:47 +0000333 """
334
335 def test_never_quote(self):
336 # Make sure quote() does not quote letters, digits, and "_,.-"
337 do_not_quote = '' .join(["ABCDEFGHIJKLMNOPQRSTUVWXYZ",
338 "abcdefghijklmnopqrstuvwxyz",
339 "0123456789",
340 "_.-"])
341 result = urllib.quote(do_not_quote)
342 self.assertEqual(do_not_quote, result,
343 "using quote(): %s != %s" % (do_not_quote, result))
344 result = urllib.quote_plus(do_not_quote)
345 self.assertEqual(do_not_quote, result,
346 "using quote_plus(): %s != %s" % (do_not_quote, result))
347
348 def test_default_safe(self):
349 # Test '/' is default value for 'safe' parameter
350 self.assertEqual(urllib.quote.func_defaults[0], '/')
351
352 def test_safe(self):
353 # Test setting 'safe' parameter does what it should do
354 quote_by_default = "<>"
355 result = urllib.quote(quote_by_default, safe=quote_by_default)
356 self.assertEqual(quote_by_default, result,
357 "using quote(): %s != %s" % (quote_by_default, result))
358 result = urllib.quote_plus(quote_by_default, safe=quote_by_default)
359 self.assertEqual(quote_by_default, result,
360 "using quote_plus(): %s != %s" %
361 (quote_by_default, result))
362
363 def test_default_quoting(self):
364 # Make sure all characters that should be quoted are by default sans
365 # space (separate test for that).
366 should_quote = [chr(num) for num in range(32)] # For 0x00 - 0x1F
367 should_quote.append('<>#%"{}|\^[]`')
368 should_quote.append(chr(127)) # For 0x7F
369 should_quote = ''.join(should_quote)
370 for char in should_quote:
371 result = urllib.quote(char)
372 self.assertEqual(hexescape(char), result,
373 "using quote(): %s should be escaped to %s, not %s" %
374 (char, hexescape(char), result))
375 result = urllib.quote_plus(char)
376 self.assertEqual(hexescape(char), result,
377 "using quote_plus(): "
Tim Petersc2659cf2003-05-12 20:19:37 +0000378 "%s should be escapes to %s, not %s" %
Brett Cannon74bfd702003-04-25 09:39:47 +0000379 (char, hexescape(char), result))
380 del should_quote
381 partial_quote = "ab[]cd"
382 expected = "ab%5B%5Dcd"
383 result = urllib.quote(partial_quote)
384 self.assertEqual(expected, result,
385 "using quote(): %s != %s" % (expected, result))
386 self.assertEqual(expected, result,
387 "using quote_plus(): %s != %s" % (expected, result))
388
389 def test_quoting_space(self):
390 # Make sure quote() and quote_plus() handle spaces as specified in
391 # their unique way
392 result = urllib.quote(' ')
393 self.assertEqual(result, hexescape(' '),
394 "using quote(): %s != %s" % (result, hexescape(' ')))
395 result = urllib.quote_plus(' ')
396 self.assertEqual(result, '+',
397 "using quote_plus(): %s != +" % result)
398 given = "a b cd e f"
399 expect = given.replace(' ', hexescape(' '))
400 result = urllib.quote(given)
401 self.assertEqual(expect, result,
402 "using quote(): %s != %s" % (expect, result))
403 expect = given.replace(' ', '+')
404 result = urllib.quote_plus(given)
405 self.assertEqual(expect, result,
406 "using quote_plus(): %s != %s" % (expect, result))
407
Raymond Hettinger2bdec7b2005-09-10 14:30:09 +0000408 def test_quoting_plus(self):
409 self.assertEqual(urllib.quote_plus('alpha+beta gamma'),
410 'alpha%2Bbeta+gamma')
411 self.assertEqual(urllib.quote_plus('alpha+beta gamma', '+'),
412 'alpha+beta+gamma')
413
Brett Cannon74bfd702003-04-25 09:39:47 +0000414class UnquotingTests(unittest.TestCase):
415 """Tests for unquote() and unquote_plus()
Tim Petersc2659cf2003-05-12 20:19:37 +0000416
Brett Cannon74bfd702003-04-25 09:39:47 +0000417 See the doc string for quoting_Tests for details on quoting and such.
418
419 """
420
421 def test_unquoting(self):
422 # Make sure unquoting of all ASCII values works
423 escape_list = []
424 for num in range(128):
425 given = hexescape(chr(num))
426 expect = chr(num)
427 result = urllib.unquote(given)
428 self.assertEqual(expect, result,
429 "using unquote(): %s != %s" % (expect, result))
430 result = urllib.unquote_plus(given)
431 self.assertEqual(expect, result,
432 "using unquote_plus(): %s != %s" %
433 (expect, result))
434 escape_list.append(given)
435 escape_string = ''.join(escape_list)
436 del escape_list
437 result = urllib.unquote(escape_string)
438 self.assertEqual(result.count('%'), 1,
439 "using quote(): not all characters escaped; %s" %
440 result)
441 result = urllib.unquote(escape_string)
442 self.assertEqual(result.count('%'), 1,
443 "using unquote(): not all characters escaped: "
444 "%s" % result)
445
446 def test_unquoting_parts(self):
447 # Make sure unquoting works when have non-quoted characters
448 # interspersed
449 given = 'ab%sd' % hexescape('c')
450 expect = "abcd"
451 result = urllib.unquote(given)
452 self.assertEqual(expect, result,
453 "using quote(): %s != %s" % (expect, result))
454 result = urllib.unquote_plus(given)
455 self.assertEqual(expect, result,
456 "using unquote_plus(): %s != %s" % (expect, result))
Tim Petersc2659cf2003-05-12 20:19:37 +0000457
Brett Cannon74bfd702003-04-25 09:39:47 +0000458 def test_unquoting_plus(self):
459 # Test difference between unquote() and unquote_plus()
460 given = "are+there+spaces..."
461 expect = given
462 result = urllib.unquote(given)
463 self.assertEqual(expect, result,
464 "using unquote(): %s != %s" % (expect, result))
465 expect = given.replace('+', ' ')
466 result = urllib.unquote_plus(given)
467 self.assertEqual(expect, result,
468 "using unquote_plus(): %s != %s" % (expect, result))
469
Raymond Hettinger4b0f20d2005-10-15 16:41:53 +0000470 def test_unquote_with_unicode(self):
471 r = urllib.unquote(u'br%C3%BCckner_sapporo_20050930.doc')
472 self.assertEqual(r, u'br\xc3\xbcckner_sapporo_20050930.doc')
473
Brett Cannon74bfd702003-04-25 09:39:47 +0000474class urlencode_Tests(unittest.TestCase):
475 """Tests for urlencode()"""
476
477 def help_inputtype(self, given, test_type):
478 """Helper method for testing different input types.
Tim Petersc2659cf2003-05-12 20:19:37 +0000479
Brett Cannon74bfd702003-04-25 09:39:47 +0000480 'given' must lead to only the pairs:
481 * 1st, 1
482 * 2nd, 2
483 * 3rd, 3
Tim Petersc2659cf2003-05-12 20:19:37 +0000484
Brett Cannon74bfd702003-04-25 09:39:47 +0000485 Test cannot assume anything about order. Docs make no guarantee and
486 have possible dictionary input.
Tim Petersc2659cf2003-05-12 20:19:37 +0000487
Brett Cannon74bfd702003-04-25 09:39:47 +0000488 """
489 expect_somewhere = ["1st=1", "2nd=2", "3rd=3"]
490 result = urllib.urlencode(given)
491 for expected in expect_somewhere:
492 self.assert_(expected in result,
493 "testing %s: %s not found in %s" %
494 (test_type, expected, result))
495 self.assertEqual(result.count('&'), 2,
496 "testing %s: expected 2 '&'s; got %s" %
497 (test_type, result.count('&')))
498 amp_location = result.index('&')
499 on_amp_left = result[amp_location - 1]
500 on_amp_right = result[amp_location + 1]
501 self.assert_(on_amp_left.isdigit() and on_amp_right.isdigit(),
502 "testing %s: '&' not located in proper place in %s" %
503 (test_type, result))
504 self.assertEqual(len(result), (5 * 3) + 2, #5 chars per thing and amps
505 "testing %s: "
506 "unexpected number of characters: %s != %s" %
507 (test_type, len(result), (5 * 3) + 2))
508
509 def test_using_mapping(self):
510 # Test passing in a mapping object as an argument.
511 self.help_inputtype({"1st":'1', "2nd":'2', "3rd":'3'},
512 "using dict as input type")
513
514 def test_using_sequence(self):
515 # Test passing in a sequence of two-item sequences as an argument.
516 self.help_inputtype([('1st', '1'), ('2nd', '2'), ('3rd', '3')],
517 "using sequence of two-item tuples as input")
518
519 def test_quoting(self):
520 # Make sure keys and values are quoted using quote_plus()
521 given = {"&":"="}
522 expect = "%s=%s" % (hexescape('&'), hexescape('='))
523 result = urllib.urlencode(given)
524 self.assertEqual(expect, result)
525 given = {"key name":"A bunch of pluses"}
526 expect = "key+name=A+bunch+of+pluses"
527 result = urllib.urlencode(given)
528 self.assertEqual(expect, result)
529
530 def test_doseq(self):
531 # Test that passing True for 'doseq' parameter works correctly
532 given = {'sequence':['1', '2', '3']}
533 expect = "sequence=%s" % urllib.quote_plus(str(['1', '2', '3']))
534 result = urllib.urlencode(given)
535 self.assertEqual(expect, result)
536 result = urllib.urlencode(given, True)
537 for value in given["sequence"]:
538 expect = "sequence=%s" % value
539 self.assert_(expect in result,
540 "%s not found in %s" % (expect, result))
541 self.assertEqual(result.count('&'), 2,
542 "Expected 2 '&'s, got %s" % result.count('&'))
543
544class Pathname_Tests(unittest.TestCase):
545 """Test pathname2url() and url2pathname()"""
546
547 def test_basic(self):
548 # Make sure simple tests pass
549 expected_path = os.path.join("parts", "of", "a", "path")
550 expected_url = "parts/of/a/path"
551 result = urllib.pathname2url(expected_path)
552 self.assertEqual(expected_url, result,
553 "pathname2url() failed; %s != %s" %
554 (result, expected_url))
555 result = urllib.url2pathname(expected_url)
556 self.assertEqual(expected_path, result,
557 "url2pathame() failed; %s != %s" %
558 (result, expected_path))
559
560 def test_quoting(self):
561 # Test automatic quoting and unquoting works for pathnam2url() and
562 # url2pathname() respectively
563 given = os.path.join("needs", "quot=ing", "here")
564 expect = "needs/%s/here" % urllib.quote("quot=ing")
565 result = urllib.pathname2url(given)
566 self.assertEqual(expect, result,
567 "pathname2url() failed; %s != %s" %
568 (expect, result))
569 expect = given
570 result = urllib.url2pathname(result)
571 self.assertEqual(expect, result,
572 "url2pathname() failed; %s != %s" %
573 (expect, result))
574 given = os.path.join("make sure", "using_quote")
575 expect = "%s/using_quote" % urllib.quote("make sure")
576 result = urllib.pathname2url(given)
577 self.assertEqual(expect, result,
578 "pathname2url() failed; %s != %s" %
579 (expect, result))
580 given = "make+sure/using_unquote"
581 expect = os.path.join("make+sure", "using_unquote")
582 result = urllib.url2pathname(given)
583 self.assertEqual(expect, result,
584 "url2pathname() failed; %s != %s" %
585 (expect, result))
Tim Petersc2659cf2003-05-12 20:19:37 +0000586
Facundo Batistad9880d02007-05-25 04:20:22 +0000587# Just commented them out.
588# Can't really tell why keep failing in windows and sparc.
589# Everywhere else they work ok, but on those machines, someteimes
590# fail in one of the tests, sometimes in other. I have a linux, and
591# the tests go ok.
592# If anybody has one of the problematic enviroments, please help!
593# . Facundo
594#
595# def server(evt):
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000596# import socket, time
Facundo Batistad9880d02007-05-25 04:20:22 +0000597# serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
598# serv.settimeout(3)
599# serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
600# serv.bind(("", 9093))
601# serv.listen(5)
602# try:
603# conn, addr = serv.accept()
604# conn.send("1 Hola mundo\n")
605# cantdata = 0
606# while cantdata < 13:
607# data = conn.recv(13-cantdata)
608# cantdata += len(data)
609# time.sleep(.3)
610# conn.send("2 No more lines\n")
611# conn.close()
612# except socket.timeout:
613# pass
614# finally:
615# serv.close()
616# evt.set()
617#
618# class FTPWrapperTests(unittest.TestCase):
619#
620# def setUp(self):
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000621# import ftplib, time, threading
Facundo Batistad9880d02007-05-25 04:20:22 +0000622# ftplib.FTP.port = 9093
623# self.evt = threading.Event()
624# threading.Thread(target=server, args=(self.evt,)).start()
625# time.sleep(.1)
626#
627# def tearDown(self):
628# self.evt.wait()
629#
630# def testBasic(self):
631# # connects
632# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000633# ftp.close()
Facundo Batistad9880d02007-05-25 04:20:22 +0000634#
635# def testTimeoutNone(self):
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000636# # global default timeout is ignored
637# import socket
638# self.assert_(socket.getdefaulttimeout() is None)
Facundo Batistad9880d02007-05-25 04:20:22 +0000639# socket.setdefaulttimeout(30)
640# try:
641# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
642# finally:
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000643# socket.setdefaulttimeout(None)
Facundo Batistad9880d02007-05-25 04:20:22 +0000644# self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000645# ftp.close()
Facundo Batistad9880d02007-05-25 04:20:22 +0000646#
Facundo Batista4f1b1ed2008-05-29 16:39:26 +0000647# def testTimeoutDefault(self):
648# # global default timeout is used
649# import socket
650# self.assert_(socket.getdefaulttimeout() is None)
651# socket.setdefaulttimeout(30)
652# try:
653# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
654# finally:
655# socket.setdefaulttimeout(None)
656# self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
657# ftp.close()
658#
659# def testTimeoutValue(self):
660# ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [],
661# timeout=30)
662# self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
663# ftp.close()
Facundo Batista711a54e2007-05-24 17:50:54 +0000664
Skip Montanaro080c9972001-01-28 21:12:22 +0000665
666
Brett Cannon74bfd702003-04-25 09:39:47 +0000667def test_main():
Brett Cannon8bb8fa52008-07-02 01:57:08 +0000668 import warnings
Brett Cannon672237d2008-09-09 00:49:16 +0000669 with warnings.catch_warnings():
Brett Cannon8bb8fa52008-07-02 01:57:08 +0000670 warnings.filterwarnings('ignore', ".*urllib\.urlopen.*Python 3.0",
671 DeprecationWarning)
672 test_support.run_unittest(
673 urlopen_FileTests,
674 urlopen_HttpTests,
675 urlretrieve_FileTests,
Benjamin Peterson2c7470d2008-09-21 21:27:51 +0000676 ProxyTests,
Brett Cannon8bb8fa52008-07-02 01:57:08 +0000677 QuotingTests,
678 UnquotingTests,
679 urlencode_Tests,
680 Pathname_Tests,
681 #FTPWrapperTests,
682 )
Brett Cannon74bfd702003-04-25 09:39:47 +0000683
684
685
686if __name__ == '__main__':
687 test_main()