1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
# Copyright (C) 2007 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Tests for HTTP transports and servers implementations.
(transport, server) implementations tested here are supplied by
HTTPTestProviderAdapter. Note that a server is characterized by a request
handler class.
Transport implementations are normally tested via
test_transport_implementations. The tests here are about the variations in HTTP
protocol implementation to guarantee the robustness of our transports.
"""
import socket
import bzrlib
from bzrlib import (
errors,
tests,
transport,
)
from bzrlib.tests import (
http_server,
http_utils,
)
from bzrlib.transport.http._urllib import HttpTransport_urllib
try:
from bzrlib.transport.http._pycurl import PyCurlTransport
pycurl_present = True
except errors.DependencyNotPresent:
pycurl_present = False
class HTTPImplementationsTestProviderAdapter(tests.TestScenarioApplier):
def __init__(self):
transport_scenarios = [('urllib',
dict(_transport=HttpTransport_urllib,
_server=http_server.HttpServer_urllib,
_qualified_prefix='http+urllib',
)),]
if pycurl_present:
transport_scenarios.append(
('pycurl', dict(_transport=PyCurlTransport,
_server=http_server.HttpServer_PyCurl,
_qualified_prefix='http+pycurl',
)))
self.scenarios = transport_scenarios
def load_tests(standard_tests, module, loader):
"""Multiply tests for http clients and protocol versions."""
adapter = HTTPImplementationsTestProviderAdapter()
result = loader.suiteClass()
for test in tests.iter_suite_tests(standard_tests):
result.addTests(adapter.adapt(test))
return result
class TestHttpTransportUrls(tests.TestCase):
"""Test the http urls."""
def test_abs_url(self):
"""Construction of absolute http URLs"""
t = self._transport('http://bazaar-vcs.org/bzr/bzr.dev/')
eq = self.assertEqualDiff
eq(t.abspath('.'), 'http://bazaar-vcs.org/bzr/bzr.dev')
eq(t.abspath('foo/bar'), 'http://bazaar-vcs.org/bzr/bzr.dev/foo/bar')
eq(t.abspath('.bzr'), 'http://bazaar-vcs.org/bzr/bzr.dev/.bzr')
eq(t.abspath('.bzr/1//2/./3'),
'http://bazaar-vcs.org/bzr/bzr.dev/.bzr/1/2/3')
def test_invalid_http_urls(self):
"""Trap invalid construction of urls"""
t = self._transport('http://bazaar-vcs.org/bzr/bzr.dev/')
self.assertRaises(errors.InvalidURL,
self._transport,
'http://http://bazaar-vcs.org/bzr/bzr.dev/')
def test_http_root_urls(self):
"""Construction of URLs from server root"""
t = self._transport('http://bzr.ozlabs.org/')
eq = self.assertEqualDiff
eq(t.abspath('.bzr/tree-version'),
'http://bzr.ozlabs.org/.bzr/tree-version')
def test_http_impl_urls(self):
"""There are servers which ask for particular clients to connect"""
server = self._server()
try:
server.setUp()
url = server.get_url()
self.assertTrue(url.startswith('%s://' % self._qualified_prefix))
finally:
server.tearDown()
class TestHttpConnections(http_utils.TestCaseWithWebserver):
"""Test the http connections."""
def setUp(self):
http_utils.TestCaseWithWebserver.setUp(self)
self.build_tree(['foo/', 'foo/bar'], line_endings='binary',
transport=self.get_transport())
def test_http_has(self):
server = self.get_readonly_server()
t = self._transport(server.get_url())
self.assertEqual(t.has('foo/bar'), True)
self.assertEqual(len(server.logs), 1)
self.assertContainsRe(server.logs[0],
r'"HEAD /foo/bar HTTP/1.." (200|302) - "-" "bzr/')
def test_http_has_not_found(self):
server = self.get_readonly_server()
t = self._transport(server.get_url())
self.assertEqual(t.has('not-found'), False)
self.assertContainsRe(server.logs[1],
r'"HEAD /not-found HTTP/1.." 404 - "-" "bzr/')
def test_http_get(self):
server = self.get_readonly_server()
t = self._transport(server.get_url())
fp = t.get('foo/bar')
self.assertEqualDiff(
fp.read(),
'contents of foo/bar\n')
self.assertEqual(len(server.logs), 1)
self.assertTrue(server.logs[0].find(
'"GET /foo/bar HTTP/1.1" 200 - "-" "bzr/%s'
% bzrlib.__version__) > -1)
def test_get_smart_medium(self):
# For HTTP, get_smart_medium should return the transport object.
server = self.get_readonly_server()
http_transport = self._transport(server.get_url())
medium = http_transport.get_smart_medium()
self.assertIs(medium, http_transport)
def test_has_on_bogus_host(self):
# Get a free address and don't 'accept' on it, so that we
# can be sure there is no http handler there, but set a
# reasonable timeout to not slow down tests too much.
default_timeout = socket.getdefaulttimeout()
try:
socket.setdefaulttimeout(2)
s = socket.socket()
s.bind(('localhost', 0))
t = self._transport('http://%s:%s/' % s.getsockname())
self.assertRaises(errors.ConnectionError, t.has, 'foo/bar')
finally:
socket.setdefaulttimeout(default_timeout)
class TestPost(tests.TestCase):
def test_post_body_is_received(self):
server = http_utils.RecordingServer(expect_body_tail='end-of-body')
server.setUp()
self.addCleanup(server.tearDown)
scheme = self._qualified_prefix
url = '%s://%s:%s/' % (scheme, server.host, server.port)
try:
http_transport = transport.get_transport(url)
except errors.UnsupportedProtocol:
raise tests.TestSkipped('%s not available' % scheme)
code, response = http_transport._post('abc def end-of-body')
self.assertTrue(
server.received_bytes.startswith('POST /.bzr/smart HTTP/1.'))
self.assertTrue('content-length: 19\r' in server.received_bytes.lower())
# The transport should not be assuming that the server can accept
# chunked encoding the first time it connects, because HTTP/1.1, so we
# check for the literal string.
self.assertTrue(
server.received_bytes.endswith('\r\n\r\nabc def end-of-body'))
|