/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
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
23
import os
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
24
import select
2000.2.2 by John Arbash Meinel
Update the urllib.has test.
25
import socket
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
26
import threading
2000.2.2 by John Arbash Meinel
Update the urllib.has test.
27
1553.1.2 by James Henstridge
Add a test to make sure the user-agent header is being sent correctly.
28
import bzrlib
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
29
from bzrlib import (
30
    errors,
31
    osutils,
32
    urlutils,
33
    )
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
34
from bzrlib.tests import (
35
    TestCase,
36
    TestSkipped,
37
    )
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
38
from bzrlib.tests.HttpServer import (
39
    HttpServer,
40
    HttpServer_PyCurl,
41
    HttpServer_urllib,
42
    )
43
from bzrlib.tests.HTTPTestUtil import (
44
    BadProtocolRequestHandler,
45
    BadStatusRequestHandler,
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
46
    FakeProxyRequestHandler,
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
47
    ForbiddenRequestHandler,
2164.2.13 by v.ladeuil+lp at free
Add tests for redirection. Preserve transport decorations.
48
    HTTPServerRedirecting,
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
49
    InvalidStatusRequestHandler,
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
50
    NoRangeRequestHandler,
51
    SingleRangeRequestHandler,
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
52
    TestCaseWithRedirectedWebserver,
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
53
    TestCaseWithTwoWebservers,
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
54
    TestCaseWithWebserver,
55
    WallRequestHandler,
56
    )
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
57
from bzrlib.transport import (
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
58
    do_catching_redirections,
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
59
    get_transport,
60
    Transport,
61
    )
2004.3.3 by vila
Better (but still incomplete) design for bogus servers.
62
from bzrlib.transport.http import (
63
    extract_auth,
64
    HttpTransportBase,
65
    )
1540.3.26 by Martin Pool
[merge] bzr.dev; pycurl not updated for readv yet
66
from bzrlib.transport.http._urllib import HttpTransport_urllib
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
67
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
68
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
69
class FakeManager(object):
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
70
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
71
    def __init__(self):
72
        self.credentials = []
2004.3.1 by vila
Test ConnectionError exceptions.
73
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
74
    def add_password(self, realm, host, username, password):
75
        self.credentials.append([realm, host, username, password])
76
1553.1.2 by James Henstridge
Add a test to make sure the user-agent header is being sent correctly.
77
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
78
class RecordingServer(object):
79
    """A fake HTTP server.
80
    
81
    It records the bytes sent to it, and replies with a 200.
82
    """
83
84
    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.
85
        """Constructor.
86
87
        :type expect_body_tail: str
88
        :param expect_body_tail: a reply won't be sent until this string is
89
            received.
90
        """
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
91
        self._expect_body_tail = expect_body_tail
92
        self.host = None
93
        self.port = None
94
        self.received_bytes = ''
95
96
    def setUp(self):
97
        self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
98
        self._sock.bind(('127.0.0.1', 0))
99
        self.host, self.port = self._sock.getsockname()
100
        self._ready = threading.Event()
101
        self._thread = threading.Thread(target=self._accept_read_and_reply)
102
        self._thread.setDaemon(True)
103
        self._thread.start()
104
        self._ready.wait(5)
105
106
    def _accept_read_and_reply(self):
107
        self._sock.listen(1)
108
        self._ready.set()
109
        self._sock.settimeout(5)
110
        try:
111
            conn, address = self._sock.accept()
112
            # On win32, the accepted connection will be non-blocking to start
113
            # with because we're using settimeout.
114
            conn.setblocking(True)
115
            while not self.received_bytes.endswith(self._expect_body_tail):
116
                self.received_bytes += conn.recv(4096)
117
            conn.sendall('HTTP/1.1 200 OK\r\n')
118
        except socket.timeout:
119
            # Make sure the client isn't stuck waiting for us to e.g. accept.
120
            self._sock.close()
2158.2.1 by v.ladeuil+lp at free
Windows tests cleanup.
121
        except socket.error:
122
            # The client may have already closed the socket.
123
            pass
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
124
125
    def tearDown(self):
126
        try:
127
            self._sock.close()
128
        except socket.error:
129
            # We might have already closed it.  We don't care.
130
            pass
131
        self.host = None
132
        self.port = None
133
134
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
135
class TestHttpUrls(TestCase):
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
136
2004.1.40 by v.ladeuil+lp at free
Fix the race condition again and correct some small typos to be in
137
    # FIXME: Some of these tests should be done for both
138
    # implementations
139
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
140
    def test_url_parsing(self):
141
        f = FakeManager()
142
        url = extract_auth('http://example.com', f)
143
        self.assertEquals('http://example.com', url)
144
        self.assertEquals(0, len(f.credentials))
1185.50.94 by John Arbash Meinel
Updated web page url to http://bazaar-vcs.org
145
        url = extract_auth('http://user:pass@www.bazaar-vcs.org/bzr/bzr.dev', f)
146
        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
147
        self.assertEquals(1, len(f.credentials))
2004.3.1 by vila
Test ConnectionError exceptions.
148
        self.assertEquals([None, 'www.bazaar-vcs.org', 'user', 'pass'],
149
                          f.credentials[0])
150
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
151
    def test_abs_url(self):
152
        """Construction of absolute http URLs"""
1185.50.94 by John Arbash Meinel
Updated web page url to http://bazaar-vcs.org
153
        t = HttpTransport_urllib('http://bazaar-vcs.org/bzr/bzr.dev/')
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
154
        eq = self.assertEqualDiff
155
        eq(t.abspath('.'),
1185.50.94 by John Arbash Meinel
Updated web page url to http://bazaar-vcs.org
156
           'http://bazaar-vcs.org/bzr/bzr.dev')
2004.3.1 by vila
Test ConnectionError exceptions.
157
        eq(t.abspath('foo/bar'),
1185.50.94 by John Arbash Meinel
Updated web page url to http://bazaar-vcs.org
158
           'http://bazaar-vcs.org/bzr/bzr.dev/foo/bar')
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
159
        eq(t.abspath('.bzr'),
1185.50.94 by John Arbash Meinel
Updated web page url to http://bazaar-vcs.org
160
           'http://bazaar-vcs.org/bzr/bzr.dev/.bzr')
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
161
        eq(t.abspath('.bzr/1//2/./3'),
1185.50.94 by John Arbash Meinel
Updated web page url to http://bazaar-vcs.org
162
           '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
163
164
    def test_invalid_http_urls(self):
165
        """Trap invalid construction of urls"""
1185.50.94 by John Arbash Meinel
Updated web page url to http://bazaar-vcs.org
166
        t = HttpTransport_urllib('http://bazaar-vcs.org/bzr/bzr.dev/')
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
167
        self.assertRaises(ValueError,
168
            t.abspath,
169
            '.bzr/')
2004.1.42 by v.ladeuil+lp at free
Fix #70803 by catching the httplib exception.
170
        t = HttpTransport_urllib('http://http://bazaar-vcs.org/bzr/bzr.dev/')
171
        self.assertRaises(errors.InvalidURL, t.has, 'foo/bar')
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
172
173
    def test_http_root_urls(self):
174
        """Construction of URLs from server root"""
1540.3.26 by Martin Pool
[merge] bzr.dev; pycurl not updated for readv yet
175
        t = HttpTransport_urllib('http://bzr.ozlabs.org/')
1185.16.68 by Martin Pool
- http url fixes suggested by Robey Pointer, and tests
176
        eq = self.assertEqualDiff
177
        eq(t.abspath('.bzr/tree-version'),
178
           '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.
179
1540.3.24 by Martin Pool
Add new protocol 'http+pycurl' that always uses PyCurl.
180
    def test_http_impl_urls(self):
181
        """There are servers which ask for particular clients to connect"""
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
182
        server = HttpServer_PyCurl()
1540.3.24 by Martin Pool
Add new protocol 'http+pycurl' that always uses PyCurl.
183
        try:
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
184
            server.setUp()
185
            url = server.get_url()
186
            self.assertTrue(url.startswith('http+pycurl://'))
187
        finally:
188
            server.tearDown()
1553.1.2 by James Henstridge
Add a test to make sure the user-agent header is being sent correctly.
189
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
190
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
191
class TestHttpConnections(object):
192
    """Test the http connections.
193
194
    This MUST be used by daughter classes that also inherit from
195
    TestCaseWithWebserver.
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
196
197
    We can't inherit directly from TestCaseWithWebserver or the
198
    test framework will try to create an instance which cannot
199
    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.
200
    """
201
202
    def setUp(self):
203
        TestCaseWithWebserver.setUp(self)
1540.3.33 by Martin Pool
Fix http tests that were failing to run tearDown when setup got a missing dependency
204
        self.build_tree(['xxx', 'foo/', 'foo/bar'], line_endings='binary',
205
                        transport=self.get_transport())
1553.1.2 by James Henstridge
Add a test to make sure the user-agent header is being sent correctly.
206
207
    def test_http_has(self):
1185.50.84 by John Arbash Meinel
[merge] bzr.dev, cleanup conflicts, fixup http tests for new TestCase layout.
208
        server = self.get_readonly_server()
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
209
        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.
210
        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.
211
        self.assertEqual(len(server.logs), 1)
2004.3.1 by vila
Test ConnectionError exceptions.
212
        self.assertContainsRe(server.logs[0],
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
213
            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
214
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
215
    def test_http_has_not_found(self):
216
        server = self.get_readonly_server()
217
        t = self._transport(server.get_url())
1553.1.5 by James Henstridge
Make HTTP transport has() method do HEAD requests, and update test to
218
        self.assertEqual(t.has('not-found'), False)
2004.3.1 by vila
Test ConnectionError exceptions.
219
        self.assertContainsRe(server.logs[1],
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
220
            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.
221
222
    def test_http_get(self):
1185.50.84 by John Arbash Meinel
[merge] bzr.dev, cleanup conflicts, fixup http tests for new TestCase layout.
223
        server = self.get_readonly_server()
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
224
        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.
225
        fp = t.get('foo/bar')
226
        self.assertEqualDiff(
227
            fp.read(),
1553.1.3 by James Henstridge
Make bzrlib.transport.http.HttpServer output referer and user agent as in
228
            'contents of foo/bar\n')
1185.50.84 by John Arbash Meinel
[merge] bzr.dev, cleanup conflicts, fixup http tests for new TestCase layout.
229
        self.assertEqual(len(server.logs), 1)
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
230
        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.
231
            '"GET /foo/bar HTTP/1.1" 200 - "-" "bzr/%s'
232
            % bzrlib.__version__) > -1)
1540.3.33 by Martin Pool
Fix http tests that were failing to run tearDown when setup got a missing dependency
233
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
234
    def test_get_smart_medium(self):
235
        # For HTTP, get_smart_medium should return the transport object.
236
        server = self.get_readonly_server()
237
        http_transport = self._transport(server.get_url())
238
        medium = http_transport.get_smart_medium()
2018.2.26 by Andrew Bennetts
Changes prompted by j-a-meinel's review.
239
        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
240
2000.2.2 by John Arbash Meinel
Update the urllib.has test.
241
    def test_has_on_bogus_host(self):
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
242
        # Get a free address and don't 'accept' on it, so that we
243
        # can be sure there is no http handler there, but set a
244
        # reasonable timeout to not slow down tests too much.
245
        default_timeout = socket.getdefaulttimeout()
246
        try:
247
            socket.setdefaulttimeout(2)
248
            s = socket.socket()
249
            s.bind(('localhost', 0))
250
            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.
251
            self.assertRaises(errors.ConnectionError, t.has, 'foo/bar')
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
252
        finally:
253
            socket.setdefaulttimeout(default_timeout)
254
1540.3.33 by Martin Pool
Fix http tests that were failing to run tearDown when setup got a missing dependency
255
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
256
class TestWithTransport_pycurl(object):
257
    """Test case to inherit from if pycurl is present"""
2004.1.40 by v.ladeuil+lp at free
Fix the race condition again and correct some small typos to be in
258
1540.3.33 by Martin Pool
Fix http tests that were failing to run tearDown when setup got a missing dependency
259
    def _get_pycurl_maybe(self):
1540.3.29 by Martin Pool
Prevent selftest failure when pycurl is not installed
260
        try:
261
            from bzrlib.transport.http._pycurl import PyCurlTransport
1612.1.1 by Martin Pool
Raise errors correctly on pycurl connection failure
262
            return PyCurlTransport
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
263
        except errors.DependencyNotPresent:
1540.3.29 by Martin Pool
Prevent selftest failure when pycurl is not installed
264
            raise TestSkipped('pycurl not present')
1540.3.15 by Martin Pool
[merge] large merge to sync with bzr.dev
265
1540.3.33 by Martin Pool
Fix http tests that were failing to run tearDown when setup got a missing dependency
266
    _transport = property(_get_pycurl_maybe)
267
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
268
269
class TestHttpConnections_urllib(TestHttpConnections, TestCaseWithWebserver):
270
    """Test http connections with urllib"""
271
272
    _transport = HttpTransport_urllib
273
274
275
276
class TestHttpConnections_pycurl(TestWithTransport_pycurl,
277
                                 TestHttpConnections,
278
                                 TestCaseWithWebserver):
279
    """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
280
281
1540.3.23 by Martin Pool
Allow urls like http+pycurl://host/ to use a particular impl
282
class TestHttpTransportRegistration(TestCase):
283
    """Test registrations of various http implementations"""
284
285
    def test_http_registered(self):
286
        # urlllib should always be present
287
        t = get_transport('http+urllib://bzr.google.com/')
288
        self.assertIsInstance(t, Transport)
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
289
        self.assertIsInstance(t, HttpTransport_urllib)
1786.1.23 by John Arbash Meinel
Move offset_to_http_ranges back onto HttpTransportBase, clarify tests.
290
291
292
class TestOffsets(TestCase):
1786.1.28 by John Arbash Meinel
Update and add tests for the HttpTransportBase.range_header
293
    """Test offsets_to_ranges method"""
1786.1.23 by John Arbash Meinel
Move offset_to_http_ranges back onto HttpTransportBase, clarify tests.
294
295
    def test_offsets_to_ranges_simple(self):
296
        to_range = HttpTransportBase.offsets_to_ranges
1786.1.39 by John Arbash Meinel
Remove the ability to read negative offsets from readv()
297
        ranges = to_range([(10, 1)])
1786.1.23 by John Arbash Meinel
Move offset_to_http_ranges back onto HttpTransportBase, clarify tests.
298
        self.assertEqual([[10, 10]], ranges)
1786.1.39 by John Arbash Meinel
Remove the ability to read negative offsets from readv()
299
300
        ranges = to_range([(0, 1), (1, 1)])
301
        self.assertEqual([[0, 1]], ranges)
302
303
        ranges = to_range([(1, 1), (0, 1)])
304
        self.assertEqual([[0, 1]], ranges)
1786.1.23 by John Arbash Meinel
Move offset_to_http_ranges back onto HttpTransportBase, clarify tests.
305
306
    def test_offset_to_ranges_overlapped(self):
307
        to_range = HttpTransportBase.offsets_to_ranges
308
1786.1.39 by John Arbash Meinel
Remove the ability to read negative offsets from readv()
309
        ranges = to_range([(10, 1), (20, 2), (22, 5)])
310
        self.assertEqual([[10, 10], [20, 26]], ranges)
311
312
        ranges = to_range([(10, 1), (11, 2), (22, 5)])
313
        self.assertEqual([[10, 12], [22, 26]], ranges)
1786.1.23 by John Arbash Meinel
Move offset_to_http_ranges back onto HttpTransportBase, clarify tests.
314
1786.1.28 by John Arbash Meinel
Update and add tests for the HttpTransportBase.range_header
315
2158.2.1 by v.ladeuil+lp at free
Windows tests cleanup.
316
class TestPost(object):
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
317
318
    def _test_post_body_is_received(self, scheme):
319
        server = RecordingServer(expect_body_tail='end-of-body')
320
        server.setUp()
321
        self.addCleanup(server.tearDown)
322
        url = '%s://%s:%s/' % (scheme, server.host, server.port)
323
        try:
324
            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.
325
        except errors.UnsupportedProtocol:
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
326
            raise TestSkipped('%s not available' % scheme)
327
        code, response = http_transport._post('abc def end-of-body')
328
        self.assertTrue(
329
            server.received_bytes.startswith('POST /.bzr/smart HTTP/1.'))
330
        self.assertTrue('content-length: 19\r' in server.received_bytes.lower())
331
        # The transport should not be assuming that the server can accept
332
        # chunked encoding the first time it connects, because HTTP/1.1, so we
333
        # check for the literal string.
334
        self.assertTrue(
335
            server.received_bytes.endswith('\r\n\r\nabc def end-of-body'))
336
2158.2.1 by v.ladeuil+lp at free
Windows tests cleanup.
337
338
class TestPost_urllib(TestCase, TestPost):
339
    """TestPost for urllib implementation"""
340
341
    _transport = HttpTransport_urllib
342
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
343
    def test_post_body_is_received_urllib(self):
344
        self._test_post_body_is_received('http+urllib')
345
2158.2.1 by v.ladeuil+lp at free
Windows tests cleanup.
346
347
class TestPost_pycurl(TestWithTransport_pycurl, TestCase, TestPost):
348
    """TestPost for pycurl implementation"""
349
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
350
    def test_post_body_is_received_pycurl(self):
351
        self._test_post_body_is_received('http+pycurl')
352
353
1786.1.28 by John Arbash Meinel
Update and add tests for the HttpTransportBase.range_header
354
class TestRangeHeader(TestCase):
355
    """Test range_header method"""
356
357
    def check_header(self, value, ranges=[], tail=0):
358
        range_header = HttpTransportBase.range_header
359
        self.assertEqual(value, range_header(ranges, tail))
360
361
    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=
362
        self.check_header('0-9', ranges=[[0,9]])
363
        self.check_header('100-109', ranges=[[100,109]])
1786.1.28 by John Arbash Meinel
Update and add tests for the HttpTransportBase.range_header
364
365
    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=
366
        self.check_header('-10', tail=10)
367
        self.check_header('-50', tail=50)
1786.1.28 by John Arbash Meinel
Update and add tests for the HttpTransportBase.range_header
368
369
    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=
370
        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
371
                          ranges=[(0,9), (100, 200), (300,5000)])
372
373
    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=
374
        self.check_header('0-9,300-5000,-50',
1786.1.28 by John Arbash Meinel
Update and add tests for the HttpTransportBase.range_header
375
                          ranges=[(0,9), (300,5000)],
376
                          tail=50)
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
377
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
378
379
class TestWallServer(object):
380
    """Tests exceptions during the connection phase"""
381
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
382
    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 :)
383
        return HttpServer(WallRequestHandler)
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
384
385
    def test_http_has(self):
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
386
        server = self.get_readonly_server()
2004.3.1 by vila
Test ConnectionError exceptions.
387
        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
388
        # Unfortunately httplib (see HTTPResponse._read_status
389
        # for details) make no distinction between a closed
390
        # socket and badly formatted status line, so we can't
391
        # just test for ConnectionError, we have to test
392
        # InvalidHttpResponse too.
393
        self.assertRaises((errors.ConnectionError, errors.InvalidHttpResponse),
394
                          t.has, 'foo/bar')
2004.3.3 by vila
Better (but still incomplete) design for bogus servers.
395
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
396
    def test_http_get(self):
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
397
        server = self.get_readonly_server()
2004.3.3 by vila
Better (but still incomplete) design for bogus servers.
398
        t = self._transport(server.get_url())
2145.1.1 by mbp at sourcefrog
merge urllib keepalive etc
399
        self.assertRaises((errors.ConnectionError, errors.InvalidHttpResponse),
400
                          t.get, 'foo/bar')
2004.3.3 by vila
Better (but still incomplete) design for bogus servers.
401
402
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
403
class TestWallServer_urllib(TestWallServer, TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
404
    """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.
405
406
    _transport = HttpTransport_urllib
407
408
409
class TestWallServer_pycurl(TestWithTransport_pycurl,
410
                            TestWallServer,
411
                            TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
412
    """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.
413
414
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
415
class TestBadStatusServer(object):
416
    """Tests bad status from server."""
417
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
418
    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 :)
419
        return HttpServer(BadStatusRequestHandler)
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
420
421
    def test_http_has(self):
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
422
        server = self.get_readonly_server()
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
423
        t = self._transport(server.get_url())
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
424
        self.assertRaises(errors.InvalidHttpResponse, t.has, 'foo/bar')
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
425
426
    def test_http_get(self):
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
427
        server = self.get_readonly_server()
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
428
        t = self._transport(server.get_url())
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
429
        self.assertRaises(errors.InvalidHttpResponse, t.get, 'foo/bar')
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
430
431
432
class TestBadStatusServer_urllib(TestBadStatusServer, TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
433
    """Tests bad status server for urllib implementation"""
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
434
435
    _transport = HttpTransport_urllib
436
437
438
class TestBadStatusServer_pycurl(TestWithTransport_pycurl,
439
                                 TestBadStatusServer,
440
                                 TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
441
    """Tests bad status server for pycurl implementation"""
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
442
443
444
class TestInvalidStatusServer(TestBadStatusServer):
445
    """Tests invalid status from server.
446
447
    Both implementations raises the same error as for a bad status.
448
    """
449
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
450
    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 :)
451
        return HttpServer(InvalidStatusRequestHandler)
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
452
453
454
class TestInvalidStatusServer_urllib(TestInvalidStatusServer,
455
                                     TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
456
    """Tests invalid status server for urllib implementation"""
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
457
458
    _transport = HttpTransport_urllib
459
460
461
class TestInvalidStatusServer_pycurl(TestWithTransport_pycurl,
462
                                     TestInvalidStatusServer,
463
                                     TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
464
    """Tests invalid status server for pycurl implementation"""
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
465
466
467
class TestBadProtocolServer(object):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
468
    """Tests bad protocol from server."""
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
469
470
    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 :)
471
        return HttpServer(BadProtocolRequestHandler)
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
472
473
    def test_http_has(self):
474
        server = self.get_readonly_server()
475
        t = self._transport(server.get_url())
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
476
        self.assertRaises(errors.InvalidHttpResponse, t.has, 'foo/bar')
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
477
478
    def test_http_get(self):
479
        server = self.get_readonly_server()
480
        t = self._transport(server.get_url())
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
481
        self.assertRaises(errors.InvalidHttpResponse, t.get, 'foo/bar')
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
482
483
484
class TestBadProtocolServer_urllib(TestBadProtocolServer,
485
                                   TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
486
    """Tests bad protocol server for urllib implementation"""
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
487
488
    _transport = HttpTransport_urllib
489
490
# curl don't check the protocol version
491
#class TestBadProtocolServer_pycurl(TestWithTransport_pycurl,
492
#                                   TestBadProtocolServer,
493
#                                   TestCaseWithWebserver):
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
494
#    """Tests bad protocol server for pycurl implementation"""
495
496
497
class TestForbiddenServer(object):
498
    """Tests forbidden server"""
499
500
    def create_transport_readonly_server(self):
501
        return HttpServer(ForbiddenRequestHandler)
502
503
    def test_http_has(self):
504
        server = self.get_readonly_server()
505
        t = self._transport(server.get_url())
506
        self.assertRaises(errors.TransportError, t.has, 'foo/bar')
507
508
    def test_http_get(self):
509
        server = self.get_readonly_server()
510
        t = self._transport(server.get_url())
511
        self.assertRaises(errors.TransportError, t.get, 'foo/bar')
512
513
514
class TestForbiddenServer_urllib(TestForbiddenServer, TestCaseWithWebserver):
515
    """Tests forbidden server for urllib implementation"""
516
517
    _transport = HttpTransport_urllib
518
519
520
class TestForbiddenServer_pycurl(TestWithTransport_pycurl,
521
                                 TestForbiddenServer,
522
                                 TestCaseWithWebserver):
523
    """Tests forbidden server for pycurl implementation"""
524
2004.1.28 by v.ladeuil+lp at free
Merge bzr.dev. Including http modifications by "smart" related code
525
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
526
class TestRecordingServer(TestCase):
527
528
    def test_create(self):
529
        server = RecordingServer(expect_body_tail=None)
530
        self.assertEqual('', server.received_bytes)
531
        self.assertEqual(None, server.host)
532
        self.assertEqual(None, server.port)
533
534
    def test_setUp_and_tearDown(self):
535
        server = RecordingServer(expect_body_tail=None)
536
        server.setUp()
537
        try:
538
            self.assertNotEqual(None, server.host)
539
            self.assertNotEqual(None, server.port)
540
        finally:
541
            server.tearDown()
542
        self.assertEqual(None, server.host)
543
        self.assertEqual(None, server.port)
544
545
    def test_send_receive_bytes(self):
546
        server = RecordingServer(expect_body_tail='c')
547
        server.setUp()
548
        self.addCleanup(server.tearDown)
549
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
550
        sock.connect((server.host, server.port))
551
        sock.sendall('abc')
552
        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
553
                         osutils.recv_all(sock, 4096))
2018.2.9 by Andrew Bennetts
(Andrew Bennetts, Robert Collins) Add test_http.RecordingServer, and use it to
554
        self.assertEqual('abc', server.received_bytes)
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
555
556
557
class TestRangeRequestServer(object):
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
558
    """Tests readv requests against server.
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
559
560
    This MUST be used by daughter classes that also inherit from
561
    TestCaseWithWebserver.
562
563
    We can't inherit directly from TestCaseWithWebserver or the
564
    test framework will try to create an instance which cannot
565
    run, its implementation being incomplete.
566
    """
567
568
    def setUp(self):
569
        TestCaseWithWebserver.setUp(self)
2004.1.30 by v.ladeuil+lp at free
Fix #62276 and #62029 by providing a more robust http range handling.
570
        self.build_tree_contents([('a', '0123456789')],)
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
571
572
    def test_readv(self):
573
        server = self.get_readonly_server()
574
        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.
575
        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.
576
        self.assertEqual(l[0], (0, '0'))
577
        self.assertEqual(l[1], (1, '1'))
578
        self.assertEqual(l[2], (3, '34'))
579
        self.assertEqual(l[3], (9, '9'))
580
581
    def test_readv_out_of_order(self):
582
        server = self.get_readonly_server()
583
        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.
584
        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.
585
        self.assertEqual(l[0], (1, '1'))
586
        self.assertEqual(l[1], (9, '9'))
587
        self.assertEqual(l[2], (0, '0'))
588
        self.assertEqual(l[3], (3, '34'))
589
2000.3.9 by v.ladeuil+lp at free
The tests that would have help avoid bug #73948 and all that mess :)
590
    def test_readv_invalid_ranges(self):
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
591
        server = self.get_readonly_server()
592
        t = self._transport(server.get_url())
593
594
        # This is intentionally reading off the end of the file
595
        # 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 :)
596
        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.
597
                              t.readv, 'a', [(1,1), (8,10)])
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
598
599
        # This is trying to seek past the end of the file, it should
600
        # 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 :)
601
        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.
602
                              t.readv, 'a', [(12,2)])
2004.1.29 by v.ladeuil+lp at free
New tests for http range requests handling.
603
604
605
class TestSingleRangeRequestServer(TestRangeRequestServer):
606
    """Test readv against a server which accept only single range requests"""
607
608
    def create_transport_readonly_server(self):
609
        return HttpServer(SingleRangeRequestHandler)
610
611
612
class TestSingleRangeRequestServer_urllib(TestSingleRangeRequestServer,
613
                                          TestCaseWithWebserver):
614
    """Tests single range requests accepting server for urllib implementation"""
615
616
    _transport = HttpTransport_urllib
617
618
619
class TestSingleRangeRequestServer_pycurl(TestWithTransport_pycurl,
620
                                          TestSingleRangeRequestServer,
621
                                          TestCaseWithWebserver):
622
    """Tests single range requests accepting server for pycurl implementation"""
623
624
625
class TestNoRangeRequestServer(TestRangeRequestServer):
626
    """Test readv against a server which do not accept range requests"""
627
628
    def create_transport_readonly_server(self):
629
        return HttpServer(NoRangeRequestHandler)
630
631
632
class TestNoRangeRequestServer_urllib(TestNoRangeRequestServer,
633
                                      TestCaseWithWebserver):
634
    """Tests range requests refusing server for urllib implementation"""
635
636
    _transport = HttpTransport_urllib
637
638
639
class TestNoRangeRequestServer_pycurl(TestWithTransport_pycurl,
640
                               TestNoRangeRequestServer,
641
                               TestCaseWithWebserver):
642
    """Tests range requests refusing server for pycurl implementation"""
643
644
2273.2.2 by v.ladeuil+lp at free
Really fix bug #83954, with tests.
645
class TestHttpProxyWhiteBox(TestCase):
646
    """Whitebox test proxy http authorization."""
647
648
    def setUp(self):
649
        TestCase.setUp(self)
650
        self._old_env = {}
651
652
    def tearDown(self):
653
        self._restore_env()
654
655
    def _set_and_capture_env_var(self, name, new_value):
656
        """Set an environment variable, and reset it when finished."""
657
        self._old_env[name] = osutils.set_or_unset_env(name, new_value)
658
659
    def _install_env(self, env):
660
        for name, value in env.iteritems():
661
            self._set_and_capture_env_var(name, value)
662
663
    def _restore_env(self):
664
        for name, value in self._old_env.iteritems():
665
            osutils.set_or_unset_env(name, value)
666
667
    def _proxied_request(self):
668
        from bzrlib.transport.http._urllib2_wrappers import (
669
            ProxyHandler,
670
            Request,
671
            )
672
673
        handler = ProxyHandler()
674
        request = Request('GET','http://baz/buzzle')
675
        handler.set_proxy(request, 'http')
676
        return request
677
678
    def test_empty_user(self):
679
        self._install_env({'http_proxy': 'http://bar.com'})
680
        request = self._proxied_request()
681
        self.assertFalse(request.headers.has_key('Proxy-authorization'))
682
683
    def test_empty_pass(self):
684
        self._install_env({'http_proxy': 'http://joe@bar.com'})
685
        request = self._proxied_request()
686
        self.assertEqual('Basic ' + 'joe:'.encode('base64').strip(),
687
                         request.headers['Proxy-authorization'])
688
    def test_user_pass(self):
689
        self._install_env({'http_proxy': 'http://joe:foo@bar.com'})
690
        request = self._proxied_request()
691
        self.assertEqual('Basic ' + 'joe:foo'.encode('base64').strip(),
692
                         request.headers['Proxy-authorization'])
693
694
695
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
696
class TestProxyHttpServer(object):
697
    """Tests proxy server.
698
699
    This MUST be used by daughter classes that also inherit from
700
    TestCaseWithTwoWebservers.
701
702
    We can't inherit directly from TestCaseWithTwoWebservers or
703
    the test framework will try to create an instance which
704
    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.
705
706
    Be aware that we do not setup a real proxy here. Instead, we
2167.3.7 by v.ladeuil+lp at free
Typos corrected.
707
    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.
708
    different content (the faked proxy server append '-proxied'
709
    to the file names).
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
710
    """
711
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
712
    # FIXME: We don't have an https server available, so we don't
713
    # test https connections.
714
2273.2.1 by v.ladeuil+lp at free
Fix bug #83954.
715
    # FIXME: Once the test suite is better fitted to test
716
    # authorization schemes, test proxy authorizations too (see
717
    # bug #83954).
718
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
719
    def setUp(self):
720
        TestCaseWithTwoWebservers.setUp(self)
721
        self.build_tree_contents([('foo', 'contents of foo\n'),
722
                                  ('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.
723
        # Let's setup some attributes for tests
724
        self.server = self.get_readonly_server()
725
        self.no_proxy_host = 'localhost:%d' % self.server.port
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
726
        # 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.
727
        self.proxy = self.get_secondary_server()
728
        self.proxy_url = self.proxy.get_url()
729
        self._old_env = {}
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
730
731
    def create_transport_secondary_server(self):
732
        """Creates an http server that will serve files with
733
        '-proxied' appended to their names.
734
        """
735
        return HttpServer(FakeProxyRequestHandler)
736
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
737
    def _set_and_capture_env_var(self, name, new_value):
738
        """Set an environment variable, and reset it when finished."""
739
        self._old_env[name] = osutils.set_or_unset_env(name, new_value)
740
741
    def _install_env(self, env):
742
        for name, value in env.iteritems():
743
            self._set_and_capture_env_var(name, value)
744
745
    def _restore_env(self):
746
        for name, value in self._old_env.iteritems():
747
            osutils.set_or_unset_env(name, value)
748
749
    def proxied_in_env(self, env):
750
        self._install_env(env)
751
        url = self.server.get_url()
752
        t = self._transport(url)
753
        try:
754
            self.assertEqual(t.get('foo').read(), 'proxied contents of foo\n')
755
        finally:
756
            self._restore_env()
757
758
    def not_proxied_in_env(self, env):
759
        self._install_env(env)
760
        url = self.server.get_url()
761
        t = self._transport(url)
762
        try:
763
            self.assertEqual(t.get('foo').read(), 'contents of foo\n')
764
        finally:
765
            self._restore_env()
766
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
767
    def test_http_proxy(self):
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
768
        self.proxied_in_env({'http_proxy': self.proxy_url})
769
770
    def test_HTTP_PROXY(self):
771
        self.proxied_in_env({'HTTP_PROXY': self.proxy_url})
772
773
    def test_all_proxy(self):
774
        self.proxied_in_env({'all_proxy': self.proxy_url})
775
776
    def test_ALL_PROXY(self):
777
        self.proxied_in_env({'ALL_PROXY': self.proxy_url})
778
779
    def test_http_proxy_with_no_proxy(self):
780
        self.not_proxied_in_env({'http_proxy': self.proxy_url,
781
                                 'no_proxy': self.no_proxy_host})
782
783
    def test_HTTP_PROXY_with_NO_PROXY(self):
784
        self.not_proxied_in_env({'HTTP_PROXY': self.proxy_url,
785
                                 'NO_PROXY': self.no_proxy_host})
786
787
    def test_all_proxy_with_no_proxy(self):
788
        self.not_proxied_in_env({'all_proxy': self.proxy_url,
789
                                 'no_proxy': self.no_proxy_host})
790
791
    def test_ALL_PROXY_with_NO_PROXY(self):
792
        self.not_proxied_in_env({'ALL_PROXY': self.proxy_url,
793
                                 'NO_PROXY': self.no_proxy_host})
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
794
795
796
class TestProxyHttpServer_urllib(TestProxyHttpServer,
797
                                 TestCaseWithTwoWebservers):
798
    """Tests proxy server for urllib implementation"""
799
800
    _transport = HttpTransport_urllib
801
802
803
class TestProxyHttpServer_pycurl(TestWithTransport_pycurl,
804
                                 TestProxyHttpServer,
805
                                 TestCaseWithTwoWebservers):
806
    """Tests proxy server for pycurl implementation"""
807
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
808
    def setUp(self):
809
        TestProxyHttpServer.setUp(self)
810
        # Oh my ! pycurl does not check for the port as part of
811
        # no_proxy :-( So we just test the host part
812
        self.no_proxy_host = 'localhost'
813
814
    def test_HTTP_PROXY(self):
815
        # pycurl do not check HTTP_PROXY for security reasons
816
        # (for use in a CGI context that we do not care
817
        # about. Should we ?)
818
        raise TestSkipped()
819
820
    def test_HTTP_PROXY_with_NO_PROXY(self):
821
        raise TestSkipped()
2183.1.1 by Aaron Bentley
Make test HTTP server's range handling more spec-compliant (Vincent Ladeuil)
822
823
2182.2.2 by v.ladeuil+lp at free
Thanks again to Aaron, the http server RFC2616 compliance
824
class TestRanges(object):
825
    """Test the Range header in GET methods..
826
827
    This MUST be used by daughter classes that also inherit from
828
    TestCaseWithWebserver.
829
830
    We can't inherit directly from TestCaseWithWebserver or the
831
    test framework will try to create an instance which cannot
832
    run, its implementation being incomplete.
833
    """
834
835
    def setUp(self):
836
        TestCaseWithWebserver.setUp(self)
837
        self.build_tree_contents([('a', '0123456789')],)
838
        server = self.get_readonly_server()
839
        self.transport = self._transport(server.get_url())
840
841
    def _file_contents(self, relpath, ranges, tail_amount=0):
842
         code, data = self.transport._get(relpath, ranges)
843
         self.assertTrue(code in (200, 206),'_get returns: %d' % code)
844
         for start, end in ranges:
845
             data.seek(start)
846
             yield data.read(end - start + 1)
847
848
    def _file_tail(self, relpath, tail_amount):
849
         code, data = self.transport._get(relpath, [], tail_amount)
850
         self.assertTrue(code in (200, 206),'_get returns: %d' % code)
851
         data.seek(-tail_amount + 1, 2)
852
         return data.read(tail_amount)
853
854
    def test_range_header(self):
855
        # Valid ranges
856
        map(self.assertEqual,['0', '234'],
857
            list(self._file_contents('a', [(0,0), (2,4)])),)
858
        # Tail
859
        self.assertEqual('789', self._file_tail('a', 3))
860
        # Syntactically invalid range
861
        self.assertRaises(errors.InvalidRange,
862
                          self.transport._get, 'a', [(4, 3)])
863
        # Semantically invalid range
864
        self.assertRaises(errors.InvalidRange,
865
                          self.transport._get, 'a', [(42, 128)])
866
867
868
class TestRanges_urllib(TestRanges, TestCaseWithWebserver):
869
    """Test the Range header in GET methods for urllib implementation"""
870
871
    _transport = HttpTransport_urllib
872
873
874
class TestRanges_pycurl(TestWithTransport_pycurl,
875
                        TestRanges,
876
                        TestCaseWithWebserver):
877
    """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.
878
2164.2.16 by Vincent Ladeuil
Add tests.
879
# FIXME: http implementations do not redirect silently anymore
880
# (they do not redirect at all in fact). The mechanism is still
881
# in place at the _urllib2_wrappers.Request level and tests
2164.2.17 by Vincent Ladeuil
Add comments and fix typos
882
# should be written to exercise it. For the pycurl implementation
883
# the redirection have been deleted as we may deprecate pycurl
884
# and I have no place to keep a working implementation.
885
#  -- vila 20070212
2164.2.13 by v.ladeuil+lp at free
Add tests for redirection. Preserve transport decorations.
886
2164.2.16 by Vincent Ladeuil
Add tests.
887
class TestHTTPRedirections(object):
888
    """Test redirection between http servers.
2164.2.13 by v.ladeuil+lp at free
Add tests for redirection. Preserve transport decorations.
889
890
    This MUST be used by daughter classes that also inherit from
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
891
    TestCaseWithRedirectedWebserver.
2164.2.13 by v.ladeuil+lp at free
Add tests for redirection. Preserve transport decorations.
892
893
    We can't inherit directly from TestCaseWithTwoWebservers or the
894
    test framework will try to create an instance which cannot
895
    run, its implementation being incomplete. 
896
    """
897
898
    def create_transport_secondary_server(self):
899
        """Create the secondary server redirecting to the primary server"""
2164.2.16 by Vincent Ladeuil
Add tests.
900
        new = self.get_readonly_server()
901
902
        redirecting = HTTPServerRedirecting()
903
        redirecting.redirect_to(new.host, new.port)
904
        return redirecting
2164.2.13 by v.ladeuil+lp at free
Add tests for redirection. Preserve transport decorations.
905
906
    def setUp(self):
2164.2.16 by Vincent Ladeuil
Add tests.
907
        super(TestHTTPRedirections, self).setUp()
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
908
        self.build_tree_contents([('a', '0123456789'),
909
                                  ('bundle',
910
                                  '# Bazaar revision bundle v0.9\n#\n')
911
                                  ],)
912
913
        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.
914
915
    def test_redirected(self):
2164.2.16 by Vincent Ladeuil
Add tests.
916
        self.assertRaises(errors.RedirectRequested, self.old_transport.get, 'a')
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
917
        t = self._transport(self.new_server.get_url())
918
        self.assertEqual('0123456789', t.get('a').read())
919
920
    def test_read_redirected_bundle_from_url(self):
921
        from bzrlib.bundle import read_bundle_from_url
922
        url = self.old_transport.abspath('bundle')
923
        bundle = read_bundle_from_url(url)
924
        # If read_bundle_from_url was successful we get an empty bundle
925
        self.assertEqual([], bundle.revisions)
2164.2.16 by Vincent Ladeuil
Add tests.
926
927
928
class TestHTTPRedirections_urllib(TestHTTPRedirections,
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
929
                                  TestCaseWithRedirectedWebserver):
2164.2.13 by v.ladeuil+lp at free
Add tests for redirection. Preserve transport decorations.
930
    """Tests redirections for urllib implementation"""
931
932
    _transport = HttpTransport_urllib
933
2164.2.16 by Vincent Ladeuil
Add tests.
934
935
936
class TestHTTPRedirections_pycurl(TestWithTransport_pycurl,
937
                                  TestHTTPRedirections,
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
938
                                  TestCaseWithRedirectedWebserver):
2164.2.16 by Vincent Ladeuil
Add tests.
939
    """Tests redirections for pycurl implementation"""
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
940
941
942
class TestDoCatchRedirections(TestCaseWithRedirectedWebserver):
943
    """Test transport.do_catching_redirections.
944
945
    We arbitrarily choose to use urllib transports
946
    """
947
948
    _transport = HttpTransport_urllib
949
950
    def setUp(self):
951
        super(TestDoCatchRedirections, self).setUp()
952
        self.build_tree_contents([('a', '0123456789'),],)
953
954
        self.old_transport = self._transport(self.old_server.get_url())
955
956
    def get_a(self, transport):
957
        return transport.get('a')
958
959
    def test_no_redirection(self):
960
        t = self._transport(self.new_server.get_url())
961
962
        # We use None for redirected so that we fail if redirected
963
        self.assertEquals('0123456789',
964
                          do_catching_redirections(self.get_a, t, None).read())
965
966
    def test_one_redirection(self):
967
        self.redirections = 0
968
969
        def redirected(transport, exception, redirection_notice):
970
            self.redirections += 1
971
            dir, file = urlutils.split(exception.target)
972
            return self._transport(dir)
973
974
        self.assertEquals('0123456789',
975
                          do_catching_redirections(self.get_a,
976
                                                   self.old_transport,
977
                                                   redirected
978
                                                   ).read())
979
        self.assertEquals(1, self.redirections)
980
981
    def test_redirection_loop(self):
982
983
        def redirected(transport, exception, redirection_notice):
984
            # By using the redirected url as a base dir for the
985
            # *old* transport, we create a loop: a => a/a =>
986
            # a/a/a
987
            return self.old_transport.clone(exception.target)
988
989
        self.assertRaises(errors.TooManyRedirections, do_catching_redirections,
990
                          self.get_a, self.old_transport, redirected)