/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_smart_request.py

  • Committer: Marius Kruger
  • Date: 2010-07-10 21:28:56 UTC
  • mto: (5384.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 5385.
  • Revision ID: marius.kruger@enerweb.co.za-20100710212856-uq4ji3go0u5se7hx
* Update documentation
* add NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
"""Tests for smart server request infrastructure (breezy.bzr.smart.request)."""
 
17
"""Tests for smart server request infrastructure (bzrlib.smart.request)."""
18
18
 
19
19
import threading
20
20
 
21
 
from breezy import (
 
21
from bzrlib import (
22
22
    errors,
23
23
    transport,
24
24
    )
25
 
from breezy.bzr.bzrdir import BzrDir
26
 
from breezy.bzr.smart import request
27
 
from breezy.tests import TestCase, TestCaseWithMemoryTransport
 
25
from bzrlib.bzrdir import BzrDir
 
26
from bzrlib.smart import request
 
27
from bzrlib.tests import TestCase, TestCaseWithMemoryTransport
28
28
 
29
29
 
30
30
class NoBodyRequest(request.SmartServerRequest):
41
41
        raise errors.NoSuchFile('xyzzy')
42
42
 
43
43
 
44
 
class DoUnexpectedErrorRequest(request.SmartServerRequest):
45
 
    """A request that encounters a generic error in self.do()"""
46
 
 
47
 
    def do(self):
48
 
        dict()[1]
49
 
 
50
 
 
51
44
class ChunkErrorRequest(request.SmartServerRequest):
52
45
    """A request that raises an error from self.do_chunk()."""
53
 
 
 
46
    
54
47
    def do(self):
55
48
        """No-op."""
56
49
        pass
61
54
 
62
55
class EndErrorRequest(request.SmartServerRequest):
63
56
    """A request that raises an error from self.do_end()."""
64
 
 
 
57
    
65
58
    def do(self):
66
59
        """No-op."""
67
60
        pass
69
62
    def do_chunk(self, bytes):
70
63
        """No-op."""
71
64
        pass
72
 
 
 
65
        
73
66
    def do_end(self):
74
67
        raise errors.NoSuchFile('xyzzy')
75
68
 
90
83
        self.jail_transports_log.append(request.jail_info.transports)
91
84
 
92
85
 
93
 
class TestErrors(TestCase):
94
 
 
95
 
    def test_disabled_method(self):
96
 
        error = request.DisabledMethod("class name")
97
 
        self.assertEqualDiff(
98
 
            "The smart server method 'class name' is disabled.", str(error))
99
 
 
100
 
 
101
86
class TestSmartRequest(TestCase):
102
87
 
103
88
    def test_request_class_without_do_body(self):
107
92
        # Create a SmartServerRequestHandler with a SmartServerRequest subclass
108
93
        # that does not implement do_body.
109
94
        handler = request.SmartServerRequestHandler(
110
 
            None, {b'foo': NoBodyRequest}, '/')
 
95
            None, {'foo': NoBodyRequest}, '/')
111
96
        # Emulate a request with no body (i.e. just args).
112
 
        handler.args_received((b'foo',))
 
97
        handler.args_received(('foo',))
113
98
        handler.end_received()
114
99
        # Request done, no exception was raised.
115
100
 
116
101
    def test_only_request_code_is_jailed(self):
117
102
        transport = 'dummy transport'
118
103
        handler = request.SmartServerRequestHandler(
119
 
            transport, {b'foo': CheckJailRequest}, '/')
120
 
        handler.args_received((b'foo',))
 
104
            transport, {'foo': CheckJailRequest}, '/')
 
105
        handler.args_received(('foo',))
121
106
        self.assertEqual(None, request.jail_info.transports)
122
 
        handler.accept_body(b'bytes')
 
107
        handler.accept_body('bytes')
123
108
        self.assertEqual(None, request.jail_info.transports)
124
109
        handler.end_received()
125
110
        self.assertEqual(None, request.jail_info.transports)
126
111
        self.assertEqual(
127
112
            [[transport]] * 3, handler._command.jail_transports_log)
128
113
 
129
 
    def test_all_registered_requests_are_safety_qualified(self):
130
 
        unclassified_requests = []
131
 
        allowed_info = ('read', 'idem', 'mutate', 'semivfs', 'semi', 'stream')
132
 
        for key in request.request_handlers.keys():
133
 
            info = request.request_handlers.get_info(key)
134
 
            if info is None or info not in allowed_info:
135
 
                unclassified_requests.append(key)
136
 
        if unclassified_requests:
137
 
            self.fail('These requests were not categorized as safe/unsafe'
138
 
                      ' to retry: %s' % (unclassified_requests,))
139
114
 
140
115
 
141
116
class TestSmartRequestHandlerErrorTranslation(TestCase):
147
122
        self.assertEqual(None, handler.response)
148
123
 
149
124
    def assertResponseIsTranslatedError(self, handler):
150
 
        expected_translation = (b'NoSuchFile', b'xyzzy')
 
125
        expected_translation = ('NoSuchFile', 'xyzzy')
151
126
        self.assertEqual(
152
127
            request.FailedSmartServerResponse(expected_translation),
153
128
            handler.response)
154
129
 
155
130
    def test_error_translation_from_args_received(self):
156
131
        handler = request.SmartServerRequestHandler(
157
 
            None, {b'foo': DoErrorRequest}, '/')
158
 
        handler.args_received((b'foo',))
 
132
            None, {'foo': DoErrorRequest}, '/')
 
133
        handler.args_received(('foo',))
159
134
        self.assertResponseIsTranslatedError(handler)
160
135
 
161
136
    def test_error_translation_from_chunk_received(self):
162
137
        handler = request.SmartServerRequestHandler(
163
 
            None, {b'foo': ChunkErrorRequest}, '/')
164
 
        handler.args_received((b'foo',))
 
138
            None, {'foo': ChunkErrorRequest}, '/')
 
139
        handler.args_received(('foo',))
165
140
        self.assertNoResponse(handler)
166
 
        handler.accept_body(b'bytes')
 
141
        handler.accept_body('bytes')
167
142
        self.assertResponseIsTranslatedError(handler)
168
143
 
169
144
    def test_error_translation_from_end_received(self):
170
145
        handler = request.SmartServerRequestHandler(
171
 
            None, {b'foo': EndErrorRequest}, '/')
172
 
        handler.args_received((b'foo',))
 
146
            None, {'foo': EndErrorRequest}, '/')
 
147
        handler.args_received(('foo',))
173
148
        self.assertNoResponse(handler)
174
149
        handler.end_received()
175
150
        self.assertResponseIsTranslatedError(handler)
176
151
 
177
 
    def test_unexpected_error_translation(self):
178
 
        handler = request.SmartServerRequestHandler(
179
 
            None, {b'foo': DoUnexpectedErrorRequest}, '/')
180
 
        handler.args_received((b'foo',))
181
 
        self.assertEqual(
182
 
            request.FailedSmartServerResponse((b'error', b'KeyError', b"1")),
183
 
            handler.response)
184
 
 
185
152
 
186
153
class TestRequestHanderErrorTranslation(TestCase):
187
 
    """Tests for breezy.bzr.smart.request._translate_error."""
 
154
    """Tests for bzrlib.smart.request._translate_error."""
188
155
 
189
156
    def assertTranslationEqual(self, expected_tuple, error):
190
157
        self.assertEqual(expected_tuple, request._translate_error(error))
191
158
 
192
159
    def test_NoSuchFile(self):
193
160
        self.assertTranslationEqual(
194
 
            (b'NoSuchFile', b'path'), errors.NoSuchFile('path'))
 
161
            ('NoSuchFile', 'path'), errors.NoSuchFile('path'))
195
162
 
196
163
    def test_LockContention(self):
197
164
        # For now, LockContentions are always transmitted with no details.
198
165
        # Eventually they should include a relpath or url or something else to
199
166
        # identify which lock is busy.
200
167
        self.assertTranslationEqual(
201
 
            (b'LockContention',), errors.LockContention('lock', 'msg'))
 
168
            ('LockContention',), errors.LockContention('lock', 'msg'))
202
169
 
203
170
    def test_TokenMismatch(self):
204
171
        self.assertTranslationEqual(
205
 
            (b'TokenMismatch', b'some-token', b'actual-token'),
206
 
            errors.TokenMismatch(b'some-token', b'actual-token'))
207
 
 
208
 
    def test_MemoryError(self):
209
 
        self.assertTranslationEqual((b"MemoryError",), MemoryError())
210
 
 
211
 
    def test_GhostRevisionsHaveNoRevno(self):
212
 
        self.assertTranslationEqual(
213
 
            (b"GhostRevisionsHaveNoRevno", b'revid1', b'revid2'),
214
 
            errors.GhostRevisionsHaveNoRevno(b'revid1', b'revid2'))
215
 
 
216
 
    def test_generic_Exception(self):
217
 
        self.assertTranslationEqual((b'error', b'Exception', b""),
218
 
                                    Exception())
219
 
 
220
 
    def test_generic_BzrError(self):
221
 
        self.assertTranslationEqual((b'error', b'BzrError', b"some text"),
222
 
                                    errors.BzrError(msg="some text"))
223
 
 
224
 
    def test_generic_zlib_error(self):
225
 
        from zlib import error
226
 
        msg = "Error -3 while decompressing data: incorrect data check"
227
 
        self.assertTranslationEqual((b'error', b'zlib.error', msg.encode('utf-8')),
228
 
                                    error(msg))
 
172
            ('TokenMismatch', 'some-token', 'actual-token'),
 
173
            errors.TokenMismatch('some-token', 'actual-token'))
229
174
 
230
175
 
231
176
class TestRequestJail(TestCaseWithMemoryTransport):
242
187
 
243
188
class TestJailHook(TestCaseWithMemoryTransport):
244
189
 
245
 
    def setUp(self):
246
 
        super(TestJailHook, self).setUp()
247
 
 
248
 
        def clear_jail_info():
249
 
            request.jail_info.transports = None
250
 
        self.addCleanup(clear_jail_info)
 
190
    def tearDown(self):
 
191
        request.jail_info.transports = None
 
192
        TestCaseWithMemoryTransport.tearDown(self)
251
193
 
252
194
    def test_jail_hook(self):
253
195
        request.jail_info.transports = None
264
206
        self.assertRaises(errors.JailBreak, _pre_open_hook, t.clone('..'))
265
207
        # A completely unrelated transport is not allowed
266
208
        self.assertRaises(errors.JailBreak, _pre_open_hook,
267
 
                          transport.get_transport_from_url('http://host/'))
 
209
                          transport.get_transport('http://host/'))
268
210
 
269
211
    def test_open_bzrdir_in_non_main_thread(self):
270
212
        """Opening a bzrdir in a non-main thread should work ok.
271
 
 
 
213
        
272
214
        This makes sure that the globally-installed
273
 
        breezy.bzr.smart.request._pre_open_hook, which uses a threading.local(),
 
215
        bzrlib.smart.request._pre_open_hook, which uses a threading.local(),
274
216
        works in a newly created thread.
275
217
        """
276
 
        bzrdir = self.make_controldir('.')
 
218
        bzrdir = self.make_bzrdir('.')
277
219
        transport = bzrdir.root_transport
278
220
        thread_result = []
279
 
 
280
221
        def t():
281
222
            BzrDir.open_from_transport(transport)
282
223
            thread_result.append('ok')
284
225
        thread.start()
285
226
        thread.join()
286
227
        self.assertEqual(['ok'], thread_result)
 
228