/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 breezy/tests/test_smart.py

  • Committer: Jelmer Vernooij
  • Date: 2018-07-08 14:45:27 UTC
  • mto: This revision was merged to the branch mainline in revision 7036.
  • Revision ID: jelmer@jelmer.uk-20180708144527-codhlvdcdg9y0nji
Fix a bunch of merge tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006-2012, 2016 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
25
25
"""
26
26
 
27
27
import bz2
28
 
from cStringIO import StringIO
 
28
from io import BytesIO
29
29
import tarfile
 
30
import zlib
30
31
 
31
 
from bzrlib import (
 
32
from breezy import (
32
33
    bencode,
33
34
    branch as _mod_branch,
34
 
    bzrdir,
 
35
    controldir,
35
36
    errors,
36
 
    pack,
 
37
    gpg,
37
38
    tests,
38
39
    transport,
39
40
    urlutils,
 
41
    )
 
42
from breezy.bzr import (
 
43
    branch as _mod_bzrbranch,
 
44
    inventory_delta,
40
45
    versionedfile,
41
46
    )
42
 
from bzrlib.smart import (
 
47
from breezy.bzr.smart import (
43
48
    branch as smart_branch,
44
49
    bzrdir as smart_dir,
45
50
    repository as smart_repo,
48
53
    server,
49
54
    vfs,
50
55
    )
51
 
from bzrlib.tests import test_server
52
 
from bzrlib.transport import (
 
56
from breezy.testament import Testament
 
57
from breezy.tests import test_server
 
58
from breezy.transport import (
53
59
    chroot,
54
60
    memory,
55
61
    )
56
62
 
57
63
 
58
 
def load_tests(standard_tests, module, loader):
 
64
def load_tests(loader, standard_tests, pattern):
59
65
    """Multiply tests version and protocol consistency."""
60
66
    # FindRepository tests.
61
67
    scenarios = [
81
87
 
82
88
    def setUp(self):
83
89
        self.vfs_transport_factory = memory.MemoryServer
84
 
        tests.TestCaseWithTransport.setUp(self)
 
90
        super(TestCaseWithChrootedTransport, self).setUp()
85
91
        self._chroot_server = None
86
92
 
87
93
    def get_transport(self, relpath=None):
89
95
            backing_transport = tests.TestCaseWithTransport.get_transport(self)
90
96
            self._chroot_server = chroot.ChrootServer(backing_transport)
91
97
            self.start_server(self._chroot_server)
92
 
        t = transport.get_transport(self._chroot_server.get_url())
 
98
        t = transport.get_transport_from_url(self._chroot_server.get_url())
93
99
        if relpath is not None:
94
100
            t = t.clone(relpath)
95
101
        return t
103
109
        # the default or a parameterized class, but rather use the
104
110
        # TestCaseWithTransport infrastructure to set up a smart server and
105
111
        # transport.
106
 
        self.transport_server = self.make_transport_server
 
112
        self.overrideAttr(self, "transport_server", self.make_transport_server)
107
113
 
108
114
    def make_transport_server(self):
109
115
        return test_server.SmartTCPServer_for_testing('-' + self.id())
117
123
 
118
124
    def test_repeated_substreams_same_kind_are_one_stream(self):
119
125
        # Make a stream - an iterable of bytestrings.
120
 
        stream = [('text', [versionedfile.FulltextContentFactory(('k1',), None,
121
 
            None, 'foo')]),('text', [
122
 
            versionedfile.FulltextContentFactory(('k2',), None, None, 'bar')])]
123
 
        fmt = bzrdir.format_registry.get('pack-0.92')().repository_format
 
126
        stream = [('text', [versionedfile.FulltextContentFactory((b'k1',), None,
 
127
            None, b'foo')]), ('text', [
 
128
            versionedfile.FulltextContentFactory((b'k2',), None, None, b'bar')])]
 
129
        fmt = controldir.format_registry.get('pack-0.92')().repository_format
124
130
        bytes = smart_repo._stream_to_byte_stream(stream, fmt)
125
131
        streams = []
126
132
        # Iterate the resulting iterable; checking that we get only one stream
135
141
class TestSmartServerResponse(tests.TestCase):
136
142
 
137
143
    def test__eq__(self):
138
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', )),
139
 
            smart_req.SmartServerResponse(('ok', )))
140
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), 'body'),
141
 
            smart_req.SmartServerResponse(('ok', ), 'body'))
142
 
        self.assertNotEqual(smart_req.SmartServerResponse(('ok', )),
143
 
            smart_req.SmartServerResponse(('notok', )))
144
 
        self.assertNotEqual(smart_req.SmartServerResponse(('ok', ), 'body'),
145
 
            smart_req.SmartServerResponse(('ok', )))
 
144
        self.assertEqual(smart_req.SmartServerResponse((b'ok', )),
 
145
            smart_req.SmartServerResponse((b'ok', )))
 
146
        self.assertEqual(smart_req.SmartServerResponse((b'ok', ), b'body'),
 
147
            smart_req.SmartServerResponse((b'ok', ), b'body'))
 
148
        self.assertNotEqual(smart_req.SmartServerResponse((b'ok', )),
 
149
            smart_req.SmartServerResponse((b'notok', )))
 
150
        self.assertNotEqual(smart_req.SmartServerResponse((b'ok', ), b'body'),
 
151
            smart_req.SmartServerResponse((b'ok', )))
146
152
        self.assertNotEqual(None,
147
 
            smart_req.SmartServerResponse(('ok', )))
 
153
            smart_req.SmartServerResponse((b'ok', )))
148
154
 
149
155
    def test__str__(self):
150
156
        """SmartServerResponses can be stringified."""
151
 
        self.assertEqual(
152
 
            "<SuccessfulSmartServerResponse args=('args',) body='body'>",
153
 
            str(smart_req.SuccessfulSmartServerResponse(('args',), 'body')))
154
 
        self.assertEqual(
155
 
            "<FailedSmartServerResponse args=('args',) body='body'>",
156
 
            str(smart_req.FailedSmartServerResponse(('args',), 'body')))
 
157
        self.assertIn(
 
158
            str(smart_req.SuccessfulSmartServerResponse((b'args',), b'body')),
 
159
            ("<SuccessfulSmartServerResponse args=(b'args',) body=b'body'>",
 
160
             "<SuccessfulSmartServerResponse args=('args',) body='body'>"))
 
161
        self.assertIn(
 
162
            str(smart_req.FailedSmartServerResponse((b'args',), b'body')),
 
163
            ("<FailedSmartServerResponse args=(b'args',) body=b'body'>",
 
164
             "<FailedSmartServerResponse args=('args',) body='body'>"))
157
165
 
158
166
 
159
167
class TestSmartServerRequest(tests.TestCaseWithMemoryTransport):
161
169
    def test_translate_client_path(self):
162
170
        transport = self.get_transport()
163
171
        request = smart_req.SmartServerRequest(transport, 'foo/')
164
 
        self.assertEqual('./', request.translate_client_path('foo/'))
165
 
        self.assertRaises(
166
 
            errors.InvalidURLJoin, request.translate_client_path, 'foo/..')
167
 
        self.assertRaises(
168
 
            errors.PathNotChild, request.translate_client_path, '/')
169
 
        self.assertRaises(
170
 
            errors.PathNotChild, request.translate_client_path, 'bar/')
171
 
        self.assertEqual('./baz', request.translate_client_path('foo/baz'))
172
 
        e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'.encode('utf-8')
173
 
        self.assertEqual('./' + urlutils.escape(e_acute),
174
 
                         request.translate_client_path('foo/' + e_acute))
 
172
        self.assertEqual('./', request.translate_client_path(b'foo/'))
 
173
        self.assertRaises(
 
174
            urlutils.InvalidURLJoin, request.translate_client_path, b'foo/..')
 
175
        self.assertRaises(
 
176
            errors.PathNotChild, request.translate_client_path, b'/')
 
177
        self.assertRaises(
 
178
            errors.PathNotChild, request.translate_client_path, b'bar/')
 
179
        self.assertEqual('./baz', request.translate_client_path(b'foo/baz'))
 
180
        e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'
 
181
        self.assertEqual(u'./' + urlutils.escape(e_acute),
 
182
                         request.translate_client_path(b'foo/' + e_acute.encode('utf-8')))
175
183
 
176
184
    def test_translate_client_path_vfs(self):
177
185
        """VfsRequests receive escaped paths rather than raw UTF-8."""
178
186
        transport = self.get_transport()
179
 
        request = vfs.VfsRequest(transport, 'foo/')
180
 
        e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'.encode('utf-8')
181
 
        escaped = urlutils.escape('foo/' + e_acute)
182
 
        self.assertEqual('./' + urlutils.escape(e_acute),
 
187
        request = vfs.VfsRequest(transport, b'foo/')
 
188
        e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'
 
189
        escaped = urlutils.escape(u'foo/' + e_acute)
 
190
        self.assertEqual(b'./' + urlutils.escape(e_acute).encode('utf-8'),
183
191
                         request.translate_client_path(escaped))
184
192
 
185
193
    def test_transport_from_client_path(self):
187
195
        request = smart_req.SmartServerRequest(transport, 'foo/')
188
196
        self.assertEqual(
189
197
            transport.base,
190
 
            request.transport_from_client_path('foo/').base)
 
198
            request.transport_from_client_path(b'foo/').base)
191
199
 
192
200
 
193
201
class TestSmartServerBzrDirRequestCloningMetaDir(
197
205
    def test_cloning_metadir(self):
198
206
        """When there is a bzrdir present, the call succeeds."""
199
207
        backing = self.get_transport()
200
 
        dir = self.make_bzrdir('.')
 
208
        dir = self.make_controldir('.')
201
209
        local_result = dir.cloning_metadir()
202
210
        request_class = smart_dir.SmartServerBzrDirRequestCloningMetaDir
203
211
        request = request_class(backing)
204
212
        expected = smart_req.SuccessfulSmartServerResponse(
205
213
            (local_result.network_name(),
206
214
            local_result.repository_format.network_name(),
207
 
            ('branch', local_result.get_branch_format().network_name())))
208
 
        self.assertEqual(expected, request.execute('', 'False'))
 
215
            (b'branch', local_result.get_branch_format().network_name())))
 
216
        self.assertEqual(expected, request.execute(b'', b'False'))
209
217
 
210
218
    def test_cloning_metadir_reference(self):
211
219
        """The request fails when bzrdir contains a branch reference."""
212
220
        backing = self.get_transport()
213
221
        referenced_branch = self.make_branch('referenced')
214
 
        dir = self.make_bzrdir('.')
 
222
        dir = self.make_controldir('.')
215
223
        local_result = dir.cloning_metadir()
216
 
        reference = _mod_branch.BranchReferenceFormat().initialize(
 
224
        reference = _mod_bzrbranch.BranchReferenceFormat().initialize(
217
225
            dir, target_branch=referenced_branch)
218
 
        reference_url = _mod_branch.BranchReferenceFormat().get_reference(dir)
 
226
        reference_url = _mod_bzrbranch.BranchReferenceFormat().get_reference(dir)
219
227
        # The server shouldn't try to follow the branch reference, so it's fine
220
228
        # if the referenced branch isn't reachable.
221
229
        backing.rename('referenced', 'moved')
222
230
        request_class = smart_dir.SmartServerBzrDirRequestCloningMetaDir
223
231
        request = request_class(backing)
224
 
        expected = smart_req.FailedSmartServerResponse(('BranchReference',))
225
 
        self.assertEqual(expected, request.execute('', 'False'))
 
232
        expected = smart_req.FailedSmartServerResponse((b'BranchReference',))
 
233
        self.assertEqual(expected, request.execute(b'', b'False'))
 
234
 
 
235
 
 
236
class TestSmartServerBzrDirRequestCloningMetaDir(
 
237
    tests.TestCaseWithMemoryTransport):
 
238
    """Tests for BzrDir.checkout_metadir."""
 
239
 
 
240
    def test_checkout_metadir(self):
 
241
        backing = self.get_transport()
 
242
        request = smart_dir.SmartServerBzrDirRequestCheckoutMetaDir(
 
243
            backing)
 
244
        branch = self.make_branch('.', format='2a')
 
245
        response = request.execute(b'')
 
246
        self.assertEqual(
 
247
            smart_req.SmartServerResponse(
 
248
                (b'Bazaar-NG meta directory, format 1\n',
 
249
                 b'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
 
250
                 b'Bazaar Branch Format 7 (needs bzr 1.6)\n')),
 
251
            response)
 
252
 
 
253
 
 
254
class TestSmartServerBzrDirRequestDestroyBranch(
 
255
    tests.TestCaseWithMemoryTransport):
 
256
    """Tests for BzrDir.destroy_branch."""
 
257
 
 
258
    def test_destroy_branch_default(self):
 
259
        """The default branch can be removed."""
 
260
        backing = self.get_transport()
 
261
        dir = self.make_branch('.').controldir
 
262
        request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
 
263
        request = request_class(backing)
 
264
        expected = smart_req.SuccessfulSmartServerResponse((b'ok',))
 
265
        self.assertEqual(expected, request.execute(b'', None))
 
266
 
 
267
    def test_destroy_branch_named(self):
 
268
        """A named branch can be removed."""
 
269
        backing = self.get_transport()
 
270
        dir = self.make_repository('.', format="development-colo").controldir
 
271
        dir.create_branch(name="branchname")
 
272
        request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
 
273
        request = request_class(backing)
 
274
        expected = smart_req.SuccessfulSmartServerResponse((b'ok',))
 
275
        self.assertEqual(expected, request.execute(b'', "branchname"))
 
276
 
 
277
    def test_destroy_branch_missing(self):
 
278
        """An error is raised if the branch didn't exist."""
 
279
        backing = self.get_transport()
 
280
        dir = self.make_controldir('.', format="development-colo")
 
281
        request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
 
282
        request = request_class(backing)
 
283
        expected = smart_req.FailedSmartServerResponse((b'nobranch',), None)
 
284
        self.assertEqual(expected, request.execute(b'', b"branchname"))
 
285
 
 
286
 
 
287
class TestSmartServerBzrDirRequestHasWorkingTree(
 
288
    tests.TestCaseWithTransport):
 
289
    """Tests for BzrDir.has_workingtree."""
 
290
 
 
291
    def test_has_workingtree_yes(self):
 
292
        """A working tree is present."""
 
293
        backing = self.get_transport()
 
294
        dir = self.make_branch_and_tree('.').controldir
 
295
        request_class = smart_dir.SmartServerBzrDirRequestHasWorkingTree
 
296
        request = request_class(backing)
 
297
        expected = smart_req.SuccessfulSmartServerResponse((b'yes',))
 
298
        self.assertEqual(expected, request.execute(b''))
 
299
 
 
300
    def test_has_workingtree_no(self):
 
301
        """A working tree is missing."""
 
302
        backing = self.get_transport()
 
303
        dir = self.make_controldir('.')
 
304
        request_class = smart_dir.SmartServerBzrDirRequestHasWorkingTree
 
305
        request = request_class(backing)
 
306
        expected = smart_req.SuccessfulSmartServerResponse((b'no',))
 
307
        self.assertEqual(expected, request.execute(b''))
 
308
 
 
309
 
 
310
class TestSmartServerBzrDirRequestDestroyRepository(
 
311
    tests.TestCaseWithMemoryTransport):
 
312
    """Tests for BzrDir.destroy_repository."""
 
313
 
 
314
    def test_destroy_repository_default(self):
 
315
        """The repository can be removed."""
 
316
        backing = self.get_transport()
 
317
        dir = self.make_repository('.').controldir
 
318
        request_class = smart_dir.SmartServerBzrDirRequestDestroyRepository
 
319
        request = request_class(backing)
 
320
        expected = smart_req.SuccessfulSmartServerResponse((b'ok',))
 
321
        self.assertEqual(expected, request.execute(b''))
 
322
 
 
323
    def test_destroy_repository_missing(self):
 
324
        """An error is raised if the repository didn't exist."""
 
325
        backing = self.get_transport()
 
326
        dir = self.make_controldir('.')
 
327
        request_class = smart_dir.SmartServerBzrDirRequestDestroyRepository
 
328
        request = request_class(backing)
 
329
        expected = smart_req.FailedSmartServerResponse(
 
330
            (b'norepository',), None)
 
331
        self.assertEqual(expected, request.execute(b''))
226
332
 
227
333
 
228
334
class TestSmartServerRequestCreateRepository(tests.TestCaseWithMemoryTransport):
231
337
    def test_makes_repository(self):
232
338
        """When there is a bzrdir present, the call succeeds."""
233
339
        backing = self.get_transport()
234
 
        self.make_bzrdir('.')
 
340
        self.make_controldir('.')
235
341
        request_class = smart_dir.SmartServerRequestCreateRepository
236
342
        request = request_class(backing)
237
 
        reference_bzrdir_format = bzrdir.format_registry.get('pack-0.92')()
 
343
        reference_bzrdir_format = controldir.format_registry.get('pack-0.92')()
238
344
        reference_format = reference_bzrdir_format.repository_format
239
345
        network_name = reference_format.network_name()
240
346
        expected = smart_req.SuccessfulSmartServerResponse(
241
 
            ('ok', 'no', 'no', 'no', network_name))
242
 
        self.assertEqual(expected, request.execute('', network_name, 'True'))
 
347
            (b'ok', b'no', b'no', b'no', network_name))
 
348
        self.assertEqual(expected, request.execute(b'', network_name, b'True'))
243
349
 
244
350
 
245
351
class TestSmartServerRequestFindRepository(tests.TestCaseWithMemoryTransport):
249
355
        """When there is no repository to be found, ('norepository', ) is returned."""
250
356
        backing = self.get_transport()
251
357
        request = self._request_class(backing)
252
 
        self.make_bzrdir('.')
253
 
        self.assertEqual(smart_req.SmartServerResponse(('norepository', )),
254
 
            request.execute(''))
 
358
        self.make_controldir('.')
 
359
        self.assertEqual(smart_req.SmartServerResponse((b'norepository', )),
 
360
            request.execute(b''))
255
361
 
256
362
    def test_nonshared_repository(self):
257
363
        # nonshared repositorys only allow 'find' to return a handle when the
260
366
        backing = self.get_transport()
261
367
        request = self._request_class(backing)
262
368
        result = self._make_repository_and_result()
263
 
        self.assertEqual(result, request.execute(''))
264
 
        self.make_bzrdir('subdir')
265
 
        self.assertEqual(smart_req.SmartServerResponse(('norepository', )),
266
 
            request.execute('subdir'))
 
369
        self.assertEqual(result, request.execute(b''))
 
370
        self.make_controldir('subdir')
 
371
        self.assertEqual(smart_req.SmartServerResponse((b'norepository', )),
 
372
            request.execute(b'subdir'))
267
373
 
268
374
    def _make_repository_and_result(self, shared=False, format=None):
269
375
        """Convenience function to setup a repository.
272
378
        """
273
379
        repo = self.make_repository('.', shared=shared, format=format)
274
380
        if repo.supports_rich_root():
275
 
            rich_root = 'yes'
 
381
            rich_root = b'yes'
276
382
        else:
277
 
            rich_root = 'no'
 
383
            rich_root = b'no'
278
384
        if repo._format.supports_tree_reference:
279
 
            subtrees = 'yes'
 
385
            subtrees = b'yes'
280
386
        else:
281
 
            subtrees = 'no'
 
387
            subtrees = b'no'
282
388
        if repo._format.supports_external_lookups:
283
 
            external = 'yes'
 
389
            external = b'yes'
284
390
        else:
285
 
            external = 'no'
 
391
            external = b'no'
286
392
        if (smart_dir.SmartServerRequestFindRepositoryV3 ==
287
393
            self._request_class):
288
394
            return smart_req.SuccessfulSmartServerResponse(
289
 
                ('ok', '', rich_root, subtrees, external,
 
395
                (b'ok', b'', rich_root, subtrees, external,
290
396
                 repo._format.network_name()))
291
397
        elif (smart_dir.SmartServerRequestFindRepositoryV2 ==
292
398
            self._request_class):
293
399
            # All tests so far are on formats, and for non-external
294
400
            # repositories.
295
401
            return smart_req.SuccessfulSmartServerResponse(
296
 
                ('ok', '', rich_root, subtrees, external))
 
402
                (b'ok', b'', rich_root, subtrees, external))
297
403
        else:
298
404
            return smart_req.SuccessfulSmartServerResponse(
299
 
                ('ok', '', rich_root, subtrees))
 
405
                (b'ok', b'', rich_root, subtrees))
300
406
 
301
407
    def test_shared_repository(self):
302
408
        """When there is a shared repository, we get 'ok', 'relpath-to-repo'."""
303
409
        backing = self.get_transport()
304
410
        request = self._request_class(backing)
305
411
        result = self._make_repository_and_result(shared=True)
306
 
        self.assertEqual(result, request.execute(''))
307
 
        self.make_bzrdir('subdir')
 
412
        self.assertEqual(result, request.execute(b''))
 
413
        self.make_controldir('subdir')
308
414
        result2 = smart_req.SmartServerResponse(
309
 
            result.args[0:1] + ('..', ) + result.args[2:])
 
415
            result.args[0:1] + (b'..', ) + result.args[2:])
310
416
        self.assertEqual(result2,
311
 
            request.execute('subdir'))
312
 
        self.make_bzrdir('subdir/deeper')
 
417
            request.execute(b'subdir'))
 
418
        self.make_controldir('subdir/deeper')
313
419
        result3 = smart_req.SmartServerResponse(
314
 
            result.args[0:1] + ('../..', ) + result.args[2:])
 
420
            result.args[0:1] + (b'../..', ) + result.args[2:])
315
421
        self.assertEqual(result3,
316
 
            request.execute('subdir/deeper'))
 
422
            request.execute(b'subdir/deeper'))
317
423
 
318
424
    def test_rich_root_and_subtree_encoding(self):
319
425
        """Test for the format attributes for rich root and subtree support."""
320
426
        backing = self.get_transport()
321
427
        request = self._request_class(backing)
322
428
        result = self._make_repository_and_result(
323
 
            format='dirstate-with-subtree')
 
429
            format='development-subtree')
324
430
        # check the test will be valid
325
 
        self.assertEqual('yes', result.args[2])
326
 
        self.assertEqual('yes', result.args[3])
327
 
        self.assertEqual(result, request.execute(''))
 
431
        self.assertEqual(b'yes', result.args[2])
 
432
        self.assertEqual(b'yes', result.args[3])
 
433
        self.assertEqual(result, request.execute(b''))
328
434
 
329
435
    def test_supports_external_lookups_no_v2(self):
330
436
        """Test for the supports_external_lookups attribute."""
331
437
        backing = self.get_transport()
332
438
        request = self._request_class(backing)
333
439
        result = self._make_repository_and_result(
334
 
            format='dirstate-with-subtree')
 
440
            format='development-subtree')
335
441
        # check the test will be valid
336
 
        self.assertEqual('no', result.args[4])
337
 
        self.assertEqual(result, request.execute(''))
 
442
        self.assertEqual(b'yes', result.args[4])
 
443
        self.assertEqual(result, request.execute(b''))
338
444
 
339
445
 
340
446
class TestSmartServerBzrDirRequestGetConfigFile(
343
449
 
344
450
    def test_present(self):
345
451
        backing = self.get_transport()
346
 
        dir = self.make_bzrdir('.')
 
452
        dir = self.make_controldir('.')
347
453
        dir.get_config().set_default_stack_on("/")
348
454
        local_result = dir._get_config()._get_config_file().read()
349
455
        request_class = smart_dir.SmartServerBzrDirRequestConfigFile
350
456
        request = request_class(backing)
351
457
        expected = smart_req.SuccessfulSmartServerResponse((), local_result)
352
 
        self.assertEqual(expected, request.execute(''))
 
458
        self.assertEqual(expected, request.execute(b''))
353
459
 
354
460
    def test_missing(self):
355
461
        backing = self.get_transport()
356
 
        dir = self.make_bzrdir('.')
 
462
        dir = self.make_controldir('.')
357
463
        request_class = smart_dir.SmartServerBzrDirRequestConfigFile
358
464
        request = request_class(backing)
359
 
        expected = smart_req.SuccessfulSmartServerResponse((), '')
360
 
        self.assertEqual(expected, request.execute(''))
 
465
        expected = smart_req.SuccessfulSmartServerResponse((), b'')
 
466
        self.assertEqual(expected, request.execute(b''))
 
467
 
 
468
 
 
469
class TestSmartServerBzrDirRequestGetBranches(
 
470
    tests.TestCaseWithMemoryTransport):
 
471
    """Tests for BzrDir.get_branches."""
 
472
 
 
473
    def test_simple(self):
 
474
        backing = self.get_transport()
 
475
        branch = self.make_branch('.')
 
476
        request_class = smart_dir.SmartServerBzrDirRequestGetBranches
 
477
        request = request_class(backing)
 
478
        local_result = bencode.bencode(
 
479
            {b"": (b"branch", branch._format.network_name())})
 
480
        expected = smart_req.SuccessfulSmartServerResponse(
 
481
            (b"success", ), local_result)
 
482
        self.assertEqual(expected, request.execute(b''))
 
483
 
 
484
    def test_empty(self):
 
485
        backing = self.get_transport()
 
486
        dir = self.make_controldir('.')
 
487
        request_class = smart_dir.SmartServerBzrDirRequestGetBranches
 
488
        request = request_class(backing)
 
489
        local_result = bencode.bencode({})
 
490
        expected = smart_req.SuccessfulSmartServerResponse(
 
491
            (b'success',), local_result)
 
492
        self.assertEqual(expected, request.execute(b''))
361
493
 
362
494
 
363
495
class TestSmartServerRequestInitializeBzrDir(tests.TestCaseWithMemoryTransport):
366
498
        """Initializing an empty dir should succeed and do it."""
367
499
        backing = self.get_transport()
368
500
        request = smart_dir.SmartServerRequestInitializeBzrDir(backing)
369
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', )),
370
 
            request.execute(''))
371
 
        made_dir = bzrdir.BzrDir.open_from_transport(backing)
 
501
        self.assertEqual(smart_req.SmartServerResponse((b'ok', )),
 
502
            request.execute(b''))
 
503
        made_dir = controldir.ControlDir.open_from_transport(backing)
372
504
        # no branch, tree or repository is expected with the current
373
505
        # default formart.
374
506
        self.assertRaises(errors.NoWorkingTree, made_dir.open_workingtree)
380
512
        backing = self.get_transport()
381
513
        request = smart_dir.SmartServerRequestInitializeBzrDir(backing)
382
514
        self.assertRaises(errors.NoSuchFile,
383
 
            request.execute, 'subdir')
 
515
            request.execute, b'subdir')
384
516
 
385
517
    def test_initialized_dir(self):
386
518
        """Initializing an extant bzrdir should fail like the bzrdir api."""
387
519
        backing = self.get_transport()
388
520
        request = smart_dir.SmartServerRequestInitializeBzrDir(backing)
389
 
        self.make_bzrdir('subdir')
390
 
        self.assertRaises(errors.FileExists,
391
 
            request.execute, 'subdir')
 
521
        self.make_controldir('subdir')
 
522
        self.assertRaises(errors.AlreadyControlDirError,
 
523
            request.execute, b'subdir')
392
524
 
393
525
 
394
526
class TestSmartServerRequestBzrDirInitializeEx(
401
533
    def test_empty_dir(self):
402
534
        """Initializing an empty dir should succeed and do it."""
403
535
        backing = self.get_transport()
404
 
        name = self.make_bzrdir('reference')._format.network_name()
 
536
        name = self.make_controldir('reference')._format.network_name()
405
537
        request = smart_dir.SmartServerRequestBzrDirInitializeEx(backing)
406
538
        self.assertEqual(
407
 
            smart_req.SmartServerResponse(('', '', '', '', '', '', name,
408
 
                                           'False', '', '', '')),
409
 
            request.execute(name, '', 'True', 'False', 'False', '', '', '', '',
410
 
                            'False'))
411
 
        made_dir = bzrdir.BzrDir.open_from_transport(backing)
 
539
            smart_req.SmartServerResponse((b'', b'', b'', b'', b'', b'', name,
 
540
                                           b'False', b'', b'', b'')),
 
541
            request.execute(name, b'', b'True', b'False', b'False', b'', b'', b'', b'',
 
542
                            b'False'))
 
543
        made_dir = controldir.ControlDir.open_from_transport(backing)
412
544
        # no branch, tree or repository is expected with the current
413
545
        # default format.
414
546
        self.assertRaises(errors.NoWorkingTree, made_dir.open_workingtree)
418
550
    def test_missing_dir(self):
419
551
        """Initializing a missing directory should fail like the bzrdir api."""
420
552
        backing = self.get_transport()
421
 
        name = self.make_bzrdir('reference')._format.network_name()
 
553
        name = self.make_controldir('reference')._format.network_name()
422
554
        request = smart_dir.SmartServerRequestBzrDirInitializeEx(backing)
423
555
        self.assertRaises(errors.NoSuchFile, request.execute, name,
424
 
            'subdir/dir', 'False', 'False', 'False', '', '', '', '', 'False')
 
556
            b'subdir/dir', b'False', b'False', b'False', b'', b'', b'', b'', b'False')
425
557
 
426
558
    def test_initialized_dir(self):
427
559
        """Initializing an extant directory should fail like the bzrdir api."""
428
560
        backing = self.get_transport()
429
 
        name = self.make_bzrdir('reference')._format.network_name()
 
561
        name = self.make_controldir('reference')._format.network_name()
430
562
        request = smart_dir.SmartServerRequestBzrDirInitializeEx(backing)
431
 
        self.make_bzrdir('subdir')
432
 
        self.assertRaises(errors.FileExists, request.execute, name, 'subdir',
433
 
            'False', 'False', 'False', '', '', '', '', 'False')
 
563
        self.make_controldir('subdir')
 
564
        self.assertRaises(errors.FileExists, request.execute, name, b'subdir',
 
565
            b'False', b'False', b'False', b'', b'', b'', b'', b'False')
434
566
 
435
567
 
436
568
class TestSmartServerRequestOpenBzrDir(tests.TestCaseWithMemoryTransport):
438
570
    def test_no_directory(self):
439
571
        backing = self.get_transport()
440
572
        request = smart_dir.SmartServerRequestOpenBzrDir(backing)
441
 
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
442
 
            request.execute('does-not-exist'))
 
573
        self.assertEqual(smart_req.SmartServerResponse((b'no', )),
 
574
            request.execute(b'does-not-exist'))
443
575
 
444
576
    def test_empty_directory(self):
445
577
        backing = self.get_transport()
446
578
        backing.mkdir('empty')
447
579
        request = smart_dir.SmartServerRequestOpenBzrDir(backing)
448
 
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
449
 
            request.execute('empty'))
 
580
        self.assertEqual(smart_req.SmartServerResponse((b'no', )),
 
581
            request.execute(b'empty'))
450
582
 
451
583
    def test_outside_root_client_path(self):
452
584
        backing = self.get_transport()
453
585
        request = smart_dir.SmartServerRequestOpenBzrDir(backing,
454
586
            root_client_path='root')
455
 
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
456
 
            request.execute('not-root'))
 
587
        self.assertEqual(smart_req.SmartServerResponse((b'no', )),
 
588
            request.execute(b'not-root'))
457
589
 
458
590
 
459
591
class TestSmartServerRequestOpenBzrDir_2_1(tests.TestCaseWithMemoryTransport):
461
593
    def test_no_directory(self):
462
594
        backing = self.get_transport()
463
595
        request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing)
464
 
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
465
 
            request.execute('does-not-exist'))
 
596
        self.assertEqual(smart_req.SmartServerResponse((b'no', )),
 
597
            request.execute(b'does-not-exist'))
466
598
 
467
599
    def test_empty_directory(self):
468
600
        backing = self.get_transport()
469
601
        backing.mkdir('empty')
470
602
        request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing)
471
 
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
472
 
            request.execute('empty'))
 
603
        self.assertEqual(smart_req.SmartServerResponse((b'no', )),
 
604
            request.execute(b'empty'))
473
605
 
474
606
    def test_present_without_workingtree(self):
475
607
        backing = self.get_transport()
476
608
        request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing)
477
 
        self.make_bzrdir('.')
478
 
        self.assertEqual(smart_req.SmartServerResponse(('yes', 'no')),
479
 
            request.execute(''))
 
609
        self.make_controldir('.')
 
610
        self.assertEqual(smart_req.SmartServerResponse((b'yes', b'no')),
 
611
            request.execute(b''))
480
612
 
481
613
    def test_outside_root_client_path(self):
482
614
        backing = self.get_transport()
483
615
        request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing,
484
616
            root_client_path='root')
485
 
        self.assertEqual(smart_req.SmartServerResponse(('no',)),
486
 
            request.execute('not-root'))
 
617
        self.assertEqual(smart_req.SmartServerResponse((b'no',)),
 
618
            request.execute(b'not-root'))
487
619
 
488
620
 
489
621
class TestSmartServerRequestOpenBzrDir_2_1_disk(TestCaseWithChrootedTransport):
492
624
        self.vfs_transport_factory = test_server.LocalURLServer
493
625
        backing = self.get_transport()
494
626
        request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing)
495
 
        bd = self.make_bzrdir('.')
 
627
        bd = self.make_controldir('.')
496
628
        bd.create_repository()
497
629
        bd.create_branch()
498
630
        bd.create_workingtree()
499
 
        self.assertEqual(smart_req.SmartServerResponse(('yes', 'yes')),
500
 
            request.execute(''))
 
631
        self.assertEqual(smart_req.SmartServerResponse((b'yes', b'yes')),
 
632
            request.execute(b''))
501
633
 
502
634
 
503
635
class TestSmartServerRequestOpenBranch(TestCaseWithChrootedTransport):
506
638
        """When there is no branch, ('nobranch', ) is returned."""
507
639
        backing = self.get_transport()
508
640
        request = smart_dir.SmartServerRequestOpenBranch(backing)
509
 
        self.make_bzrdir('.')
510
 
        self.assertEqual(smart_req.SmartServerResponse(('nobranch', )),
511
 
            request.execute(''))
 
641
        self.make_controldir('.')
 
642
        self.assertEqual(smart_req.SmartServerResponse((b'nobranch', )),
 
643
            request.execute(b''))
512
644
 
513
645
    def test_branch(self):
514
646
        """When there is a branch, 'ok' is returned."""
515
647
        backing = self.get_transport()
516
648
        request = smart_dir.SmartServerRequestOpenBranch(backing)
517
649
        self.make_branch('.')
518
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', '')),
519
 
            request.execute(''))
 
650
        self.assertEqual(smart_req.SmartServerResponse((b'ok', b'')),
 
651
            request.execute(b''))
520
652
 
521
653
    def test_branch_reference(self):
522
654
        """When there is a branch reference, the reference URL is returned."""
524
656
        backing = self.get_transport()
525
657
        request = smart_dir.SmartServerRequestOpenBranch(backing)
526
658
        branch = self.make_branch('branch')
527
 
        checkout = branch.create_checkout('reference',lightweight=True)
528
 
        reference_url = _mod_branch.BranchReferenceFormat().get_reference(
529
 
            checkout.bzrdir)
 
659
        checkout = branch.create_checkout('reference', lightweight=True)
 
660
        reference_url = _mod_bzrbranch.BranchReferenceFormat().get_reference(
 
661
            checkout.controldir).encode('utf-8')
530
662
        self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
531
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', reference_url)),
532
 
            request.execute('reference'))
 
663
        self.assertEqual(smart_req.SmartServerResponse((b'ok', reference_url)),
 
664
            request.execute(b'reference'))
533
665
 
534
666
    def test_notification_on_branch_from_repository(self):
535
667
        """When there is a repository, the error should return details."""
536
668
        backing = self.get_transport()
537
669
        request = smart_dir.SmartServerRequestOpenBranch(backing)
538
670
        repo = self.make_repository('.')
539
 
        self.assertEqual(smart_req.SmartServerResponse(('nobranch',)),
540
 
            request.execute(''))
 
671
        self.assertEqual(smart_req.SmartServerResponse((b'nobranch',)),
 
672
            request.execute(b''))
541
673
 
542
674
 
543
675
class TestSmartServerRequestOpenBranchV2(TestCaseWithChrootedTransport):
545
677
    def test_no_branch(self):
546
678
        """When there is no branch, ('nobranch', ) is returned."""
547
679
        backing = self.get_transport()
548
 
        self.make_bzrdir('.')
 
680
        self.make_controldir('.')
549
681
        request = smart_dir.SmartServerRequestOpenBranchV2(backing)
550
 
        self.assertEqual(smart_req.SmartServerResponse(('nobranch', )),
551
 
            request.execute(''))
 
682
        self.assertEqual(smart_req.SmartServerResponse((b'nobranch', )),
 
683
            request.execute(b''))
552
684
 
553
685
    def test_branch(self):
554
686
        """When there is a branch, 'ok' is returned."""
556
688
        expected = self.make_branch('.')._format.network_name()
557
689
        request = smart_dir.SmartServerRequestOpenBranchV2(backing)
558
690
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(
559
 
                ('branch', expected)),
560
 
                         request.execute(''))
 
691
                (b'branch', expected)),
 
692
                request.execute(b''))
561
693
 
562
694
    def test_branch_reference(self):
563
695
        """When there is a branch reference, the reference URL is returned."""
565
697
        backing = self.get_transport()
566
698
        request = smart_dir.SmartServerRequestOpenBranchV2(backing)
567
699
        branch = self.make_branch('branch')
568
 
        checkout = branch.create_checkout('reference',lightweight=True)
569
 
        reference_url = _mod_branch.BranchReferenceFormat().get_reference(
570
 
            checkout.bzrdir)
 
700
        checkout = branch.create_checkout('reference', lightweight=True)
 
701
        reference_url = _mod_bzrbranch.BranchReferenceFormat().get_reference(
 
702
            checkout.controldir).encode('utf-8')
571
703
        self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
572
704
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(
573
 
                ('ref', reference_url)),
574
 
                         request.execute('reference'))
 
705
                (b'ref', reference_url)),
 
706
                request.execute(b'reference'))
575
707
 
576
708
    def test_stacked_branch(self):
577
709
        """Opening a stacked branch does not open the stacked-on branch."""
585
717
        request = smart_dir.SmartServerRequestOpenBranchV2(backing)
586
718
        request.setup_jail()
587
719
        try:
588
 
            response = request.execute('feature')
 
720
            response = request.execute(b'feature')
589
721
        finally:
590
722
            request.teardown_jail()
591
723
        expected_format = feature._format.network_name()
592
724
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(
593
 
                ('branch', expected_format)),
 
725
                (b'branch', expected_format)),
594
726
                         response)
595
727
        self.assertLength(1, opened_branches)
596
728
 
599
731
        backing = self.get_transport()
600
732
        request = smart_dir.SmartServerRequestOpenBranchV2(backing)
601
733
        repo = self.make_repository('.')
602
 
        self.assertEqual(smart_req.SmartServerResponse(('nobranch',)),
603
 
            request.execute(''))
 
734
        self.assertEqual(smart_req.SmartServerResponse((b'nobranch',)),
 
735
            request.execute(b''))
604
736
 
605
737
 
606
738
class TestSmartServerRequestOpenBranchV3(TestCaseWithChrootedTransport):
608
740
    def test_no_branch(self):
609
741
        """When there is no branch, ('nobranch', ) is returned."""
610
742
        backing = self.get_transport()
611
 
        self.make_bzrdir('.')
 
743
        self.make_controldir('.')
612
744
        request = smart_dir.SmartServerRequestOpenBranchV3(backing)
613
 
        self.assertEqual(smart_req.SmartServerResponse(('nobranch',)),
614
 
            request.execute(''))
 
745
        self.assertEqual(smart_req.SmartServerResponse((b'nobranch',)),
 
746
            request.execute(b''))
615
747
 
616
748
    def test_branch(self):
617
749
        """When there is a branch, 'ok' is returned."""
619
751
        expected = self.make_branch('.')._format.network_name()
620
752
        request = smart_dir.SmartServerRequestOpenBranchV3(backing)
621
753
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(
622
 
                ('branch', expected)),
623
 
                         request.execute(''))
 
754
                (b'branch', expected)),
 
755
                         request.execute(b''))
624
756
 
625
757
    def test_branch_reference(self):
626
758
        """When there is a branch reference, the reference URL is returned."""
628
760
        backing = self.get_transport()
629
761
        request = smart_dir.SmartServerRequestOpenBranchV3(backing)
630
762
        branch = self.make_branch('branch')
631
 
        checkout = branch.create_checkout('reference',lightweight=True)
632
 
        reference_url = _mod_branch.BranchReferenceFormat().get_reference(
633
 
            checkout.bzrdir)
 
763
        checkout = branch.create_checkout('reference', lightweight=True)
 
764
        reference_url = _mod_bzrbranch.BranchReferenceFormat().get_reference(
 
765
            checkout.controldir).encode('utf-8')
634
766
        self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
635
767
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(
636
 
                ('ref', reference_url)),
637
 
                         request.execute('reference'))
 
768
                (b'ref', reference_url)),
 
769
                         request.execute(b'reference'))
638
770
 
639
771
    def test_stacked_branch(self):
640
772
        """Opening a stacked branch does not open the stacked-on branch."""
648
780
        request = smart_dir.SmartServerRequestOpenBranchV3(backing)
649
781
        request.setup_jail()
650
782
        try:
651
 
            response = request.execute('feature')
 
783
            response = request.execute(b'feature')
652
784
        finally:
653
785
            request.teardown_jail()
654
786
        expected_format = feature._format.network_name()
655
787
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(
656
 
                ('branch', expected_format)),
 
788
                (b'branch', expected_format)),
657
789
                         response)
658
790
        self.assertLength(1, opened_branches)
659
791
 
663
795
        request = smart_dir.SmartServerRequestOpenBranchV3(backing)
664
796
        repo = self.make_repository('.')
665
797
        self.assertEqual(smart_req.SmartServerResponse(
666
 
                ('nobranch', 'location is a repository')),
667
 
                         request.execute(''))
 
798
                (b'nobranch', b'location is a repository')),
 
799
                         request.execute(b''))
668
800
 
669
801
 
670
802
class TestSmartServerRequestRevisionHistory(tests.TestCaseWithMemoryTransport):
674
806
        backing = self.get_transport()
675
807
        request = smart_branch.SmartServerRequestRevisionHistory(backing)
676
808
        self.make_branch('.')
677
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), ''),
678
 
            request.execute(''))
 
809
        self.assertEqual(smart_req.SmartServerResponse((b'ok', ), b''),
 
810
            request.execute(b''))
679
811
 
680
812
    def test_not_empty(self):
681
813
        """For a non-empty branch, the body is empty."""
688
820
        r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
689
821
        tree.unlock()
690
822
        self.assertEqual(
691
 
            smart_req.SmartServerResponse(('ok', ), ('\x00'.join([r1, r2]))),
692
 
            request.execute(''))
 
823
            smart_req.SmartServerResponse((b'ok', ), (b'\x00'.join([r1, r2]))),
 
824
            request.execute(b''))
693
825
 
694
826
 
695
827
class TestSmartServerBranchRequest(tests.TestCaseWithMemoryTransport):
698
830
        """When there is a bzrdir and no branch, NotBranchError is raised."""
699
831
        backing = self.get_transport()
700
832
        request = smart_branch.SmartServerBranchRequest(backing)
701
 
        self.make_bzrdir('.')
 
833
        self.make_controldir('.')
702
834
        self.assertRaises(errors.NotBranchError,
703
 
            request.execute, '')
 
835
            request.execute, b'')
704
836
 
705
837
    def test_branch_reference(self):
706
838
        """When there is a branch reference, NotBranchError is raised."""
707
839
        backing = self.get_transport()
708
840
        request = smart_branch.SmartServerBranchRequest(backing)
709
841
        branch = self.make_branch('branch')
710
 
        checkout = branch.create_checkout('reference',lightweight=True)
 
842
        checkout = branch.create_checkout('reference', lightweight=True)
711
843
        self.assertRaises(errors.NotBranchError,
712
 
            request.execute, 'checkout')
 
844
            request.execute, b'checkout')
713
845
 
714
846
 
715
847
class TestSmartServerBranchRequestLastRevisionInfo(
716
848
    tests.TestCaseWithMemoryTransport):
717
849
 
718
850
    def test_empty(self):
719
 
        """For an empty branch, the result is ('ok', '0', 'null:')."""
 
851
        """For an empty branch, the result is ('ok', '0', b'null:')."""
720
852
        backing = self.get_transport()
721
853
        request = smart_branch.SmartServerBranchRequestLastRevisionInfo(backing)
722
854
        self.make_branch('.')
723
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', '0', 'null:')),
724
 
            request.execute(''))
 
855
        self.assertEqual(smart_req.SmartServerResponse((b'ok', b'0', b'null:')),
 
856
            request.execute(b''))
 
857
 
 
858
    def test_ghost(self):
 
859
        """For an empty branch, the result is ('ok', '0', b'null:')."""
 
860
        backing = self.get_transport()
 
861
        request = smart_branch.SmartServerBranchRequestLastRevisionInfo(backing)
 
862
        branch = self.make_branch('.')
 
863
        def last_revision_info():
 
864
            raise errors.GhostRevisionsHaveNoRevno(b'revid1', b'revid2')
 
865
        self.overrideAttr(branch, 'last_revision_info', last_revision_info)
 
866
        self.assertRaises(errors.GhostRevisionsHaveNoRevno,
 
867
            request.do_with_branch, branch)
725
868
 
726
869
    def test_not_empty(self):
727
870
        """For a non-empty branch, the result is ('ok', 'revno', 'revid')."""
735
878
        r2 = tree.commit('2nd commit', rev_id=rev_id_utf8)
736
879
        tree.unlock()
737
880
        self.assertEqual(
738
 
            smart_req.SmartServerResponse(('ok', '2', rev_id_utf8)),
739
 
            request.execute(''))
 
881
            smart_req.SmartServerResponse((b'ok', b'2', rev_id_utf8)),
 
882
            request.execute(b''))
 
883
 
 
884
 
 
885
class TestSmartServerBranchRequestRevisionIdToRevno(
 
886
    tests.TestCaseWithMemoryTransport):
 
887
 
 
888
    def test_null(self):
 
889
        backing = self.get_transport()
 
890
        request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
 
891
            backing)
 
892
        self.make_branch('.')
 
893
        self.assertEqual(smart_req.SmartServerResponse((b'ok', b'0')),
 
894
            request.execute(b'', b'null:'))
 
895
 
 
896
    def test_simple(self):
 
897
        backing = self.get_transport()
 
898
        request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
 
899
            backing)
 
900
        tree = self.make_branch_and_memory_tree('.')
 
901
        tree.lock_write()
 
902
        tree.add('')
 
903
        r1 = tree.commit('1st commit')
 
904
        tree.unlock()
 
905
        self.assertEqual(
 
906
            smart_req.SmartServerResponse((b'ok', b'1')),
 
907
            request.execute(b'', r1))
 
908
 
 
909
    def test_not_found(self):
 
910
        backing = self.get_transport()
 
911
        request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
 
912
            backing)
 
913
        branch = self.make_branch('.')
 
914
        self.assertEqual(
 
915
            smart_req.FailedSmartServerResponse(
 
916
                (b'NoSuchRevision', b'idontexist')),
 
917
            request.execute(b'', b'idontexist'))
740
918
 
741
919
 
742
920
class TestSmartServerBranchRequestGetConfigFile(
748
926
        request = smart_branch.SmartServerBranchGetConfigFile(backing)
749
927
        branch = self.make_branch('.')
750
928
        # there should be no file by default
751
 
        content = ''
752
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), content),
753
 
            request.execute(''))
 
929
        content = b''
 
930
        self.assertEqual(smart_req.SmartServerResponse((b'ok', ), content),
 
931
            request.execute(b''))
754
932
 
755
933
    def test_with_content(self):
756
934
        # SmartServerBranchGetConfigFile should return the content from
759
937
        backing = self.get_transport()
760
938
        request = smart_branch.SmartServerBranchGetConfigFile(backing)
761
939
        branch = self.make_branch('.')
762
 
        branch._transport.put_bytes('branch.conf', 'foo bar baz')
763
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), 'foo bar baz'),
764
 
            request.execute(''))
 
940
        branch._transport.put_bytes('branch.conf', b'foo bar baz')
 
941
        self.assertEqual(smart_req.SmartServerResponse((b'ok', ), b'foo bar baz'),
 
942
            request.execute(b''))
765
943
 
766
944
 
767
945
class TestLockedBranch(tests.TestCaseWithMemoryTransport):
768
946
 
769
947
    def get_lock_tokens(self, branch):
770
 
        branch_token = branch.lock_write()
771
 
        repo_token = branch.repository.lock_write()
 
948
        branch_token = branch.lock_write().token
 
949
        repo_token = branch.repository.lock_write().repository_token
772
950
        branch.repository.unlock()
773
951
        return branch_token, repo_token
774
952
 
775
953
 
 
954
class TestSmartServerBranchRequestPutConfigFile(TestLockedBranch):
 
955
 
 
956
    def test_with_content(self):
 
957
        backing = self.get_transport()
 
958
        request = smart_branch.SmartServerBranchPutConfigFile(backing)
 
959
        branch = self.make_branch('.')
 
960
        branch_token, repo_token = self.get_lock_tokens(branch)
 
961
        self.assertIs(None, request.execute(b'', branch_token, repo_token))
 
962
        self.assertEqual(
 
963
            smart_req.SmartServerResponse((b'ok', )),
 
964
            request.do_body(b'foo bar baz'))
 
965
        self.assertEqual(
 
966
            branch.control_transport.get_bytes(b'branch.conf'),
 
967
            b'foo bar baz')
 
968
        branch.unlock()
 
969
 
 
970
 
776
971
class TestSmartServerBranchRequestSetConfigOption(TestLockedBranch):
777
972
 
778
973
    def test_value_name(self):
779
974
        branch = self.make_branch('.')
780
975
        request = smart_branch.SmartServerBranchRequestSetConfigOption(
781
 
            branch.bzrdir.root_transport)
 
976
            branch.controldir.root_transport)
782
977
        branch_token, repo_token = self.get_lock_tokens(branch)
783
978
        config = branch._get_config()
784
 
        result = request.execute('', branch_token, repo_token, 'bar', 'foo',
785
 
            '')
 
979
        result = request.execute(b'', branch_token, repo_token, b'bar', b'foo',
 
980
            b'')
786
981
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
787
982
        self.assertEqual('bar', config.get_option('foo'))
788
983
        # Cleanup
791
986
    def test_value_name_section(self):
792
987
        branch = self.make_branch('.')
793
988
        request = smart_branch.SmartServerBranchRequestSetConfigOption(
794
 
            branch.bzrdir.root_transport)
 
989
            branch.controldir.root_transport)
795
990
        branch_token, repo_token = self.get_lock_tokens(branch)
796
991
        config = branch._get_config()
797
 
        result = request.execute('', branch_token, repo_token, 'bar', 'foo',
798
 
            'gam')
 
992
        result = request.execute(b'', branch_token, repo_token, b'bar', b'foo',
 
993
            b'gam')
799
994
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
800
995
        self.assertEqual('bar', config.get_option('foo', 'gam'))
801
996
        # Cleanup
802
997
        branch.unlock()
803
998
 
804
999
 
 
1000
class TestSmartServerBranchRequestSetConfigOptionDict(TestLockedBranch):
 
1001
 
 
1002
    def setUp(self):
 
1003
        TestLockedBranch.setUp(self)
 
1004
        # A dict with non-ascii keys and values to exercise unicode
 
1005
        # roundtripping.
 
1006
        self.encoded_value_dict = (
 
1007
            b'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde')
 
1008
        self.value_dict = {
 
1009
            'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
 
1010
 
 
1011
    def test_value_name(self):
 
1012
        branch = self.make_branch('.')
 
1013
        request = smart_branch.SmartServerBranchRequestSetConfigOptionDict(
 
1014
            branch.controldir.root_transport)
 
1015
        branch_token, repo_token = self.get_lock_tokens(branch)
 
1016
        config = branch._get_config()
 
1017
        result = request.execute(b'', branch_token, repo_token,
 
1018
            self.encoded_value_dict, b'foo', b'')
 
1019
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
 
1020
        self.assertEqual(self.value_dict, config.get_option('foo'))
 
1021
        # Cleanup
 
1022
        branch.unlock()
 
1023
 
 
1024
    def test_value_name_section(self):
 
1025
        branch = self.make_branch('.')
 
1026
        request = smart_branch.SmartServerBranchRequestSetConfigOptionDict(
 
1027
            branch.controldir.root_transport)
 
1028
        branch_token, repo_token = self.get_lock_tokens(branch)
 
1029
        config = branch._get_config()
 
1030
        result = request.execute(b'', branch_token, repo_token,
 
1031
            self.encoded_value_dict, b'foo', b'gam')
 
1032
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
 
1033
        self.assertEqual(self.value_dict, config.get_option('foo', 'gam'))
 
1034
        # Cleanup
 
1035
        branch.unlock()
 
1036
 
 
1037
 
805
1038
class TestSmartServerBranchRequestSetTagsBytes(TestLockedBranch):
806
1039
    # Only called when the branch format and tags match [yay factory
807
1040
    # methods] so only need to test straight forward cases.
813
1046
        branch_token, repo_token = self.get_lock_tokens(base_branch)
814
1047
        request = smart_branch.SmartServerBranchSetTagsBytes(
815
1048
            self.get_transport())
816
 
        response = request.execute('base', branch_token, repo_token)
 
1049
        response = request.execute(b'base', branch_token, repo_token)
817
1050
        self.assertEqual(None, response)
818
1051
        response = request.do_chunk(tag_bytes)
819
1052
        self.assertEqual(None, response)
820
1053
        response = request.do_end()
821
 
        self.assertEquals(
 
1054
        self.assertEqual(
822
1055
            smart_req.SuccessfulSmartServerResponse(()), response)
823
1056
        base_branch.unlock()
824
1057
 
829
1062
        request = smart_branch.SmartServerBranchSetTagsBytes(
830
1063
            self.get_transport())
831
1064
        self.assertRaises(errors.TokenMismatch, request.execute,
832
 
            'base', 'wrong token', 'wrong token')
 
1065
            b'base', b'wrong token', b'wrong token')
833
1066
        # The request handler will keep processing the message parts, so even
834
1067
        # if the request fails immediately do_chunk and do_end are still
835
1068
        # called.
843
1076
    """Base test case for verbs that implement set_last_revision."""
844
1077
 
845
1078
    def setUp(self):
846
 
        tests.TestCaseWithMemoryTransport.setUp(self)
 
1079
        super(SetLastRevisionTestBase, self).setUp()
847
1080
        backing_transport = self.get_transport()
848
1081
        self.request = self.request_class(backing_transport)
849
1082
        self.tree = self.make_branch_and_memory_tree('.')
863
1096
 
864
1097
    def assertRequestSucceeds(self, revision_id, revno):
865
1098
        response = self.set_last_revision(revision_id, revno)
866
 
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
 
1099
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
867
1100
                         response)
868
1101
 
869
1102
 
871
1104
    """Mixin test case for verbs that implement set_last_revision."""
872
1105
 
873
1106
    def test_set_null_to_null(self):
874
 
        """An empty branch can have its last revision set to 'null:'."""
875
 
        self.assertRequestSucceeds('null:', 0)
 
1107
        """An empty branch can have its last revision set to b'null:'."""
 
1108
        self.assertRequestSucceeds(b'null:', 0)
876
1109
 
877
1110
    def test_NoSuchRevision(self):
878
1111
        """If the revision_id is not present, the verb returns NoSuchRevision.
879
1112
        """
880
 
        revision_id = 'non-existent revision'
881
 
        self.assertEqual(smart_req.FailedSmartServerResponse(('NoSuchRevision',
 
1113
        revision_id = b'non-existent revision'
 
1114
        self.assertEqual(smart_req.FailedSmartServerResponse((b'NoSuchRevision',
882
1115
                                                              revision_id)),
883
1116
                         self.set_last_revision(revision_id, 1))
884
1117
 
887
1120
        self.tree.add('')
888
1121
        rev_id_utf8 = u'\xc8'.encode('utf-8')
889
1122
        r1 = self.tree.commit('1st commit', rev_id=rev_id_utf8)
890
 
        r2 = self.tree.commit('2nd commit', rev_id='rev-2')
 
1123
        r2 = self.tree.commit('2nd commit', rev_id=b'rev-2')
891
1124
        self.tree.unlock()
892
1125
 
893
1126
    def test_branch_last_revision_info_is_updated(self):
898
1131
        # its repository.
899
1132
        self.make_tree_with_two_commits()
900
1133
        rev_id_utf8 = u'\xc8'.encode('utf-8')
901
 
        self.tree.branch.set_revision_history([])
 
1134
        self.tree.branch.set_last_revision_info(0, b'null:')
902
1135
        self.assertEqual(
903
 
            (0, 'null:'), self.tree.branch.last_revision_info())
 
1136
            (0, b'null:'), self.tree.branch.last_revision_info())
904
1137
        # We can update the branch to a revision that is present in the
905
1138
        # repository.
906
1139
        self.assertRequestSucceeds(rev_id_utf8, 1)
914
1147
        self.make_tree_with_two_commits()
915
1148
        rev_id_utf8 = u'\xc8'.encode('utf-8')
916
1149
        self.assertEqual(
917
 
            (2, 'rev-2'), self.tree.branch.last_revision_info())
 
1150
            (2, b'rev-2'), self.tree.branch.last_revision_info())
918
1151
        self.assertRequestSucceeds(rev_id_utf8, 1)
919
1152
        self.assertEqual(
920
1153
            (1, rev_id_utf8), self.tree.branch.last_revision_info())
930
1163
            'pre_change_branch_tip', hook_that_rejects, None)
931
1164
        self.assertEqual(
932
1165
            smart_req.FailedSmartServerResponse(
933
 
                ('TipChangeRejected', rejection_message.encode('utf-8'))),
934
 
            self.set_last_revision('null:', 0))
 
1166
                (b'TipChangeRejected', rejection_message.encode('utf-8'))),
 
1167
            self.set_last_revision(b'null:', 0))
935
1168
 
936
1169
 
937
1170
class TestSmartServerBranchRequestSetLastRevision(
942
1175
 
943
1176
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
944
1177
        return self.request.execute(
945
 
            '', branch_token, repo_token, revision_id)
 
1178
            b'', branch_token, repo_token, revision_id)
946
1179
 
947
1180
 
948
1181
class TestSmartServerBranchRequestSetLastRevisionInfo(
953
1186
 
954
1187
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
955
1188
        return self.request.execute(
956
 
            '', branch_token, repo_token, revno, revision_id)
 
1189
            b'', branch_token, repo_token, revno, revision_id)
957
1190
 
958
1191
    def test_NoSuchRevision(self):
959
1192
        """Branch.set_last_revision_info does not have to return
970
1203
 
971
1204
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
972
1205
        return self.request.execute(
973
 
            '', branch_token, repo_token, revision_id, 0, 0)
 
1206
            b'', branch_token, repo_token, revision_id, 0, 0)
974
1207
 
975
1208
    def assertRequestSucceeds(self, revision_id, revno):
976
1209
        response = self.set_last_revision(revision_id, revno)
977
1210
        self.assertEqual(
978
 
            smart_req.SuccessfulSmartServerResponse(('ok', revno, revision_id)),
 
1211
            smart_req.SuccessfulSmartServerResponse((b'ok', revno, revision_id)),
979
1212
            response)
980
1213
 
981
1214
    def test_branch_last_revision_info_rewind(self):
985
1218
        self.make_tree_with_two_commits()
986
1219
        rev_id_utf8 = u'\xc8'.encode('utf-8')
987
1220
        self.assertEqual(
988
 
            (2, 'rev-2'), self.tree.branch.last_revision_info())
 
1221
            (2, b'rev-2'), self.tree.branch.last_revision_info())
989
1222
        # If allow_overwrite_descendant flag is 0, then trying to set the tip
990
1223
        # to an older revision ID has no effect.
991
1224
        branch_token, repo_token = self.lock_branch()
992
1225
        response = self.request.execute(
993
 
            '', branch_token, repo_token, rev_id_utf8, 0, 0)
 
1226
            b'', branch_token, repo_token, rev_id_utf8, 0, 0)
994
1227
        self.assertEqual(
995
 
            smart_req.SuccessfulSmartServerResponse(('ok', 2, 'rev-2')),
 
1228
            smart_req.SuccessfulSmartServerResponse((b'ok', 2, b'rev-2')),
996
1229
            response)
997
1230
        self.assertEqual(
998
 
            (2, 'rev-2'), self.tree.branch.last_revision_info())
 
1231
            (2, b'rev-2'), self.tree.branch.last_revision_info())
999
1232
 
1000
1233
        # If allow_overwrite_descendant flag is 1, then setting the tip to an
1001
1234
        # ancestor works.
1002
1235
        response = self.request.execute(
1003
 
            '', branch_token, repo_token, rev_id_utf8, 0, 1)
 
1236
            b'', branch_token, repo_token, rev_id_utf8, 0, 1)
1004
1237
        self.assertEqual(
1005
 
            smart_req.SuccessfulSmartServerResponse(('ok', 1, rev_id_utf8)),
 
1238
            smart_req.SuccessfulSmartServerResponse((b'ok', 1, rev_id_utf8)),
1006
1239
            response)
1007
1240
        self.unlock_branch()
1008
1241
        self.assertEqual(
1018
1251
        self.tree.add('')
1019
1252
        r1 = self.tree.commit('1st commit')
1020
1253
        revno_1, revid_1 = self.tree.branch.last_revision_info()
1021
 
        r2 = self.tree.commit('2nd commit', rev_id='child-1')
 
1254
        r2 = self.tree.commit('2nd commit', rev_id=b'child-1')
1022
1255
        # Undo the second commit
1023
1256
        self.tree.branch.set_last_revision_info(revno_1, revid_1)
1024
1257
        self.tree.set_parent_ids([revid_1])
1025
1258
        # Make a new second commit, child-2.  child-2 has diverged from
1026
1259
        # child-1.
1027
 
        new_r2 = self.tree.commit('2nd commit', rev_id='child-2')
 
1260
        new_r2 = self.tree.commit('2nd commit', rev_id=b'child-2')
1028
1261
        self.tree.unlock()
1029
1262
 
1030
1263
    def test_not_allow_diverged(self):
1033
1266
        """
1034
1267
        self.make_branch_with_divergent_history()
1035
1268
        self.assertEqual(
1036
 
            smart_req.FailedSmartServerResponse(('Diverged',)),
1037
 
            self.set_last_revision('child-1', 2))
 
1269
            smart_req.FailedSmartServerResponse((b'Diverged',)),
 
1270
            self.set_last_revision(b'child-1', 2))
1038
1271
        # The branch tip was not changed.
1039
 
        self.assertEqual('child-2', self.tree.branch.last_revision())
 
1272
        self.assertEqual(b'child-2', self.tree.branch.last_revision())
1040
1273
 
1041
1274
    def test_allow_diverged(self):
1042
1275
        """If allow_diverged is passed, then setting a divergent history
1045
1278
        self.make_branch_with_divergent_history()
1046
1279
        branch_token, repo_token = self.lock_branch()
1047
1280
        response = self.request.execute(
1048
 
            '', branch_token, repo_token, 'child-1', 1, 0)
 
1281
            b'', branch_token, repo_token, b'child-1', 1, 0)
1049
1282
        self.assertEqual(
1050
 
            smart_req.SuccessfulSmartServerResponse(('ok', 2, 'child-1')),
 
1283
            smart_req.SuccessfulSmartServerResponse((b'ok', 2, b'child-1')),
1051
1284
            response)
1052
1285
        self.unlock_branch()
1053
1286
        # The branch tip was changed.
1054
 
        self.assertEqual('child-1', self.tree.branch.last_revision())
 
1287
        self.assertEqual(b'child-1', self.tree.branch.last_revision())
 
1288
 
 
1289
 
 
1290
class TestSmartServerBranchBreakLock(tests.TestCaseWithMemoryTransport):
 
1291
 
 
1292
    def test_lock_to_break(self):
 
1293
        base_branch = self.make_branch('base')
 
1294
        request = smart_branch.SmartServerBranchBreakLock(
 
1295
            self.get_transport())
 
1296
        base_branch.lock_write()
 
1297
        self.assertEqual(
 
1298
            smart_req.SuccessfulSmartServerResponse((b'ok', ), None),
 
1299
            request.execute(b'base'))
 
1300
 
 
1301
    def test_nothing_to_break(self):
 
1302
        base_branch = self.make_branch('base')
 
1303
        request = smart_branch.SmartServerBranchBreakLock(
 
1304
            self.get_transport())
 
1305
        self.assertEqual(
 
1306
            smart_req.SuccessfulSmartServerResponse((b'ok', ), None),
 
1307
            request.execute(b'base'))
1055
1308
 
1056
1309
 
1057
1310
class TestSmartServerBranchRequestGetParent(tests.TestCaseWithMemoryTransport):
1059
1312
    def test_get_parent_none(self):
1060
1313
        base_branch = self.make_branch('base')
1061
1314
        request = smart_branch.SmartServerBranchGetParent(self.get_transport())
1062
 
        response = request.execute('base')
1063
 
        self.assertEquals(
1064
 
            smart_req.SuccessfulSmartServerResponse(('',)), response)
 
1315
        response = request.execute(b'base')
 
1316
        self.assertEqual(
 
1317
            smart_req.SuccessfulSmartServerResponse((b'',)), response)
1065
1318
 
1066
1319
    def test_get_parent_something(self):
1067
1320
        base_branch = self.make_branch('base')
1068
1321
        base_branch.set_parent(self.get_url('foo'))
1069
1322
        request = smart_branch.SmartServerBranchGetParent(self.get_transport())
1070
 
        response = request.execute('base')
1071
 
        self.assertEquals(
1072
 
            smart_req.SuccessfulSmartServerResponse(("../foo",)),
 
1323
        response = request.execute(b'base')
 
1324
        self.assertEqual(
 
1325
            smart_req.SuccessfulSmartServerResponse((b"../foo",)),
1073
1326
            response)
1074
1327
 
1075
1328
 
1076
 
class TestSmartServerBranchRequestSetParent(tests.TestCaseWithMemoryTransport):
 
1329
class TestSmartServerBranchRequestSetParent(TestLockedBranch):
1077
1330
 
1078
1331
    def test_set_parent_none(self):
1079
1332
        branch = self.make_branch('base', format="1.9")
1082
1335
        branch.unlock()
1083
1336
        request = smart_branch.SmartServerBranchRequestSetParentLocation(
1084
1337
            self.get_transport())
1085
 
        branch_token = branch.lock_write()
1086
 
        repo_token = branch.repository.lock_write()
 
1338
        branch_token, repo_token = self.get_lock_tokens(branch)
1087
1339
        try:
1088
 
            response = request.execute('base', branch_token, repo_token, '')
 
1340
            response = request.execute(b'base', branch_token, repo_token, b'')
1089
1341
        finally:
1090
 
            branch.repository.unlock()
1091
1342
            branch.unlock()
1092
1343
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
 
1344
        # Refresh branch as SetParentLocation modified it
 
1345
        branch = branch.controldir.open_branch()
1093
1346
        self.assertEqual(None, branch.get_parent())
1094
1347
 
1095
1348
    def test_set_parent_something(self):
1096
1349
        branch = self.make_branch('base', format="1.9")
1097
1350
        request = smart_branch.SmartServerBranchRequestSetParentLocation(
1098
1351
            self.get_transport())
1099
 
        branch_token = branch.lock_write()
1100
 
        repo_token = branch.repository.lock_write()
 
1352
        branch_token, repo_token = self.get_lock_tokens(branch)
1101
1353
        try:
1102
 
            response = request.execute('base', branch_token, repo_token,
1103
 
            'http://bar/')
 
1354
            response = request.execute(b'base', branch_token, repo_token,
 
1355
                                       b'http://bar/')
1104
1356
        finally:
1105
 
            branch.repository.unlock()
1106
1357
            branch.unlock()
1107
1358
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
1108
 
        self.assertEqual('http://bar/', branch.get_parent())
 
1359
        refreshed = _mod_branch.Branch.open(branch.base)
 
1360
        self.assertEqual('http://bar/', refreshed.get_parent())
1109
1361
 
1110
1362
 
1111
1363
class TestSmartServerBranchRequestGetTagsBytes(
1117
1369
        base_branch = self.make_branch('base')
1118
1370
        request = smart_branch.SmartServerBranchGetTagsBytes(
1119
1371
            self.get_transport())
1120
 
        response = request.execute('base')
1121
 
        self.assertEquals(
1122
 
            smart_req.SuccessfulSmartServerResponse(('',)), response)
 
1372
        response = request.execute(b'base')
 
1373
        self.assertEqual(
 
1374
            smart_req.SuccessfulSmartServerResponse((b'',)), response)
1123
1375
 
1124
1376
 
1125
1377
class TestSmartServerBranchRequestGetStackedOnURL(tests.TestCaseWithMemoryTransport):
1131
1383
        stacked_branch.set_stacked_on_url('../base')
1132
1384
        request = smart_branch.SmartServerBranchRequestGetStackedOnURL(
1133
1385
            self.get_transport())
1134
 
        response = request.execute('stacked')
1135
 
        self.assertEquals(
1136
 
            smart_req.SmartServerResponse(('ok', '../base')),
 
1386
        response = request.execute(b'stacked')
 
1387
        self.assertEqual(
 
1388
            smart_req.SmartServerResponse((b'ok', b'../base')),
1137
1389
            response)
1138
1390
 
1139
1391
 
1140
 
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithMemoryTransport):
1141
 
 
1142
 
    def setUp(self):
1143
 
        tests.TestCaseWithMemoryTransport.setUp(self)
 
1392
class TestSmartServerBranchRequestLockWrite(TestLockedBranch):
1144
1393
 
1145
1394
    def test_lock_write_on_unlocked_branch(self):
1146
1395
        backing = self.get_transport()
1147
1396
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1148
1397
        branch = self.make_branch('.', format='knit')
1149
1398
        repository = branch.repository
1150
 
        response = request.execute('')
 
1399
        response = request.execute(b'')
1151
1400
        branch_nonce = branch.control_files._lock.peek().get('nonce')
1152
1401
        repository_nonce = repository.control_files._lock.peek().get('nonce')
1153
1402
        self.assertEqual(smart_req.SmartServerResponse(
1154
 
                ('ok', branch_nonce, repository_nonce)),
 
1403
                (b'ok', branch_nonce, repository_nonce)),
1155
1404
                         response)
1156
1405
        # The branch (and associated repository) is now locked.  Verify that
1157
1406
        # with a new branch object.
1158
 
        new_branch = repository.bzrdir.open_branch()
 
1407
        new_branch = repository.controldir.open_branch()
1159
1408
        self.assertRaises(errors.LockContention, new_branch.lock_write)
1160
1409
        # Cleanup
1161
1410
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1162
 
        response = request.execute('', branch_nonce, repository_nonce)
 
1411
        response = request.execute(b'', branch_nonce, repository_nonce)
1163
1412
 
1164
1413
    def test_lock_write_on_locked_branch(self):
1165
1414
        backing = self.get_transport()
1166
1415
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1167
1416
        branch = self.make_branch('.')
1168
 
        branch_token = branch.lock_write()
 
1417
        branch_token = branch.lock_write().token
1169
1418
        branch.leave_lock_in_place()
1170
1419
        branch.unlock()
1171
 
        response = request.execute('')
 
1420
        response = request.execute(b'')
1172
1421
        self.assertEqual(
1173
 
            smart_req.SmartServerResponse(('LockContention',)), response)
 
1422
            smart_req.SmartServerResponse((b'LockContention',)), response)
1174
1423
        # Cleanup
1175
1424
        branch.lock_write(branch_token)
1176
1425
        branch.dont_leave_lock_in_place()
1180
1429
        backing = self.get_transport()
1181
1430
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1182
1431
        branch = self.make_branch('.', format='knit')
1183
 
        branch_token = branch.lock_write()
1184
 
        repo_token = branch.repository.lock_write()
1185
 
        branch.repository.unlock()
 
1432
        branch_token, repo_token = self.get_lock_tokens(branch)
1186
1433
        branch.leave_lock_in_place()
1187
1434
        branch.repository.leave_lock_in_place()
1188
1435
        branch.unlock()
1189
 
        response = request.execute('',
 
1436
        response = request.execute(b'',
1190
1437
                                   branch_token, repo_token)
1191
1438
        self.assertEqual(
1192
 
            smart_req.SmartServerResponse(('ok', branch_token, repo_token)),
 
1439
            smart_req.SmartServerResponse((b'ok', branch_token, repo_token)),
1193
1440
            response)
1194
1441
        # Cleanup
1195
1442
        branch.repository.lock_write(repo_token)
1203
1450
        backing = self.get_transport()
1204
1451
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1205
1452
        branch = self.make_branch('.', format='knit')
1206
 
        branch_token = branch.lock_write()
1207
 
        repo_token = branch.repository.lock_write()
1208
 
        branch.repository.unlock()
 
1453
        branch_token, repo_token = self.get_lock_tokens(branch)
1209
1454
        branch.leave_lock_in_place()
1210
1455
        branch.repository.leave_lock_in_place()
1211
1456
        branch.unlock()
1212
 
        response = request.execute('',
1213
 
                                   branch_token+'xxx', repo_token)
 
1457
        response = request.execute(b'',
 
1458
                                   branch_token+b'xxx', repo_token)
1214
1459
        self.assertEqual(
1215
 
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
 
1460
            smart_req.SmartServerResponse((b'TokenMismatch',)), response)
1216
1461
        # Cleanup
1217
1462
        branch.repository.lock_write(repo_token)
1218
1463
        branch.repository.dont_leave_lock_in_place()
1226
1471
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1227
1472
        branch = self.make_branch('.', format='knit')
1228
1473
        repo = branch.repository
1229
 
        repo_token = repo.lock_write()
 
1474
        repo_token = repo.lock_write().repository_token
1230
1475
        repo.leave_lock_in_place()
1231
1476
        repo.unlock()
1232
 
        response = request.execute('')
 
1477
        response = request.execute(b'')
1233
1478
        self.assertEqual(
1234
 
            smart_req.SmartServerResponse(('LockContention',)), response)
 
1479
            smart_req.SmartServerResponse((b'LockContention',)), response)
1235
1480
        # Cleanup
1236
1481
        repo.lock_write(repo_token)
1237
1482
        repo.dont_leave_lock_in_place()
1243
1488
        branch = self.make_branch('.')
1244
1489
        root = self.get_transport().clone('/')
1245
1490
        path = urlutils.relative_url(root.base, self.get_transport().base)
1246
 
        response = request.execute(path)
 
1491
        response = request.execute(path.encode('utf-8'))
1247
1492
        error_name, lock_str, why_str = response.args
1248
1493
        self.assertFalse(response.is_successful())
1249
 
        self.assertEqual('LockFailed', error_name)
1250
 
 
1251
 
 
1252
 
class TestSmartServerBranchRequestUnlock(tests.TestCaseWithMemoryTransport):
1253
 
 
1254
 
    def setUp(self):
1255
 
        tests.TestCaseWithMemoryTransport.setUp(self)
 
1494
        self.assertEqual(b'LockFailed', error_name)
 
1495
 
 
1496
 
 
1497
class TestSmartServerBranchRequestGetPhysicalLockStatus(TestLockedBranch):
 
1498
 
 
1499
    def test_true(self):
 
1500
        backing = self.get_transport()
 
1501
        request = smart_branch.SmartServerBranchRequestGetPhysicalLockStatus(
 
1502
            backing)
 
1503
        branch = self.make_branch('.')
 
1504
        branch_token, repo_token = self.get_lock_tokens(branch)
 
1505
        self.assertEqual(True, branch.get_physical_lock_status())
 
1506
        response = request.execute(b'')
 
1507
        self.assertEqual(
 
1508
            smart_req.SmartServerResponse((b'yes',)), response)
 
1509
        branch.unlock()
 
1510
 
 
1511
    def test_false(self):
 
1512
        backing = self.get_transport()
 
1513
        request = smart_branch.SmartServerBranchRequestGetPhysicalLockStatus(
 
1514
            backing)
 
1515
        branch = self.make_branch('.')
 
1516
        self.assertEqual(False, branch.get_physical_lock_status())
 
1517
        response = request.execute(b'')
 
1518
        self.assertEqual(
 
1519
            smart_req.SmartServerResponse((b'no',)), response)
 
1520
 
 
1521
 
 
1522
class TestSmartServerBranchRequestUnlock(TestLockedBranch):
1256
1523
 
1257
1524
    def test_unlock_on_locked_branch_and_repo(self):
1258
1525
        backing = self.get_transport()
1259
1526
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1260
1527
        branch = self.make_branch('.', format='knit')
1261
1528
        # Lock the branch
1262
 
        branch_token = branch.lock_write()
1263
 
        repo_token = branch.repository.lock_write()
1264
 
        branch.repository.unlock()
 
1529
        branch_token, repo_token = self.get_lock_tokens(branch)
1265
1530
        # Unlock the branch (and repo) object, leaving the physical locks
1266
1531
        # in place.
1267
1532
        branch.leave_lock_in_place()
1268
1533
        branch.repository.leave_lock_in_place()
1269
1534
        branch.unlock()
1270
 
        response = request.execute('',
 
1535
        response = request.execute(b'',
1271
1536
                                   branch_token, repo_token)
1272
1537
        self.assertEqual(
1273
 
            smart_req.SmartServerResponse(('ok',)), response)
 
1538
            smart_req.SmartServerResponse((b'ok',)), response)
1274
1539
        # The branch is now unlocked.  Verify that with a new branch
1275
1540
        # object.
1276
 
        new_branch = branch.bzrdir.open_branch()
 
1541
        new_branch = branch.controldir.open_branch()
1277
1542
        new_branch.lock_write()
1278
1543
        new_branch.unlock()
1279
1544
 
1282
1547
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1283
1548
        branch = self.make_branch('.', format='knit')
1284
1549
        response = request.execute(
1285
 
            '', 'branch token', 'repo token')
 
1550
            b'', b'branch token', b'repo token')
1286
1551
        self.assertEqual(
1287
 
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
 
1552
            smart_req.SmartServerResponse((b'TokenMismatch',)), response)
1288
1553
 
1289
1554
    def test_unlock_on_unlocked_branch_locked_repo(self):
1290
1555
        backing = self.get_transport()
1291
1556
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1292
1557
        branch = self.make_branch('.', format='knit')
1293
1558
        # Lock the repository.
1294
 
        repo_token = branch.repository.lock_write()
 
1559
        repo_token = branch.repository.lock_write().repository_token
1295
1560
        branch.repository.leave_lock_in_place()
1296
1561
        branch.repository.unlock()
1297
1562
        # Issue branch lock_write request on the unlocked branch (with locked
1298
1563
        # repo).
1299
 
        response = request.execute(
1300
 
            '', 'branch token', repo_token)
 
1564
        response = request.execute(b'', b'branch token', repo_token)
1301
1565
        self.assertEqual(
1302
 
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
 
1566
            smart_req.SmartServerResponse((b'TokenMismatch',)), response)
1303
1567
        # Cleanup
1304
1568
        branch.repository.lock_write(repo_token)
1305
1569
        branch.repository.dont_leave_lock_in_place()
1317
1581
        backing = self.get_transport()
1318
1582
        request = smart_repo.SmartServerRepositoryRequest(backing)
1319
1583
        self.make_repository('.', shared=True)
1320
 
        self.make_bzrdir('subdir')
 
1584
        self.make_controldir('subdir')
1321
1585
        self.assertRaises(errors.NoRepositoryPresent,
1322
 
            request.execute, 'subdir')
 
1586
            request.execute, b'subdir')
 
1587
 
 
1588
 
 
1589
class TestSmartServerRepositoryAddSignatureText(tests.TestCaseWithMemoryTransport):
 
1590
 
 
1591
    def test_add_text(self):
 
1592
        backing = self.get_transport()
 
1593
        request = smart_repo.SmartServerRepositoryAddSignatureText(backing)
 
1594
        tree = self.make_branch_and_memory_tree('.')
 
1595
        write_token = tree.lock_write()
 
1596
        self.addCleanup(tree.unlock)
 
1597
        tree.add('')
 
1598
        tree.commit("Message", rev_id=b'rev1')
 
1599
        tree.branch.repository.start_write_group()
 
1600
        write_group_tokens = tree.branch.repository.suspend_write_group()
 
1601
        self.assertEqual(None, request.execute(b'', write_token,
 
1602
            b'rev1', *write_group_tokens))
 
1603
        response = request.do_body(b'somesignature')
 
1604
        self.assertTrue(response.is_successful())
 
1605
        self.assertEqual(response.args[0], b'ok')
 
1606
        write_group_tokens = response.args[1:]
 
1607
        tree.branch.repository.resume_write_group(write_group_tokens)
 
1608
        tree.branch.repository.commit_write_group()
 
1609
        tree.unlock()
 
1610
        self.assertEqual(b"somesignature",
 
1611
            tree.branch.repository.get_signature_text(b"rev1"))
 
1612
 
 
1613
 
 
1614
class TestSmartServerRepositoryAllRevisionIds(
 
1615
    tests.TestCaseWithMemoryTransport):
 
1616
 
 
1617
    def test_empty(self):
 
1618
        """An empty body should be returned for an empty repository."""
 
1619
        backing = self.get_transport()
 
1620
        request = smart_repo.SmartServerRepositoryAllRevisionIds(backing)
 
1621
        self.make_repository('.')
 
1622
        self.assertEqual(
 
1623
            smart_req.SuccessfulSmartServerResponse((b"ok", ), b""),
 
1624
            request.execute(b''))
 
1625
 
 
1626
    def test_some_revisions(self):
 
1627
        """An empty body should be returned for an empty repository."""
 
1628
        backing = self.get_transport()
 
1629
        request = smart_repo.SmartServerRepositoryAllRevisionIds(backing)
 
1630
        tree = self.make_branch_and_memory_tree('.')
 
1631
        tree.lock_write()
 
1632
        tree.add('')
 
1633
        tree.commit(rev_id=b'origineel', message="message")
 
1634
        tree.commit(rev_id=b'nog-een-revisie', message="message")
 
1635
        tree.unlock()
 
1636
        self.assertIn(
 
1637
            request.execute(b''),
 
1638
            [smart_req.SuccessfulSmartServerResponse((b"ok", ),
 
1639
                b"origineel\nnog-een-revisie"),
 
1640
             smart_req.SuccessfulSmartServerResponse((b"ok", ),
 
1641
                b"nog-een-revisie\norigineel")])
 
1642
 
 
1643
 
 
1644
class TestSmartServerRepositoryBreakLock(tests.TestCaseWithMemoryTransport):
 
1645
 
 
1646
    def test_lock_to_break(self):
 
1647
        backing = self.get_transport()
 
1648
        request = smart_repo.SmartServerRepositoryBreakLock(backing)
 
1649
        tree = self.make_branch_and_memory_tree('.')
 
1650
        tree.branch.repository.lock_write()
 
1651
        self.assertEqual(
 
1652
            smart_req.SuccessfulSmartServerResponse((b'ok', ), None),
 
1653
            request.execute(b''))
 
1654
 
 
1655
    def test_nothing_to_break(self):
 
1656
        backing = self.get_transport()
 
1657
        request = smart_repo.SmartServerRepositoryBreakLock(backing)
 
1658
        tree = self.make_branch_and_memory_tree('.')
 
1659
        self.assertEqual(
 
1660
            smart_req.SuccessfulSmartServerResponse((b'ok', ), None),
 
1661
            request.execute(b''))
1323
1662
 
1324
1663
 
1325
1664
class TestSmartServerRepositoryGetParentMap(tests.TestCaseWithMemoryTransport):
1331
1670
        tree = self.make_branch_and_memory_tree('.')
1332
1671
 
1333
1672
        self.assertEqual(None,
1334
 
            request.execute('', 'missing-id'))
 
1673
            request.execute(b'', b'missing-id'))
1335
1674
        # Note that it returns a body that is bzipped.
1336
1675
        self.assertEqual(
1337
 
            smart_req.SuccessfulSmartServerResponse(('ok', ), bz2.compress('')),
1338
 
            request.do_body('\n\n0\n'))
 
1676
            smart_req.SuccessfulSmartServerResponse((b'ok', ), bz2.compress(b'')),
 
1677
            request.do_body(b'\n\n0\n'))
1339
1678
 
1340
1679
    def test_trivial_include_missing(self):
1341
1680
        backing = self.get_transport()
1343
1682
        tree = self.make_branch_and_memory_tree('.')
1344
1683
 
1345
1684
        self.assertEqual(None,
1346
 
            request.execute('', 'missing-id', 'include-missing:'))
 
1685
            request.execute(b'', b'missing-id', b'include-missing:'))
1347
1686
        self.assertEqual(
1348
 
            smart_req.SuccessfulSmartServerResponse(('ok', ),
1349
 
                bz2.compress('missing:missing-id')),
1350
 
            request.do_body('\n\n0\n'))
 
1687
            smart_req.SuccessfulSmartServerResponse((b'ok', ),
 
1688
                bz2.compress(b'missing:missing-id')),
 
1689
            request.do_body(b'\n\n0\n'))
1351
1690
 
1352
1691
 
1353
1692
class TestSmartServerRepositoryGetRevisionGraph(
1365
1704
 
1366
1705
        # the lines of revision_id->revision_parent_list has no guaranteed
1367
1706
        # order coming out of a dict, so sort both our test and response
1368
 
        lines = sorted([' '.join([r2, r1]), r1])
1369
 
        response = request.execute('', '')
1370
 
        response.body = '\n'.join(sorted(response.body.split('\n')))
 
1707
        lines = sorted([b' '.join([r2, r1]), r1])
 
1708
        response = request.execute(b'', b'')
 
1709
        response.body = b'\n'.join(sorted(response.body.split(b'\n')))
1371
1710
 
1372
1711
        self.assertEqual(
1373
 
            smart_req.SmartServerResponse(('ok', ), '\n'.join(lines)), response)
 
1712
            smart_req.SmartServerResponse((b'ok', ), b'\n'.join(lines)), response)
1374
1713
 
1375
1714
    def test_specific_revision_argument(self):
1376
1715
        backing = self.get_transport()
1383
1722
        r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
1384
1723
        tree.unlock()
1385
1724
 
1386
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), rev_id_utf8),
1387
 
            request.execute('', rev_id_utf8))
 
1725
        self.assertEqual(smart_req.SmartServerResponse((b'ok', ), rev_id_utf8),
 
1726
            request.execute(b'', rev_id_utf8))
1388
1727
 
1389
1728
    def test_no_such_revision(self):
1390
1729
        backing = self.get_transport()
1397
1736
 
1398
1737
        # Note that it still returns body (of zero bytes).
1399
1738
        self.assertEqual(smart_req.SmartServerResponse(
1400
 
                ('nosuchrevision', 'missingrevision', ), ''),
1401
 
                         request.execute('', 'missingrevision'))
 
1739
                (b'nosuchrevision', b'missingrevision', ), b''),
 
1740
                         request.execute(b'', b'missingrevision'))
1402
1741
 
1403
1742
 
1404
1743
class TestSmartServerRepositoryGetRevIdForRevno(
1416
1755
        tree.commit('2nd commit', rev_id=rev2_id_utf8)
1417
1756
        tree.unlock()
1418
1757
 
1419
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', rev1_id_utf8)),
1420
 
            request.execute('', 1, (2, rev2_id_utf8)))
 
1758
        self.assertEqual(smart_req.SmartServerResponse((b'ok', rev1_id_utf8)),
 
1759
            request.execute(b'', 1, (2, rev2_id_utf8)))
1421
1760
 
1422
1761
    def test_known_revid_missing(self):
1423
1762
        backing = self.get_transport()
1424
1763
        request = smart_repo.SmartServerRepositoryGetRevIdForRevno(backing)
1425
1764
        repo = self.make_repository('.')
1426
1765
        self.assertEqual(
1427
 
            smart_req.FailedSmartServerResponse(('nosuchrevision', 'ghost')),
1428
 
            request.execute('', 1, (2, 'ghost')))
 
1766
            smart_req.FailedSmartServerResponse((b'nosuchrevision', b'ghost')),
 
1767
            request.execute(b'', 1, (2, b'ghost')))
1429
1768
 
1430
1769
    def test_history_incomplete(self):
1431
1770
        backing = self.get_transport()
1432
1771
        request = smart_repo.SmartServerRepositoryGetRevIdForRevno(backing)
1433
1772
        parent = self.make_branch_and_memory_tree('parent', format='1.9')
1434
1773
        parent.lock_write()
1435
 
        parent.add([''], ['TREE_ROOT'])
 
1774
        parent.add([''], [b'TREE_ROOT'])
1436
1775
        r1 = parent.commit(message='first commit')
1437
1776
        r2 = parent.commit(message='second commit')
1438
1777
        parent.unlock()
1443
1782
        local.branch.create_clone_on_transport(
1444
1783
            self.get_transport('stacked'), stacked_on=self.get_url('parent'))
1445
1784
        self.assertEqual(
1446
 
            smart_req.SmartServerResponse(('history-incomplete', 2, r2)),
1447
 
            request.execute('stacked', 1, (3, r3)))
1448
 
 
1449
 
 
1450
 
class TestSmartServerRepositoryGetStream(tests.TestCaseWithMemoryTransport):
 
1785
            smart_req.SmartServerResponse((b'history-incomplete', 2, r2)),
 
1786
            request.execute(b'stacked', 1, (3, r3)))
 
1787
 
 
1788
 
 
1789
class TestSmartServerRepositoryIterRevisions(
 
1790
    tests.TestCaseWithMemoryTransport):
 
1791
 
 
1792
    def test_basic(self):
 
1793
        backing = self.get_transport()
 
1794
        request = smart_repo.SmartServerRepositoryIterRevisions(backing)
 
1795
        tree = self.make_branch_and_memory_tree('.', format='2a')
 
1796
        tree.lock_write()
 
1797
        tree.add('')
 
1798
        tree.commit('1st commit', rev_id=b"rev1")
 
1799
        tree.commit('2nd commit', rev_id=b"rev2")
 
1800
        tree.unlock()
 
1801
 
 
1802
        self.assertIs(None, request.execute(b''))
 
1803
        response = request.do_body(b"rev1\nrev2")
 
1804
        self.assertTrue(response.is_successful())
 
1805
        # Format 2a uses serializer format 10
 
1806
        self.assertEqual(response.args, (b"ok", b"10"))
 
1807
 
 
1808
        self.addCleanup(tree.branch.lock_read().unlock)
 
1809
        entries = [zlib.compress(record.get_bytes_as("fulltext")) for record in
 
1810
            tree.branch.repository.revisions.get_record_stream(
 
1811
            [(b"rev1", ), (b"rev2", )], "unordered", True)]
 
1812
 
 
1813
        contents = b"".join(response.body_stream)
 
1814
        self.assertTrue(contents in (
 
1815
            b"".join([entries[0], entries[1]]),
 
1816
            b"".join([entries[1], entries[0]])))
 
1817
 
 
1818
    def test_missing(self):
 
1819
        backing = self.get_transport()
 
1820
        request = smart_repo.SmartServerRepositoryIterRevisions(backing)
 
1821
        tree = self.make_branch_and_memory_tree('.', format='2a')
 
1822
 
 
1823
        self.assertIs(None, request.execute(b''))
 
1824
        response = request.do_body(b"rev1\nrev2")
 
1825
        self.assertTrue(response.is_successful())
 
1826
        # Format 2a uses serializer format 10
 
1827
        self.assertEqual(response.args, (b"ok", b"10"))
 
1828
 
 
1829
        contents = b"".join(response.body_stream)
 
1830
        self.assertEqual(contents, b"")
 
1831
 
 
1832
 
 
1833
class GetStreamTestBase(tests.TestCaseWithMemoryTransport):
1451
1834
 
1452
1835
    def make_two_commit_repo(self):
1453
1836
        tree = self.make_branch_and_memory_tree('.')
1459
1842
        repo = tree.branch.repository
1460
1843
        return repo, r1, r2
1461
1844
 
 
1845
 
 
1846
class TestSmartServerRepositoryGetStream(GetStreamTestBase):
 
1847
 
1462
1848
    def test_ancestry_of(self):
1463
1849
        """The search argument may be a 'ancestry-of' some heads'."""
1464
1850
        backing = self.get_transport()
1465
1851
        request = smart_repo.SmartServerRepositoryGetStream(backing)
1466
1852
        repo, r1, r2 = self.make_two_commit_repo()
1467
 
        fetch_spec = ['ancestry-of', r2]
1468
 
        lines = '\n'.join(fetch_spec)
1469
 
        request.execute('', repo._format.network_name())
 
1853
        fetch_spec = [b'ancestry-of', r2]
 
1854
        lines = b'\n'.join(fetch_spec)
 
1855
        request.execute(b'', repo._format.network_name())
1470
1856
        response = request.do_body(lines)
1471
 
        self.assertEqual(('ok',), response.args)
1472
 
        stream_bytes = ''.join(response.body_stream)
1473
 
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
 
1857
        self.assertEqual((b'ok',), response.args)
 
1858
        stream_bytes = b''.join(response.body_stream)
 
1859
        self.assertStartsWith(stream_bytes, b'Bazaar pack format 1')
1474
1860
 
1475
1861
    def test_search(self):
1476
1862
        """The search argument may be a 'search' of some explicit keys."""
1477
1863
        backing = self.get_transport()
1478
1864
        request = smart_repo.SmartServerRepositoryGetStream(backing)
1479
1865
        repo, r1, r2 = self.make_two_commit_repo()
1480
 
        fetch_spec = ['search', '%s %s' % (r1, r2), 'null:', '2']
1481
 
        lines = '\n'.join(fetch_spec)
1482
 
        request.execute('', repo._format.network_name())
 
1866
        fetch_spec = [b'search', r1 + b' ' + r2, b'null:', b'2']
 
1867
        lines = b'\n'.join(fetch_spec)
 
1868
        request.execute(b'', repo._format.network_name())
1483
1869
        response = request.do_body(lines)
1484
 
        self.assertEqual(('ok',), response.args)
1485
 
        stream_bytes = ''.join(response.body_stream)
1486
 
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
 
1870
        self.assertEqual((b'ok',), response.args)
 
1871
        stream_bytes = b''.join(response.body_stream)
 
1872
        self.assertStartsWith(stream_bytes, b'Bazaar pack format 1')
 
1873
 
 
1874
    def test_search_everything(self):
 
1875
        """A search of 'everything' returns a stream."""
 
1876
        backing = self.get_transport()
 
1877
        request = smart_repo.SmartServerRepositoryGetStream_1_19(backing)
 
1878
        repo, r1, r2 = self.make_two_commit_repo()
 
1879
        serialised_fetch_spec = b'everything'
 
1880
        request.execute(b'', repo._format.network_name())
 
1881
        response = request.do_body(serialised_fetch_spec)
 
1882
        self.assertEqual((b'ok',), response.args)
 
1883
        stream_bytes = b''.join(response.body_stream)
 
1884
        self.assertStartsWith(stream_bytes, b'Bazaar pack format 1')
1487
1885
 
1488
1886
 
1489
1887
class TestSmartServerRequestHasRevision(tests.TestCaseWithMemoryTransport):
1493
1891
        backing = self.get_transport()
1494
1892
        request = smart_repo.SmartServerRequestHasRevision(backing)
1495
1893
        self.make_repository('.')
1496
 
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
1497
 
            request.execute('', 'revid'))
 
1894
        self.assertEqual(smart_req.SmartServerResponse((b'no', )),
 
1895
            request.execute(b'', b'revid'))
1498
1896
 
1499
1897
    def test_present_revision(self):
1500
1898
        """For a present revision, ('yes', ) is returned."""
1507
1905
        r1 = tree.commit('a commit', rev_id=rev_id_utf8)
1508
1906
        tree.unlock()
1509
1907
        self.assertTrue(tree.branch.repository.has_revision(rev_id_utf8))
1510
 
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
1511
 
            request.execute('', rev_id_utf8))
 
1908
        self.assertEqual(smart_req.SmartServerResponse((b'yes', )),
 
1909
            request.execute(b'', rev_id_utf8))
 
1910
 
 
1911
 
 
1912
class TestSmartServerRepositoryIterFilesBytes(tests.TestCaseWithTransport):
 
1913
 
 
1914
    def test_single(self):
 
1915
        backing = self.get_transport()
 
1916
        request = smart_repo.SmartServerRepositoryIterFilesBytes(backing)
 
1917
        t = self.make_branch_and_tree('.')
 
1918
        self.addCleanup(t.lock_write().unlock)
 
1919
        self.build_tree_contents([("file", b"somecontents")])
 
1920
        t.add(["file"], [b"thefileid"])
 
1921
        t.commit(rev_id=b'somerev', message="add file")
 
1922
        self.assertIs(None, request.execute(b''))
 
1923
        response = request.do_body(b"thefileid\0somerev\n")
 
1924
        self.assertTrue(response.is_successful())
 
1925
        self.assertEqual(response.args, (b"ok", ))
 
1926
        self.assertEqual(b"".join(response.body_stream),
 
1927
            b"ok\x000\n" + zlib.compress(b"somecontents"))
 
1928
 
 
1929
    def test_missing(self):
 
1930
        backing = self.get_transport()
 
1931
        request = smart_repo.SmartServerRepositoryIterFilesBytes(backing)
 
1932
        t = self.make_branch_and_tree('.')
 
1933
        self.addCleanup(t.lock_write().unlock)
 
1934
        self.assertIs(None, request.execute(b''))
 
1935
        response = request.do_body(b"thefileid\0revision\n")
 
1936
        self.assertTrue(response.is_successful())
 
1937
        self.assertEqual(response.args, (b"ok", ))
 
1938
        self.assertEqual(b"".join(response.body_stream),
 
1939
            b"absent\x00thefileid\x00revision\x000\n")
 
1940
 
 
1941
 
 
1942
class TestSmartServerRequestHasSignatureForRevisionId(
 
1943
        tests.TestCaseWithMemoryTransport):
 
1944
 
 
1945
    def test_missing_revision(self):
 
1946
        """For a missing revision, NoSuchRevision is returned."""
 
1947
        backing = self.get_transport()
 
1948
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1949
            backing)
 
1950
        self.make_repository('.')
 
1951
        self.assertEqual(
 
1952
            smart_req.FailedSmartServerResponse(
 
1953
                (b'nosuchrevision', b'revid'), None),
 
1954
            request.execute(b'', b'revid'))
 
1955
 
 
1956
    def test_missing_signature(self):
 
1957
        """For a missing signature, ('no', ) is returned."""
 
1958
        backing = self.get_transport()
 
1959
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1960
            backing)
 
1961
        tree = self.make_branch_and_memory_tree('.')
 
1962
        tree.lock_write()
 
1963
        tree.add('')
 
1964
        r1 = tree.commit('a commit', rev_id=b'A')
 
1965
        tree.unlock()
 
1966
        self.assertTrue(tree.branch.repository.has_revision(b'A'))
 
1967
        self.assertEqual(smart_req.SmartServerResponse((b'no', )),
 
1968
            request.execute(b'', b'A'))
 
1969
 
 
1970
    def test_present_signature(self):
 
1971
        """For a present signature, ('yes', ) is returned."""
 
1972
        backing = self.get_transport()
 
1973
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1974
            backing)
 
1975
        strategy = gpg.LoopbackGPGStrategy(None)
 
1976
        tree = self.make_branch_and_memory_tree('.')
 
1977
        tree.lock_write()
 
1978
        tree.add('')
 
1979
        r1 = tree.commit('a commit', rev_id=b'A')
 
1980
        tree.branch.repository.start_write_group()
 
1981
        tree.branch.repository.sign_revision(b'A', strategy)
 
1982
        tree.branch.repository.commit_write_group()
 
1983
        tree.unlock()
 
1984
        self.assertTrue(tree.branch.repository.has_revision(b'A'))
 
1985
        self.assertEqual(smart_req.SmartServerResponse((b'yes', )),
 
1986
            request.execute(b'', b'A'))
1512
1987
 
1513
1988
 
1514
1989
class TestSmartServerRepositoryGatherStats(tests.TestCaseWithMemoryTransport):
1519
1994
        request = smart_repo.SmartServerRepositoryGatherStats(backing)
1520
1995
        repository = self.make_repository('.')
1521
1996
        stats = repository.gather_stats()
1522
 
        expected_body = 'revisions: 0\n'
1523
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), expected_body),
1524
 
                         request.execute('', '', 'no'))
 
1997
        expected_body = b'revisions: 0\n'
 
1998
        self.assertEqual(smart_req.SmartServerResponse((b'ok', ), expected_body),
 
1999
                         request.execute(b'', b'', b'no'))
1525
2000
 
1526
2001
    def test_revid_with_committers(self):
1527
2002
        """For a revid we get more infos."""
1538
2013
        tree.unlock()
1539
2014
 
1540
2015
        stats = tree.branch.repository.gather_stats()
1541
 
        expected_body = ('firstrev: 123456.200 3600\n'
1542
 
                         'latestrev: 654321.400 0\n'
1543
 
                         'revisions: 2\n')
1544
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), expected_body),
1545
 
                         request.execute('',
1546
 
                                         rev_id_utf8, 'no'))
 
2016
        expected_body = (b'firstrev: 123456.200 3600\n'
 
2017
                         b'latestrev: 654321.400 0\n'
 
2018
                         b'revisions: 2\n')
 
2019
        self.assertEqual(smart_req.SmartServerResponse((b'ok', ), expected_body),
 
2020
                         request.execute(b'', rev_id_utf8, b'no'))
1547
2021
 
1548
2022
    def test_not_empty_repository_with_committers(self):
1549
2023
        """For a revid and requesting committers we get the whole thing."""
1561
2035
        tree.unlock()
1562
2036
        stats = tree.branch.repository.gather_stats()
1563
2037
 
1564
 
        expected_body = ('committers: 2\n'
1565
 
                         'firstrev: 123456.200 3600\n'
1566
 
                         'latestrev: 654321.400 0\n'
1567
 
                         'revisions: 2\n')
1568
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), expected_body),
1569
 
                         request.execute('',
1570
 
                                         rev_id_utf8, 'yes'))
 
2038
        expected_body = (b'committers: 2\n'
 
2039
                         b'firstrev: 123456.200 3600\n'
 
2040
                         b'latestrev: 654321.400 0\n'
 
2041
                         b'revisions: 2\n')
 
2042
        self.assertEqual(smart_req.SmartServerResponse((b'ok', ), expected_body),
 
2043
                         request.execute(b'',
 
2044
                                         rev_id_utf8, b'yes'))
 
2045
 
 
2046
    def test_unknown_revid(self):
 
2047
        """An unknown revision id causes a 'nosuchrevision' error."""
 
2048
        backing = self.get_transport()
 
2049
        request = smart_repo.SmartServerRepositoryGatherStats(backing)
 
2050
        repository = self.make_repository('.')
 
2051
        expected_body = b'revisions: 0\n'
 
2052
        self.assertEqual(
 
2053
            smart_req.FailedSmartServerResponse(
 
2054
                (b'nosuchrevision', b'mia'), None),
 
2055
            request.execute(b'', b'mia', b'yes'))
1571
2056
 
1572
2057
 
1573
2058
class TestSmartServerRepositoryIsShared(tests.TestCaseWithMemoryTransport):
1577
2062
        backing = self.get_transport()
1578
2063
        request = smart_repo.SmartServerRepositoryIsShared(backing)
1579
2064
        self.make_repository('.', shared=True)
1580
 
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
1581
 
            request.execute('', ))
 
2065
        self.assertEqual(smart_req.SmartServerResponse((b'yes', )),
 
2066
            request.execute(b'', ))
1582
2067
 
1583
2068
    def test_is_not_shared(self):
1584
2069
        """For a shared repository, ('no', ) is returned."""
1585
2070
        backing = self.get_transport()
1586
2071
        request = smart_repo.SmartServerRepositoryIsShared(backing)
1587
2072
        self.make_repository('.', shared=False)
1588
 
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
1589
 
            request.execute('', ))
 
2073
        self.assertEqual(smart_req.SmartServerResponse((b'no', )),
 
2074
            request.execute(b'', ))
 
2075
 
 
2076
 
 
2077
class TestSmartServerRepositoryGetRevisionSignatureText(
 
2078
        tests.TestCaseWithMemoryTransport):
 
2079
 
 
2080
    def test_get_signature(self):
 
2081
        backing = self.get_transport()
 
2082
        request = smart_repo.SmartServerRepositoryGetRevisionSignatureText(
 
2083
            backing)
 
2084
        bb = self.make_branch_builder('.')
 
2085
        bb.build_commit(rev_id=b'A')
 
2086
        repo = bb.get_branch().repository
 
2087
        strategy = gpg.LoopbackGPGStrategy(None)
 
2088
        self.addCleanup(repo.lock_write().unlock)
 
2089
        repo.start_write_group()
 
2090
        repo.sign_revision(b'A', strategy)
 
2091
        repo.commit_write_group()
 
2092
        expected_body = (
 
2093
            b'-----BEGIN PSEUDO-SIGNED CONTENT-----\n' +
 
2094
            Testament.from_revision(repo, b'A').as_short_text() +
 
2095
            b'-----END PSEUDO-SIGNED CONTENT-----\n')
 
2096
        self.assertEqual(
 
2097
            smart_req.SmartServerResponse((b'ok', ), expected_body),
 
2098
            request.execute(b'', b'A'))
 
2099
 
 
2100
 
 
2101
class TestSmartServerRepositoryMakeWorkingTrees(
 
2102
        tests.TestCaseWithMemoryTransport):
 
2103
 
 
2104
    def test_make_working_trees(self):
 
2105
        """For a repository with working trees, ('yes', ) is returned."""
 
2106
        backing = self.get_transport()
 
2107
        request = smart_repo.SmartServerRepositoryMakeWorkingTrees(backing)
 
2108
        r = self.make_repository('.')
 
2109
        r.set_make_working_trees(True)
 
2110
        self.assertEqual(smart_req.SmartServerResponse((b'yes', )),
 
2111
            request.execute(b'', ))
 
2112
 
 
2113
    def test_is_not_shared(self):
 
2114
        """For a repository with working trees, ('no', ) is returned."""
 
2115
        backing = self.get_transport()
 
2116
        request = smart_repo.SmartServerRepositoryMakeWorkingTrees(backing)
 
2117
        r = self.make_repository('.')
 
2118
        r.set_make_working_trees(False)
 
2119
        self.assertEqual(smart_req.SmartServerResponse((b'no', )),
 
2120
            request.execute(b'', ))
1590
2121
 
1591
2122
 
1592
2123
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
1595
2126
        backing = self.get_transport()
1596
2127
        request = smart_repo.SmartServerRepositoryLockWrite(backing)
1597
2128
        repository = self.make_repository('.', format='knit')
1598
 
        response = request.execute('')
 
2129
        response = request.execute(b'')
1599
2130
        nonce = repository.control_files._lock.peek().get('nonce')
1600
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', nonce)), response)
 
2131
        self.assertEqual(smart_req.SmartServerResponse((b'ok', nonce)), response)
1601
2132
        # The repository is now locked.  Verify that with a new repository
1602
2133
        # object.
1603
 
        new_repo = repository.bzrdir.open_repository()
 
2134
        new_repo = repository.controldir.open_repository()
1604
2135
        self.assertRaises(errors.LockContention, new_repo.lock_write)
1605
2136
        # Cleanup
1606
2137
        request = smart_repo.SmartServerRepositoryUnlock(backing)
1607
 
        response = request.execute('', nonce)
 
2138
        response = request.execute(b'', nonce)
1608
2139
 
1609
2140
    def test_lock_write_on_locked_repo(self):
1610
2141
        backing = self.get_transport()
1611
2142
        request = smart_repo.SmartServerRepositoryLockWrite(backing)
1612
2143
        repository = self.make_repository('.', format='knit')
1613
 
        repo_token = repository.lock_write()
 
2144
        repo_token = repository.lock_write().repository_token
1614
2145
        repository.leave_lock_in_place()
1615
2146
        repository.unlock()
1616
 
        response = request.execute('')
 
2147
        response = request.execute(b'')
1617
2148
        self.assertEqual(
1618
 
            smart_req.SmartServerResponse(('LockContention',)), response)
 
2149
            smart_req.SmartServerResponse((b'LockContention',)), response)
1619
2150
        # Cleanup
1620
2151
        repository.lock_write(repo_token)
1621
2152
        repository.dont_leave_lock_in_place()
1625
2156
        backing = self.get_readonly_transport()
1626
2157
        request = smart_repo.SmartServerRepositoryLockWrite(backing)
1627
2158
        repository = self.make_repository('.', format='knit')
1628
 
        response = request.execute('')
 
2159
        response = request.execute(b'')
1629
2160
        self.assertFalse(response.is_successful())
1630
 
        self.assertEqual('LockFailed', response.args[0])
 
2161
        self.assertEqual(b'LockFailed', response.args[0])
1631
2162
 
1632
2163
 
1633
2164
class TestInsertStreamBase(tests.TestCaseWithMemoryTransport):
1634
2165
 
1635
2166
    def make_empty_byte_stream(self, repo):
1636
2167
        byte_stream = smart_repo._stream_to_byte_stream([], repo._format)
1637
 
        return ''.join(byte_stream)
 
2168
        return b''.join(byte_stream)
1638
2169
 
1639
2170
 
1640
2171
class TestSmartServerRepositoryInsertStream(TestInsertStreamBase):
1643
2174
        backing = self.get_transport()
1644
2175
        request = smart_repo.SmartServerRepositoryInsertStream(backing)
1645
2176
        repository = self.make_repository('.')
1646
 
        response = request.execute('', '')
 
2177
        response = request.execute(b'', b'')
1647
2178
        self.assertEqual(None, response)
1648
2179
        response = request.do_chunk(self.make_empty_byte_stream(repository))
1649
2180
        self.assertEqual(None, response)
1650
2181
        response = request.do_end()
1651
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', )), response)
 
2182
        self.assertEqual(smart_req.SmartServerResponse((b'ok', )), response)
1652
2183
 
1653
2184
 
1654
2185
class TestSmartServerRepositoryInsertStreamLocked(TestInsertStreamBase):
1658
2189
        request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1659
2190
            backing)
1660
2191
        repository = self.make_repository('.', format='knit')
1661
 
        lock_token = repository.lock_write()
1662
 
        response = request.execute('', '', lock_token)
 
2192
        lock_token = repository.lock_write().repository_token
 
2193
        response = request.execute(b'', b'', lock_token)
1663
2194
        self.assertEqual(None, response)
1664
2195
        response = request.do_chunk(self.make_empty_byte_stream(repository))
1665
2196
        self.assertEqual(None, response)
1666
2197
        response = request.do_end()
1667
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', )), response)
 
2198
        self.assertEqual(smart_req.SmartServerResponse((b'ok', )), response)
1668
2199
        repository.unlock()
1669
2200
 
1670
2201
    def test_insert_stream_with_wrong_lock_token(self):
1672
2203
        request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1673
2204
            backing)
1674
2205
        repository = self.make_repository('.', format='knit')
1675
 
        lock_token = repository.lock_write()
 
2206
        lock_token = repository.lock_write().repository_token
1676
2207
        self.assertRaises(
1677
 
            errors.TokenMismatch, request.execute, '', '', 'wrong-token')
 
2208
            errors.TokenMismatch, request.execute, b'', b'', b'wrong-token')
1678
2209
        repository.unlock()
1679
2210
 
1680
2211
 
1681
2212
class TestSmartServerRepositoryUnlock(tests.TestCaseWithMemoryTransport):
1682
2213
 
1683
 
    def setUp(self):
1684
 
        tests.TestCaseWithMemoryTransport.setUp(self)
1685
 
 
1686
2214
    def test_unlock_on_locked_repo(self):
1687
2215
        backing = self.get_transport()
1688
2216
        request = smart_repo.SmartServerRepositoryUnlock(backing)
1689
2217
        repository = self.make_repository('.', format='knit')
1690
 
        token = repository.lock_write()
 
2218
        token = repository.lock_write().repository_token
1691
2219
        repository.leave_lock_in_place()
1692
2220
        repository.unlock()
1693
 
        response = request.execute('', token)
 
2221
        response = request.execute(b'', token)
1694
2222
        self.assertEqual(
1695
 
            smart_req.SmartServerResponse(('ok',)), response)
 
2223
            smart_req.SmartServerResponse((b'ok',)), response)
1696
2224
        # The repository is now unlocked.  Verify that with a new repository
1697
2225
        # object.
1698
 
        new_repo = repository.bzrdir.open_repository()
 
2226
        new_repo = repository.controldir.open_repository()
1699
2227
        new_repo.lock_write()
1700
2228
        new_repo.unlock()
1701
2229
 
1703
2231
        backing = self.get_transport()
1704
2232
        request = smart_repo.SmartServerRepositoryUnlock(backing)
1705
2233
        repository = self.make_repository('.', format='knit')
1706
 
        response = request.execute('', 'some token')
 
2234
        response = request.execute(b'', b'some token')
1707
2235
        self.assertEqual(
1708
 
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
 
2236
            smart_req.SmartServerResponse((b'TokenMismatch',)), response)
 
2237
 
 
2238
 
 
2239
class TestSmartServerRepositoryGetPhysicalLockStatus(
 
2240
    tests.TestCaseWithTransport):
 
2241
 
 
2242
    def test_with_write_lock(self):
 
2243
        backing = self.get_transport()
 
2244
        repo = self.make_repository('.')
 
2245
        self.addCleanup(repo.lock_write().unlock)
 
2246
        # lock_write() doesn't necessarily actually take a physical
 
2247
        # lock out.
 
2248
        if repo.get_physical_lock_status():
 
2249
            expected = b'yes'
 
2250
        else:
 
2251
            expected = b'no'
 
2252
        request_class = smart_repo.SmartServerRepositoryGetPhysicalLockStatus
 
2253
        request = request_class(backing)
 
2254
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((expected,)),
 
2255
            request.execute(b'', ))
 
2256
 
 
2257
    def test_without_write_lock(self):
 
2258
        backing = self.get_transport()
 
2259
        repo = self.make_repository('.')
 
2260
        self.assertEqual(False, repo.get_physical_lock_status())
 
2261
        request_class = smart_repo.SmartServerRepositoryGetPhysicalLockStatus
 
2262
        request = request_class(backing)
 
2263
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'no',)),
 
2264
            request.execute(b'', ))
 
2265
 
 
2266
 
 
2267
class TestSmartServerRepositoryReconcile(tests.TestCaseWithTransport):
 
2268
 
 
2269
    def test_reconcile(self):
 
2270
        backing = self.get_transport()
 
2271
        repo = self.make_repository('.')
 
2272
        token = repo.lock_write().repository_token
 
2273
        self.addCleanup(repo.unlock)
 
2274
        request_class = smart_repo.SmartServerRepositoryReconcile
 
2275
        request = request_class(backing)
 
2276
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(
 
2277
            (b'ok', ),
 
2278
             b'garbage_inventories: 0\n'
 
2279
             b'inconsistent_parents: 0\n'),
 
2280
            request.execute(b'', token))
1709
2281
 
1710
2282
 
1711
2283
class TestSmartServerIsReadonly(tests.TestCaseWithMemoryTransport):
1715
2287
        request = smart_req.SmartServerIsReadonly(backing)
1716
2288
        response = request.execute()
1717
2289
        self.assertEqual(
1718
 
            smart_req.SmartServerResponse(('no',)), response)
 
2290
            smart_req.SmartServerResponse((b'no',)), response)
1719
2291
 
1720
2292
    def test_is_readonly_yes(self):
1721
2293
        backing = self.get_readonly_transport()
1722
2294
        request = smart_req.SmartServerIsReadonly(backing)
1723
2295
        response = request.execute()
1724
2296
        self.assertEqual(
1725
 
            smart_req.SmartServerResponse(('yes',)), response)
 
2297
            smart_req.SmartServerResponse((b'yes',)), response)
1726
2298
 
1727
2299
 
1728
2300
class TestSmartServerRepositorySetMakeWorkingTrees(
1734
2306
        repo.set_make_working_trees(True)
1735
2307
        request_class = smart_repo.SmartServerRepositorySetMakeWorkingTrees
1736
2308
        request = request_class(backing)
1737
 
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
1738
 
            request.execute('', 'False'))
1739
 
        repo = repo.bzrdir.open_repository()
 
2309
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
 
2310
            request.execute(b'', b'False'))
 
2311
        repo = repo.controldir.open_repository()
1740
2312
        self.assertFalse(repo.make_working_trees())
1741
2313
 
1742
2314
    def test_set_true(self):
1745
2317
        repo.set_make_working_trees(False)
1746
2318
        request_class = smart_repo.SmartServerRepositorySetMakeWorkingTrees
1747
2319
        request = request_class(backing)
1748
 
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
1749
 
            request.execute('', 'True'))
1750
 
        repo = repo.bzrdir.open_repository()
 
2320
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
 
2321
            request.execute(b'', b'True'))
 
2322
        repo = repo.controldir.open_repository()
1751
2323
        self.assertTrue(repo.make_working_trees())
1752
2324
 
1753
2325
 
 
2326
class TestSmartServerRepositoryGetSerializerFormat(
 
2327
    tests.TestCaseWithMemoryTransport):
 
2328
 
 
2329
    def test_get_serializer_format(self):
 
2330
        backing = self.get_transport()
 
2331
        repo = self.make_repository('.', format='2a')
 
2332
        request_class = smart_repo.SmartServerRepositoryGetSerializerFormat
 
2333
        request = request_class(backing)
 
2334
        self.assertEqual(
 
2335
            smart_req.SuccessfulSmartServerResponse((b'ok', b'10')),
 
2336
            request.execute(b''))
 
2337
 
 
2338
 
 
2339
class TestSmartServerRepositoryWriteGroup(
 
2340
    tests.TestCaseWithMemoryTransport):
 
2341
 
 
2342
    def test_start_write_group(self):
 
2343
        backing = self.get_transport()
 
2344
        repo = self.make_repository('.')
 
2345
        lock_token = repo.lock_write().repository_token
 
2346
        self.addCleanup(repo.unlock)
 
2347
        request_class = smart_repo.SmartServerRepositoryStartWriteGroup
 
2348
        request = request_class(backing)
 
2349
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok', [])),
 
2350
            request.execute(b'', lock_token))
 
2351
 
 
2352
    def test_start_write_group_unsuspendable(self):
 
2353
        backing = self.get_transport()
 
2354
        repo = self.make_repository('.', format='knit')
 
2355
        lock_token = repo.lock_write().repository_token
 
2356
        self.addCleanup(repo.unlock)
 
2357
        request_class = smart_repo.SmartServerRepositoryStartWriteGroup
 
2358
        request = request_class(backing)
 
2359
        self.assertEqual(
 
2360
            smart_req.FailedSmartServerResponse((b'UnsuspendableWriteGroup',)),
 
2361
            request.execute(b'', lock_token))
 
2362
 
 
2363
    def test_commit_write_group(self):
 
2364
        backing = self.get_transport()
 
2365
        repo = self.make_repository('.')
 
2366
        lock_token = repo.lock_write().repository_token
 
2367
        self.addCleanup(repo.unlock)
 
2368
        repo.start_write_group()
 
2369
        tokens = repo.suspend_write_group()
 
2370
        request_class = smart_repo.SmartServerRepositoryCommitWriteGroup
 
2371
        request = request_class(backing)
 
2372
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
 
2373
            request.execute(b'', lock_token, tokens))
 
2374
 
 
2375
    def test_abort_write_group(self):
 
2376
        backing = self.get_transport()
 
2377
        repo = self.make_repository('.')
 
2378
        lock_token = repo.lock_write().repository_token
 
2379
        repo.start_write_group()
 
2380
        tokens = repo.suspend_write_group()
 
2381
        self.addCleanup(repo.unlock)
 
2382
        request_class = smart_repo.SmartServerRepositoryAbortWriteGroup
 
2383
        request = request_class(backing)
 
2384
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
 
2385
            request.execute(b'', lock_token, tokens))
 
2386
 
 
2387
    def test_check_write_group(self):
 
2388
        backing = self.get_transport()
 
2389
        repo = self.make_repository('.')
 
2390
        lock_token = repo.lock_write().repository_token
 
2391
        repo.start_write_group()
 
2392
        tokens = repo.suspend_write_group()
 
2393
        self.addCleanup(repo.unlock)
 
2394
        request_class = smart_repo.SmartServerRepositoryCheckWriteGroup
 
2395
        request = request_class(backing)
 
2396
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
 
2397
            request.execute(b'', lock_token, tokens))
 
2398
 
 
2399
    def test_check_write_group_invalid(self):
 
2400
        backing = self.get_transport()
 
2401
        repo = self.make_repository('.')
 
2402
        lock_token = repo.lock_write().repository_token
 
2403
        self.addCleanup(repo.unlock)
 
2404
        request_class = smart_repo.SmartServerRepositoryCheckWriteGroup
 
2405
        request = request_class(backing)
 
2406
        self.assertEqual(smart_req.FailedSmartServerResponse(
 
2407
            (b'UnresumableWriteGroup', [b'random'],
 
2408
                b'Malformed write group token')),
 
2409
            request.execute(b'', lock_token, [b"random"]))
 
2410
 
 
2411
 
1754
2412
class TestSmartServerPackRepositoryAutopack(tests.TestCaseWithTransport):
1755
2413
 
1756
2414
    def make_repo_needing_autopacking(self, path='.'):
1772
2430
        backing = self.get_transport()
1773
2431
        request = smart_packrepo.SmartServerPackRepositoryAutopack(
1774
2432
            backing)
1775
 
        response = request.execute('')
1776
 
        self.assertEqual(smart_req.SmartServerResponse(('ok',)), response)
 
2433
        response = request.execute(b'')
 
2434
        self.assertEqual(smart_req.SmartServerResponse((b'ok',)), response)
1777
2435
        repo._pack_collection.reload_pack_names()
1778
2436
        self.assertEqual(1, len(repo._pack_collection.names()))
1779
2437
 
1787
2445
        backing = self.get_transport()
1788
2446
        request = smart_packrepo.SmartServerPackRepositoryAutopack(
1789
2447
            backing)
1790
 
        response = request.execute('')
1791
 
        self.assertEqual(smart_req.SmartServerResponse(('ok',)), response)
 
2448
        response = request.execute(b'')
 
2449
        self.assertEqual(smart_req.SmartServerResponse((b'ok',)), response)
1792
2450
        repo._pack_collection.reload_pack_names()
1793
2451
        self.assertEqual(9, len(repo._pack_collection.names()))
1794
2452
 
1798
2456
        backing = self.get_transport()
1799
2457
        request = smart_packrepo.SmartServerPackRepositoryAutopack(
1800
2458
            backing)
1801
 
        response = request.execute('')
1802
 
        self.assertEqual(smart_req.SmartServerResponse(('ok',)), response)
 
2459
        response = request.execute(b'')
 
2460
        self.assertEqual(smart_req.SmartServerResponse((b'ok',)), response)
1803
2461
 
1804
2462
 
1805
2463
class TestSmartServerVfsGet(tests.TestCaseWithMemoryTransport):
1810
2468
        filename_escaped = urlutils.escape(filename)
1811
2469
        backing = self.get_transport()
1812
2470
        request = vfs.GetRequest(backing)
1813
 
        backing.put_bytes_non_atomic(filename_escaped, 'contents')
1814
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), 'contents'),
 
2471
        backing.put_bytes_non_atomic(filename_escaped, b'contents')
 
2472
        self.assertEqual(smart_req.SmartServerResponse((b'ok', ), b'contents'),
1815
2473
            request.execute(filename_escaped))
1816
2474
 
1817
2475
 
1822
2480
        """All registered request_handlers can be found."""
1823
2481
        # If there's a typo in a register_lazy call, this loop will fail with
1824
2482
        # an AttributeError.
1825
 
        for key, item in smart_req.request_handlers.iteritems():
1826
 
            pass
 
2483
        for key in smart_req.request_handlers.keys():
 
2484
            try:
 
2485
                item = smart_req.request_handlers.get(key)
 
2486
            except AttributeError as e:
 
2487
                raise AttributeError('failed to get %s: %s' % (key, e))
1827
2488
 
1828
2489
    def assertHandlerEqual(self, verb, handler):
1829
2490
        self.assertEqual(smart_req.request_handlers.get(verb), handler)
1830
2491
 
1831
2492
    def test_registered_methods(self):
1832
2493
        """Test that known methods are registered to the correct object."""
1833
 
        self.assertHandlerEqual('Branch.get_config_file',
 
2494
        self.assertHandlerEqual(b'Branch.break_lock',
 
2495
            smart_branch.SmartServerBranchBreakLock)
 
2496
        self.assertHandlerEqual(b'Branch.get_config_file',
1834
2497
            smart_branch.SmartServerBranchGetConfigFile)
1835
 
        self.assertHandlerEqual('Branch.get_parent',
 
2498
        self.assertHandlerEqual(b'Branch.put_config_file',
 
2499
            smart_branch.SmartServerBranchPutConfigFile)
 
2500
        self.assertHandlerEqual(b'Branch.get_parent',
1836
2501
            smart_branch.SmartServerBranchGetParent)
1837
 
        self.assertHandlerEqual('Branch.get_tags_bytes',
 
2502
        self.assertHandlerEqual(b'Branch.get_physical_lock_status',
 
2503
            smart_branch.SmartServerBranchRequestGetPhysicalLockStatus)
 
2504
        self.assertHandlerEqual(b'Branch.get_tags_bytes',
1838
2505
            smart_branch.SmartServerBranchGetTagsBytes)
1839
 
        self.assertHandlerEqual('Branch.lock_write',
 
2506
        self.assertHandlerEqual(b'Branch.lock_write',
1840
2507
            smart_branch.SmartServerBranchRequestLockWrite)
1841
 
        self.assertHandlerEqual('Branch.last_revision_info',
 
2508
        self.assertHandlerEqual(b'Branch.last_revision_info',
1842
2509
            smart_branch.SmartServerBranchRequestLastRevisionInfo)
1843
 
        self.assertHandlerEqual('Branch.revision_history',
 
2510
        self.assertHandlerEqual(b'Branch.revision_history',
1844
2511
            smart_branch.SmartServerRequestRevisionHistory)
1845
 
        self.assertHandlerEqual('Branch.set_config_option',
 
2512
        self.assertHandlerEqual(b'Branch.revision_id_to_revno',
 
2513
            smart_branch.SmartServerBranchRequestRevisionIdToRevno)
 
2514
        self.assertHandlerEqual(b'Branch.set_config_option',
1846
2515
            smart_branch.SmartServerBranchRequestSetConfigOption)
1847
 
        self.assertHandlerEqual('Branch.set_last_revision',
 
2516
        self.assertHandlerEqual(b'Branch.set_last_revision',
1848
2517
            smart_branch.SmartServerBranchRequestSetLastRevision)
1849
 
        self.assertHandlerEqual('Branch.set_last_revision_info',
 
2518
        self.assertHandlerEqual(b'Branch.set_last_revision_info',
1850
2519
            smart_branch.SmartServerBranchRequestSetLastRevisionInfo)
1851
 
        self.assertHandlerEqual('Branch.set_last_revision_ex',
 
2520
        self.assertHandlerEqual(b'Branch.set_last_revision_ex',
1852
2521
            smart_branch.SmartServerBranchRequestSetLastRevisionEx)
1853
 
        self.assertHandlerEqual('Branch.set_parent_location',
 
2522
        self.assertHandlerEqual(b'Branch.set_parent_location',
1854
2523
            smart_branch.SmartServerBranchRequestSetParentLocation)
1855
 
        self.assertHandlerEqual('Branch.unlock',
 
2524
        self.assertHandlerEqual(b'Branch.unlock',
1856
2525
            smart_branch.SmartServerBranchRequestUnlock)
1857
 
        self.assertHandlerEqual('BzrDir.find_repository',
 
2526
        self.assertHandlerEqual(b'BzrDir.destroy_branch',
 
2527
            smart_dir.SmartServerBzrDirRequestDestroyBranch)
 
2528
        self.assertHandlerEqual(b'BzrDir.find_repository',
1858
2529
            smart_dir.SmartServerRequestFindRepositoryV1)
1859
 
        self.assertHandlerEqual('BzrDir.find_repositoryV2',
 
2530
        self.assertHandlerEqual(b'BzrDir.find_repositoryV2',
1860
2531
            smart_dir.SmartServerRequestFindRepositoryV2)
1861
 
        self.assertHandlerEqual('BzrDirFormat.initialize',
 
2532
        self.assertHandlerEqual(b'BzrDirFormat.initialize',
1862
2533
            smart_dir.SmartServerRequestInitializeBzrDir)
1863
 
        self.assertHandlerEqual('BzrDirFormat.initialize_ex_1.16',
 
2534
        self.assertHandlerEqual(b'BzrDirFormat.initialize_ex_1.16',
1864
2535
            smart_dir.SmartServerRequestBzrDirInitializeEx)
1865
 
        self.assertHandlerEqual('BzrDir.cloning_metadir',
 
2536
        self.assertHandlerEqual(b'BzrDir.checkout_metadir',
 
2537
            smart_dir.SmartServerBzrDirRequestCheckoutMetaDir)
 
2538
        self.assertHandlerEqual(b'BzrDir.cloning_metadir',
1866
2539
            smart_dir.SmartServerBzrDirRequestCloningMetaDir)
1867
 
        self.assertHandlerEqual('BzrDir.get_config_file',
 
2540
        self.assertHandlerEqual(b'BzrDir.get_branches',
 
2541
            smart_dir.SmartServerBzrDirRequestGetBranches)
 
2542
        self.assertHandlerEqual(b'BzrDir.get_config_file',
1868
2543
            smart_dir.SmartServerBzrDirRequestConfigFile)
1869
 
        self.assertHandlerEqual('BzrDir.open_branch',
 
2544
        self.assertHandlerEqual(b'BzrDir.open_branch',
1870
2545
            smart_dir.SmartServerRequestOpenBranch)
1871
 
        self.assertHandlerEqual('BzrDir.open_branchV2',
 
2546
        self.assertHandlerEqual(b'BzrDir.open_branchV2',
1872
2547
            smart_dir.SmartServerRequestOpenBranchV2)
1873
 
        self.assertHandlerEqual('BzrDir.open_branchV3',
 
2548
        self.assertHandlerEqual(b'BzrDir.open_branchV3',
1874
2549
            smart_dir.SmartServerRequestOpenBranchV3)
1875
 
        self.assertHandlerEqual('PackRepository.autopack',
 
2550
        self.assertHandlerEqual(b'PackRepository.autopack',
1876
2551
            smart_packrepo.SmartServerPackRepositoryAutopack)
1877
 
        self.assertHandlerEqual('Repository.gather_stats',
 
2552
        self.assertHandlerEqual(b'Repository.add_signature_text',
 
2553
            smart_repo.SmartServerRepositoryAddSignatureText)
 
2554
        self.assertHandlerEqual(b'Repository.all_revision_ids',
 
2555
            smart_repo.SmartServerRepositoryAllRevisionIds)
 
2556
        self.assertHandlerEqual(b'Repository.break_lock',
 
2557
            smart_repo.SmartServerRepositoryBreakLock)
 
2558
        self.assertHandlerEqual(b'Repository.gather_stats',
1878
2559
            smart_repo.SmartServerRepositoryGatherStats)
1879
 
        self.assertHandlerEqual('Repository.get_parent_map',
 
2560
        self.assertHandlerEqual(b'Repository.get_parent_map',
1880
2561
            smart_repo.SmartServerRepositoryGetParentMap)
1881
 
        self.assertHandlerEqual('Repository.get_rev_id_for_revno',
 
2562
        self.assertHandlerEqual(b'Repository.get_physical_lock_status',
 
2563
            smart_repo.SmartServerRepositoryGetPhysicalLockStatus)
 
2564
        self.assertHandlerEqual(b'Repository.get_rev_id_for_revno',
1882
2565
            smart_repo.SmartServerRepositoryGetRevIdForRevno)
1883
 
        self.assertHandlerEqual('Repository.get_revision_graph',
 
2566
        self.assertHandlerEqual(b'Repository.get_revision_graph',
1884
2567
            smart_repo.SmartServerRepositoryGetRevisionGraph)
1885
 
        self.assertHandlerEqual('Repository.get_stream',
 
2568
        self.assertHandlerEqual(b'Repository.get_revision_signature_text',
 
2569
            smart_repo.SmartServerRepositoryGetRevisionSignatureText)
 
2570
        self.assertHandlerEqual(b'Repository.get_stream',
1886
2571
            smart_repo.SmartServerRepositoryGetStream)
1887
 
        self.assertHandlerEqual('Repository.has_revision',
 
2572
        self.assertHandlerEqual(b'Repository.get_stream_1.19',
 
2573
            smart_repo.SmartServerRepositoryGetStream_1_19)
 
2574
        self.assertHandlerEqual(b'Repository.iter_revisions',
 
2575
            smart_repo.SmartServerRepositoryIterRevisions)
 
2576
        self.assertHandlerEqual(b'Repository.has_revision',
1888
2577
            smart_repo.SmartServerRequestHasRevision)
1889
 
        self.assertHandlerEqual('Repository.insert_stream',
 
2578
        self.assertHandlerEqual(b'Repository.insert_stream',
1890
2579
            smart_repo.SmartServerRepositoryInsertStream)
1891
 
        self.assertHandlerEqual('Repository.insert_stream_locked',
 
2580
        self.assertHandlerEqual(b'Repository.insert_stream_locked',
1892
2581
            smart_repo.SmartServerRepositoryInsertStreamLocked)
1893
 
        self.assertHandlerEqual('Repository.is_shared',
 
2582
        self.assertHandlerEqual(b'Repository.is_shared',
1894
2583
            smart_repo.SmartServerRepositoryIsShared)
1895
 
        self.assertHandlerEqual('Repository.lock_write',
 
2584
        self.assertHandlerEqual(b'Repository.iter_files_bytes',
 
2585
            smart_repo.SmartServerRepositoryIterFilesBytes)
 
2586
        self.assertHandlerEqual(b'Repository.lock_write',
1896
2587
            smart_repo.SmartServerRepositoryLockWrite)
1897
 
        self.assertHandlerEqual('Repository.tarball',
 
2588
        self.assertHandlerEqual(b'Repository.make_working_trees',
 
2589
            smart_repo.SmartServerRepositoryMakeWorkingTrees)
 
2590
        self.assertHandlerEqual(b'Repository.pack',
 
2591
            smart_repo.SmartServerRepositoryPack)
 
2592
        self.assertHandlerEqual(b'Repository.reconcile',
 
2593
            smart_repo.SmartServerRepositoryReconcile)
 
2594
        self.assertHandlerEqual(b'Repository.tarball',
1898
2595
            smart_repo.SmartServerRepositoryTarball)
1899
 
        self.assertHandlerEqual('Repository.unlock',
 
2596
        self.assertHandlerEqual(b'Repository.unlock',
1900
2597
            smart_repo.SmartServerRepositoryUnlock)
1901
 
        self.assertHandlerEqual('Transport.is_readonly',
 
2598
        self.assertHandlerEqual(b'Repository.start_write_group',
 
2599
            smart_repo.SmartServerRepositoryStartWriteGroup)
 
2600
        self.assertHandlerEqual(b'Repository.check_write_group',
 
2601
            smart_repo.SmartServerRepositoryCheckWriteGroup)
 
2602
        self.assertHandlerEqual(b'Repository.commit_write_group',
 
2603
            smart_repo.SmartServerRepositoryCommitWriteGroup)
 
2604
        self.assertHandlerEqual(b'Repository.abort_write_group',
 
2605
            smart_repo.SmartServerRepositoryAbortWriteGroup)
 
2606
        self.assertHandlerEqual(b'VersionedFileRepository.get_serializer_format',
 
2607
            smart_repo.SmartServerRepositoryGetSerializerFormat)
 
2608
        self.assertHandlerEqual(b'VersionedFileRepository.get_inventories',
 
2609
            smart_repo.SmartServerRepositoryGetInventories)
 
2610
        self.assertHandlerEqual(b'Transport.is_readonly',
1902
2611
            smart_req.SmartServerIsReadonly)
 
2612
 
 
2613
 
 
2614
class SmartTCPServerHookTests(tests.TestCaseWithMemoryTransport):
 
2615
    """Tests for SmartTCPServer hooks."""
 
2616
 
 
2617
    def setUp(self):
 
2618
        super(SmartTCPServerHookTests, self).setUp()
 
2619
        self.server = server.SmartTCPServer(self.get_transport())
 
2620
 
 
2621
    def test_run_server_started_hooks(self):
 
2622
        """Test the server started hooks get fired properly."""
 
2623
        started_calls = []
 
2624
        server.SmartTCPServer.hooks.install_named_hook('server_started',
 
2625
            lambda backing_urls, url: started_calls.append((backing_urls, url)),
 
2626
            None)
 
2627
        started_ex_calls = []
 
2628
        server.SmartTCPServer.hooks.install_named_hook('server_started_ex',
 
2629
            lambda backing_urls, url: started_ex_calls.append((backing_urls, url)),
 
2630
            None)
 
2631
        self.server._sockname = ('example.com', 42)
 
2632
        self.server.run_server_started_hooks()
 
2633
        self.assertEqual(started_calls,
 
2634
            [([self.get_transport().base], 'bzr://example.com:42/')])
 
2635
        self.assertEqual(started_ex_calls,
 
2636
            [([self.get_transport().base], self.server)])
 
2637
 
 
2638
    def test_run_server_started_hooks_ipv6(self):
 
2639
        """Test that socknames can contain 4-tuples."""
 
2640
        self.server._sockname = ('::', 42, 0, 0)
 
2641
        started_calls = []
 
2642
        server.SmartTCPServer.hooks.install_named_hook('server_started',
 
2643
            lambda backing_urls, url: started_calls.append((backing_urls, url)),
 
2644
            None)
 
2645
        self.server.run_server_started_hooks()
 
2646
        self.assertEqual(started_calls,
 
2647
                [([self.get_transport().base], 'bzr://:::42/')])
 
2648
 
 
2649
    def test_run_server_stopped_hooks(self):
 
2650
        """Test the server stopped hooks."""
 
2651
        self.server._sockname = ('example.com', 42)
 
2652
        stopped_calls = []
 
2653
        server.SmartTCPServer.hooks.install_named_hook('server_stopped',
 
2654
            lambda backing_urls, url: stopped_calls.append((backing_urls, url)),
 
2655
            None)
 
2656
        self.server.run_server_stopped_hooks()
 
2657
        self.assertEqual(stopped_calls,
 
2658
            [([self.get_transport().base], 'bzr://example.com:42/')])
 
2659
 
 
2660
 
 
2661
class TestSmartServerRepositoryPack(tests.TestCaseWithMemoryTransport):
 
2662
 
 
2663
    def test_pack(self):
 
2664
        backing = self.get_transport()
 
2665
        request = smart_repo.SmartServerRepositoryPack(backing)
 
2666
        tree = self.make_branch_and_memory_tree('.')
 
2667
        repo_token = tree.branch.repository.lock_write().repository_token
 
2668
 
 
2669
        self.assertIs(None, request.execute(b'', repo_token, False))
 
2670
 
 
2671
        self.assertEqual(
 
2672
            smart_req.SuccessfulSmartServerResponse((b'ok', ), ),
 
2673
            request.do_body(b''))
 
2674
 
 
2675
 
 
2676
class TestSmartServerRepositoryGetInventories(tests.TestCaseWithTransport):
 
2677
 
 
2678
    def _get_serialized_inventory_delta(self, repository, base_revid, revid):
 
2679
        base_inv = repository.revision_tree(base_revid).root_inventory
 
2680
        inv = repository.revision_tree(revid).root_inventory
 
2681
        inv_delta = inv._make_delta(base_inv)
 
2682
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
 
2683
        return b"".join(serializer.delta_to_lines(base_revid, revid, inv_delta))
 
2684
 
 
2685
    def test_single(self):
 
2686
        backing = self.get_transport()
 
2687
        request = smart_repo.SmartServerRepositoryGetInventories(backing)
 
2688
        t = self.make_branch_and_tree('.', format='2a')
 
2689
        self.addCleanup(t.lock_write().unlock)
 
2690
        self.build_tree_contents([("file", b"somecontents")])
 
2691
        t.add(["file"], [b"thefileid"])
 
2692
        t.commit(rev_id=b'somerev', message="add file")
 
2693
        self.assertIs(None, request.execute(b'', b'unordered'))
 
2694
        response = request.do_body(b"somerev\n")
 
2695
        self.assertTrue(response.is_successful())
 
2696
        self.assertEqual(response.args, (b"ok", ))
 
2697
        stream = [('inventory-deltas', [
 
2698
            versionedfile.FulltextContentFactory(b'somerev', None, None,
 
2699
                self._get_serialized_inventory_delta(
 
2700
                    t.branch.repository, b'null:', b'somerev'))])]
 
2701
        fmt = controldir.format_registry.get('2a')().repository_format
 
2702
        self.assertEqual(
 
2703
            b"".join(response.body_stream),
 
2704
            b"".join(smart_repo._stream_to_byte_stream(stream, fmt)))
 
2705
 
 
2706
    def test_empty(self):
 
2707
        backing = self.get_transport()
 
2708
        request = smart_repo.SmartServerRepositoryGetInventories(backing)
 
2709
        t = self.make_branch_and_tree('.', format='2a')
 
2710
        self.addCleanup(t.lock_write().unlock)
 
2711
        self.build_tree_contents([("file", b"somecontents")])
 
2712
        t.add(["file"], [b"thefileid"])
 
2713
        t.commit(rev_id=b'somerev', message="add file")
 
2714
        self.assertIs(None, request.execute(b'', b'unordered'))
 
2715
        response = request.do_body(b"")
 
2716
        self.assertTrue(response.is_successful())
 
2717
        self.assertEqual(response.args, (b"ok", ))
 
2718
        self.assertEqual(b"".join(response.body_stream),
 
2719
            b"Bazaar pack format 1 (introduced in 0.18)\nB54\n\nBazaar repository format 2a (needs bzr 1.16 or later)\nE")
 
2720
 
 
2721
 
 
2722
class TestSmartServerRepositoryGetStreamForMissingKeys(GetStreamTestBase):
 
2723
 
 
2724
    def test_missing(self):
 
2725
        """The search argument may be a 'ancestry-of' some heads'."""
 
2726
        backing = self.get_transport()
 
2727
        request = smart_repo.SmartServerRepositoryGetStreamForMissingKeys(
 
2728
            backing)
 
2729
        repo, r1, r2 = self.make_two_commit_repo()
 
2730
        request.execute(b'', repo._format.network_name())
 
2731
        lines = b'inventories\t' + r1
 
2732
        response = request.do_body(lines)
 
2733
        self.assertEqual((b'ok',), response.args)
 
2734
        stream_bytes = b''.join(response.body_stream)
 
2735
        self.assertStartsWith(stream_bytes, b'Bazaar pack format 1')
 
2736
 
 
2737
    def test_unknown_format(self):
 
2738
        """The format may not be known by the remote server."""
 
2739
        backing = self.get_transport()
 
2740
        request = smart_repo.SmartServerRepositoryGetStreamForMissingKeys(
 
2741
            backing)
 
2742
        repo, r1, r2 = self.make_two_commit_repo()
 
2743
        request.execute(b'', b'yada yada yada')
 
2744
        expected = smart_req.FailedSmartServerResponse(
 
2745
            (b'UnknownFormat', b'repository', b'yada yada yada'))
 
2746
 
 
2747
 
 
2748
class TestSmartServerRepositoryRevisionArchive(tests.TestCaseWithTransport):
 
2749
    def test_get(self):
 
2750
        backing = self.get_transport()
 
2751
        request = smart_repo.SmartServerRepositoryRevisionArchive(backing)
 
2752
        t = self.make_branch_and_tree('.')
 
2753
        self.addCleanup(t.lock_write().unlock)
 
2754
        self.build_tree_contents([("file", b"somecontents")])
 
2755
        t.add(["file"], [b"thefileid"])
 
2756
        t.commit(rev_id=b'somerev', message="add file")
 
2757
        response = request.execute(b'', b"somerev", b"tar", b"foo.tar", b"foo")
 
2758
        self.assertTrue(response.is_successful())
 
2759
        self.assertEqual(response.args, (b"ok", ))
 
2760
        b = BytesIO(b"".join(response.body_stream))
 
2761
        with tarfile.open(mode='r', fileobj=b) as tf:
 
2762
            self.assertEqual(['foo/file'], tf.getnames())
 
2763
 
 
2764
 
 
2765
class TestSmartServerRepositoryAnnotateFileRevision(tests.TestCaseWithTransport):
 
2766
 
 
2767
    def test_get(self):
 
2768
        backing = self.get_transport()
 
2769
        request = smart_repo.SmartServerRepositoryAnnotateFileRevision(backing)
 
2770
        t = self.make_branch_and_tree('.')
 
2771
        self.addCleanup(t.lock_write().unlock)
 
2772
        self.build_tree_contents([("file", b"somecontents\nmorecontents\n")])
 
2773
        t.add(["file"], [b"thefileid"])
 
2774
        t.commit(rev_id=b'somerev', message="add file")
 
2775
        response = request.execute(b'', b"somerev", b"file")
 
2776
        self.assertTrue(response.is_successful())
 
2777
        self.assertEqual(response.args, (b"ok", ))
 
2778
        self.assertEqual(
 
2779
                [['somerev', 'somecontents\n'], ['somerev', 'morecontents\n']],
 
2780
                bencode.bdecode(response.body))