28
32
return request.SuccessfulSmartServerResponse(('ok',))
35
class DoErrorRequest(request.SmartServerRequest):
36
"""A request that raises an error from self.do()."""
39
raise errors.NoSuchFile('xyzzy')
42
class ChunkErrorRequest(request.SmartServerRequest):
43
"""A request that raises an error from self.do_chunk()."""
49
def do_chunk(self, bytes):
50
raise errors.NoSuchFile('xyzzy')
53
class EndErrorRequest(request.SmartServerRequest):
54
"""A request that raises an error from self.do_end()."""
60
def do_chunk(self, bytes):
65
raise errors.NoSuchFile('xyzzy')
68
class CheckJailRequest(request.SmartServerRequest):
70
def __init__(self, *args):
71
request.SmartServerRequest.__init__(self, *args)
72
self.jail_transports_log = []
75
self.jail_transports_log.append(request.jail_info.transports)
77
def do_chunk(self, bytes):
78
self.jail_transports_log.append(request.jail_info.transports)
81
self.jail_transports_log.append(request.jail_info.transports)
31
84
class TestSmartRequest(TestCase):
33
86
def test_request_class_without_do_body(self):
43
96
handler.end_received()
44
97
# Request done, no exception was raised.
46
def test_unexpected_body(self):
47
"""If a request implementation receives an unexpected body, it
99
def test_only_request_code_is_jailed(self):
100
transport = 'dummy transport'
101
handler = request.SmartServerRequestHandler(
102
transport, {'foo': CheckJailRequest}, '/')
103
handler.args_received(('foo',))
104
self.assertEqual(None, request.jail_info.transports)
105
handler.accept_body('bytes')
106
self.assertEqual(None, request.jail_info.transports)
107
handler.end_received()
108
self.assertEqual(None, request.jail_info.transports)
110
[[transport]] * 3, handler._command.jail_transports_log)
114
class TestSmartRequestHandlerErrorTranslation(TestCase):
115
"""Tests that SmartServerRequestHandler will translate exceptions raised by
116
a SmartServerRequest into FailedSmartServerResponses.
119
def assertNoResponse(self, handler):
120
self.assertEqual(None, handler.response)
122
def assertResponseIsTranslatedError(self, handler):
123
expected_translation = ('NoSuchFile', 'xyzzy')
125
request.FailedSmartServerResponse(expected_translation),
128
def test_error_translation_from_args_received(self):
129
handler = request.SmartServerRequestHandler(
130
None, {'foo': DoErrorRequest}, '/')
131
handler.args_received(('foo',))
132
self.assertResponseIsTranslatedError(handler)
134
def test_error_translation_from_chunk_received(self):
135
handler = request.SmartServerRequestHandler(
136
None, {'foo': ChunkErrorRequest}, '/')
137
handler.args_received(('foo',))
138
self.assertNoResponse(handler)
139
handler.accept_body('bytes')
140
self.assertResponseIsTranslatedError(handler)
142
def test_error_translation_from_end_received(self):
143
handler = request.SmartServerRequestHandler(
144
None, {'foo': EndErrorRequest}, '/')
145
handler.args_received(('foo',))
146
self.assertNoResponse(handler)
147
handler.end_received()
148
self.assertResponseIsTranslatedError(handler)
151
class TestRequestHanderErrorTranslation(TestCase):
152
"""Tests for bzrlib.smart.request._translate_error."""
154
def assertTranslationEqual(self, expected_tuple, error):
155
self.assertEqual(expected_tuple, request._translate_error(error))
157
def test_NoSuchFile(self):
158
self.assertTranslationEqual(
159
('NoSuchFile', 'path'), errors.NoSuchFile('path'))
161
def test_LockContention(self):
162
self.assertTranslationEqual(
163
('LockContention', 'lock', 'msg'),
164
errors.LockContention('lock', 'msg'))
166
def test_TokenMismatch(self):
167
self.assertTranslationEqual(
168
('TokenMismatch', 'some-token', 'actual-token'),
169
errors.TokenMismatch('some-token', 'actual-token'))
172
class TestRequestJail(TestCaseWithMemoryTransport):
175
transport = self.get_transport('blah')
176
req = request.SmartServerRequest(transport)
177
self.assertEqual(None, request.jail_info.transports)
179
self.assertEqual([transport], request.jail_info.transports)
181
self.assertEqual(None, request.jail_info.transports)
184
class TestJailHook(TestCaseWithMemoryTransport):
187
request.jail_info.transports = None
188
TestCaseWithMemoryTransport.tearDown(self)
190
def test_jail_hook(self):
191
request.jail_info.transports = None
192
_pre_open_hook = request._pre_open_hook
193
# Any transport is fine if jail_info.transports is None
194
t = self.get_transport('foo')
196
# A transport in jail_info.transports is allowed
197
request.jail_info.transports = [t]
199
# A child of a transport in jail_info is allowed
200
_pre_open_hook(t.clone('child'))
201
# A parent is not allowed
202
self.assertRaises(errors.BzrError, _pre_open_hook, t.clone('..'))
203
# A completely unrelated transport is not allowed
205
errors.BzrError, _pre_open_hook, get_transport('http://host/'))
207
def test_open_bzrdir_in_non_main_thread(self):
208
"""Opening a bzrdir in a non-main thread should work ok.
210
This makes sure that the globally-installed
211
bzrlib.smart.request._pre_open_hook, which uses a threading.local(),
212
works in a newly created thread.
50
# Create a SmartServerRequestHandler with a SmartServerRequest subclass
51
# that does not implement do_body.
52
handler = request.SmartServerRequestHandler(
53
None, {'foo': NoBodyRequest}, '/')
54
# Emulate a request with a body
55
handler.args_received(('foo',))
56
handler.accept_body('some body bytes')
57
# Note that the exception currently occurs at the end of the request.
58
# In principle it would also be ok for it to happen earlier, during
60
exc = self.assertRaises(errors.SmartProtocolError, handler.end_received)
61
self.assertEquals('Request does not expect a body', exc.details)
214
bzrdir = self.make_bzrdir('.')
215
transport = bzrdir.root_transport
218
BzrDir.open_from_transport(transport)
219
thread_result.append('ok')
220
thread = threading.Thread(target=t)
223
self.assertEqual(['ok'], thread_result)