1"""Regresssion tests for urllib"""
2
3import urllib
4import httplib
5import unittest
6from test import test_support
7import os
8import sys
9import mimetools
10import tempfile
11import StringIO
12
13def hexescape(char):
14    """Escape char as RFC 2396 specifies"""
15    hex_repr = hex(ord(char))[2:].upper()
16    if len(hex_repr) == 1:
17        hex_repr = "0%s" % hex_repr
18    return "%" + hex_repr
19
20class urlopen_FileTests(unittest.TestCase):
21    """Test urlopen() opening a temporary file.
22
23    Try to test as much functionality as possible so as to cut down on reliance
24    on connecting to the Net for testing.
25
26    """
27
28    def setUp(self):
29        """Setup of a temp file to use for testing"""
30        self.text = "test_urllib: %s\n" % self.__class__.__name__
31        FILE = file(test_support.TESTFN, 'wb')
32        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)
38
39    def tearDown(self):
40        """Shut down the open object"""
41        self.returned_obj.close()
42        os.remove(test_support.TESTFN)
43
44    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", "getcode", "__iter__"):
48            self.assertTrue(hasattr(self.returned_obj, attr),
49                         "object returned by urlopen() lacks %s attribute" %
50                         attr)
51
52    def test_read(self):
53        self.assertEqual(self.text, self.returned_obj.read())
54
55    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")
60
61    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")
67
68    def test_fileno(self):
69        file_num = self.returned_obj.fileno()
70        self.assertIsInstance(file_num, int, "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")
74
75    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()
79
80    def test_info(self):
81        self.assertIsInstance(self.returned_obj.info(), mimetools.Message)
82
83    def test_geturl(self):
84        self.assertEqual(self.returned_obj.geturl(), self.pathname)
85
86    def test_getcode(self):
87        self.assertEqual(self.returned_obj.getcode(), None)
88
89    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)
96
97class ProxyTests(unittest.TestCase):
98
99    def setUp(self):
100        # Records changes to env vars
101        self.env = test_support.EnvironmentVarGuard()
102        # Delete all proxy related env vars
103        for k in os.environ.keys():
104            if 'proxy' in k.lower():
105                self.env.unset(k)
106
107    def tearDown(self):
108        # Restore all proxy related env vars
109        self.env.__exit__()
110        del self.env
111
112    def test_getproxies_environment_keep_no_proxies(self):
113        self.env.set('NO_PROXY', 'localhost')
114        proxies = urllib.getproxies_environment()
115        # getproxies_environment use lowered case truncated (no '_proxy') keys
116        self.assertEqual('localhost', proxies['no'])
117
118
119class urlopen_HttpTests(unittest.TestCase):
120    """Test urlopen() opening a fake http connection."""
121
122    def fakehttp(self, fakedata):
123        class FakeSocket(StringIO.StringIO):
124            def sendall(self, str): pass
125            def makefile(self, mode, name): return self
126            def read(self, amt=None):
127                if self.closed: return ''
128                return StringIO.StringIO.read(self, amt)
129            def readline(self, length=None):
130                if self.closed: return ''
131                return StringIO.StringIO.readline(self, length)
132        class FakeHTTPConnection(httplib.HTTPConnection):
133            def connect(self):
134                self.sock = FakeSocket(fakedata)
135        assert httplib.HTTP._connection_class == httplib.HTTPConnection
136        httplib.HTTP._connection_class = FakeHTTPConnection
137
138    def unfakehttp(self):
139        httplib.HTTP._connection_class = httplib.HTTPConnection
140
141    def test_read(self):
142        self.fakehttp('Hello!')
143        try:
144            fp = urllib.urlopen("http://python.org/")
145            self.assertEqual(fp.readline(), 'Hello!')
146            self.assertEqual(fp.readline(), '')
147            self.assertEqual(fp.geturl(), 'http://python.org/')
148            self.assertEqual(fp.getcode(), 200)
149        finally:
150            self.unfakehttp()
151
152    def test_url_fragment(self):
153        # Issue #11703: geturl() omits fragments in the original URL.
154        url = 'http://docs.python.org/library/urllib.html#OK'
155        self.fakehttp('Hello!')
156        try:
157            fp = urllib.urlopen(url)
158            self.assertEqual(fp.geturl(), url)
159        finally:
160            self.unfakehttp()
161
162    def test_read_bogus(self):
163        # urlopen() should raise IOError for many error codes.
164        self.fakehttp('''HTTP/1.1 401 Authentication Required
165Date: Wed, 02 Jan 2008 03:03:54 GMT
166Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e
167Connection: close
168Content-Type: text/html; charset=iso-8859-1
169''')
170        try:
171            self.assertRaises(IOError, urllib.urlopen, "http://python.org/")
172        finally:
173            self.unfakehttp()
174
175    def test_invalid_redirect(self):
176        # urlopen() should raise IOError for many error codes.
177        self.fakehttp("""HTTP/1.1 302 Found
178Date: Wed, 02 Jan 2008 03:03:54 GMT
179Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e
180Location: file:README
181Connection: close
182Content-Type: text/html; charset=iso-8859-1
183""")
184        try:
185            self.assertRaises(IOError, urllib.urlopen, "http://python.org/")
186        finally:
187            self.unfakehttp()
188
189    def test_empty_socket(self):
190        # urlopen() raises IOError if the underlying socket does not send any
191        # data. (#1680230)
192        self.fakehttp('')
193        try:
194            self.assertRaises(IOError, urllib.urlopen, 'http://something')
195        finally:
196            self.unfakehttp()
197
198class urlretrieve_FileTests(unittest.TestCase):
199    """Test urllib.urlretrieve() on local files"""
200
201    def setUp(self):
202        # Create a list of temporary files. Each item in the list is a file
203        # name (absolute path or relative to the current working directory).
204        # All files in this list will be deleted in the tearDown method. Note,
205        # this only helps to makes sure temporary files get deleted, but it
206        # does nothing about trying to close files that may still be open. It
207        # is the responsibility of the developer to properly close files even
208        # when exceptional conditions occur.
209        self.tempFiles = []
210
211        # Create a temporary file.
212        self.registerFileForCleanUp(test_support.TESTFN)
213        self.text = 'testing urllib.urlretrieve'
214        try:
215            FILE = file(test_support.TESTFN, 'wb')
216            FILE.write(self.text)
217            FILE.close()
218        finally:
219            try: FILE.close()
220            except: pass
221
222    def tearDown(self):
223        # Delete the temporary files.
224        for each in self.tempFiles:
225            try: os.remove(each)
226            except: pass
227
228    def constructLocalFileUrl(self, filePath):
229        return "file://%s" % urllib.pathname2url(os.path.abspath(filePath))
230
231    def createNewTempFile(self, data=""):
232        """Creates a new temporary file containing the specified data,
233        registers the file for deletion during the test fixture tear down, and
234        returns the absolute path of the file."""
235
236        newFd, newFilePath = tempfile.mkstemp()
237        try:
238            self.registerFileForCleanUp(newFilePath)
239            newFile = os.fdopen(newFd, "wb")
240            newFile.write(data)
241            newFile.close()
242        finally:
243            try: newFile.close()
244            except: pass
245        return newFilePath
246
247    def registerFileForCleanUp(self, fileName):
248        self.tempFiles.append(fileName)
249
250    def test_basic(self):
251        # Make sure that a local file just gets its own location returned and
252        # a headers value is returned.
253        result = urllib.urlretrieve("file:%s" % test_support.TESTFN)
254        self.assertEqual(result[0], test_support.TESTFN)
255        self.assertIsInstance(result[1], mimetools.Message,
256                              "did not get a mimetools.Message instance as "
257                              "second returned value")
258
259    def test_copy(self):
260        # Test that setting the filename argument works.
261        second_temp = "%s.2" % test_support.TESTFN
262        self.registerFileForCleanUp(second_temp)
263        result = urllib.urlretrieve(self.constructLocalFileUrl(
264            test_support.TESTFN), second_temp)
265        self.assertEqual(second_temp, result[0])
266        self.assertTrue(os.path.exists(second_temp), "copy of the file was not "
267                                                  "made")
268        FILE = file(second_temp, 'rb')
269        try:
270            text = FILE.read()
271            FILE.close()
272        finally:
273            try: FILE.close()
274            except: pass
275        self.assertEqual(self.text, text)
276
277    def test_reporthook(self):
278        # Make sure that the reporthook works.
279        def hooktester(count, block_size, total_size, count_holder=[0]):
280            self.assertIsInstance(count, int)
281            self.assertIsInstance(block_size, int)
282            self.assertIsInstance(total_size, int)
283            self.assertEqual(count, count_holder[0])
284            count_holder[0] = count_holder[0] + 1
285        second_temp = "%s.2" % test_support.TESTFN
286        self.registerFileForCleanUp(second_temp)
287        urllib.urlretrieve(self.constructLocalFileUrl(test_support.TESTFN),
288            second_temp, hooktester)
289
290    def test_reporthook_0_bytes(self):
291        # Test on zero length file. Should call reporthook only 1 time.
292        report = []
293        def hooktester(count, block_size, total_size, _report=report):
294            _report.append((count, block_size, total_size))
295        srcFileName = self.createNewTempFile()
296        urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
297            test_support.TESTFN, hooktester)
298        self.assertEqual(len(report), 1)
299        self.assertEqual(report[0][2], 0)
300
301    def test_reporthook_5_bytes(self):
302        # Test on 5 byte file. Should call reporthook only 2 times (once when
303        # the "network connection" is established and once when the block is
304        # read). Since the block size is 8192 bytes, only one block read is
305        # required to read the entire file.
306        report = []
307        def hooktester(count, block_size, total_size, _report=report):
308            _report.append((count, block_size, total_size))
309        srcFileName = self.createNewTempFile("x" * 5)
310        urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
311            test_support.TESTFN, hooktester)
312        self.assertEqual(len(report), 2)
313        self.assertEqual(report[0][1], 8192)
314        self.assertEqual(report[0][2], 5)
315
316    def test_reporthook_8193_bytes(self):
317        # Test on 8193 byte file. Should call reporthook only 3 times (once
318        # when the "network connection" is established, once for the next 8192
319        # bytes, and once for the last byte).
320        report = []
321        def hooktester(count, block_size, total_size, _report=report):
322            _report.append((count, block_size, total_size))
323        srcFileName = self.createNewTempFile("x" * 8193)
324        urllib.urlretrieve(self.constructLocalFileUrl(srcFileName),
325            test_support.TESTFN, hooktester)
326        self.assertEqual(len(report), 3)
327        self.assertEqual(report[0][1], 8192)
328        self.assertEqual(report[0][2], 8193)
329
330class QuotingTests(unittest.TestCase):
331    """Tests for urllib.quote() and urllib.quote_plus()
332
333    According to RFC 2396 ("Uniform Resource Identifiers), to escape a
334    character you write it as '%' + <2 character US-ASCII hex value>.  The Python
335    code of ``'%' + hex(ord(<character>))[2:]`` escapes a character properly.
336    Case does not matter on the hex letters.
337
338    The various character sets specified are:
339
340    Reserved characters : ";/?:@&=+$,"
341        Have special meaning in URIs and must be escaped if not being used for
342        their special meaning
343    Data characters : letters, digits, and "-_.!~*'()"
344        Unreserved and do not need to be escaped; can be, though, if desired
345    Control characters : 0x00 - 0x1F, 0x7F
346        Have no use in URIs so must be escaped
347    space : 0x20
348        Must be escaped
349    Delimiters : '<>#%"'
350        Must be escaped
351    Unwise : "{}|\^[]`"
352        Must be escaped
353
354    """
355
356    def test_never_quote(self):
357        # Make sure quote() does not quote letters, digits, and "_,.-"
358        do_not_quote = '' .join(["ABCDEFGHIJKLMNOPQRSTUVWXYZ",
359                                 "abcdefghijklmnopqrstuvwxyz",
360                                 "0123456789",
361                                 "_.-"])
362        result = urllib.quote(do_not_quote)
363        self.assertEqual(do_not_quote, result,
364                         "using quote(): %s != %s" % (do_not_quote, result))
365        result = urllib.quote_plus(do_not_quote)
366        self.assertEqual(do_not_quote, result,
367                        "using quote_plus(): %s != %s" % (do_not_quote, result))
368
369    def test_default_safe(self):
370        # Test '/' is default value for 'safe' parameter
371        self.assertEqual(urllib.quote.func_defaults[0], '/')
372
373    def test_safe(self):
374        # Test setting 'safe' parameter does what it should do
375        quote_by_default = "<>"
376        result = urllib.quote(quote_by_default, safe=quote_by_default)
377        self.assertEqual(quote_by_default, result,
378                         "using quote(): %s != %s" % (quote_by_default, result))
379        result = urllib.quote_plus(quote_by_default, safe=quote_by_default)
380        self.assertEqual(quote_by_default, result,
381                         "using quote_plus(): %s != %s" %
382                         (quote_by_default, result))
383
384    def test_default_quoting(self):
385        # Make sure all characters that should be quoted are by default sans
386        # space (separate test for that).
387        should_quote = [chr(num) for num in range(32)] # For 0x00 - 0x1F
388        should_quote.append('<>#%"{}|\^[]`')
389        should_quote.append(chr(127)) # For 0x7F
390        should_quote = ''.join(should_quote)
391        for char in should_quote:
392            result = urllib.quote(char)
393            self.assertEqual(hexescape(char), result,
394                             "using quote(): %s should be escaped to %s, not %s" %
395                             (char, hexescape(char), result))
396            result = urllib.quote_plus(char)
397            self.assertEqual(hexescape(char), result,
398                             "using quote_plus(): "
399                             "%s should be escapes to %s, not %s" %
400                             (char, hexescape(char), result))
401        del should_quote
402        partial_quote = "ab[]cd"
403        expected = "ab%5B%5Dcd"
404        result = urllib.quote(partial_quote)
405        self.assertEqual(expected, result,
406                         "using quote(): %s != %s" % (expected, result))
407        self.assertEqual(expected, result,
408                         "using quote_plus(): %s != %s" % (expected, result))
409        self.assertRaises(TypeError, urllib.quote, None)
410
411    def test_quoting_space(self):
412        # Make sure quote() and quote_plus() handle spaces as specified in
413        # their unique way
414        result = urllib.quote(' ')
415        self.assertEqual(result, hexescape(' '),
416                         "using quote(): %s != %s" % (result, hexescape(' ')))
417        result = urllib.quote_plus(' ')
418        self.assertEqual(result, '+',
419                         "using quote_plus(): %s != +" % result)
420        given = "a b cd e f"
421        expect = given.replace(' ', hexescape(' '))
422        result = urllib.quote(given)
423        self.assertEqual(expect, result,
424                         "using quote(): %s != %s" % (expect, result))
425        expect = given.replace(' ', '+')
426        result = urllib.quote_plus(given)
427        self.assertEqual(expect, result,
428                         "using quote_plus(): %s != %s" % (expect, result))
429
430    def test_quoting_plus(self):
431        self.assertEqual(urllib.quote_plus('alpha+beta gamma'),
432                         'alpha%2Bbeta+gamma')
433        self.assertEqual(urllib.quote_plus('alpha+beta gamma', '+'),
434                         'alpha+beta+gamma')
435
436class UnquotingTests(unittest.TestCase):
437    """Tests for unquote() and unquote_plus()
438
439    See the doc string for quoting_Tests for details on quoting and such.
440
441    """
442
443    def test_unquoting(self):
444        # Make sure unquoting of all ASCII values works
445        escape_list = []
446        for num in range(128):
447            given = hexescape(chr(num))
448            expect = chr(num)
449            result = urllib.unquote(given)
450            self.assertEqual(expect, result,
451                             "using unquote(): %s != %s" % (expect, result))
452            result = urllib.unquote_plus(given)
453            self.assertEqual(expect, result,
454                             "using unquote_plus(): %s != %s" %
455                             (expect, result))
456            escape_list.append(given)
457        escape_string = ''.join(escape_list)
458        del escape_list
459        result = urllib.unquote(escape_string)
460        self.assertEqual(result.count('%'), 1,
461                         "using quote(): not all characters escaped; %s" %
462                         result)
463        result = urllib.unquote(escape_string)
464        self.assertEqual(result.count('%'), 1,
465                         "using unquote(): not all characters escaped: "
466                         "%s" % result)
467
468    def test_unquoting_badpercent(self):
469        # Test unquoting on bad percent-escapes
470        given = '%xab'
471        expect = given
472        result = urllib.unquote(given)
473        self.assertEqual(expect, result, "using unquote(): %r != %r"
474                         % (expect, result))
475        given = '%x'
476        expect = given
477        result = urllib.unquote(given)
478        self.assertEqual(expect, result, "using unquote(): %r != %r"
479                         % (expect, result))
480        given = '%'
481        expect = given
482        result = urllib.unquote(given)
483        self.assertEqual(expect, result, "using unquote(): %r != %r"
484                         % (expect, result))
485
486    def test_unquoting_mixed_case(self):
487        # Test unquoting on mixed-case hex digits in the percent-escapes
488        given = '%Ab%eA'
489        expect = '\xab\xea'
490        result = urllib.unquote(given)
491        self.assertEqual(expect, result, "using unquote(): %r != %r"
492                         % (expect, result))
493
494    def test_unquoting_parts(self):
495        # Make sure unquoting works when have non-quoted characters
496        # interspersed
497        given = 'ab%sd' % hexescape('c')
498        expect = "abcd"
499        result = urllib.unquote(given)
500        self.assertEqual(expect, result,
501                         "using quote(): %s != %s" % (expect, result))
502        result = urllib.unquote_plus(given)
503        self.assertEqual(expect, result,
504                         "using unquote_plus(): %s != %s" % (expect, result))
505
506    def test_unquoting_plus(self):
507        # Test difference between unquote() and unquote_plus()
508        given = "are+there+spaces..."
509        expect = given
510        result = urllib.unquote(given)
511        self.assertEqual(expect, result,
512                         "using unquote(): %s != %s" % (expect, result))
513        expect = given.replace('+', ' ')
514        result = urllib.unquote_plus(given)
515        self.assertEqual(expect, result,
516                         "using unquote_plus(): %s != %s" % (expect, result))
517
518    def test_unquote_with_unicode(self):
519        r = urllib.unquote(u'br%C3%BCckner_sapporo_20050930.doc')
520        self.assertEqual(r, u'br\xc3\xbcckner_sapporo_20050930.doc')
521
522class urlencode_Tests(unittest.TestCase):
523    """Tests for urlencode()"""
524
525    def help_inputtype(self, given, test_type):
526        """Helper method for testing different input types.
527
528        'given' must lead to only the pairs:
529            * 1st, 1
530            * 2nd, 2
531            * 3rd, 3
532
533        Test cannot assume anything about order.  Docs make no guarantee and
534        have possible dictionary input.
535
536        """
537        expect_somewhere = ["1st=1", "2nd=2", "3rd=3"]
538        result = urllib.urlencode(given)
539        for expected in expect_somewhere:
540            self.assertIn(expected, result,
541                         "testing %s: %s not found in %s" %
542                         (test_type, expected, result))
543        self.assertEqual(result.count('&'), 2,
544                         "testing %s: expected 2 '&'s; got %s" %
545                         (test_type, result.count('&')))
546        amp_location = result.index('&')
547        on_amp_left = result[amp_location - 1]
548        on_amp_right = result[amp_location + 1]
549        self.assertTrue(on_amp_left.isdigit() and on_amp_right.isdigit(),
550                     "testing %s: '&' not located in proper place in %s" %
551                     (test_type, result))
552        self.assertEqual(len(result), (5 * 3) + 2, #5 chars per thing and amps
553                         "testing %s: "
554                         "unexpected number of characters: %s != %s" %
555                         (test_type, len(result), (5 * 3) + 2))
556
557    def test_using_mapping(self):
558        # Test passing in a mapping object as an argument.
559        self.help_inputtype({"1st":'1', "2nd":'2', "3rd":'3'},
560                            "using dict as input type")
561
562    def test_using_sequence(self):
563        # Test passing in a sequence of two-item sequences as an argument.
564        self.help_inputtype([('1st', '1'), ('2nd', '2'), ('3rd', '3')],
565                            "using sequence of two-item tuples as input")
566
567    def test_quoting(self):
568        # Make sure keys and values are quoted using quote_plus()
569        given = {"&":"="}
570        expect = "%s=%s" % (hexescape('&'), hexescape('='))
571        result = urllib.urlencode(given)
572        self.assertEqual(expect, result)
573        given = {"key name":"A bunch of pluses"}
574        expect = "key+name=A+bunch+of+pluses"
575        result = urllib.urlencode(given)
576        self.assertEqual(expect, result)
577
578    def test_doseq(self):
579        # Test that passing True for 'doseq' parameter works correctly
580        given = {'sequence':['1', '2', '3']}
581        expect = "sequence=%s" % urllib.quote_plus(str(['1', '2', '3']))
582        result = urllib.urlencode(given)
583        self.assertEqual(expect, result)
584        result = urllib.urlencode(given, True)
585        for value in given["sequence"]:
586            expect = "sequence=%s" % value
587            self.assertIn(expect, result)
588        self.assertEqual(result.count('&'), 2,
589                         "Expected 2 '&'s, got %s" % result.count('&'))
590
591class Pathname_Tests(unittest.TestCase):
592    """Test pathname2url() and url2pathname()"""
593
594    def test_basic(self):
595        # Make sure simple tests pass
596        expected_path = os.path.join("parts", "of", "a", "path")
597        expected_url = "parts/of/a/path"
598        result = urllib.pathname2url(expected_path)
599        self.assertEqual(expected_url, result,
600                         "pathname2url() failed; %s != %s" %
601                         (result, expected_url))
602        result = urllib.url2pathname(expected_url)
603        self.assertEqual(expected_path, result,
604                         "url2pathame() failed; %s != %s" %
605                         (result, expected_path))
606
607    def test_quoting(self):
608        # Test automatic quoting and unquoting works for pathnam2url() and
609        # url2pathname() respectively
610        given = os.path.join("needs", "quot=ing", "here")
611        expect = "needs/%s/here" % urllib.quote("quot=ing")
612        result = urllib.pathname2url(given)
613        self.assertEqual(expect, result,
614                         "pathname2url() failed; %s != %s" %
615                         (expect, result))
616        expect = given
617        result = urllib.url2pathname(result)
618        self.assertEqual(expect, result,
619                         "url2pathname() failed; %s != %s" %
620                         (expect, result))
621        given = os.path.join("make sure", "using_quote")
622        expect = "%s/using_quote" % urllib.quote("make sure")
623        result = urllib.pathname2url(given)
624        self.assertEqual(expect, result,
625                         "pathname2url() failed; %s != %s" %
626                         (expect, result))
627        given = "make+sure/using_unquote"
628        expect = os.path.join("make+sure", "using_unquote")
629        result = urllib.url2pathname(given)
630        self.assertEqual(expect, result,
631                         "url2pathname() failed; %s != %s" %
632                         (expect, result))
633
634    @unittest.skipUnless(sys.platform == 'win32',
635                         'test specific to the nturl2path library')
636    def test_ntpath(self):
637        given = ('/C:/', '///C:/', '/C|//')
638        expect = 'C:\\'
639        for url in given:
640            result = urllib.url2pathname(url)
641            self.assertEqual(expect, result,
642                             'nturl2path.url2pathname() failed; %s != %s' %
643                             (expect, result))
644        given = '///C|/path'
645        expect = 'C:\\path'
646        result = urllib.url2pathname(given)
647        self.assertEqual(expect, result,
648                         'nturl2path.url2pathname() failed; %s != %s' %
649                         (expect, result))
650
651class Utility_Tests(unittest.TestCase):
652    """Testcase to test the various utility functions in the urllib."""
653
654    def test_splitpasswd(self):
655        """Some of the password examples are not sensible, but it is added to
656        confirming to RFC2617 and addressing issue4675.
657        """
658        self.assertEqual(('user', 'ab'),urllib.splitpasswd('user:ab'))
659        self.assertEqual(('user', 'a\nb'),urllib.splitpasswd('user:a\nb'))
660        self.assertEqual(('user', 'a\tb'),urllib.splitpasswd('user:a\tb'))
661        self.assertEqual(('user', 'a\rb'),urllib.splitpasswd('user:a\rb'))
662        self.assertEqual(('user', 'a\fb'),urllib.splitpasswd('user:a\fb'))
663        self.assertEqual(('user', 'a\vb'),urllib.splitpasswd('user:a\vb'))
664        self.assertEqual(('user', 'a:b'),urllib.splitpasswd('user:a:b'))
665
666
667class URLopener_Tests(unittest.TestCase):
668    """Testcase to test the open method of URLopener class."""
669
670    def test_quoted_open(self):
671        class DummyURLopener(urllib.URLopener):
672            def open_spam(self, url):
673                return url
674
675        self.assertEqual(DummyURLopener().open(
676            'spam://example/ /'),'//example/%20/')
677
678        # test the safe characters are not quoted by urlopen
679        self.assertEqual(DummyURLopener().open(
680            "spam://c:|windows%/:=&?~#+!$,;'@()*[]|/path/"),
681            "//c:|windows%/:=&?~#+!$,;'@()*[]|/path/")
682
683
684# Just commented them out.
685# Can't really tell why keep failing in windows and sparc.
686# Everywhere else they work ok, but on those machines, sometimes
687# fail in one of the tests, sometimes in other. I have a linux, and
688# the tests go ok.
689# If anybody has one of the problematic enviroments, please help!
690# .   Facundo
691#
692# def server(evt):
693#     import socket, time
694#     serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
695#     serv.settimeout(3)
696#     serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
697#     serv.bind(("", 9093))
698#     serv.listen(5)
699#     try:
700#         conn, addr = serv.accept()
701#         conn.send("1 Hola mundo\n")
702#         cantdata = 0
703#         while cantdata < 13:
704#             data = conn.recv(13-cantdata)
705#             cantdata += len(data)
706#             time.sleep(.3)
707#         conn.send("2 No more lines\n")
708#         conn.close()
709#     except socket.timeout:
710#         pass
711#     finally:
712#         serv.close()
713#         evt.set()
714#
715# class FTPWrapperTests(unittest.TestCase):
716#
717#     def setUp(self):
718#         import ftplib, time, threading
719#         ftplib.FTP.port = 9093
720#         self.evt = threading.Event()
721#         threading.Thread(target=server, args=(self.evt,)).start()
722#         time.sleep(.1)
723#
724#     def tearDown(self):
725#         self.evt.wait()
726#
727#     def testBasic(self):
728#         # connects
729#         ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
730#         ftp.close()
731#
732#     def testTimeoutNone(self):
733#         # global default timeout is ignored
734#         import socket
735#         self.assertTrue(socket.getdefaulttimeout() is None)
736#         socket.setdefaulttimeout(30)
737#         try:
738#             ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
739#         finally:
740#             socket.setdefaulttimeout(None)
741#         self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
742#         ftp.close()
743#
744#     def testTimeoutDefault(self):
745#         # global default timeout is used
746#         import socket
747#         self.assertTrue(socket.getdefaulttimeout() is None)
748#         socket.setdefaulttimeout(30)
749#         try:
750#             ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [])
751#         finally:
752#             socket.setdefaulttimeout(None)
753#         self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
754#         ftp.close()
755#
756#     def testTimeoutValue(self):
757#         ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, [],
758#                                 timeout=30)
759#         self.assertEqual(ftp.ftp.sock.gettimeout(), 30)
760#         ftp.close()
761
762
763
764def test_main():
765    import warnings
766    with warnings.catch_warnings():
767        warnings.filterwarnings('ignore', ".*urllib\.urlopen.*Python 3.0",
768                                DeprecationWarning)
769        test_support.run_unittest(
770            urlopen_FileTests,
771            urlopen_HttpTests,
772            urlretrieve_FileTests,
773            ProxyTests,
774            QuotingTests,
775            UnquotingTests,
776            urlencode_Tests,
777            Pathname_Tests,
778            Utility_Tests,
779            URLopener_Tests,
780            #FTPWrapperTests,
781        )
782
783
784
785if __name__ == '__main__':
786    test_main()
787