/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_http.py

separate out the client medium from the client encoding protocol for the smart server.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006 Canonical
 
2
#
 
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.
 
7
#
 
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.
 
12
#
 
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
 
16
 
 
17
# FIXME: This test should be repeated for each available http client
 
18
# implementation; at the moment we have urllib and pycurl.
 
19
 
 
20
# TODO: Should be renamed to bzrlib.transport.http.tests?
 
21
 
 
22
import socket
 
23
 
 
24
import bzrlib
 
25
from bzrlib.errors import DependencyNotPresent
 
26
from bzrlib.tests import TestCase, TestSkipped
 
27
from bzrlib.transport import Transport
 
28
from bzrlib.transport.http import extract_auth, HttpTransportBase
 
29
from bzrlib.transport.http._urllib import HttpTransport_urllib
 
30
from bzrlib.tests.HTTPTestUtil import TestCaseWithWebserver
 
31
 
 
32
 
 
33
class FakeManager (object):
 
34
 
 
35
    def __init__(self):
 
36
        self.credentials = []
 
37
        
 
38
    def add_password(self, realm, host, username, password):
 
39
        self.credentials.append([realm, host, username, password])
 
40
 
 
41
 
 
42
class TestHttpUrls(TestCase):
 
43
 
 
44
    def test_url_parsing(self):
 
45
        f = FakeManager()
 
46
        url = extract_auth('http://example.com', f)
 
47
        self.assertEquals('http://example.com', url)
 
48
        self.assertEquals(0, len(f.credentials))
 
49
        url = extract_auth('http://user:pass@www.bazaar-vcs.org/bzr/bzr.dev', f)
 
50
        self.assertEquals('http://www.bazaar-vcs.org/bzr/bzr.dev', url)
 
51
        self.assertEquals(1, len(f.credentials))
 
52
        self.assertEquals([None, 'www.bazaar-vcs.org', 'user', 'pass'], f.credentials[0])
 
53
        
 
54
    def test_abs_url(self):
 
55
        """Construction of absolute http URLs"""
 
56
        t = HttpTransport_urllib('http://bazaar-vcs.org/bzr/bzr.dev/')
 
57
        eq = self.assertEqualDiff
 
58
        eq(t.abspath('.'),
 
59
           'http://bazaar-vcs.org/bzr/bzr.dev')
 
60
        eq(t.abspath('foo/bar'), 
 
61
           'http://bazaar-vcs.org/bzr/bzr.dev/foo/bar')
 
62
        eq(t.abspath('.bzr'),
 
63
           'http://bazaar-vcs.org/bzr/bzr.dev/.bzr')
 
64
        eq(t.abspath('.bzr/1//2/./3'),
 
65
           'http://bazaar-vcs.org/bzr/bzr.dev/.bzr/1/2/3')
 
66
 
 
67
    def test_invalid_http_urls(self):
 
68
        """Trap invalid construction of urls"""
 
69
        t = HttpTransport_urllib('http://bazaar-vcs.org/bzr/bzr.dev/')
 
70
        self.assertRaises(ValueError,
 
71
            t.abspath,
 
72
            '.bzr/')
 
73
 
 
74
    def test_http_root_urls(self):
 
75
        """Construction of URLs from server root"""
 
76
        t = HttpTransport_urllib('http://bzr.ozlabs.org/')
 
77
        eq = self.assertEqualDiff
 
78
        eq(t.abspath('.bzr/tree-version'),
 
79
           'http://bzr.ozlabs.org/.bzr/tree-version')
 
80
 
 
81
    def test_http_impl_urls(self):
 
82
        """There are servers which ask for particular clients to connect"""
 
83
        try:
 
84
            from bzrlib.transport.http._pycurl import HttpServer_PyCurl
 
85
            server = HttpServer_PyCurl()
 
86
            try:
 
87
                server.setUp()
 
88
                url = server.get_url()
 
89
                self.assertTrue(url.startswith('http+pycurl://'))
 
90
            finally:
 
91
                server.tearDown()
 
92
        except DependencyNotPresent:
 
93
            raise TestSkipped('pycurl not present')
 
94
 
 
95
 
 
96
class TestHttpMixins(object):
 
97
 
 
98
    def _prep_tree(self):
 
99
        self.build_tree(['xxx', 'foo/', 'foo/bar'], line_endings='binary',
 
100
                        transport=self.get_transport())
 
101
 
 
102
    def test_http_has(self):
 
103
        server = self.get_readonly_server()
 
104
        t = self._transport(server.get_url())
 
105
        self.assertEqual(t.has('foo/bar'), True)
 
106
        self.assertEqual(len(server.logs), 1)
 
107
        self.assertContainsRe(server.logs[0], 
 
108
            r'"HEAD /foo/bar HTTP/1.." (200|302) - "-" "bzr/')
 
109
 
 
110
    def test_http_has_not_found(self):
 
111
        server = self.get_readonly_server()
 
112
        t = self._transport(server.get_url())
 
113
        self.assertEqual(t.has('not-found'), False)
 
114
        self.assertContainsRe(server.logs[1], 
 
115
            r'"HEAD /not-found HTTP/1.." 404 - "-" "bzr/')
 
116
 
 
117
    def test_http_get(self):
 
118
        server = self.get_readonly_server()
 
119
        t = self._transport(server.get_url())
 
120
        fp = t.get('foo/bar')
 
121
        self.assertEqualDiff(
 
122
            fp.read(),
 
123
            'contents of foo/bar\n')
 
124
        self.assertEqual(len(server.logs), 1)
 
125
        self.assertTrue(server.logs[0].find(
 
126
            '"GET /foo/bar HTTP/1.1" 200 - "-" "bzr/%s' % bzrlib.__version__) > -1)
 
127
 
 
128
    def test_get_smart_medium(self):
 
129
        # For HTTP, get_smart_medium should return the transport object.
 
130
        server = self.get_readonly_server()
 
131
        http_transport = self._transport(server.get_url())
 
132
        medium = http_transport.get_smart_medium()
 
133
        self.assertTrue(medium is http_transport)
 
134
 
 
135
 
 
136
class TestHttpConnections_urllib(TestCaseWithWebserver, TestHttpMixins):
 
137
 
 
138
    _transport = HttpTransport_urllib
 
139
 
 
140
    def setUp(self):
 
141
        TestCaseWithWebserver.setUp(self)
 
142
        self._prep_tree()
 
143
 
 
144
    def test_has_on_bogus_host(self):
 
145
        import urllib2
 
146
        # Get a random address, so that we can be sure there is no
 
147
        # http handler there.
 
148
        s = socket.socket()
 
149
        s.bind(('localhost', 0))
 
150
        t = self._transport('http://%s:%s/' % s.getsockname())
 
151
        self.assertRaises(urllib2.URLError, t.has, 'foo/bar')
 
152
 
 
153
 
 
154
class TestHttpConnections_pycurl(TestCaseWithWebserver, TestHttpMixins):
 
155
 
 
156
    def _get_pycurl_maybe(self):
 
157
        try:
 
158
            from bzrlib.transport.http._pycurl import PyCurlTransport
 
159
            return PyCurlTransport
 
160
        except DependencyNotPresent:
 
161
            raise TestSkipped('pycurl not present')
 
162
 
 
163
    _transport = property(_get_pycurl_maybe)
 
164
 
 
165
    def setUp(self):
 
166
        TestCaseWithWebserver.setUp(self)
 
167
        self._prep_tree()
 
168
 
 
169
 
 
170
 
 
171
class TestHttpTransportRegistration(TestCase):
 
172
    """Test registrations of various http implementations"""
 
173
 
 
174
    def test_http_registered(self):
 
175
        import bzrlib.transport.http._urllib
 
176
        from bzrlib.transport import get_transport
 
177
        # urlllib should always be present
 
178
        t = get_transport('http+urllib://bzr.google.com/')
 
179
        self.assertIsInstance(t, Transport)
 
180
        self.assertIsInstance(t, bzrlib.transport.http._urllib.HttpTransport_urllib)
 
181
 
 
182
 
 
183
class TestOffsets(TestCase):
 
184
    """Test offsets_to_ranges method"""
 
185
 
 
186
    def test_offsets_to_ranges_simple(self):
 
187
        to_range = HttpTransportBase.offsets_to_ranges
 
188
        ranges = to_range([(10, 1)])
 
189
        self.assertEqual([[10, 10]], ranges)
 
190
 
 
191
        ranges = to_range([(0, 1), (1, 1)])
 
192
        self.assertEqual([[0, 1]], ranges)
 
193
 
 
194
        ranges = to_range([(1, 1), (0, 1)])
 
195
        self.assertEqual([[0, 1]], ranges)
 
196
 
 
197
    def test_offset_to_ranges_overlapped(self):
 
198
        to_range = HttpTransportBase.offsets_to_ranges
 
199
 
 
200
        ranges = to_range([(10, 1), (20, 2), (22, 5)])
 
201
        self.assertEqual([[10, 10], [20, 26]], ranges)
 
202
 
 
203
        ranges = to_range([(10, 1), (11, 2), (22, 5)])
 
204
        self.assertEqual([[10, 12], [22, 26]], ranges)
 
205
 
 
206
 
 
207
class TestRangeHeader(TestCase):
 
208
    """Test range_header method"""
 
209
 
 
210
    def check_header(self, value, ranges=[], tail=0):
 
211
        range_header = HttpTransportBase.range_header
 
212
        self.assertEqual(value, range_header(ranges, tail))
 
213
 
 
214
    def test_range_header_single(self):
 
215
        self.check_header('0-9', ranges=[[0,9]])
 
216
        self.check_header('100-109', ranges=[[100,109]])
 
217
 
 
218
    def test_range_header_tail(self):
 
219
        self.check_header('-10', tail=10)
 
220
        self.check_header('-50', tail=50)
 
221
 
 
222
    def test_range_header_multi(self):
 
223
        self.check_header('0-9,100-200,300-5000',
 
224
                          ranges=[(0,9), (100, 200), (300,5000)])
 
225
 
 
226
    def test_range_header_mixed(self):
 
227
        self.check_header('0-9,300-5000,-50',
 
228
                          ranges=[(0,9), (300,5000)],
 
229
                          tail=50)