13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
"""Tests for smart server request infrastructure (bzrlib.smart.request)."""
25
from bzrlib.bzrdir import BzrDir
19
from bzrlib import errors
26
20
from bzrlib.smart import request
27
from bzrlib.tests import TestCase, TestCaseWithMemoryTransport
21
from bzrlib.tests import TestCase
30
24
class NoBodyRequest(request.SmartServerRequest):
67
61
raise errors.NoSuchFile('xyzzy')
70
class CheckJailRequest(request.SmartServerRequest):
72
def __init__(self, *args):
73
request.SmartServerRequest.__init__(self, *args)
74
self.jail_transports_log = []
77
self.jail_transports_log.append(request.jail_info.transports)
79
def do_chunk(self, bytes):
80
self.jail_transports_log.append(request.jail_info.transports)
83
self.jail_transports_log.append(request.jail_info.transports)
86
64
class TestSmartRequest(TestCase):
88
66
def test_request_class_without_do_body(self):
98
76
handler.end_received()
99
77
# Request done, no exception was raised.
101
def test_only_request_code_is_jailed(self):
102
transport = 'dummy transport'
103
handler = request.SmartServerRequestHandler(
104
transport, {'foo': CheckJailRequest}, '/')
105
handler.args_received(('foo',))
106
self.assertEqual(None, request.jail_info.transports)
107
handler.accept_body('bytes')
108
self.assertEqual(None, request.jail_info.transports)
109
handler.end_received()
110
self.assertEqual(None, request.jail_info.transports)
112
[[transport]] * 3, handler._command.jail_transports_log)
116
80
class TestSmartRequestHandlerErrorTranslation(TestCase):
117
81
"""Tests that SmartServerRequestHandler will translate exceptions raised by
161
125
('NoSuchFile', 'path'), errors.NoSuchFile('path'))
163
127
def test_LockContention(self):
164
# For now, LockContentions are always transmitted with no details.
165
# Eventually they should include a relpath or url or something else to
166
# identify which lock is busy.
167
128
self.assertTranslationEqual(
168
('LockContention',), errors.LockContention('lock', 'msg'))
129
('LockContention', 'lock', 'msg'),
130
errors.LockContention('lock', 'msg'))
170
132
def test_TokenMismatch(self):
171
133
self.assertTranslationEqual(
172
134
('TokenMismatch', 'some-token', 'actual-token'),
173
135
errors.TokenMismatch('some-token', 'actual-token'))
176
class TestRequestJail(TestCaseWithMemoryTransport):
179
transport = self.get_transport('blah')
180
req = request.SmartServerRequest(transport)
181
self.assertEqual(None, request.jail_info.transports)
183
self.assertEqual([transport], request.jail_info.transports)
185
self.assertEqual(None, request.jail_info.transports)
188
class TestJailHook(TestCaseWithMemoryTransport):
191
super(TestJailHook, self).setUp()
192
def clear_jail_info():
193
request.jail_info.transports = None
194
self.addCleanup(clear_jail_info)
196
def test_jail_hook(self):
197
request.jail_info.transports = None
198
_pre_open_hook = request._pre_open_hook
199
# Any transport is fine if jail_info.transports is None
200
t = self.get_transport('foo')
202
# A transport in jail_info.transports is allowed
203
request.jail_info.transports = [t]
205
# A child of a transport in jail_info is allowed
206
_pre_open_hook(t.clone('child'))
207
# A parent is not allowed
208
self.assertRaises(errors.JailBreak, _pre_open_hook, t.clone('..'))
209
# A completely unrelated transport is not allowed
210
self.assertRaises(errors.JailBreak, _pre_open_hook,
211
transport.get_transport('http://host/'))
213
def test_open_bzrdir_in_non_main_thread(self):
214
"""Opening a bzrdir in a non-main thread should work ok.
216
This makes sure that the globally-installed
217
bzrlib.smart.request._pre_open_hook, which uses a threading.local(),
218
works in a newly created thread.
220
bzrdir = self.make_bzrdir('.')
221
transport = bzrdir.root_transport
224
BzrDir.open_from_transport(transport)
225
thread_result.append('ok')
226
thread = threading.Thread(target=t)
229
self.assertEqual(['ok'], thread_result)