/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: 2019-09-01 15:33:59 UTC
  • mto: This revision was merged to the branch mainline in revision 7404.
  • Revision ID: jelmer@jelmer.uk-20190901153359-9gl0ai0x5wuiv444
Rename init-repo to init-shared-repo.

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