1
# Copyright (C) 2005, 2006 Canonical
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.
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.
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
17
# FIXME: This test should be repeated for each available http client
18
# implementation; at the moment we have urllib and pycurl.
20
# TODO: Should be renamed to bzrlib.transport.http.tests?
23
from bzrlib.errors import DependencyNotPresent
24
from bzrlib.tests import TestCase, TestSkipped
25
from bzrlib.transport import Transport
26
from bzrlib.transport.http import extract_auth, HttpTransportBase
27
from bzrlib.transport.http._urllib import HttpTransport_urllib
28
from bzrlib.tests.HTTPTestUtil import TestCaseWithWebserver
3
from bzrlib.tests import TestCase
4
from bzrlib.transport.http import HttpTransport, extract_auth
31
6
class FakeManager (object):
34
8
self.credentials = []
36
10
def add_password(self, realm, host, username, password):
37
11
self.credentials.append([realm, host, username, password])
40
14
class TestHttpUrls(TestCase):
42
15
def test_url_parsing(self):
44
17
url = extract_auth('http://example.com', f)
45
18
self.assertEquals('http://example.com', url)
46
19
self.assertEquals(0, len(f.credentials))
47
url = extract_auth('http://user:pass@www.bazaar-vcs.org/bzr/bzr.dev', f)
48
self.assertEquals('http://www.bazaar-vcs.org/bzr/bzr.dev', url)
20
url = extract_auth('http://user:pass@www.bazaar-ng.org/bzr/bzr.dev', f)
21
self.assertEquals('http://www.bazaar-ng.org/bzr/bzr.dev', url)
49
22
self.assertEquals(1, len(f.credentials))
50
self.assertEquals([None, 'www.bazaar-vcs.org', 'user', 'pass'], f.credentials[0])
23
self.assertEquals([None, 'www.bazaar-ng.org', 'user', 'pass'], f.credentials[0])
52
25
def test_abs_url(self):
53
26
"""Construction of absolute http URLs"""
54
t = HttpTransport_urllib('http://bazaar-vcs.org/bzr/bzr.dev/')
27
t = HttpTransport('http://bazaar-ng.org/bzr/bzr.dev/')
55
28
eq = self.assertEqualDiff
57
'http://bazaar-vcs.org/bzr/bzr.dev')
30
'http://bazaar-ng.org/bzr/bzr.dev')
58
31
eq(t.abspath('foo/bar'),
59
'http://bazaar-vcs.org/bzr/bzr.dev/foo/bar')
32
'http://bazaar-ng.org/bzr/bzr.dev/foo/bar')
60
33
eq(t.abspath('.bzr'),
61
'http://bazaar-vcs.org/bzr/bzr.dev/.bzr')
34
'http://bazaar-ng.org/bzr/bzr.dev/.bzr')
62
35
eq(t.abspath('.bzr/1//2/./3'),
63
'http://bazaar-vcs.org/bzr/bzr.dev/.bzr/1/2/3')
36
'http://bazaar-ng.org/bzr/bzr.dev/.bzr/1/2/3')
65
38
def test_invalid_http_urls(self):
66
39
"""Trap invalid construction of urls"""
67
t = HttpTransport_urllib('http://bazaar-vcs.org/bzr/bzr.dev/')
40
t = HttpTransport('http://bazaar-ng.org/bzr/bzr.dev/')
68
41
self.assertRaises(ValueError,
75
48
def test_http_root_urls(self):
76
49
"""Construction of URLs from server root"""
77
t = HttpTransport_urllib('http://bzr.ozlabs.org/')
50
t = HttpTransport('http://bzr.ozlabs.org/')
78
51
eq = self.assertEqualDiff
79
52
eq(t.abspath('.bzr/tree-version'),
80
53
'http://bzr.ozlabs.org/.bzr/tree-version')
82
def test_http_impl_urls(self):
83
"""There are servers which ask for particular clients to connect"""
85
from bzrlib.transport.http._pycurl import HttpServer_PyCurl
86
server = HttpServer_PyCurl()
89
url = server.get_url()
90
self.assertTrue(url.startswith('http+pycurl://'))
93
except DependencyNotPresent:
94
raise TestSkipped('pycurl not present')
97
class TestHttpMixins(object):
100
self.build_tree(['xxx', 'foo/', 'foo/bar'], line_endings='binary',
101
transport=self.get_transport())
103
def test_http_has(self):
104
server = self.get_readonly_server()
105
t = self._transport(server.get_url())
106
self.assertEqual(t.has('foo/bar'), True)
107
self.assertEqual(len(server.logs), 1)
108
self.assertContainsRe(server.logs[0],
109
r'"HEAD /foo/bar HTTP/1.." (200|302) - "-" "bzr/')
111
def test_http_has_not_found(self):
112
server = self.get_readonly_server()
113
t = self._transport(server.get_url())
114
self.assertEqual(t.has('not-found'), False)
115
self.assertContainsRe(server.logs[1],
116
r'"HEAD /not-found HTTP/1.." 404 - "-" "bzr/')
118
def test_http_get(self):
119
server = self.get_readonly_server()
120
t = self._transport(server.get_url())
121
fp = t.get('foo/bar')
122
self.assertEqualDiff(
124
'contents of foo/bar\n')
125
self.assertEqual(len(server.logs), 1)
126
self.assertTrue(server.logs[0].find(
127
'"GET /foo/bar HTTP/1.1" 200 - "-" "bzr/%s' % bzrlib.__version__) > -1)
130
class TestHttpConnections_urllib(TestCaseWithWebserver, TestHttpMixins):
132
_transport = HttpTransport_urllib
135
TestCaseWithWebserver.setUp(self)
140
class TestHttpConnections_pycurl(TestCaseWithWebserver, TestHttpMixins):
142
def _get_pycurl_maybe(self):
144
from bzrlib.transport.http._pycurl import PyCurlTransport
145
return PyCurlTransport
146
except DependencyNotPresent:
147
raise TestSkipped('pycurl not present')
149
_transport = property(_get_pycurl_maybe)
152
TestCaseWithWebserver.setUp(self)
157
class TestHttpTransportRegistration(TestCase):
158
"""Test registrations of various http implementations"""
160
def test_http_registered(self):
161
import bzrlib.transport.http._urllib
162
from bzrlib.transport import get_transport
163
# urlllib should always be present
164
t = get_transport('http+urllib://bzr.google.com/')
165
self.assertIsInstance(t, Transport)
166
self.assertIsInstance(t, bzrlib.transport.http._urllib.HttpTransport_urllib)
169
class TestOffsets(TestCase):
170
"""Test offsets_to_ranges method"""
172
def test_offsets_to_ranges_simple(self):
173
to_range = HttpTransportBase.offsets_to_ranges
174
ranges = to_range([(10, 1)])
175
self.assertEqual([[10, 10]], ranges)
177
ranges = to_range([(0, 1), (1, 1)])
178
self.assertEqual([[0, 1]], ranges)
180
ranges = to_range([(1, 1), (0, 1)])
181
self.assertEqual([[0, 1]], ranges)
183
def test_offset_to_ranges_overlapped(self):
184
to_range = HttpTransportBase.offsets_to_ranges
186
ranges = to_range([(10, 1), (20, 2), (22, 5)])
187
self.assertEqual([[10, 10], [20, 26]], ranges)
189
ranges = to_range([(10, 1), (11, 2), (22, 5)])
190
self.assertEqual([[10, 12], [22, 26]], ranges)
193
class TestRangeHeader(TestCase):
194
"""Test range_header method"""
196
def check_header(self, value, ranges=[], tail=0):
197
range_header = HttpTransportBase.range_header
198
self.assertEqual(value, range_header(ranges, tail))
200
def test_range_header_single(self):
201
self.check_header('0-9', ranges=[[0,9]])
202
self.check_header('100-109', ranges=[[100,109]])
204
def test_range_header_tail(self):
205
self.check_header('-10', tail=10)
206
self.check_header('-50', tail=50)
208
def test_range_header_multi(self):
209
self.check_header('0-9,100-200,300-5000',
210
ranges=[(0,9), (100, 200), (300,5000)])
212
def test_range_header_mixed(self):
213
self.check_header('0-9,300-5000,-50',
214
ranges=[(0,9), (300,5000)],