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