/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
1
# Copyright (C) 2005, 2006 Canonical Ltd
1540.3.24 by Martin Pool
Add new protocol 'http+pycurl' that always uses PyCurl.
2
#
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1540.3.24 by Martin Pool
Add new protocol 'http+pycurl' that always uses PyCurl.
7
#
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1540.3.24 by Martin Pool
Add new protocol 'http+pycurl' that always uses PyCurl.
12
#
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
16
1540.3.3 by Martin Pool
Review updates of pycurl transport
17
# FIXME: This test should be repeated for each available http client
18
# implementation; at the moment we have urllib and pycurl.
19
1540.3.22 by Martin Pool
[patch] Add TestCase.assertIsInstance
20
# TODO: Should be renamed to bzrlib.transport.http.tests?
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
21
# TODO: What about renaming to bzrlib.tests.transport.http ?
1540.3.22 by Martin Pool
[patch] Add TestCase.assertIsInstance
22
2363.4.12 by Vincent Ladeuil
Take jam's review comments into account. Fix typos, give better
23
from cStringIO import StringIO
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
24
import os
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
25
import select
2000.2.2 by John Arbash Meinel
Update the urllib.has test.
26
import socket
2420.1.20 by Vincent Ladeuil
Fix test failure on pqm.
27
import sys
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
28
import threading
2000.2.2 by John Arbash Meinel
Update the urllib.has test.
29
1553.1.2 by James Henstridge
Add a test to make sure the user-agent header is being sent correctly.
30
import bzrlib
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
31
from bzrlib import (
32
    errors,
33
    osutils,
2363.4.12 by Vincent Ladeuil
Take jam's review comments into account. Fix typos, give better
34
    ui,
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
35
    urlutils,
36
    )
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
37
from bzrlib.tests import (
38
    TestCase,
2363.4.10 by Vincent Ladeuil
Complete tests.
39
    TestUIFactory,
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
40
    TestSkipped,
2363.4.10 by Vincent Ladeuil
Complete tests.
41
    StringIOWrapper,
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
42
    )
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
43
from bzrlib.tests.HttpServer import (
44
    HttpServer,
45
    HttpServer_PyCurl,
46
    HttpServer_urllib,
47
    )
48
from bzrlib.tests.HTTPTestUtil import (
49
    BadProtocolRequestHandler,
50
    BadStatusRequestHandler,
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
51
    ForbiddenRequestHandler,
2420.1.9 by Vincent Ladeuil
Refactor proxy and auth test classes. Tests failing for digest auth.
52
    HTTPBasicAuthServer,
53
    HTTPDigestAuthServer,
2164.2.13 by v.ladeuil+lp at free
Add tests for redirection. Preserve transport decorations.
54
    HTTPServerRedirecting,
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
55
    InvalidStatusRequestHandler,
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
56
    NoRangeRequestHandler,
2420.1.9 by Vincent Ladeuil
Refactor proxy and auth test classes. Tests failing for digest auth.
57
    ProxyBasicAuthServer,
58
    ProxyDigestAuthServer,
59
    ProxyServer,
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
60
    SingleRangeRequestHandler,
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
61
    TestCaseWithRedirectedWebserver,
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
62
    TestCaseWithTwoWebservers,
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
63
    TestCaseWithWebserver,
64
    WallRequestHandler,
65
    )
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
66
from bzrlib.transport import (
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
67
    do_catching_redirections,
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
68
    get_transport,
69
    Transport,
70
    )
2004.3.3 by vila
Better (but still incomplete) design for bogus servers.
71
from bzrlib.transport.http import (
72
    extract_auth,
73
    HttpTransportBase,
2164.2.29 by Vincent Ladeuil
Test the http redirection at the request level even if it's not
74
    _urllib2_wrappers,
2004.3.3 by vila
Better (but still incomplete) design for bogus servers.
75
    )
1540.3.26 by Martin Pool
[merge] bzr.dev; pycurl not updated for readv yet
76
from bzrlib.transport.http._urllib import HttpTransport_urllib
2420.1.3 by Vincent Ladeuil
Implement http proxy basic authentication.
77
from bzrlib.transport.http._urllib2_wrappers import (
78
    PasswordManager,
79
    ProxyHandler,
80
    Request,
81
    )
1185.40.20 by Robey Pointer
allow user:pass@ info in http urls to be used for auth; this should be easily expandable later to use auth config files
82
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
83
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
84
class FakeManager(object):
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
85
1185.40.20 by Robey Pointer
allow user:pass@ info in http urls to be used for auth; this should be easily expandable later to use auth config files
86
    def __init__(self):
87
        self.credentials = []
2004.3.1 by vila
Test ConnectionError exceptions.
88
1185.40.20 by Robey Pointer
allow user:pass@ info in http urls to be used for auth; this should be easily expandable later to use auth config files
89
    def add_password(self, realm, host, username, password):
90
        self.credentials.append([realm, host, username, password])
91
1553.1.2 by James Henstridge
Add a test to make sure the user-agent header is being sent correctly.
92
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
93
class RecordingServer(object):
94
    """A fake HTTP server.
95
    
96
    It records the bytes sent to it, and replies with a 200.
97
    """
98
99
    def __init__(self, expect_body_tail=None):
2018.2.28 by Andrew Bennetts
Changes in response to review: re-use _base_curl, rather than keeping a seperate _post_curl object; add docstring to test_http.RecordingServer, set is_user_error on some new exceptions.
100
        """Constructor.
101
102
        :type expect_body_tail: str
103
        :param expect_body_tail: a reply won't be sent until this string is
104
            received.
105
        """
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
106
        self._expect_body_tail = expect_body_tail
107
        self.host = None
108
        self.port = None
109
        self.received_bytes = ''
110
111
    def setUp(self):
112
        self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
113
        self._sock.bind(('127.0.0.1', 0))
114
        self.host, self.port = self._sock.getsockname()
115
        self._ready = threading.Event()
116
        self._thread = threading.Thread(target=self._accept_read_and_reply)
117
        self._thread.setDaemon(True)
118
        self._thread.start()
119
        self._ready.wait(5)
120
121
    def _accept_read_and_reply(self):
122
        self._sock.listen(1)
123
        self._ready.set()
124
        self._sock.settimeout(5)
125
        try:
126
            conn, address = self._sock.accept()
127
            # On win32, the accepted connection will be non-blocking to start
128
            # with because we're using settimeout.
129
            conn.setblocking(True)
130
            while not self.received_bytes.endswith(self._expect_body_tail):
131
                self.received_bytes += conn.recv(4096)
132
            conn.sendall('HTTP/1.1 200 OK\r\n')
133
        except socket.timeout:
134
            # Make sure the client isn't stuck waiting for us to e.g. accept.
135
            self._sock.close()
2158.2.1 by v.ladeuil+lp at free
Windows tests cleanup.
136
        except socket.error:
137
            # The client may have already closed the socket.
138
            pass
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
139
140
    def tearDown(self):
141
        try:
142
            self._sock.close()
143
        except socket.error:
144
            # We might have already closed it.  We don't care.
145
            pass
146
        self.host = None
147
        self.port = None
148
149
2294.3.1 by Vincent Ladeuil
Fix #85305 by issuing an exception instead of a traceback.
150
class TestWithTransport_pycurl(object):
151
    """Test case to inherit from if pycurl is present"""
152
153
    def _get_pycurl_maybe(self):
154
        try:
155
            from bzrlib.transport.http._pycurl import PyCurlTransport
156
            return PyCurlTransport
157
        except errors.DependencyNotPresent:
158
            raise TestSkipped('pycurl not present')
159
160
    _transport = property(_get_pycurl_maybe)
161
162
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
163
class TestHttpUrls(TestCase):
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
164
2294.3.1 by Vincent Ladeuil
Fix #85305 by issuing an exception instead of a traceback.
165
    # TODO: This should be moved to authorization tests once they
166
    # are written.
2004.1.40 by v.ladeuil+lp at free
Fix the race condition again and correct some small typos to be in
167
1185.40.20 by Robey Pointer
allow user:pass@ info in http urls to be used for auth; this should be easily expandable later to use auth config files
168
    def test_url_parsing(self):
169
        f = FakeManager()
170
        url = extract_auth('http://example.com', f)
171
        self.assertEquals('http://example.com', url)
172
        self.assertEquals(0, len(f.credentials))
1185.50.94 by John Arbash Meinel
Updated web page url to http://bazaar-vcs.org
173
        url = extract_auth('http://user:pass@www.bazaar-vcs.org/bzr/bzr.dev', f)
174
        self.assertEquals('http://www.bazaar-vcs.org/bzr/bzr.dev', url)
1185.40.20 by Robey Pointer
allow user:pass@ info in http urls to be used for auth; this should be easily expandable later to use auth config files
175
        self.assertEquals(1, len(f.credentials))
2004.3.1 by vila
Test ConnectionError exceptions.
176
        self.assertEquals([None, 'www.bazaar-vcs.org', 'user', 'pass'],
177
                          f.credentials[0])
178
2294.3.1 by Vincent Ladeuil
Fix #85305 by issuing an exception instead of a traceback.
179
180
class TestHttpTransportUrls(object):
181
    """Test the http urls.
182
183
    This MUST be used by daughter classes that also inherit from
184
    TestCase.
185
186
    We can't inherit directly from TestCase or the
187
    test framework will try to create an instance which cannot
188
    run, its implementation being incomplete.
189
    """
190
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
191
    def test_abs_url(self):
192
        """Construction of absolute http URLs"""
2294.3.1 by Vincent Ladeuil
Fix #85305 by issuing an exception instead of a traceback.
193
        t = self._transport('http://bazaar-vcs.org/bzr/bzr.dev/')
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
194
        eq = self.assertEqualDiff
2294.3.1 by Vincent Ladeuil
Fix #85305 by issuing an exception instead of a traceback.
195
        eq(t.abspath('.'), 'http://bazaar-vcs.org/bzr/bzr.dev')
196
        eq(t.abspath('foo/bar'), 'http://bazaar-vcs.org/bzr/bzr.dev/foo/bar')
197
        eq(t.abspath('.bzr'), 'http://bazaar-vcs.org/bzr/bzr.dev/.bzr')
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
198
        eq(t.abspath('.bzr/1//2/./3'),
1185.50.94 by John Arbash Meinel
Updated web page url to http://bazaar-vcs.org
199
           'http://bazaar-vcs.org/bzr/bzr.dev/.bzr/1/2/3')
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
200
201
    def test_invalid_http_urls(self):
202
        """Trap invalid construction of urls"""
2294.3.1 by Vincent Ladeuil
Fix #85305 by issuing an exception instead of a traceback.
203
        t = self._transport('http://bazaar-vcs.org/bzr/bzr.dev/')
204
        self.assertRaises(ValueError, t.abspath, '.bzr/')
205
        t = self._transport('http://http://bazaar-vcs.org/bzr/bzr.dev/')
206
        self.assertRaises((errors.InvalidURL, errors.ConnectionError),
207
                          t.has, 'foo/bar')
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
208
209
    def test_http_root_urls(self):
210
        """Construction of URLs from server root"""
2294.3.1 by Vincent Ladeuil
Fix #85305 by issuing an exception instead of a traceback.
211
        t = self._transport('http://bzr.ozlabs.org/')
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
212
        eq = self.assertEqualDiff
213
        eq(t.abspath('.bzr/tree-version'),
214
           'http://bzr.ozlabs.org/.bzr/tree-version')
1553.1.2 by James Henstridge
Add a test to make sure the user-agent header is being sent correctly.
215
1540.3.24 by Martin Pool
Add new protocol 'http+pycurl' that always uses PyCurl.
216
    def test_http_impl_urls(self):
217
        """There are servers which ask for particular clients to connect"""
2294.3.1 by Vincent Ladeuil
Fix #85305 by issuing an exception instead of a traceback.
218
        server = self._server()
1540.3.24 by Martin Pool
Add new protocol 'http+pycurl' that always uses PyCurl.
219
        try:
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
220
            server.setUp()
221
            url = server.get_url()
2294.3.1 by Vincent Ladeuil
Fix #85305 by issuing an exception instead of a traceback.
222
            self.assertTrue(url.startswith('%s://' % self._qualified_prefix))
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
223
        finally:
224
            server.tearDown()
1553.1.2 by James Henstridge
Add a test to make sure the user-agent header is being sent correctly.
225
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
226
2294.3.1 by Vincent Ladeuil
Fix #85305 by issuing an exception instead of a traceback.
227
class TestHttpUrls_urllib(TestHttpTransportUrls, TestCase):
228
    """Test http urls with urllib"""
229
230
    _transport = HttpTransport_urllib
231
    _server = HttpServer_urllib
232
    _qualified_prefix = 'http+urllib'
233
234
235
class TestHttpUrls_pycurl(TestWithTransport_pycurl, TestHttpTransportUrls,
236
                          TestCase):
237
    """Test http urls with pycurl"""
238
239
    _server = HttpServer_PyCurl
240
    _qualified_prefix = 'http+pycurl'
241
242
    # TODO: This should really be moved into another pycurl
243
    # specific test. When https tests will be implemented, take
244
    # this one into account.
245
    def test_pycurl_without_https_support(self):
246
        """Test that pycurl without SSL do not fail with a traceback.
247
248
        For the purpose of the test, we force pycurl to ignore
249
        https by supplying a fake version_info that do not
250
        support it.
251
        """
252
        try:
253
            import pycurl
254
        except ImportError:
255
            raise TestSkipped('pycurl not present')
256
        # Now that we have pycurl imported, we can fake its version_info
257
        # This was taken from a windows pycurl without SSL
258
        # (thanks to bialix)
259
        pycurl.version_info = lambda : (2,
260
                                        '7.13.2',
261
                                        462082,
262
                                        'i386-pc-win32',
263
                                        2576,
264
                                        None,
265
                                        0,
266
                                        None,
2294.3.2 by Aaron Bentley
Remove trailing whitespace
267
                                        ('ftp', 'gopher', 'telnet',
2294.3.1 by Vincent Ladeuil
Fix #85305 by issuing an exception instead of a traceback.
268
                                         'dict', 'ldap', 'http', 'file'),
269
                                        None,
270
                                        0,
271
                                        None)
272
        self.assertRaises(errors.DependencyNotPresent, self._transport,
273
                          'https://launchpad.net')
274
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
275
class TestHttpConnections(object):
276
    """Test the http connections.
277
278
    This MUST be used by daughter classes that also inherit from
279
    TestCaseWithWebserver.
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
280
281
    We can't inherit directly from TestCaseWithWebserver or the
282
    test framework will try to create an instance which cannot
283
    run, its implementation being incomplete.
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
284
    """
285
286
    def setUp(self):
287
        TestCaseWithWebserver.setUp(self)
1540.3.33 by Martin Pool
Fix http tests that were failing to run tearDown when setup got a missing dependency
288
        self.build_tree(['xxx', 'foo/', 'foo/bar'], line_endings='binary',
289
                        transport=self.get_transport())
1553.1.2 by James Henstridge
Add a test to make sure the user-agent header is being sent correctly.
290
291
    def test_http_has(self):
1185.50.84 by John Arbash Meinel
[merge] bzr.dev, cleanup conflicts, fixup http tests for new TestCase layout.
292
        server = self.get_readonly_server()
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
293
        t = self._transport(server.get_url())
1553.1.2 by James Henstridge
Add a test to make sure the user-agent header is being sent correctly.
294
        self.assertEqual(t.has('foo/bar'), True)
1185.50.84 by John Arbash Meinel
[merge] bzr.dev, cleanup conflicts, fixup http tests for new TestCase layout.
295
        self.assertEqual(len(server.logs), 1)
2004.3.1 by vila
Test ConnectionError exceptions.
296
        self.assertContainsRe(server.logs[0],
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
297
            r'"HEAD /foo/bar HTTP/1.." (200|302) - "-" "bzr/')
1553.1.5 by James Henstridge
Make HTTP transport has() method do HEAD requests, and update test to
298
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
299
    def test_http_has_not_found(self):
300
        server = self.get_readonly_server()
301
        t = self._transport(server.get_url())
1553.1.5 by James Henstridge
Make HTTP transport has() method do HEAD requests, and update test to
302
        self.assertEqual(t.has('not-found'), False)
2004.3.1 by vila
Test ConnectionError exceptions.
303
        self.assertContainsRe(server.logs[1],
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
304
            r'"HEAD /not-found HTTP/1.." 404 - "-" "bzr/')
1553.1.2 by James Henstridge
Add a test to make sure the user-agent header is being sent correctly.
305
306
    def test_http_get(self):
1185.50.84 by John Arbash Meinel
[merge] bzr.dev, cleanup conflicts, fixup http tests for new TestCase layout.
307
        server = self.get_readonly_server()
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
308
        t = self._transport(server.get_url())
1553.1.2 by James Henstridge
Add a test to make sure the user-agent header is being sent correctly.
309
        fp = t.get('foo/bar')
310
        self.assertEqualDiff(
311
            fp.read(),
1553.1.3 by James Henstridge
Make bzrlib.transport.http.HttpServer output referer and user agent as in
312
            'contents of foo/bar\n')
1185.50.84 by John Arbash Meinel
[merge] bzr.dev, cleanup conflicts, fixup http tests for new TestCase layout.
313
        self.assertEqual(len(server.logs), 1)
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
314
        self.assertTrue(server.logs[0].find(
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
315
            '"GET /foo/bar HTTP/1.1" 200 - "-" "bzr/%s'
316
            % bzrlib.__version__) > -1)
1540.3.33 by Martin Pool
Fix http tests that were failing to run tearDown when setup got a missing dependency
317
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
318
    def test_get_smart_medium(self):
319
        # For HTTP, get_smart_medium should return the transport object.
320
        server = self.get_readonly_server()
321
        http_transport = self._transport(server.get_url())
322
        medium = http_transport.get_smart_medium()
2018.2.26 by Andrew Bennetts
Changes prompted by j-a-meinel's review.
323
        self.assertIs(medium, http_transport)
1540.3.33 by Martin Pool
Fix http tests that were failing to run tearDown when setup got a missing dependency
324
2000.2.2 by John Arbash Meinel
Update the urllib.has test.
325
    def test_has_on_bogus_host(self):
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
326
        # Get a free address and don't 'accept' on it, so that we
327
        # can be sure there is no http handler there, but set a
328
        # reasonable timeout to not slow down tests too much.
329
        default_timeout = socket.getdefaulttimeout()
330
        try:
331
            socket.setdefaulttimeout(2)
332
            s = socket.socket()
333
            s.bind(('localhost', 0))
334
            t = self._transport('http://%s:%s/' % s.getsockname())
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
335
            self.assertRaises(errors.ConnectionError, t.has, 'foo/bar')
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
336
        finally:
337
            socket.setdefaulttimeout(default_timeout)
338
1540.3.33 by Martin Pool
Fix http tests that were failing to run tearDown when setup got a missing dependency
339
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
340
class TestHttpConnections_urllib(TestHttpConnections, TestCaseWithWebserver):
341
    """Test http connections with urllib"""
342
343
    _transport = HttpTransport_urllib
344
345
346
347
class TestHttpConnections_pycurl(TestWithTransport_pycurl,
348
                                 TestHttpConnections,
349
                                 TestCaseWithWebserver):
350
    """Test http connections with pycurl"""
1540.3.33 by Martin Pool
Fix http tests that were failing to run tearDown when setup got a missing dependency
351
352
1540.3.23 by Martin Pool
Allow urls like http+pycurl://host/ to use a particular impl
353
class TestHttpTransportRegistration(TestCase):
354
    """Test registrations of various http implementations"""
355
356
    def test_http_registered(self):
357
        # urlllib should always be present
358
        t = get_transport('http+urllib://bzr.google.com/')
359
        self.assertIsInstance(t, Transport)
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
360
        self.assertIsInstance(t, HttpTransport_urllib)
1786.1.23 by John Arbash Meinel
Move offset_to_http_ranges back onto HttpTransportBase, clarify tests.
361
362
363
class TestOffsets(TestCase):
1786.1.28 by John Arbash Meinel
Update and add tests for the HttpTransportBase.range_header
364
    """Test offsets_to_ranges method"""
1786.1.23 by John Arbash Meinel
Move offset_to_http_ranges back onto HttpTransportBase, clarify tests.
365
366
    def test_offsets_to_ranges_simple(self):
367
        to_range = HttpTransportBase.offsets_to_ranges
1786.1.39 by John Arbash Meinel
Remove the ability to read negative offsets from readv()
368
        ranges = to_range([(10, 1)])
1786.1.23 by John Arbash Meinel
Move offset_to_http_ranges back onto HttpTransportBase, clarify tests.
369
        self.assertEqual([[10, 10]], ranges)
1786.1.39 by John Arbash Meinel
Remove the ability to read negative offsets from readv()
370
371
        ranges = to_range([(0, 1), (1, 1)])
372
        self.assertEqual([[0, 1]], ranges)
373
374
        ranges = to_range([(1, 1), (0, 1)])
375
        self.assertEqual([[0, 1]], ranges)
1786.1.23 by John Arbash Meinel
Move offset_to_http_ranges back onto HttpTransportBase, clarify tests.
376
377
    def test_offset_to_ranges_overlapped(self):
378
        to_range = HttpTransportBase.offsets_to_ranges
379
1786.1.39 by John Arbash Meinel
Remove the ability to read negative offsets from readv()
380
        ranges = to_range([(10, 1), (20, 2), (22, 5)])
381
        self.assertEqual([[10, 10], [20, 26]], ranges)
382
383
        ranges = to_range([(10, 1), (11, 2), (22, 5)])
384
        self.assertEqual([[10, 12], [22, 26]], ranges)
1786.1.23 by John Arbash Meinel
Move offset_to_http_ranges back onto HttpTransportBase, clarify tests.
385
1786.1.28 by John Arbash Meinel
Update and add tests for the HttpTransportBase.range_header
386
2158.2.1 by v.ladeuil+lp at free
Windows tests cleanup.
387
class TestPost(object):
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
388
389
    def _test_post_body_is_received(self, scheme):
390
        server = RecordingServer(expect_body_tail='end-of-body')
391
        server.setUp()
392
        self.addCleanup(server.tearDown)
393
        url = '%s://%s:%s/' % (scheme, server.host, server.port)
394
        try:
395
            http_transport = get_transport(url)
2004.1.30 by v.ladeuil+lp at free
Fix #62276 and #62029 by providing a more robust http range handling.
396
        except errors.UnsupportedProtocol:
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
397
            raise TestSkipped('%s not available' % scheme)
398
        code, response = http_transport._post('abc def end-of-body')
399
        self.assertTrue(
400
            server.received_bytes.startswith('POST /.bzr/smart HTTP/1.'))
401
        self.assertTrue('content-length: 19\r' in server.received_bytes.lower())
402
        # The transport should not be assuming that the server can accept
403
        # chunked encoding the first time it connects, because HTTP/1.1, so we
404
        # check for the literal string.
405
        self.assertTrue(
406
            server.received_bytes.endswith('\r\n\r\nabc def end-of-body'))
407
2158.2.1 by v.ladeuil+lp at free
Windows tests cleanup.
408
409
class TestPost_urllib(TestCase, TestPost):
410
    """TestPost for urllib implementation"""
411
412
    _transport = HttpTransport_urllib
413
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
414
    def test_post_body_is_received_urllib(self):
415
        self._test_post_body_is_received('http+urllib')
416
2158.2.1 by v.ladeuil+lp at free
Windows tests cleanup.
417
418
class TestPost_pycurl(TestWithTransport_pycurl, TestCase, TestPost):
419
    """TestPost for pycurl implementation"""
420
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
421
    def test_post_body_is_received_pycurl(self):
422
        self._test_post_body_is_received('http+pycurl')
423
424
1786.1.28 by John Arbash Meinel
Update and add tests for the HttpTransportBase.range_header
425
class TestRangeHeader(TestCase):
426
    """Test range_header method"""
427
428
    def check_header(self, value, ranges=[], tail=0):
429
        range_header = HttpTransportBase.range_header
430
        self.assertEqual(value, range_header(ranges, tail))
431
432
    def test_range_header_single(self):
1786.1.36 by John Arbash Meinel
pycurl expects us to just set the range of bytes, not including bytes=
433
        self.check_header('0-9', ranges=[[0,9]])
434
        self.check_header('100-109', ranges=[[100,109]])
1786.1.28 by John Arbash Meinel
Update and add tests for the HttpTransportBase.range_header
435
436
    def test_range_header_tail(self):
1786.1.36 by John Arbash Meinel
pycurl expects us to just set the range of bytes, not including bytes=
437
        self.check_header('-10', tail=10)
438
        self.check_header('-50', tail=50)
1786.1.28 by John Arbash Meinel
Update and add tests for the HttpTransportBase.range_header
439
440
    def test_range_header_multi(self):
1786.1.36 by John Arbash Meinel
pycurl expects us to just set the range of bytes, not including bytes=
441
        self.check_header('0-9,100-200,300-5000',
1786.1.28 by John Arbash Meinel
Update and add tests for the HttpTransportBase.range_header
442
                          ranges=[(0,9), (100, 200), (300,5000)])
443
444
    def test_range_header_mixed(self):
1786.1.36 by John Arbash Meinel
pycurl expects us to just set the range of bytes, not including bytes=
445
        self.check_header('0-9,300-5000,-50',
1786.1.28 by John Arbash Meinel
Update and add tests for the HttpTransportBase.range_header
446
                          ranges=[(0,9), (300,5000)],
447
                          tail=50)
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
448
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
449
450
class TestWallServer(object):
451
    """Tests exceptions during the connection phase"""
452
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
453
    def create_transport_readonly_server(self):
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
454
        return HttpServer(WallRequestHandler)
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
455
456
    def test_http_has(self):
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
457
        server = self.get_readonly_server()
2004.3.1 by vila
Test ConnectionError exceptions.
458
        t = self._transport(server.get_url())
2004.1.40 by v.ladeuil+lp at free
Fix the race condition again and correct some small typos to be in
459
        # Unfortunately httplib (see HTTPResponse._read_status
460
        # for details) make no distinction between a closed
461
        # socket and badly formatted status line, so we can't
462
        # just test for ConnectionError, we have to test
463
        # InvalidHttpResponse too.
464
        self.assertRaises((errors.ConnectionError, errors.InvalidHttpResponse),
465
                          t.has, 'foo/bar')
2004.3.3 by vila
Better (but still incomplete) design for bogus servers.
466
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
467
    def test_http_get(self):
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
468
        server = self.get_readonly_server()
2004.3.3 by vila
Better (but still incomplete) design for bogus servers.
469
        t = self._transport(server.get_url())
2145.1.1 by mbp at sourcefrog
merge urllib keepalive etc
470
        self.assertRaises((errors.ConnectionError, errors.InvalidHttpResponse),
471
                          t.get, 'foo/bar')
2004.3.3 by vila
Better (but still incomplete) design for bogus servers.
472
473
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
474
class TestWallServer_urllib(TestWallServer, TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
475
    """Tests "wall" server for urllib implementation"""
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
476
477
    _transport = HttpTransport_urllib
478
479
480
class TestWallServer_pycurl(TestWithTransport_pycurl,
481
                            TestWallServer,
482
                            TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
483
    """Tests "wall" server for pycurl implementation"""
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
484
485
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
486
class TestBadStatusServer(object):
487
    """Tests bad status from server."""
488
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
489
    def create_transport_readonly_server(self):
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
490
        return HttpServer(BadStatusRequestHandler)
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
491
492
    def test_http_has(self):
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
493
        server = self.get_readonly_server()
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
494
        t = self._transport(server.get_url())
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
495
        self.assertRaises(errors.InvalidHttpResponse, t.has, 'foo/bar')
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
496
497
    def test_http_get(self):
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
498
        server = self.get_readonly_server()
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
499
        t = self._transport(server.get_url())
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
500
        self.assertRaises(errors.InvalidHttpResponse, t.get, 'foo/bar')
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
501
502
503
class TestBadStatusServer_urllib(TestBadStatusServer, TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
504
    """Tests bad status server for urllib implementation"""
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
505
506
    _transport = HttpTransport_urllib
507
508
509
class TestBadStatusServer_pycurl(TestWithTransport_pycurl,
510
                                 TestBadStatusServer,
511
                                 TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
512
    """Tests bad status server for pycurl implementation"""
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
513
514
515
class TestInvalidStatusServer(TestBadStatusServer):
516
    """Tests invalid status from server.
517
518
    Both implementations raises the same error as for a bad status.
519
    """
520
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
521
    def create_transport_readonly_server(self):
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
522
        return HttpServer(InvalidStatusRequestHandler)
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
523
524
525
class TestInvalidStatusServer_urllib(TestInvalidStatusServer,
526
                                     TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
527
    """Tests invalid status server for urllib implementation"""
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
528
529
    _transport = HttpTransport_urllib
530
531
532
class TestInvalidStatusServer_pycurl(TestWithTransport_pycurl,
533
                                     TestInvalidStatusServer,
534
                                     TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
535
    """Tests invalid status server for pycurl implementation"""
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
536
537
538
class TestBadProtocolServer(object):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
539
    """Tests bad protocol from server."""
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
540
541
    def create_transport_readonly_server(self):
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
542
        return HttpServer(BadProtocolRequestHandler)
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
543
544
    def test_http_has(self):
545
        server = self.get_readonly_server()
546
        t = self._transport(server.get_url())
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
547
        self.assertRaises(errors.InvalidHttpResponse, t.has, 'foo/bar')
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
548
549
    def test_http_get(self):
550
        server = self.get_readonly_server()
551
        t = self._transport(server.get_url())
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
552
        self.assertRaises(errors.InvalidHttpResponse, t.get, 'foo/bar')
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
553
554
555
class TestBadProtocolServer_urllib(TestBadProtocolServer,
556
                                   TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
557
    """Tests bad protocol server for urllib implementation"""
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
558
559
    _transport = HttpTransport_urllib
560
561
# curl don't check the protocol version
562
#class TestBadProtocolServer_pycurl(TestWithTransport_pycurl,
563
#                                   TestBadProtocolServer,
564
#                                   TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
565
#    """Tests bad protocol server for pycurl implementation"""
566
567
568
class TestForbiddenServer(object):
569
    """Tests forbidden server"""
570
571
    def create_transport_readonly_server(self):
572
        return HttpServer(ForbiddenRequestHandler)
573
574
    def test_http_has(self):
575
        server = self.get_readonly_server()
576
        t = self._transport(server.get_url())
577
        self.assertRaises(errors.TransportError, t.has, 'foo/bar')
578
579
    def test_http_get(self):
580
        server = self.get_readonly_server()
581
        t = self._transport(server.get_url())
582
        self.assertRaises(errors.TransportError, t.get, 'foo/bar')
583
584
585
class TestForbiddenServer_urllib(TestForbiddenServer, TestCaseWithWebserver):
586
    """Tests forbidden server for urllib implementation"""
587
588
    _transport = HttpTransport_urllib
589
590
591
class TestForbiddenServer_pycurl(TestWithTransport_pycurl,
592
                                 TestForbiddenServer,
593
                                 TestCaseWithWebserver):
594
    """Tests forbidden server for pycurl implementation"""
595
2004.1.28 by v.ladeuil+lp at free
Merge bzr.dev. Including http modifications by "smart" related code
596
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
597
class TestRecordingServer(TestCase):
598
599
    def test_create(self):
600
        server = RecordingServer(expect_body_tail=None)
601
        self.assertEqual('', server.received_bytes)
602
        self.assertEqual(None, server.host)
603
        self.assertEqual(None, server.port)
604
605
    def test_setUp_and_tearDown(self):
606
        server = RecordingServer(expect_body_tail=None)
607
        server.setUp()
608
        try:
609
            self.assertNotEqual(None, server.host)
610
            self.assertNotEqual(None, server.port)
611
        finally:
612
            server.tearDown()
613
        self.assertEqual(None, server.host)
614
        self.assertEqual(None, server.port)
615
616
    def test_send_receive_bytes(self):
617
        server = RecordingServer(expect_body_tail='c')
618
        server.setUp()
619
        self.addCleanup(server.tearDown)
620
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
621
        sock.connect((server.host, server.port))
622
        sock.sendall('abc')
623
        self.assertEqual('HTTP/1.1 200 OK\r\n',
2091.1.1 by Martin Pool
Avoid MSG_WAITALL as it doesn't work on Windows
624
                         osutils.recv_all(sock, 4096))
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
625
        self.assertEqual('abc', server.received_bytes)
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
626
627
628
class TestRangeRequestServer(object):
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
629
    """Tests readv requests against server.
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
630
631
    This MUST be used by daughter classes that also inherit from
632
    TestCaseWithWebserver.
633
634
    We can't inherit directly from TestCaseWithWebserver or the
635
    test framework will try to create an instance which cannot
636
    run, its implementation being incomplete.
637
    """
638
639
    def setUp(self):
640
        TestCaseWithWebserver.setUp(self)
2004.1.30 by v.ladeuil+lp at free
Fix #62276 and #62029 by providing a more robust http range handling.
641
        self.build_tree_contents([('a', '0123456789')],)
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
642
643
    def test_readv(self):
644
        server = self.get_readonly_server()
645
        t = self._transport(server.get_url())
2004.1.30 by v.ladeuil+lp at free
Fix #62276 and #62029 by providing a more robust http range handling.
646
        l = list(t.readv('a', ((0, 1), (1, 1), (3, 2), (9, 1))))
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
647
        self.assertEqual(l[0], (0, '0'))
648
        self.assertEqual(l[1], (1, '1'))
649
        self.assertEqual(l[2], (3, '34'))
650
        self.assertEqual(l[3], (9, '9'))
651
652
    def test_readv_out_of_order(self):
653
        server = self.get_readonly_server()
654
        t = self._transport(server.get_url())
2004.1.30 by v.ladeuil+lp at free
Fix #62276 and #62029 by providing a more robust http range handling.
655
        l = list(t.readv('a', ((1, 1), (9, 1), (0, 1), (3, 2))))
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
656
        self.assertEqual(l[0], (1, '1'))
657
        self.assertEqual(l[1], (9, '9'))
658
        self.assertEqual(l[2], (0, '0'))
659
        self.assertEqual(l[3], (3, '34'))
660
2000.3.9 by v.ladeuil+lp at free
The tests that would have help avoid bug #73948 and all that mess :)
661
    def test_readv_invalid_ranges(self):
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
662
        server = self.get_readonly_server()
663
        t = self._transport(server.get_url())
664
665
        # This is intentionally reading off the end of the file
666
        # since we are sure that it cannot get there
2000.3.9 by v.ladeuil+lp at free
The tests that would have help avoid bug #73948 and all that mess :)
667
        self.assertListRaises((errors.InvalidRange, errors.ShortReadvError,),
2004.1.30 by v.ladeuil+lp at free
Fix #62276 and #62029 by providing a more robust http range handling.
668
                              t.readv, 'a', [(1,1), (8,10)])
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
669
670
        # This is trying to seek past the end of the file, it should
671
        # also raise a special error
2000.3.9 by v.ladeuil+lp at free
The tests that would have help avoid bug #73948 and all that mess :)
672
        self.assertListRaises((errors.InvalidRange, errors.ShortReadvError,),
2004.1.30 by v.ladeuil+lp at free
Fix #62276 and #62029 by providing a more robust http range handling.
673
                              t.readv, 'a', [(12,2)])
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
674
675
676
class TestSingleRangeRequestServer(TestRangeRequestServer):
677
    """Test readv against a server which accept only single range requests"""
678
679
    def create_transport_readonly_server(self):
680
        return HttpServer(SingleRangeRequestHandler)
681
682
683
class TestSingleRangeRequestServer_urllib(TestSingleRangeRequestServer,
684
                                          TestCaseWithWebserver):
685
    """Tests single range requests accepting server for urllib implementation"""
686
687
    _transport = HttpTransport_urllib
688
689
690
class TestSingleRangeRequestServer_pycurl(TestWithTransport_pycurl,
691
                                          TestSingleRangeRequestServer,
692
                                          TestCaseWithWebserver):
693
    """Tests single range requests accepting server for pycurl implementation"""
694
695
696
class TestNoRangeRequestServer(TestRangeRequestServer):
697
    """Test readv against a server which do not accept range requests"""
698
699
    def create_transport_readonly_server(self):
700
        return HttpServer(NoRangeRequestHandler)
701
702
703
class TestNoRangeRequestServer_urllib(TestNoRangeRequestServer,
704
                                      TestCaseWithWebserver):
705
    """Tests range requests refusing server for urllib implementation"""
706
707
    _transport = HttpTransport_urllib
708
709
710
class TestNoRangeRequestServer_pycurl(TestWithTransport_pycurl,
711
                               TestNoRangeRequestServer,
712
                               TestCaseWithWebserver):
713
    """Tests range requests refusing server for pycurl implementation"""
714
715
2273.2.2 by v.ladeuil+lp at free
Really fix bug #83954, with tests.
716
class TestHttpProxyWhiteBox(TestCase):
2298.7.1 by Vincent Ladeuil
Fix bug #87765: proxy env variables without scheme should cause
717
    """Whitebox test proxy http authorization.
718
2420.1.3 by Vincent Ladeuil
Implement http proxy basic authentication.
719
    Only the urllib implementation is tested here.
2298.7.1 by Vincent Ladeuil
Fix bug #87765: proxy env variables without scheme should cause
720
    """
2273.2.2 by v.ladeuil+lp at free
Really fix bug #83954, with tests.
721
722
    def setUp(self):
723
        TestCase.setUp(self)
724
        self._old_env = {}
725
726
    def tearDown(self):
727
        self._restore_env()
728
729
    def _install_env(self, env):
730
        for name, value in env.iteritems():
2420.1.2 by Vincent Ladeuil
Define tests for http proxy basic authentication. They fail.
731
            self._old_env[name] = osutils.set_or_unset_env(name, value)
2273.2.2 by v.ladeuil+lp at free
Really fix bug #83954, with tests.
732
733
    def _restore_env(self):
734
        for name, value in self._old_env.iteritems():
735
            osutils.set_or_unset_env(name, value)
736
737
    def _proxied_request(self):
2420.1.3 by Vincent Ladeuil
Implement http proxy basic authentication.
738
        handler = ProxyHandler(PasswordManager())
739
        request = Request('GET','http://baz/buzzle')
2273.2.2 by v.ladeuil+lp at free
Really fix bug #83954, with tests.
740
        handler.set_proxy(request, 'http')
741
        return request
742
743
    def test_empty_user(self):
744
        self._install_env({'http_proxy': 'http://bar.com'})
745
        request = self._proxied_request()
746
        self.assertFalse(request.headers.has_key('Proxy-authorization'))
747
2298.7.1 by Vincent Ladeuil
Fix bug #87765: proxy env variables without scheme should cause
748
    def test_invalid_proxy(self):
749
        """A proxy env variable without scheme"""
750
        self._install_env({'http_proxy': 'host:1234'})
751
        self.assertRaises(errors.InvalidURL, self._proxied_request)
2273.2.2 by v.ladeuil+lp at free
Really fix bug #83954, with tests.
752
753
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
754
class TestProxyHttpServer(object):
755
    """Tests proxy server.
756
757
    This MUST be used by daughter classes that also inherit from
758
    TestCaseWithTwoWebservers.
759
760
    We can't inherit directly from TestCaseWithTwoWebservers or
761
    the test framework will try to create an instance which
762
    cannot run, its implementation being incomplete.
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
763
764
    Be aware that we do not setup a real proxy here. Instead, we
2167.3.7 by v.ladeuil+lp at free
Typos corrected.
765
    check that the *connection* goes through the proxy by serving
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
766
    different content (the faked proxy server append '-proxied'
767
    to the file names).
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
768
    """
769
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
770
    # FIXME: We don't have an https server available, so we don't
771
    # test https connections.
772
2273.2.1 by v.ladeuil+lp at free
Fix bug #83954.
773
    # FIXME: Once the test suite is better fitted to test
774
    # authorization schemes, test proxy authorizations too (see
775
    # bug #83954).
776
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
777
    def setUp(self):
778
        TestCaseWithTwoWebservers.setUp(self)
779
        self.build_tree_contents([('foo', 'contents of foo\n'),
780
                                  ('foo-proxied', 'proxied contents of foo\n')])
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
781
        # Let's setup some attributes for tests
782
        self.server = self.get_readonly_server()
2420.1.2 by Vincent Ladeuil
Define tests for http proxy basic authentication. They fail.
783
        self.proxy_address = '%s:%d' % (self.server.host, self.server.port)
2298.7.1 by Vincent Ladeuil
Fix bug #87765: proxy env variables without scheme should cause
784
        self.no_proxy_host = self.proxy_address
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
785
        # The secondary server is the proxy
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
786
        self.proxy = self.get_secondary_server()
787
        self.proxy_url = self.proxy.get_url()
788
        self._old_env = {}
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
789
790
    def create_transport_secondary_server(self):
791
        """Creates an http server that will serve files with
792
        '-proxied' appended to their names.
793
        """
2420.1.9 by Vincent Ladeuil
Refactor proxy and auth test classes. Tests failing for digest auth.
794
        return ProxyServer()
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
795
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
796
    def _install_env(self, env):
797
        for name, value in env.iteritems():
2420.1.2 by Vincent Ladeuil
Define tests for http proxy basic authentication. They fail.
798
            self._old_env[name] = osutils.set_or_unset_env(name, value)
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
799
800
    def _restore_env(self):
801
        for name, value in self._old_env.iteritems():
802
            osutils.set_or_unset_env(name, value)
803
804
    def proxied_in_env(self, env):
805
        self._install_env(env)
806
        url = self.server.get_url()
807
        t = self._transport(url)
808
        try:
809
            self.assertEqual(t.get('foo').read(), 'proxied contents of foo\n')
810
        finally:
811
            self._restore_env()
812
813
    def not_proxied_in_env(self, env):
814
        self._install_env(env)
815
        url = self.server.get_url()
816
        t = self._transport(url)
817
        try:
818
            self.assertEqual(t.get('foo').read(), 'contents of foo\n')
819
        finally:
820
            self._restore_env()
821
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
822
    def test_http_proxy(self):
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
823
        self.proxied_in_env({'http_proxy': self.proxy_url})
824
825
    def test_HTTP_PROXY(self):
826
        self.proxied_in_env({'HTTP_PROXY': self.proxy_url})
827
828
    def test_all_proxy(self):
829
        self.proxied_in_env({'all_proxy': self.proxy_url})
830
831
    def test_ALL_PROXY(self):
832
        self.proxied_in_env({'ALL_PROXY': self.proxy_url})
833
834
    def test_http_proxy_with_no_proxy(self):
835
        self.not_proxied_in_env({'http_proxy': self.proxy_url,
836
                                 'no_proxy': self.no_proxy_host})
837
838
    def test_HTTP_PROXY_with_NO_PROXY(self):
839
        self.not_proxied_in_env({'HTTP_PROXY': self.proxy_url,
840
                                 'NO_PROXY': self.no_proxy_host})
841
842
    def test_all_proxy_with_no_proxy(self):
843
        self.not_proxied_in_env({'all_proxy': self.proxy_url,
844
                                 'no_proxy': self.no_proxy_host})
845
846
    def test_ALL_PROXY_with_NO_PROXY(self):
847
        self.not_proxied_in_env({'ALL_PROXY': self.proxy_url,
848
                                 'NO_PROXY': self.no_proxy_host})
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
849
2298.7.1 by Vincent Ladeuil
Fix bug #87765: proxy env variables without scheme should cause
850
    def test_http_proxy_without_scheme(self):
851
        self.assertRaises(errors.InvalidURL,
852
                          self.proxied_in_env,
853
                          {'http_proxy': self.proxy_address})
854
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
855
856
class TestProxyHttpServer_urllib(TestProxyHttpServer,
857
                                 TestCaseWithTwoWebservers):
858
    """Tests proxy server for urllib implementation"""
859
860
    _transport = HttpTransport_urllib
861
862
863
class TestProxyHttpServer_pycurl(TestWithTransport_pycurl,
864
                                 TestProxyHttpServer,
865
                                 TestCaseWithTwoWebservers):
866
    """Tests proxy server for pycurl implementation"""
867
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
868
    def setUp(self):
869
        TestProxyHttpServer.setUp(self)
870
        # Oh my ! pycurl does not check for the port as part of
871
        # no_proxy :-( So we just test the host part
872
        self.no_proxy_host = 'localhost'
873
874
    def test_HTTP_PROXY(self):
875
        # pycurl do not check HTTP_PROXY for security reasons
876
        # (for use in a CGI context that we do not care
877
        # about. Should we ?)
878
        raise TestSkipped()
879
880
    def test_HTTP_PROXY_with_NO_PROXY(self):
881
        raise TestSkipped()
2183.1.1 by Aaron Bentley
Make test HTTP server's range handling more spec-compliant (Vincent Ladeuil)
882
2298.7.1 by Vincent Ladeuil
Fix bug #87765: proxy env variables without scheme should cause
883
    def test_http_proxy_without_scheme(self):
884
        # pycurl *ignores* invalid proxy env variables. If that
885
        # ever change in the future, this test will fail
886
        # indicating that pycurl do not ignore anymore such
887
        # variables.
888
        self.not_proxied_in_env({'http_proxy': self.proxy_address})
889
2183.1.1 by Aaron Bentley
Make test HTTP server's range handling more spec-compliant (Vincent Ladeuil)
890
2182.2.2 by v.ladeuil+lp at free
Thanks again to Aaron, the http server RFC2616 compliance
891
class TestRanges(object):
892
    """Test the Range header in GET methods..
893
894
    This MUST be used by daughter classes that also inherit from
895
    TestCaseWithWebserver.
896
897
    We can't inherit directly from TestCaseWithWebserver or the
898
    test framework will try to create an instance which cannot
899
    run, its implementation being incomplete.
900
    """
901
902
    def setUp(self):
903
        TestCaseWithWebserver.setUp(self)
904
        self.build_tree_contents([('a', '0123456789')],)
905
        server = self.get_readonly_server()
906
        self.transport = self._transport(server.get_url())
907
908
    def _file_contents(self, relpath, ranges, tail_amount=0):
909
         code, data = self.transport._get(relpath, ranges)
910
         self.assertTrue(code in (200, 206),'_get returns: %d' % code)
911
         for start, end in ranges:
912
             data.seek(start)
913
             yield data.read(end - start + 1)
914
915
    def _file_tail(self, relpath, tail_amount):
916
         code, data = self.transport._get(relpath, [], tail_amount)
917
         self.assertTrue(code in (200, 206),'_get returns: %d' % code)
918
         data.seek(-tail_amount + 1, 2)
919
         return data.read(tail_amount)
920
921
    def test_range_header(self):
922
        # Valid ranges
923
        map(self.assertEqual,['0', '234'],
924
            list(self._file_contents('a', [(0,0), (2,4)])),)
925
        # Tail
926
        self.assertEqual('789', self._file_tail('a', 3))
927
        # Syntactically invalid range
928
        self.assertRaises(errors.InvalidRange,
929
                          self.transport._get, 'a', [(4, 3)])
930
        # Semantically invalid range
931
        self.assertRaises(errors.InvalidRange,
932
                          self.transport._get, 'a', [(42, 128)])
933
934
935
class TestRanges_urllib(TestRanges, TestCaseWithWebserver):
936
    """Test the Range header in GET methods for urllib implementation"""
937
938
    _transport = HttpTransport_urllib
939
940
941
class TestRanges_pycurl(TestWithTransport_pycurl,
942
                        TestRanges,
943
                        TestCaseWithWebserver):
944
    """Test the Range header in GET methods for pycurl implementation"""
2164.2.13 by v.ladeuil+lp at free
Add tests for redirection. Preserve transport decorations.
945
946
2164.2.16 by Vincent Ladeuil
Add tests.
947
class TestHTTPRedirections(object):
948
    """Test redirection between http servers.
2164.2.13 by v.ladeuil+lp at free
Add tests for redirection. Preserve transport decorations.
949
950
    This MUST be used by daughter classes that also inherit from
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
951
    TestCaseWithRedirectedWebserver.
2164.2.13 by v.ladeuil+lp at free
Add tests for redirection. Preserve transport decorations.
952
953
    We can't inherit directly from TestCaseWithTwoWebservers or the
954
    test framework will try to create an instance which cannot
955
    run, its implementation being incomplete. 
956
    """
957
958
    def create_transport_secondary_server(self):
959
        """Create the secondary server redirecting to the primary server"""
2164.2.16 by Vincent Ladeuil
Add tests.
960
        new = self.get_readonly_server()
961
962
        redirecting = HTTPServerRedirecting()
963
        redirecting.redirect_to(new.host, new.port)
964
        return redirecting
2164.2.13 by v.ladeuil+lp at free
Add tests for redirection. Preserve transport decorations.
965
966
    def setUp(self):
2164.2.16 by Vincent Ladeuil
Add tests.
967
        super(TestHTTPRedirections, self).setUp()
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
968
        self.build_tree_contents([('a', '0123456789'),
969
                                  ('bundle',
970
                                  '# Bazaar revision bundle v0.9\n#\n')
971
                                  ],)
972
973
        self.old_transport = self._transport(self.old_server.get_url())
2164.2.13 by v.ladeuil+lp at free
Add tests for redirection. Preserve transport decorations.
974
975
    def test_redirected(self):
2164.2.16 by Vincent Ladeuil
Add tests.
976
        self.assertRaises(errors.RedirectRequested, self.old_transport.get, 'a')
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
977
        t = self._transport(self.new_server.get_url())
978
        self.assertEqual('0123456789', t.get('a').read())
979
980
    def test_read_redirected_bundle_from_url(self):
981
        from bzrlib.bundle import read_bundle_from_url
982
        url = self.old_transport.abspath('bundle')
983
        bundle = read_bundle_from_url(url)
984
        # If read_bundle_from_url was successful we get an empty bundle
985
        self.assertEqual([], bundle.revisions)
2164.2.16 by Vincent Ladeuil
Add tests.
986
987
988
class TestHTTPRedirections_urllib(TestHTTPRedirections,
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
989
                                  TestCaseWithRedirectedWebserver):
2164.2.13 by v.ladeuil+lp at free
Add tests for redirection. Preserve transport decorations.
990
    """Tests redirections for urllib implementation"""
991
992
    _transport = HttpTransport_urllib
993
2164.2.16 by Vincent Ladeuil
Add tests.
994
995
996
class TestHTTPRedirections_pycurl(TestWithTransport_pycurl,
997
                                  TestHTTPRedirections,
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
998
                                  TestCaseWithRedirectedWebserver):
2164.2.16 by Vincent Ladeuil
Add tests.
999
    """Tests redirections for pycurl implementation"""
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1000
1001
2420.1.3 by Vincent Ladeuil
Implement http proxy basic authentication.
1002
class RedirectedRequest(Request):
2164.2.29 by Vincent Ladeuil
Test the http redirection at the request level even if it's not
1003
    """Request following redirections"""
1004
2420.1.3 by Vincent Ladeuil
Implement http proxy basic authentication.
1005
    init_orig = Request.__init__
2164.2.29 by Vincent Ladeuil
Test the http redirection at the request level even if it's not
1006
1007
    def __init__(self, method, url, *args, **kwargs):
1008
        RedirectedRequest.init_orig(self, method, url, args, kwargs)
1009
        self.follow_redirections = True
1010
1011
1012
class TestHTTPSilentRedirections_urllib(TestCaseWithRedirectedWebserver):
1013
    """Test redirections provided by urllib.
1014
1015
    http implementations do not redirect silently anymore (they
1016
    do not redirect at all in fact). The mechanism is still in
1017
    place at the _urllib2_wrappers.Request level and these tests
1018
    exercise it.
1019
1020
    For the pycurl implementation
1021
    the redirection have been deleted as we may deprecate pycurl
1022
    and I have no place to keep a working implementation.
1023
    -- vila 20070212
1024
    """
1025
1026
    _transport = HttpTransport_urllib
1027
1028
    def setUp(self):
1029
        super(TestHTTPSilentRedirections_urllib, self).setUp()
1030
        self.setup_redirected_request()
1031
        self.addCleanup(self.cleanup_redirected_request)
1032
        self.build_tree_contents([('a','a'),
1033
                                  ('1/',),
1034
                                  ('1/a', 'redirected once'),
1035
                                  ('2/',),
1036
                                  ('2/a', 'redirected twice'),
1037
                                  ('3/',),
1038
                                  ('3/a', 'redirected thrice'),
1039
                                  ('4/',),
1040
                                  ('4/a', 'redirected 4 times'),
1041
                                  ('5/',),
1042
                                  ('5/a', 'redirected 5 times'),
1043
                                  ],)
1044
1045
        self.old_transport = self._transport(self.old_server.get_url())
1046
1047
    def setup_redirected_request(self):
1048
        self.original_class = _urllib2_wrappers.Request
1049
        _urllib2_wrappers.Request = RedirectedRequest
1050
1051
    def cleanup_redirected_request(self):
1052
        _urllib2_wrappers.Request = self.original_class
1053
1054
    def create_transport_secondary_server(self):
1055
        """Create the secondary server, redirections are defined in the tests"""
1056
        return HTTPServerRedirecting()
1057
1058
    def test_one_redirection(self):
1059
        t = self.old_transport
1060
1061
        req = RedirectedRequest('GET', t.abspath('a'))
1062
        req.follow_redirections = True
1063
        new_prefix = 'http://%s:%s' % (self.new_server.host,
1064
                                       self.new_server.port)
1065
        self.old_server.redirections = \
1066
            [('(.*)', r'%s/1\1' % (new_prefix), 301),]
1067
        self.assertEquals('redirected once',t._perform(req).read())
1068
1069
    def test_five_redirections(self):
1070
        t = self.old_transport
1071
1072
        req = RedirectedRequest('GET', t.abspath('a'))
1073
        req.follow_redirections = True
1074
        old_prefix = 'http://%s:%s' % (self.old_server.host,
1075
                                       self.old_server.port)
1076
        new_prefix = 'http://%s:%s' % (self.new_server.host,
1077
                                       self.new_server.port)
1078
        self.old_server.redirections = \
1079
            [('/1(.*)', r'%s/2\1' % (old_prefix), 302),
1080
             ('/2(.*)', r'%s/3\1' % (old_prefix), 303),
1081
             ('/3(.*)', r'%s/4\1' % (old_prefix), 307),
1082
             ('/4(.*)', r'%s/5\1' % (new_prefix), 301),
1083
             ('(/[^/]+)', r'%s/1\1' % (old_prefix), 301),
1084
             ]
1085
        self.assertEquals('redirected 5 times',t._perform(req).read())
1086
1087
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1088
class TestDoCatchRedirections(TestCaseWithRedirectedWebserver):
1089
    """Test transport.do_catching_redirections.
1090
1091
    We arbitrarily choose to use urllib transports
1092
    """
1093
1094
    _transport = HttpTransport_urllib
1095
1096
    def setUp(self):
1097
        super(TestDoCatchRedirections, self).setUp()
1098
        self.build_tree_contents([('a', '0123456789'),],)
1099
1100
        self.old_transport = self._transport(self.old_server.get_url())
1101
1102
    def get_a(self, transport):
1103
        return transport.get('a')
1104
1105
    def test_no_redirection(self):
1106
        t = self._transport(self.new_server.get_url())
1107
1108
        # We use None for redirected so that we fail if redirected
1109
        self.assertEquals('0123456789',
1110
                          do_catching_redirections(self.get_a, t, None).read())
1111
1112
    def test_one_redirection(self):
1113
        self.redirections = 0
1114
1115
        def redirected(transport, exception, redirection_notice):
1116
            self.redirections += 1
1117
            dir, file = urlutils.split(exception.target)
1118
            return self._transport(dir)
1119
1120
        self.assertEquals('0123456789',
1121
                          do_catching_redirections(self.get_a,
1122
                                                   self.old_transport,
1123
                                                   redirected
1124
                                                   ).read())
1125
        self.assertEquals(1, self.redirections)
1126
1127
    def test_redirection_loop(self):
1128
1129
        def redirected(transport, exception, redirection_notice):
1130
            # By using the redirected url as a base dir for the
1131
            # *old* transport, we create a loop: a => a/a =>
1132
            # a/a/a
1133
            return self.old_transport.clone(exception.target)
1134
1135
        self.assertRaises(errors.TooManyRedirections, do_catching_redirections,
1136
                          self.get_a, self.old_transport, redirected)
2363.4.5 by Vincent Ladeuil
Add white box tests for basic HTTP auth.
1137
1138
2420.1.9 by Vincent Ladeuil
Refactor proxy and auth test classes. Tests failing for digest auth.
1139
class TestAuth(object):
2420.1.2 by Vincent Ladeuil
Define tests for http proxy basic authentication. They fail.
1140
    """Test some authentication scheme specified by daughter class.
1141
1142
    This MUST be used by daughter classes that also inherit from
1143
    either TestCaseWithWebserver or TestCaseWithTwoWebservers.
1144
    """
2363.4.5 by Vincent Ladeuil
Add white box tests for basic HTTP auth.
1145
2363.4.7 by Vincent Ladeuil
Deeper tests, prepare the auth setting that will avoid the
1146
    def setUp(self):
2420.1.2 by Vincent Ladeuil
Define tests for http proxy basic authentication. They fail.
1147
        """Set up the test environment
1148
1149
        Daughter classes should set up their own environment
1150
        (including self.server) and explicitely call this
1151
        method. This is needed because we want to reuse the same
1152
        tests for proxy and no-proxy accesses which have
1153
        different ways of setting self.server.
1154
        """
2363.4.8 by Vincent Ladeuil
Implement a basic auth HTTP server, rewrite tests accordingly.
1155
        self.build_tree_contents([('a', 'contents of a\n'),
1156
                                  ('b', 'contents of b\n'),])
2363.4.12 by Vincent Ladeuil
Take jam's review comments into account. Fix typos, give better
1157
        self.old_factory = ui.ui_factory
2420.1.20 by Vincent Ladeuil
Fix test failure on pqm.
1158
        self.old_stdout = sys.stdout
1159
        sys.stdout = StringIOWrapper()
2363.4.10 by Vincent Ladeuil
Complete tests.
1160
        self.addCleanup(self.restoreUIFactory)
1161
1162
    def restoreUIFactory(self):
2363.4.12 by Vincent Ladeuil
Take jam's review comments into account. Fix typos, give better
1163
        ui.ui_factory = self.old_factory
2420.1.20 by Vincent Ladeuil
Fix test failure on pqm.
1164
        sys.stdout = self.old_stdout
2363.4.10 by Vincent Ladeuil
Complete tests.
1165
1166
    def get_user_url(self, user=None, password=None):
2363.4.8 by Vincent Ladeuil
Implement a basic auth HTTP server, rewrite tests accordingly.
1167
        """Build an url embedding user and password"""
1168
        url = '%s://' % self.server._url_protocol
1169
        if user is not None:
1170
            url += user
1171
            if password is not None:
1172
                url += ':' + password
1173
            url += '@'
1174
        url += '%s:%s/' % (self.server.host, self.server.port)
1175
        return url
2363.4.5 by Vincent Ladeuil
Add white box tests for basic HTTP auth.
1176
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1177
    def test_no_user(self):
1178
        self.server.add_user('joe', 'foo')
1179
        t = self.get_user_transport()
1180
        self.assertRaises(errors.InvalidHttpResponse, t.get, 'a')
1181
        # Only one 'Authentication Required' error should occur
1182
        self.assertEqual(1, self.server.auth_required_errors)
1183
2363.4.5 by Vincent Ladeuil
Add white box tests for basic HTTP auth.
1184
    def test_empty_pass(self):
2363.4.8 by Vincent Ladeuil
Implement a basic auth HTTP server, rewrite tests accordingly.
1185
        self.server.add_user('joe', '')
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1186
        t = self.get_user_transport('joe', '')
2363.4.10 by Vincent Ladeuil
Complete tests.
1187
        self.assertEqual('contents of a\n', t.get('a').read())
2420.1.4 by Vincent Ladeuil
Add test checking the number of roundtrips due to 401 or 407 errors.
1188
        # Only one 'Authentication Required' error should occur
1189
        self.assertEqual(1, self.server.auth_required_errors)
2363.4.5 by Vincent Ladeuil
Add white box tests for basic HTTP auth.
1190
1191
    def test_user_pass(self):
2363.4.8 by Vincent Ladeuil
Implement a basic auth HTTP server, rewrite tests accordingly.
1192
        self.server.add_user('joe', 'foo')
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1193
        t = self.get_user_transport('joe', 'foo')
2363.4.10 by Vincent Ladeuil
Complete tests.
1194
        self.assertEqual('contents of a\n', t.get('a').read())
2420.1.4 by Vincent Ladeuil
Add test checking the number of roundtrips due to 401 or 407 errors.
1195
        # Only one 'Authentication Required' error should occur
1196
        self.assertEqual(1, self.server.auth_required_errors)
2363.4.10 by Vincent Ladeuil
Complete tests.
1197
2363.4.12 by Vincent Ladeuil
Take jam's review comments into account. Fix typos, give better
1198
    def test_unknown_user(self):
1199
        self.server.add_user('joe', 'foo')
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1200
        t = self.get_user_transport('bill', 'foo')
2363.4.12 by Vincent Ladeuil
Take jam's review comments into account. Fix typos, give better
1201
        self.assertRaises(errors.InvalidHttpResponse, t.get, 'a')
2420.1.4 by Vincent Ladeuil
Add test checking the number of roundtrips due to 401 or 407 errors.
1202
        # Two 'Authentication Required' errors should occur (the
1203
        # initial 'who are you' and 'I don't know you, who are
1204
        # you').
1205
        self.assertEqual(2, self.server.auth_required_errors)
2363.4.12 by Vincent Ladeuil
Take jam's review comments into account. Fix typos, give better
1206
2363.4.10 by Vincent Ladeuil
Complete tests.
1207
    def test_wrong_pass(self):
1208
        self.server.add_user('joe', 'foo')
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1209
        t = self.get_user_transport('joe', 'bar')
2363.4.10 by Vincent Ladeuil
Complete tests.
1210
        self.assertRaises(errors.InvalidHttpResponse, t.get, 'a')
2420.1.16 by Vincent Ladeuil
Handle nonce changes. Fix a nasty bug breaking the auth parameters sharing.
1211
        # Two 'Authentication Required' errors should occur (the
2420.1.4 by Vincent Ladeuil
Add test checking the number of roundtrips due to 401 or 407 errors.
1212
        # initial 'who are you' and 'this is not you, who are you')
1213
        self.assertEqual(2, self.server.auth_required_errors)
2363.4.10 by Vincent Ladeuil
Complete tests.
1214
1215
    def test_prompt_for_password(self):
1216
        self.server.add_user('joe', 'foo')
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1217
        t = self.get_user_transport('joe', None)
2420.1.20 by Vincent Ladeuil
Fix test failure on pqm.
1218
        ui.ui_factory = TestUIFactory(stdin='foo\n')
2363.4.10 by Vincent Ladeuil
Complete tests.
1219
        self.assertEqual('contents of a\n',t.get('a').read())
1220
        # stdin should be empty
2363.4.12 by Vincent Ladeuil
Take jam's review comments into account. Fix typos, give better
1221
        self.assertEqual('', ui.ui_factory.stdin.readline())
2363.4.10 by Vincent Ladeuil
Complete tests.
1222
        # And we shouldn't prompt again for a different request
1223
        # against the same transport.
1224
        self.assertEqual('contents of b\n',t.get('b').read())
2363.4.12 by Vincent Ladeuil
Take jam's review comments into account. Fix typos, give better
1225
        t2 = t.clone()
1226
        # And neither against a clone
1227
        self.assertEqual('contents of b\n',t2.get('b').read())
2420.1.4 by Vincent Ladeuil
Add test checking the number of roundtrips due to 401 or 407 errors.
1228
        # Only one 'Authentication Required' error should occur
1229
        self.assertEqual(1, self.server.auth_required_errors)
1230
2420.1.2 by Vincent Ladeuil
Define tests for http proxy basic authentication. They fail.
1231
2420.1.9 by Vincent Ladeuil
Refactor proxy and auth test classes. Tests failing for digest auth.
1232
class TestHTTPAuth(TestAuth):
1233
    """Test HTTP authentication schemes.
1234
1235
    Daughter classes MUST inherit from TestCaseWithWebserver too.
1236
    """
1237
2420.1.2 by Vincent Ladeuil
Define tests for http proxy basic authentication. They fail.
1238
    _auth_header = 'Authorization'
1239
1240
    def setUp(self):
1241
        TestCaseWithWebserver.setUp(self)
1242
        self.server = self.get_readonly_server()
2420.1.9 by Vincent Ladeuil
Refactor proxy and auth test classes. Tests failing for digest auth.
1243
        TestAuth.setUp(self)
2420.1.2 by Vincent Ladeuil
Define tests for http proxy basic authentication. They fail.
1244
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1245
    def get_user_transport(self, user=None, password=None):
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1246
        return self._transport(self.get_user_url(user, password))
1247
2420.1.2 by Vincent Ladeuil
Define tests for http proxy basic authentication. They fail.
1248
2420.1.9 by Vincent Ladeuil
Refactor proxy and auth test classes. Tests failing for digest auth.
1249
class TestProxyAuth(TestAuth):
1250
    """Test proxy authentication schemes.
2420.1.2 by Vincent Ladeuil
Define tests for http proxy basic authentication. They fail.
1251
2420.1.9 by Vincent Ladeuil
Refactor proxy and auth test classes. Tests failing for digest auth.
1252
    Daughter classes MUST also inherit from TestCaseWithWebserver.
1253
    """
2420.1.2 by Vincent Ladeuil
Define tests for http proxy basic authentication. They fail.
1254
    _auth_header = 'Proxy-authorization'
1255
1256
    def setUp(self):
2420.1.9 by Vincent Ladeuil
Refactor proxy and auth test classes. Tests failing for digest auth.
1257
        TestCaseWithWebserver.setUp(self)
2420.1.2 by Vincent Ladeuil
Define tests for http proxy basic authentication. They fail.
1258
        self.server = self.get_readonly_server()
1259
        self._old_env = {}
1260
        self.addCleanup(self._restore_env)
2420.1.9 by Vincent Ladeuil
Refactor proxy and auth test classes. Tests failing for digest auth.
1261
        TestAuth.setUp(self)
2420.1.2 by Vincent Ladeuil
Define tests for http proxy basic authentication. They fail.
1262
        # Override the contents to avoid false positives
1263
        self.build_tree_contents([('a', 'not proxied contents of a\n'),
1264
                                  ('b', 'not proxied contents of b\n'),
1265
                                  ('a-proxied', 'contents of a\n'),
1266
                                  ('b-proxied', 'contents of b\n'),
1267
                                  ])
1268
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1269
    def get_user_transport(self, user=None, password=None):
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1270
        self._install_env({'all_proxy': self.get_user_url(user, password)})
1271
        return self._transport(self.server.get_url())
2420.1.9 by Vincent Ladeuil
Refactor proxy and auth test classes. Tests failing for digest auth.
1272
1273
    def _install_env(self, env):
1274
        for name, value in env.iteritems():
1275
            self._old_env[name] = osutils.set_or_unset_env(name, value)
1276
1277
    def _restore_env(self):
1278
        for name, value in self._old_env.iteritems():
1279
            osutils.set_or_unset_env(name, value)
1280
1281
1282
class TestHTTPBasicAuth(TestHTTPAuth, TestCaseWithWebserver):
1283
    """Test http basic authentication scheme"""
1284
1285
    _transport = HttpTransport_urllib
1286
1287
    def create_transport_readonly_server(self):
1288
        return HTTPBasicAuthServer()
1289
1290
1291
class TestHTTPProxyBasicAuth(TestProxyAuth, TestCaseWithWebserver):
1292
    """Test proxy basic authentication scheme"""
1293
1294
    _transport = HttpTransport_urllib
1295
1296
    def create_transport_readonly_server(self):
1297
        return ProxyBasicAuthServer()
1298
1299
2420.1.15 by Vincent Ladeuil
Check digest robustness.
1300
class TestDigestAuth(object):
1301
    """Digest Authentication specific tests"""
1302
1303
    def test_changing_nonce(self):
1304
        self.server.add_user('joe', 'foo')
1305
        t = self.get_user_transport('joe', 'foo')
1306
        self.assertEqual('contents of a\n', t.get('a').read())
1307
        self.assertEqual('contents of b\n', t.get('b').read())
1308
        # Only one 'Authentication Required' error should have
1309
        # occured so far
1310
        self.assertEqual(1, self.server.auth_required_errors)
2420.1.16 by Vincent Ladeuil
Handle nonce changes. Fix a nasty bug breaking the auth parameters sharing.
1311
        # The server invalidates the current nonce
1312
        self.server.auth_nonce = self.server.auth_nonce + '. No, now!'
2420.1.15 by Vincent Ladeuil
Check digest robustness.
1313
        self.assertEqual('contents of a\n', t.get('a').read())
2420.1.16 by Vincent Ladeuil
Handle nonce changes. Fix a nasty bug breaking the auth parameters sharing.
1314
        # Two 'Authentication Required' errors should occur (the
2420.1.15 by Vincent Ladeuil
Check digest robustness.
1315
        # initial 'who are you' and a second 'who are you' with the new nonce)
1316
        self.assertEqual(2, self.server.auth_required_errors)
1317
1318
1319
class TestHTTPDigestAuth(TestHTTPAuth, TestDigestAuth, TestCaseWithWebserver):
2420.1.9 by Vincent Ladeuil
Refactor proxy and auth test classes. Tests failing for digest auth.
1320
    """Test http digest authentication scheme"""
1321
1322
    _transport = HttpTransport_urllib
1323
1324
    def create_transport_readonly_server(self):
1325
        return HTTPDigestAuthServer()
1326
1327
2420.1.15 by Vincent Ladeuil
Check digest robustness.
1328
class TestHTTPProxyDigestAuth(TestProxyAuth, TestDigestAuth,
1329
                              TestCaseWithWebserver):
2420.1.9 by Vincent Ladeuil
Refactor proxy and auth test classes. Tests failing for digest auth.
1330
    """Test proxy digest authentication scheme"""
1331
1332
    _transport = HttpTransport_urllib
1333
1334
    def create_transport_readonly_server(self):
1335
        return ProxyDigestAuthServer()
1336