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