Home | History | Annotate | Download | only in test
      1 #!/usr/bin/env python
      2 
      3 import unittest
      4 from test import test_support
      5 
      6 import socket
      7 import urllib
      8 import sys
      9 import os
     10 import time
     11 
     12 mimetools = test_support.import_module("mimetools", deprecated=True)
     13 
     14 
     15 def _open_with_retry(func, host, *args, **kwargs):
     16     # Connecting to remote hosts is flaky.  Make it more robust
     17     # by retrying the connection several times.
     18     for i in range(3):
     19         try:
     20             return func(host, *args, **kwargs)
     21         except IOError, last_exc:
     22             continue
     23         except:
     24             raise
     25     raise last_exc
     26 
     27 
     28 class URLTimeoutTest(unittest.TestCase):
     29 
     30     TIMEOUT = 10.0
     31 
     32     def setUp(self):
     33         socket.setdefaulttimeout(self.TIMEOUT)
     34 
     35     def tearDown(self):
     36         socket.setdefaulttimeout(None)
     37 
     38     def testURLread(self):
     39         f = _open_with_retry(urllib.urlopen, "http://www.python.org/")
     40         x = f.read()
     41 
     42 class urlopenNetworkTests(unittest.TestCase):
     43     """Tests urllib.urlopen using the network.
     44 
     45     These tests are not exhaustive.  Assuming that testing using files does a
     46     good job overall of some of the basic interface features.  There are no
     47     tests exercising the optional 'data' and 'proxies' arguments.  No tests
     48     for transparent redirection have been written.
     49 
     50     setUp is not used for always constructing a connection to
     51     http://www.python.org/ since there a few tests that don't use that address
     52     and making a connection is expensive enough to warrant minimizing unneeded
     53     connections.
     54 
     55     """
     56 
     57     def urlopen(self, *args):
     58         return _open_with_retry(urllib.urlopen, *args)
     59 
     60     def test_basic(self):
     61         # Simple test expected to pass.
     62         open_url = self.urlopen("http://www.python.org/")
     63         for attr in ("read", "readline", "readlines", "fileno", "close",
     64                      "info", "geturl"):
     65             self.assertTrue(hasattr(open_url, attr), "object returned from "
     66                             "urlopen lacks the %s attribute" % attr)
     67         try:
     68             self.assertTrue(open_url.read(), "calling 'read' failed")
     69         finally:
     70             open_url.close()
     71 
     72     def test_readlines(self):
     73         # Test both readline and readlines.
     74         open_url = self.urlopen("http://www.python.org/")
     75         try:
     76             self.assertIsInstance(open_url.readline(), basestring,
     77                                   "readline did not return a string")
     78             self.assertIsInstance(open_url.readlines(), list,
     79                                   "readlines did not return a list")
     80         finally:
     81             open_url.close()
     82 
     83     def test_info(self):
     84         # Test 'info'.
     85         open_url = self.urlopen("http://www.python.org/")
     86         try:
     87             info_obj = open_url.info()
     88         finally:
     89             open_url.close()
     90             self.assertIsInstance(info_obj, mimetools.Message,
     91                                   "object returned by 'info' is not an "
     92                                   "instance of mimetools.Message")
     93             self.assertEqual(info_obj.getsubtype(), "html")
     94 
     95     def test_geturl(self):
     96         # Make sure same URL as opened is returned by geturl.
     97         URL = "http://www.python.org/"
     98         open_url = self.urlopen(URL)
     99         try:
    100             gotten_url = open_url.geturl()
    101         finally:
    102             open_url.close()
    103         self.assertEqual(gotten_url, URL)
    104 
    105     def test_getcode(self):
    106         # test getcode() with the fancy opener to get 404 error codes
    107         URL = "http://www.python.org/XXXinvalidXXX"
    108         open_url = urllib.FancyURLopener().open(URL)
    109         try:
    110             code = open_url.getcode()
    111         finally:
    112             open_url.close()
    113         self.assertEqual(code, 404)
    114 
    115     def test_fileno(self):
    116         if (sys.platform in ('win32',) or
    117                 not hasattr(os, 'fdopen')):
    118             # On Windows, socket handles are not file descriptors; this
    119             # test can't pass on Windows.
    120             return
    121         # Make sure fd returned by fileno is valid.
    122         open_url = self.urlopen("http://www.python.org/")
    123         fd = open_url.fileno()
    124         FILE = os.fdopen(fd)
    125         try:
    126             self.assertTrue(FILE.read(), "reading from file created using fd "
    127                                       "returned by fileno failed")
    128         finally:
    129             FILE.close()
    130 
    131     def test_bad_address(self):
    132         # Make sure proper exception is raised when connecting to a bogus
    133         # address.
    134         bogus_domain = "sadflkjsasf.i.nvali.d"
    135         try:
    136             socket.gethostbyname(bogus_domain)
    137         except socket.gaierror:
    138             pass
    139         else:
    140             # This happens with some overzealous DNS providers such as OpenDNS
    141             self.skipTest("%r should not resolve for test to work" % bogus_domain)
    142         self.assertRaises(IOError,
    143                           # SF patch 809915:  In Sep 2003, VeriSign started
    144                           # highjacking invalid .com and .net addresses to
    145                           # boost traffic to their own site.  This test
    146                           # started failing then.  One hopes the .invalid
    147                           # domain will be spared to serve its defined
    148                           # purpose.
    149                           # urllib.urlopen, "http://www.sadflkjsasadf.com/")
    150                           urllib.urlopen, "http://sadflkjsasf.i.nvali.d/")
    151 
    152 class urlretrieveNetworkTests(unittest.TestCase):
    153     """Tests urllib.urlretrieve using the network."""
    154 
    155     def urlretrieve(self, *args):
    156         return _open_with_retry(urllib.urlretrieve, *args)
    157 
    158     def test_basic(self):
    159         # Test basic functionality.
    160         file_location,info = self.urlretrieve("http://www.python.org/")
    161         self.assertTrue(os.path.exists(file_location), "file location returned by"
    162                         " urlretrieve is not a valid path")
    163         FILE = file(file_location)
    164         try:
    165             self.assertTrue(FILE.read(), "reading from the file location returned"
    166                          " by urlretrieve failed")
    167         finally:
    168             FILE.close()
    169             os.unlink(file_location)
    170 
    171     def test_specified_path(self):
    172         # Make sure that specifying the location of the file to write to works.
    173         file_location,info = self.urlretrieve("http://www.python.org/",
    174                                               test_support.TESTFN)
    175         self.assertEqual(file_location, test_support.TESTFN)
    176         self.assertTrue(os.path.exists(file_location))
    177         FILE = file(file_location)
    178         try:
    179             self.assertTrue(FILE.read(), "reading from temporary file failed")
    180         finally:
    181             FILE.close()
    182             os.unlink(file_location)
    183 
    184     def test_header(self):
    185         # Make sure header returned as 2nd value from urlretrieve is good.
    186         file_location, header = self.urlretrieve("http://www.python.org/")
    187         os.unlink(file_location)
    188         self.assertIsInstance(header, mimetools.Message,
    189                               "header is not an instance of mimetools.Message")
    190 
    191     def test_data_header(self):
    192         logo = "http://www.python.org/community/logos/python-logo-master-v3-TM.png"
    193         file_location, fileheaders = self.urlretrieve(logo)
    194         os.unlink(file_location)
    195         datevalue = fileheaders.getheader('Date')
    196         dateformat = '%a, %d %b %Y %H:%M:%S GMT'
    197         try:
    198             time.strptime(datevalue, dateformat)
    199         except ValueError:
    200             self.fail('Date value not in %r format', dateformat)
    201 
    202 
    203 
    204 def test_main():
    205     test_support.requires('network')
    206     with test_support.check_py3k_warnings(
    207             ("urllib.urlopen.. has been removed", DeprecationWarning)):
    208         test_support.run_unittest(URLTimeoutTest,
    209                                   urlopenNetworkTests,
    210                                   urlretrieveNetworkTests)
    211 
    212 if __name__ == "__main__":
    213     test_main()
    214