1#!/usr/bin/env python
2
3import unittest
4from test import test_support
5
6import socket
7import urllib
8import sys
9import os
10import time
11
12mimetools = test_support.import_module("mimetools", deprecated=True)
13
14
15def _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
28class 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
42class 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        self.assertRaises(IOError,
135                          # SF patch 809915:  In Sep 2003, VeriSign started
136                          # highjacking invalid .com and .net addresses to
137                          # boost traffic to their own site.  This test
138                          # started failing then.  One hopes the .invalid
139                          # domain will be spared to serve its defined
140                          # purpose.
141                          # urllib.urlopen, "http://www.sadflkjsasadf.com/")
142                          urllib.urlopen, "http://sadflkjsasf.i.nvali.d/")
143
144class urlretrieveNetworkTests(unittest.TestCase):
145    """Tests urllib.urlretrieve using the network."""
146
147    def urlretrieve(self, *args):
148        return _open_with_retry(urllib.urlretrieve, *args)
149
150    def test_basic(self):
151        # Test basic functionality.
152        file_location,info = self.urlretrieve("http://www.python.org/")
153        self.assertTrue(os.path.exists(file_location), "file location returned by"
154                        " urlretrieve is not a valid path")
155        FILE = file(file_location)
156        try:
157            self.assertTrue(FILE.read(), "reading from the file location returned"
158                         " by urlretrieve failed")
159        finally:
160            FILE.close()
161            os.unlink(file_location)
162
163    def test_specified_path(self):
164        # Make sure that specifying the location of the file to write to works.
165        file_location,info = self.urlretrieve("http://www.python.org/",
166                                              test_support.TESTFN)
167        self.assertEqual(file_location, test_support.TESTFN)
168        self.assertTrue(os.path.exists(file_location))
169        FILE = file(file_location)
170        try:
171            self.assertTrue(FILE.read(), "reading from temporary file failed")
172        finally:
173            FILE.close()
174            os.unlink(file_location)
175
176    def test_header(self):
177        # Make sure header returned as 2nd value from urlretrieve is good.
178        file_location, header = self.urlretrieve("http://www.python.org/")
179        os.unlink(file_location)
180        self.assertIsInstance(header, mimetools.Message,
181                              "header is not an instance of mimetools.Message")
182
183    def test_data_header(self):
184        logo = "http://www.python.org/community/logos/python-logo-master-v3-TM.png"
185        file_location, fileheaders = self.urlretrieve(logo)
186        os.unlink(file_location)
187        datevalue = fileheaders.getheader('Date')
188        dateformat = '%a, %d %b %Y %H:%M:%S GMT'
189        try:
190            time.strptime(datevalue, dateformat)
191        except ValueError:
192            self.fail('Date value not in %r format', dateformat)
193
194
195
196def test_main():
197    test_support.requires('network')
198    with test_support.check_py3k_warnings(
199            ("urllib.urlopen.. has been removed", DeprecationWarning)):
200        test_support.run_unittest(URLTimeoutTest,
201                                  urlopenNetworkTests,
202                                  urlretrieveNetworkTests)
203
204if __name__ == "__main__":
205    test_main()
206