/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: 2020-01-19 15:14:16 UTC
  • mto: This revision was merged to the branch mainline in revision 7455.
  • Revision ID: jelmer@jelmer.uk-20200119151416-f2x9y9rtvwxndr2l
Don't show submodules that are not checked out as deltas.

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()
771
 
        repo_token = branch.repository.lock_write()
 
974
        branch_token = branch.lock_write().token
 
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
 
1076
 
class TestSmartServerBranchRequestSetParent(tests.TestCaseWithMemoryTransport):
 
1357
class TestSmartServerBranchRequestSetParent(TestLockedBranch):
1077
1358
 
1078
1359
    def test_set_parent_none(self):
1079
1360
        branch = self.make_branch('base', format="1.9")
1082
1363
        branch.unlock()
1083
1364
        request = smart_branch.SmartServerBranchRequestSetParentLocation(
1084
1365
            self.get_transport())
1085
 
        branch_token = branch.lock_write()
1086
 
        repo_token = branch.repository.lock_write()
 
1366
        branch_token, repo_token = self.get_lock_tokens(branch)
1087
1367
        try:
1088
 
            response = request.execute('base', branch_token, repo_token, '')
 
1368
            response = request.execute(b'base', branch_token, repo_token, b'')
1089
1369
        finally:
1090
 
            branch.repository.unlock()
1091
1370
            branch.unlock()
1092
1371
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
 
1372
        # Refresh branch as SetParentLocation modified it
 
1373
        branch = branch.controldir.open_branch()
1093
1374
        self.assertEqual(None, branch.get_parent())
1094
1375
 
1095
1376
    def test_set_parent_something(self):
1096
1377
        branch = self.make_branch('base', format="1.9")
1097
1378
        request = smart_branch.SmartServerBranchRequestSetParentLocation(
1098
1379
            self.get_transport())
1099
 
        branch_token = branch.lock_write()
1100
 
        repo_token = branch.repository.lock_write()
 
1380
        branch_token, repo_token = self.get_lock_tokens(branch)
1101
1381
        try:
1102
 
            response = request.execute('base', branch_token, repo_token,
1103
 
            'http://bar/')
 
1382
            response = request.execute(b'base', branch_token, repo_token,
 
1383
                                       b'http://bar/')
1104
1384
        finally:
1105
 
            branch.repository.unlock()
1106
1385
            branch.unlock()
1107
1386
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
1108
 
        self.assertEqual('http://bar/', branch.get_parent())
 
1387
        refreshed = _mod_branch.Branch.open(branch.base)
 
1388
        self.assertEqual('http://bar/', refreshed.get_parent())
1109
1389
 
1110
1390
 
1111
1391
class TestSmartServerBranchRequestGetTagsBytes(
1112
 
    tests.TestCaseWithMemoryTransport):
 
1392
        tests.TestCaseWithMemoryTransport):
1113
1393
    # Only called when the branch format and tags match [yay factory
1114
1394
    # methods] so only need to test straight forward cases.
1115
1395
 
1116
1396
    def test_get_bytes(self):
1117
 
        base_branch = self.make_branch('base')
 
1397
        self.make_branch('base')
1118
1398
        request = smart_branch.SmartServerBranchGetTagsBytes(
1119
1399
            self.get_transport())
1120
 
        response = request.execute('base')
1121
 
        self.assertEquals(
1122
 
            smart_req.SuccessfulSmartServerResponse(('',)), response)
1123
 
 
1124
 
 
1125
 
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):
1126
1407
 
1127
1408
    def test_get_stacked_on_url(self):
1128
 
        base_branch = self.make_branch('base', format='1.6')
 
1409
        self.make_branch('base', format='1.6')
1129
1410
        stacked_branch = self.make_branch('stacked', format='1.6')
1130
1411
        # typically should be relative
1131
1412
        stacked_branch.set_stacked_on_url('../base')
1132
1413
        request = smart_branch.SmartServerBranchRequestGetStackedOnURL(
1133
1414
            self.get_transport())
1134
 
        response = request.execute('stacked')
1135
 
        self.assertEquals(
1136
 
            smart_req.SmartServerResponse(('ok', '../base')),
 
1415
        response = request.execute(b'stacked')
 
1416
        self.assertEqual(
 
1417
            smart_req.SmartServerResponse((b'ok', b'../base')),
1137
1418
            response)
1138
1419
 
1139
1420
 
1140
 
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithMemoryTransport):
1141
 
 
1142
 
    def setUp(self):
1143
 
        tests.TestCaseWithMemoryTransport.setUp(self)
 
1421
class TestSmartServerBranchRequestLockWrite(TestLockedBranch):
1144
1422
 
1145
1423
    def test_lock_write_on_unlocked_branch(self):
1146
1424
        backing = self.get_transport()
1147
1425
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1148
1426
        branch = self.make_branch('.', format='knit')
1149
1427
        repository = branch.repository
1150
 
        response = request.execute('')
 
1428
        response = request.execute(b'')
1151
1429
        branch_nonce = branch.control_files._lock.peek().get('nonce')
1152
1430
        repository_nonce = repository.control_files._lock.peek().get('nonce')
1153
1431
        self.assertEqual(smart_req.SmartServerResponse(
1154
 
                ('ok', branch_nonce, repository_nonce)),
1155
 
                         response)
 
1432
            (b'ok', branch_nonce, repository_nonce)),
 
1433
            response)
1156
1434
        # The branch (and associated repository) is now locked.  Verify that
1157
1435
        # with a new branch object.
1158
 
        new_branch = repository.bzrdir.open_branch()
 
1436
        new_branch = repository.controldir.open_branch()
1159
1437
        self.assertRaises(errors.LockContention, new_branch.lock_write)
1160
1438
        # Cleanup
1161
1439
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1162
 
        response = request.execute('', branch_nonce, repository_nonce)
 
1440
        response = request.execute(b'', branch_nonce, repository_nonce)
1163
1441
 
1164
1442
    def test_lock_write_on_locked_branch(self):
1165
1443
        backing = self.get_transport()
1166
1444
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1167
1445
        branch = self.make_branch('.')
1168
 
        branch_token = branch.lock_write()
 
1446
        branch_token = branch.lock_write().token
1169
1447
        branch.leave_lock_in_place()
1170
1448
        branch.unlock()
1171
 
        response = request.execute('')
 
1449
        response = request.execute(b'')
1172
1450
        self.assertEqual(
1173
 
            smart_req.SmartServerResponse(('LockContention',)), response)
 
1451
            smart_req.SmartServerResponse((b'LockContention',)), response)
1174
1452
        # Cleanup
1175
1453
        branch.lock_write(branch_token)
1176
1454
        branch.dont_leave_lock_in_place()
1180
1458
        backing = self.get_transport()
1181
1459
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1182
1460
        branch = self.make_branch('.', format='knit')
1183
 
        branch_token = branch.lock_write()
1184
 
        repo_token = branch.repository.lock_write()
1185
 
        branch.repository.unlock()
 
1461
        branch_token, repo_token = self.get_lock_tokens(branch)
1186
1462
        branch.leave_lock_in_place()
1187
1463
        branch.repository.leave_lock_in_place()
1188
1464
        branch.unlock()
1189
 
        response = request.execute('',
 
1465
        response = request.execute(b'',
1190
1466
                                   branch_token, repo_token)
1191
1467
        self.assertEqual(
1192
 
            smart_req.SmartServerResponse(('ok', branch_token, repo_token)),
 
1468
            smart_req.SmartServerResponse((b'ok', branch_token, repo_token)),
1193
1469
            response)
1194
1470
        # Cleanup
1195
1471
        branch.repository.lock_write(repo_token)
1203
1479
        backing = self.get_transport()
1204
1480
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1205
1481
        branch = self.make_branch('.', format='knit')
1206
 
        branch_token = branch.lock_write()
1207
 
        repo_token = branch.repository.lock_write()
1208
 
        branch.repository.unlock()
 
1482
        branch_token, repo_token = self.get_lock_tokens(branch)
1209
1483
        branch.leave_lock_in_place()
1210
1484
        branch.repository.leave_lock_in_place()
1211
1485
        branch.unlock()
1212
 
        response = request.execute('',
1213
 
                                   branch_token+'xxx', repo_token)
 
1486
        response = request.execute(b'',
 
1487
                                   branch_token + b'xxx', repo_token)
1214
1488
        self.assertEqual(
1215
 
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
 
1489
            smart_req.SmartServerResponse((b'TokenMismatch',)), response)
1216
1490
        # Cleanup
1217
1491
        branch.repository.lock_write(repo_token)
1218
1492
        branch.repository.dont_leave_lock_in_place()
1226
1500
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1227
1501
        branch = self.make_branch('.', format='knit')
1228
1502
        repo = branch.repository
1229
 
        repo_token = repo.lock_write()
 
1503
        repo_token = repo.lock_write().repository_token
1230
1504
        repo.leave_lock_in_place()
1231
1505
        repo.unlock()
1232
 
        response = request.execute('')
 
1506
        response = request.execute(b'')
1233
1507
        self.assertEqual(
1234
 
            smart_req.SmartServerResponse(('LockContention',)), response)
 
1508
            smart_req.SmartServerResponse((b'LockContention',)), response)
1235
1509
        # Cleanup
1236
1510
        repo.lock_write(repo_token)
1237
1511
        repo.dont_leave_lock_in_place()
1240
1514
    def test_lock_write_on_readonly_transport(self):
1241
1515
        backing = self.get_readonly_transport()
1242
1516
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1243
 
        branch = self.make_branch('.')
 
1517
        self.make_branch('.')
1244
1518
        root = self.get_transport().clone('/')
1245
1519
        path = urlutils.relative_url(root.base, self.get_transport().base)
1246
 
        response = request.execute(path)
 
1520
        response = request.execute(path.encode('utf-8'))
1247
1521
        error_name, lock_str, why_str = response.args
1248
1522
        self.assertFalse(response.is_successful())
1249
 
        self.assertEqual('LockFailed', error_name)
1250
 
 
1251
 
 
1252
 
class TestSmartServerBranchRequestUnlock(tests.TestCaseWithMemoryTransport):
1253
 
 
1254
 
    def setUp(self):
1255
 
        tests.TestCaseWithMemoryTransport.setUp(self)
 
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)
 
1549
 
 
1550
 
 
1551
class TestSmartServerBranchRequestUnlock(TestLockedBranch):
1256
1552
 
1257
1553
    def test_unlock_on_locked_branch_and_repo(self):
1258
1554
        backing = self.get_transport()
1259
1555
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1260
1556
        branch = self.make_branch('.', format='knit')
1261
1557
        # Lock the branch
1262
 
        branch_token = branch.lock_write()
1263
 
        repo_token = branch.repository.lock_write()
1264
 
        branch.repository.unlock()
 
1558
        branch_token, repo_token = self.get_lock_tokens(branch)
1265
1559
        # Unlock the branch (and repo) object, leaving the physical locks
1266
1560
        # in place.
1267
1561
        branch.leave_lock_in_place()
1268
1562
        branch.repository.leave_lock_in_place()
1269
1563
        branch.unlock()
1270
 
        response = request.execute('',
 
1564
        response = request.execute(b'',
1271
1565
                                   branch_token, repo_token)
1272
1566
        self.assertEqual(
1273
 
            smart_req.SmartServerResponse(('ok',)), response)
 
1567
            smart_req.SmartServerResponse((b'ok',)), response)
1274
1568
        # The branch is now unlocked.  Verify that with a new branch
1275
1569
        # object.
1276
 
        new_branch = branch.bzrdir.open_branch()
 
1570
        new_branch = branch.controldir.open_branch()
1277
1571
        new_branch.lock_write()
1278
1572
        new_branch.unlock()
1279
1573
 
1280
1574
    def test_unlock_on_unlocked_branch_unlocked_repo(self):
1281
1575
        backing = self.get_transport()
1282
1576
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1283
 
        branch = self.make_branch('.', format='knit')
 
1577
        self.make_branch('.', format='knit')
1284
1578
        response = request.execute(
1285
 
            '', 'branch token', 'repo token')
 
1579
            b'', b'branch token', b'repo token')
1286
1580
        self.assertEqual(
1287
 
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
 
1581
            smart_req.SmartServerResponse((b'TokenMismatch',)), response)
1288
1582
 
1289
1583
    def test_unlock_on_unlocked_branch_locked_repo(self):
1290
1584
        backing = self.get_transport()
1291
1585
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1292
1586
        branch = self.make_branch('.', format='knit')
1293
1587
        # Lock the repository.
1294
 
        repo_token = branch.repository.lock_write()
 
1588
        repo_token = branch.repository.lock_write().repository_token
1295
1589
        branch.repository.leave_lock_in_place()
1296
1590
        branch.repository.unlock()
1297
1591
        # Issue branch lock_write request on the unlocked branch (with locked
1298
1592
        # repo).
1299
 
        response = request.execute(
1300
 
            '', 'branch token', repo_token)
 
1593
        response = request.execute(b'', b'branch token', repo_token)
1301
1594
        self.assertEqual(
1302
 
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
 
1595
            smart_req.SmartServerResponse((b'TokenMismatch',)), response)
1303
1596
        # Cleanup
1304
1597
        branch.repository.lock_write(repo_token)
1305
1598
        branch.repository.dont_leave_lock_in_place()
1317
1610
        backing = self.get_transport()
1318
1611
        request = smart_repo.SmartServerRepositoryRequest(backing)
1319
1612
        self.make_repository('.', shared=True)
1320
 
        self.make_bzrdir('subdir')
 
1613
        self.make_controldir('subdir')
1321
1614
        self.assertRaises(errors.NoRepositoryPresent,
1322
 
            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''))
1323
1695
 
1324
1696
 
1325
1697
class TestSmartServerRepositoryGetParentMap(tests.TestCaseWithMemoryTransport):
1328
1700
        # This tests that the wire encoding is actually bzipped
1329
1701
        backing = self.get_transport()
1330
1702
        request = smart_repo.SmartServerRepositoryGetParentMap(backing)
1331
 
        tree = self.make_branch_and_memory_tree('.')
 
1703
        self.make_branch_and_memory_tree('.')
1332
1704
 
1333
1705
        self.assertEqual(None,
1334
 
            request.execute('', 'missing-id'))
 
1706
                         request.execute(b'', b'missing-id'))
1335
1707
        # Note that it returns a body that is bzipped.
1336
1708
        self.assertEqual(
1337
 
            smart_req.SuccessfulSmartServerResponse(('ok', ), bz2.compress('')),
1338
 
            request.do_body('\n\n0\n'))
 
1709
            smart_req.SuccessfulSmartServerResponse(
 
1710
                (b'ok', ), bz2.compress(b'')),
 
1711
            request.do_body(b'\n\n0\n'))
1339
1712
 
1340
1713
    def test_trivial_include_missing(self):
1341
1714
        backing = self.get_transport()
1342
1715
        request = smart_repo.SmartServerRepositoryGetParentMap(backing)
1343
 
        tree = self.make_branch_and_memory_tree('.')
 
1716
        self.make_branch_and_memory_tree('.')
1344
1717
 
1345
 
        self.assertEqual(None,
1346
 
            request.execute('', 'missing-id', 'include-missing:'))
1347
 
        self.assertEqual(
1348
 
            smart_req.SuccessfulSmartServerResponse(('ok', ),
1349
 
                bz2.compress('missing:missing-id')),
1350
 
            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'))
1351
1724
 
1352
1725
 
1353
1726
class TestSmartServerRepositoryGetRevisionGraph(
1354
 
    tests.TestCaseWithMemoryTransport):
 
1727
        tests.TestCaseWithMemoryTransport):
1355
1728
 
1356
1729
    def test_none_argument(self):
1357
1730
        backing = self.get_transport()
1365
1738
 
1366
1739
        # the lines of revision_id->revision_parent_list has no guaranteed
1367
1740
        # order coming out of a dict, so sort both our test and response
1368
 
        lines = sorted([' '.join([r2, r1]), r1])
1369
 
        response = request.execute('', '')
1370
 
        response.body = '\n'.join(sorted(response.body.split('\n')))
 
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')))
1371
1744
 
1372
1745
        self.assertEqual(
1373
 
            smart_req.SmartServerResponse(('ok', ), '\n'.join(lines)), response)
 
1746
            smart_req.SmartServerResponse((b'ok', ), b'\n'.join(lines)),
 
1747
            response)
1374
1748
 
1375
1749
    def test_specific_revision_argument(self):
1376
1750
        backing = self.get_transport()
1379
1753
        tree.lock_write()
1380
1754
        tree.add('')
1381
1755
        rev_id_utf8 = u'\xc9'.encode('utf-8')
1382
 
        r1 = tree.commit('1st commit', rev_id=rev_id_utf8)
1383
 
        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'))
1384
1758
        tree.unlock()
1385
1759
 
1386
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), rev_id_utf8),
1387
 
            request.execute('', rev_id_utf8))
 
1760
        self.assertEqual(smart_req.SmartServerResponse((b'ok', ), rev_id_utf8),
 
1761
                         request.execute(b'', rev_id_utf8))
1388
1762
 
1389
1763
    def test_no_such_revision(self):
1390
1764
        backing = self.get_transport()
1392
1766
        tree = self.make_branch_and_memory_tree('.')
1393
1767
        tree.lock_write()
1394
1768
        tree.add('')
1395
 
        r1 = tree.commit('1st commit')
 
1769
        tree.commit('1st commit')
1396
1770
        tree.unlock()
1397
1771
 
1398
1772
        # Note that it still returns body (of zero bytes).
1399
1773
        self.assertEqual(smart_req.SmartServerResponse(
1400
 
                ('nosuchrevision', 'missingrevision', ), ''),
1401
 
                         request.execute('', 'missingrevision'))
 
1774
            (b'nosuchrevision', b'missingrevision', ), b''),
 
1775
            request.execute(b'', b'missingrevision'))
1402
1776
 
1403
1777
 
1404
1778
class TestSmartServerRepositoryGetRevIdForRevno(
1405
 
    tests.TestCaseWithMemoryTransport):
 
1779
        tests.TestCaseWithMemoryTransport):
1406
1780
 
1407
1781
    def test_revno_found(self):
1408
1782
        backing = self.get_transport()
1416
1790
        tree.commit('2nd commit', rev_id=rev2_id_utf8)
1417
1791
        tree.unlock()
1418
1792
 
1419
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', rev1_id_utf8)),
1420
 
            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)))
1421
1795
 
1422
1796
    def test_known_revid_missing(self):
1423
1797
        backing = self.get_transport()
1424
1798
        request = smart_repo.SmartServerRepositoryGetRevIdForRevno(backing)
1425
 
        repo = self.make_repository('.')
 
1799
        self.make_repository('.')
1426
1800
        self.assertEqual(
1427
 
            smart_req.FailedSmartServerResponse(('nosuchrevision', 'ghost')),
1428
 
            request.execute('', 1, (2, 'ghost')))
 
1801
            smart_req.FailedSmartServerResponse((b'nosuchrevision', b'ghost')),
 
1802
            request.execute(b'', 1, (2, b'ghost')))
1429
1803
 
1430
1804
    def test_history_incomplete(self):
1431
1805
        backing = self.get_transport()
1432
1806
        request = smart_repo.SmartServerRepositoryGetRevIdForRevno(backing)
1433
1807
        parent = self.make_branch_and_memory_tree('parent', format='1.9')
1434
1808
        parent.lock_write()
1435
 
        parent.add([''], ['TREE_ROOT'])
1436
 
        r1 = parent.commit(message='first commit')
 
1809
        parent.add([''], [b'TREE_ROOT'])
 
1810
        parent.commit(message='first commit')
1437
1811
        r2 = parent.commit(message='second commit')
1438
1812
        parent.unlock()
1439
1813
        local = self.make_branch_and_memory_tree('local', format='1.9')
1443
1817
        local.branch.create_clone_on_transport(
1444
1818
            self.get_transport('stacked'), stacked_on=self.get_url('parent'))
1445
1819
        self.assertEqual(
1446
 
            smart_req.SmartServerResponse(('history-incomplete', 2, r2)),
1447
 
            request.execute('stacked', 1, (3, r3)))
1448
 
 
1449
 
 
1450
 
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):
1451
1869
 
1452
1870
    def make_two_commit_repo(self):
1453
1871
        tree = self.make_branch_and_memory_tree('.')
1459
1877
        repo = tree.branch.repository
1460
1878
        return repo, r1, r2
1461
1879
 
 
1880
 
 
1881
class TestSmartServerRepositoryGetStream(GetStreamTestBase):
 
1882
 
1462
1883
    def test_ancestry_of(self):
1463
1884
        """The search argument may be a 'ancestry-of' some heads'."""
1464
1885
        backing = self.get_transport()
1465
1886
        request = smart_repo.SmartServerRepositoryGetStream(backing)
1466
1887
        repo, r1, r2 = self.make_two_commit_repo()
1467
 
        fetch_spec = ['ancestry-of', r2]
1468
 
        lines = '\n'.join(fetch_spec)
1469
 
        request.execute('', repo._format.network_name())
 
1888
        fetch_spec = [b'ancestry-of', r2]
 
1889
        lines = b'\n'.join(fetch_spec)
 
1890
        request.execute(b'', repo._format.network_name())
1470
1891
        response = request.do_body(lines)
1471
 
        self.assertEqual(('ok',), response.args)
1472
 
        stream_bytes = ''.join(response.body_stream)
1473
 
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
 
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')
1474
1895
 
1475
1896
    def test_search(self):
1476
1897
        """The search argument may be a 'search' of some explicit keys."""
1477
1898
        backing = self.get_transport()
1478
1899
        request = smart_repo.SmartServerRepositoryGetStream(backing)
1479
1900
        repo, r1, r2 = self.make_two_commit_repo()
1480
 
        fetch_spec = ['search', '%s %s' % (r1, r2), 'null:', '2']
1481
 
        lines = '\n'.join(fetch_spec)
1482
 
        request.execute('', repo._format.network_name())
 
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())
1483
1904
        response = request.do_body(lines)
1484
 
        self.assertEqual(('ok',), response.args)
1485
 
        stream_bytes = ''.join(response.body_stream)
1486
 
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
 
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')
1487
1920
 
1488
1921
 
1489
1922
class TestSmartServerRequestHasRevision(tests.TestCaseWithMemoryTransport):
1493
1926
        backing = self.get_transport()
1494
1927
        request = smart_repo.SmartServerRequestHasRevision(backing)
1495
1928
        self.make_repository('.')
1496
 
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
1497
 
            request.execute('', 'revid'))
 
1929
        self.assertEqual(smart_req.SmartServerResponse((b'no', )),
 
1930
                         request.execute(b'', b'revid'))
1498
1931
 
1499
1932
    def test_present_revision(self):
1500
1933
        """For a present revision, ('yes', ) is returned."""
1504
1937
        tree.lock_write()
1505
1938
        tree.add('')
1506
1939
        rev_id_utf8 = u'\xc8abc'.encode('utf-8')
1507
 
        r1 = tree.commit('a commit', rev_id=rev_id_utf8)
 
1940
        tree.commit('a commit', rev_id=rev_id_utf8)
1508
1941
        tree.unlock()
1509
1942
        self.assertTrue(tree.branch.repository.has_revision(rev_id_utf8))
1510
 
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
1511
 
            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'))
1512
2022
 
1513
2023
 
1514
2024
class TestSmartServerRepositoryGatherStats(tests.TestCaseWithMemoryTransport):
1518
2028
        backing = self.get_transport()
1519
2029
        request = smart_repo.SmartServerRepositoryGatherStats(backing)
1520
2030
        repository = self.make_repository('.')
1521
 
        stats = repository.gather_stats()
1522
 
        expected_body = 'revisions: 0\n'
1523
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), expected_body),
1524
 
                         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'))
1525
2036
 
1526
2037
    def test_revid_with_committers(self):
1527
2038
        """For a revid we get more infos."""
1537
2048
                    rev_id=rev_id_utf8)
1538
2049
        tree.unlock()
1539
2050
 
1540
 
        stats = tree.branch.repository.gather_stats()
1541
 
        expected_body = ('firstrev: 123456.200 3600\n'
1542
 
                         'latestrev: 654321.400 0\n'
1543
 
                         'revisions: 2\n')
1544
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), expected_body),
1545
 
                         request.execute('',
1546
 
                                         rev_id_utf8, 'no'))
 
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'))
1547
2058
 
1548
2059
    def test_not_empty_repository_with_committers(self):
1549
2060
        """For a revid and requesting committers we get the whole thing."""
1559
2070
        tree.commit('a commit', timestamp=654321.4, timezone=0,
1560
2071
                    committer='bar', rev_id=rev_id_utf8)
1561
2072
        tree.unlock()
1562
 
        stats = tree.branch.repository.gather_stats()
1563
 
 
1564
 
        expected_body = ('committers: 2\n'
1565
 
                         'firstrev: 123456.200 3600\n'
1566
 
                         'latestrev: 654321.400 0\n'
1567
 
                         'revisions: 2\n')
1568
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), expected_body),
1569
 
                         request.execute('',
1570
 
                                         rev_id_utf8, 'yes'))
 
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'))
1571
2092
 
1572
2093
 
1573
2094
class TestSmartServerRepositoryIsShared(tests.TestCaseWithMemoryTransport):
1577
2098
        backing = self.get_transport()
1578
2099
        request = smart_repo.SmartServerRepositoryIsShared(backing)
1579
2100
        self.make_repository('.', shared=True)
1580
 
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
1581
 
            request.execute('', ))
 
2101
        self.assertEqual(smart_req.SmartServerResponse((b'yes', )),
 
2102
                         request.execute(b'', ))
1582
2103
 
1583
2104
    def test_is_not_shared(self):
1584
2105
        """For a shared repository, ('no', ) is returned."""
1585
2106
        backing = self.get_transport()
1586
2107
        request = smart_repo.SmartServerRepositoryIsShared(backing)
1587
2108
        self.make_repository('.', shared=False)
1588
 
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
1589
 
            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'', ))
1590
2157
 
1591
2158
 
1592
2159
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
1595
2162
        backing = self.get_transport()
1596
2163
        request = smart_repo.SmartServerRepositoryLockWrite(backing)
1597
2164
        repository = self.make_repository('.', format='knit')
1598
 
        response = request.execute('')
 
2165
        response = request.execute(b'')
1599
2166
        nonce = repository.control_files._lock.peek().get('nonce')
1600
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', nonce)), response)
 
2167
        self.assertEqual(smart_req.SmartServerResponse(
 
2168
            (b'ok', nonce)), response)
1601
2169
        # The repository is now locked.  Verify that with a new repository
1602
2170
        # object.
1603
 
        new_repo = repository.bzrdir.open_repository()
 
2171
        new_repo = repository.controldir.open_repository()
1604
2172
        self.assertRaises(errors.LockContention, new_repo.lock_write)
1605
2173
        # Cleanup
1606
2174
        request = smart_repo.SmartServerRepositoryUnlock(backing)
1607
 
        response = request.execute('', nonce)
 
2175
        response = request.execute(b'', nonce)
1608
2176
 
1609
2177
    def test_lock_write_on_locked_repo(self):
1610
2178
        backing = self.get_transport()
1611
2179
        request = smart_repo.SmartServerRepositoryLockWrite(backing)
1612
2180
        repository = self.make_repository('.', format='knit')
1613
 
        repo_token = repository.lock_write()
 
2181
        repo_token = repository.lock_write().repository_token
1614
2182
        repository.leave_lock_in_place()
1615
2183
        repository.unlock()
1616
 
        response = request.execute('')
 
2184
        response = request.execute(b'')
1617
2185
        self.assertEqual(
1618
 
            smart_req.SmartServerResponse(('LockContention',)), response)
 
2186
            smart_req.SmartServerResponse((b'LockContention',)), response)
1619
2187
        # Cleanup
1620
2188
        repository.lock_write(repo_token)
1621
2189
        repository.dont_leave_lock_in_place()
1624
2192
    def test_lock_write_on_readonly_transport(self):
1625
2193
        backing = self.get_readonly_transport()
1626
2194
        request = smart_repo.SmartServerRepositoryLockWrite(backing)
1627
 
        repository = self.make_repository('.', format='knit')
1628
 
        response = request.execute('')
 
2195
        self.make_repository('.', format='knit')
 
2196
        response = request.execute(b'')
1629
2197
        self.assertFalse(response.is_successful())
1630
 
        self.assertEqual('LockFailed', response.args[0])
 
2198
        self.assertEqual(b'LockFailed', response.args[0])
1631
2199
 
1632
2200
 
1633
2201
class TestInsertStreamBase(tests.TestCaseWithMemoryTransport):
1634
2202
 
1635
2203
    def make_empty_byte_stream(self, repo):
1636
2204
        byte_stream = smart_repo._stream_to_byte_stream([], repo._format)
1637
 
        return ''.join(byte_stream)
 
2205
        return b''.join(byte_stream)
1638
2206
 
1639
2207
 
1640
2208
class TestSmartServerRepositoryInsertStream(TestInsertStreamBase):
1643
2211
        backing = self.get_transport()
1644
2212
        request = smart_repo.SmartServerRepositoryInsertStream(backing)
1645
2213
        repository = self.make_repository('.')
1646
 
        response = request.execute('', '')
 
2214
        response = request.execute(b'', b'')
1647
2215
        self.assertEqual(None, response)
1648
2216
        response = request.do_chunk(self.make_empty_byte_stream(repository))
1649
2217
        self.assertEqual(None, response)
1650
2218
        response = request.do_end()
1651
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', )), response)
 
2219
        self.assertEqual(smart_req.SmartServerResponse((b'ok', )), response)
1652
2220
 
1653
2221
 
1654
2222
class TestSmartServerRepositoryInsertStreamLocked(TestInsertStreamBase):
1658
2226
        request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1659
2227
            backing)
1660
2228
        repository = self.make_repository('.', format='knit')
1661
 
        lock_token = repository.lock_write()
1662
 
        response = request.execute('', '', lock_token)
 
2229
        lock_token = repository.lock_write().repository_token
 
2230
        response = request.execute(b'', b'', lock_token)
1663
2231
        self.assertEqual(None, response)
1664
2232
        response = request.do_chunk(self.make_empty_byte_stream(repository))
1665
2233
        self.assertEqual(None, response)
1666
2234
        response = request.do_end()
1667
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', )), response)
 
2235
        self.assertEqual(smart_req.SmartServerResponse((b'ok', )), response)
1668
2236
        repository.unlock()
1669
2237
 
1670
2238
    def test_insert_stream_with_wrong_lock_token(self):
1672
2240
        request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1673
2241
            backing)
1674
2242
        repository = self.make_repository('.', format='knit')
1675
 
        lock_token = repository.lock_write()
1676
 
        self.assertRaises(
1677
 
            errors.TokenMismatch, request.execute, '', '', 'wrong-token')
1678
 
        repository.unlock()
 
2243
        with repository.lock_write():
 
2244
            self.assertRaises(
 
2245
                errors.TokenMismatch, request.execute, b'', b'',
 
2246
                b'wrong-token')
1679
2247
 
1680
2248
 
1681
2249
class TestSmartServerRepositoryUnlock(tests.TestCaseWithMemoryTransport):
1682
2250
 
1683
 
    def setUp(self):
1684
 
        tests.TestCaseWithMemoryTransport.setUp(self)
1685
 
 
1686
2251
    def test_unlock_on_locked_repo(self):
1687
2252
        backing = self.get_transport()
1688
2253
        request = smart_repo.SmartServerRepositoryUnlock(backing)
1689
2254
        repository = self.make_repository('.', format='knit')
1690
 
        token = repository.lock_write()
 
2255
        token = repository.lock_write().repository_token
1691
2256
        repository.leave_lock_in_place()
1692
2257
        repository.unlock()
1693
 
        response = request.execute('', token)
 
2258
        response = request.execute(b'', token)
1694
2259
        self.assertEqual(
1695
 
            smart_req.SmartServerResponse(('ok',)), response)
 
2260
            smart_req.SmartServerResponse((b'ok',)), response)
1696
2261
        # The repository is now unlocked.  Verify that with a new repository
1697
2262
        # object.
1698
 
        new_repo = repository.bzrdir.open_repository()
 
2263
        new_repo = repository.controldir.open_repository()
1699
2264
        new_repo.lock_write()
1700
2265
        new_repo.unlock()
1701
2266
 
1702
2267
    def test_unlock_on_unlocked_repo(self):
1703
2268
        backing = self.get_transport()
1704
2269
        request = smart_repo.SmartServerRepositoryUnlock(backing)
1705
 
        repository = self.make_repository('.', format='knit')
1706
 
        response = request.execute('', 'some token')
 
2270
        self.make_repository('.', format='knit')
 
2271
        response = request.execute(b'', b'some token')
1707
2272
        self.assertEqual(
1708
 
            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))
1709
2318
 
1710
2319
 
1711
2320
class TestSmartServerIsReadonly(tests.TestCaseWithMemoryTransport):
1715
2324
        request = smart_req.SmartServerIsReadonly(backing)
1716
2325
        response = request.execute()
1717
2326
        self.assertEqual(
1718
 
            smart_req.SmartServerResponse(('no',)), response)
 
2327
            smart_req.SmartServerResponse((b'no',)), response)
1719
2328
 
1720
2329
    def test_is_readonly_yes(self):
1721
2330
        backing = self.get_readonly_transport()
1722
2331
        request = smart_req.SmartServerIsReadonly(backing)
1723
2332
        response = request.execute()
1724
2333
        self.assertEqual(
1725
 
            smart_req.SmartServerResponse(('yes',)), response)
 
2334
            smart_req.SmartServerResponse((b'yes',)), response)
1726
2335
 
1727
2336
 
1728
2337
class TestSmartServerRepositorySetMakeWorkingTrees(
1729
 
    tests.TestCaseWithMemoryTransport):
 
2338
        tests.TestCaseWithMemoryTransport):
1730
2339
 
1731
2340
    def test_set_false(self):
1732
2341
        backing = self.get_transport()
1734
2343
        repo.set_make_working_trees(True)
1735
2344
        request_class = smart_repo.SmartServerRepositorySetMakeWorkingTrees
1736
2345
        request = request_class(backing)
1737
 
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
1738
 
            request.execute('', 'False'))
1739
 
        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()
1740
2349
        self.assertFalse(repo.make_working_trees())
1741
2350
 
1742
2351
    def test_set_true(self):
1745
2354
        repo.set_make_working_trees(False)
1746
2355
        request_class = smart_repo.SmartServerRepositorySetMakeWorkingTrees
1747
2356
        request = request_class(backing)
1748
 
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
1749
 
            request.execute('', 'True'))
1750
 
        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()
1751
2360
        self.assertTrue(repo.make_working_trees())
1752
2361
 
1753
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
 
1754
2449
class TestSmartServerPackRepositoryAutopack(tests.TestCaseWithTransport):
1755
2450
 
1756
2451
    def make_repo_needing_autopacking(self, path='.'):
1772
2467
        backing = self.get_transport()
1773
2468
        request = smart_packrepo.SmartServerPackRepositoryAutopack(
1774
2469
            backing)
1775
 
        response = request.execute('')
1776
 
        self.assertEqual(smart_req.SmartServerResponse(('ok',)), response)
 
2470
        response = request.execute(b'')
 
2471
        self.assertEqual(smart_req.SmartServerResponse((b'ok',)), response)
1777
2472
        repo._pack_collection.reload_pack_names()
1778
2473
        self.assertEqual(1, len(repo._pack_collection.names()))
1779
2474
 
1787
2482
        backing = self.get_transport()
1788
2483
        request = smart_packrepo.SmartServerPackRepositoryAutopack(
1789
2484
            backing)
1790
 
        response = request.execute('')
1791
 
        self.assertEqual(smart_req.SmartServerResponse(('ok',)), response)
 
2485
        response = request.execute(b'')
 
2486
        self.assertEqual(smart_req.SmartServerResponse((b'ok',)), response)
1792
2487
        repo._pack_collection.reload_pack_names()
1793
2488
        self.assertEqual(9, len(repo._pack_collection.names()))
1794
2489
 
1798
2493
        backing = self.get_transport()
1799
2494
        request = smart_packrepo.SmartServerPackRepositoryAutopack(
1800
2495
            backing)
1801
 
        response = request.execute('')
1802
 
        self.assertEqual(smart_req.SmartServerResponse(('ok',)), response)
 
2496
        response = request.execute(b'')
 
2497
        self.assertEqual(smart_req.SmartServerResponse((b'ok',)), response)
1803
2498
 
1804
2499
 
1805
2500
class TestSmartServerVfsGet(tests.TestCaseWithMemoryTransport):
1810
2505
        filename_escaped = urlutils.escape(filename)
1811
2506
        backing = self.get_transport()
1812
2507
        request = vfs.GetRequest(backing)
1813
 
        backing.put_bytes_non_atomic(filename_escaped, 'contents')
1814
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), 'contents'),
1815
 
            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')))
1816
2511
 
1817
2512
 
1818
2513
class TestHandlers(tests.TestCase):
1822
2517
        """All registered request_handlers can be found."""
1823
2518
        # If there's a typo in a register_lazy call, this loop will fail with
1824
2519
        # an AttributeError.
1825
 
        for key, item in smart_req.request_handlers.iteritems():
1826
 
            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))
1827
2525
 
1828
2526
    def assertHandlerEqual(self, verb, handler):
1829
2527
        self.assertEqual(smart_req.request_handlers.get(verb), handler)
1830
2528
 
1831
2529
    def test_registered_methods(self):
1832
2530
        """Test that known methods are registered to the correct object."""
1833
 
        self.assertHandlerEqual('Branch.get_config_file',
1834
 
            smart_branch.SmartServerBranchGetConfigFile)
1835
 
        self.assertHandlerEqual('Branch.get_parent',
1836
 
            smart_branch.SmartServerBranchGetParent)
1837
 
        self.assertHandlerEqual('Branch.get_tags_bytes',
1838
 
            smart_branch.SmartServerBranchGetTagsBytes)
1839
 
        self.assertHandlerEqual('Branch.lock_write',
1840
 
            smart_branch.SmartServerBranchRequestLockWrite)
1841
 
        self.assertHandlerEqual('Branch.last_revision_info',
1842
 
            smart_branch.SmartServerBranchRequestLastRevisionInfo)
1843
 
        self.assertHandlerEqual('Branch.revision_history',
1844
 
            smart_branch.SmartServerRequestRevisionHistory)
1845
 
        self.assertHandlerEqual('Branch.set_config_option',
1846
 
            smart_branch.SmartServerBranchRequestSetConfigOption)
1847
 
        self.assertHandlerEqual('Branch.set_last_revision',
1848
 
            smart_branch.SmartServerBranchRequestSetLastRevision)
1849
 
        self.assertHandlerEqual('Branch.set_last_revision_info',
1850
 
            smart_branch.SmartServerBranchRequestSetLastRevisionInfo)
1851
 
        self.assertHandlerEqual('Branch.set_last_revision_ex',
1852
 
            smart_branch.SmartServerBranchRequestSetLastRevisionEx)
1853
 
        self.assertHandlerEqual('Branch.set_parent_location',
1854
 
            smart_branch.SmartServerBranchRequestSetParentLocation)
1855
 
        self.assertHandlerEqual('Branch.unlock',
1856
 
            smart_branch.SmartServerBranchRequestUnlock)
1857
 
        self.assertHandlerEqual('BzrDir.find_repository',
1858
 
            smart_dir.SmartServerRequestFindRepositoryV1)
1859
 
        self.assertHandlerEqual('BzrDir.find_repositoryV2',
1860
 
            smart_dir.SmartServerRequestFindRepositoryV2)
1861
 
        self.assertHandlerEqual('BzrDirFormat.initialize',
1862
 
            smart_dir.SmartServerRequestInitializeBzrDir)
1863
 
        self.assertHandlerEqual('BzrDirFormat.initialize_ex_1.16',
1864
 
            smart_dir.SmartServerRequestBzrDirInitializeEx)
1865
 
        self.assertHandlerEqual('BzrDir.cloning_metadir',
1866
 
            smart_dir.SmartServerBzrDirRequestCloningMetaDir)
1867
 
        self.assertHandlerEqual('BzrDir.get_config_file',
1868
 
            smart_dir.SmartServerBzrDirRequestConfigFile)
1869
 
        self.assertHandlerEqual('BzrDir.open_branch',
1870
 
            smart_dir.SmartServerRequestOpenBranch)
1871
 
        self.assertHandlerEqual('BzrDir.open_branchV2',
1872
 
            smart_dir.SmartServerRequestOpenBranchV2)
1873
 
        self.assertHandlerEqual('BzrDir.open_branchV3',
1874
 
            smart_dir.SmartServerRequestOpenBranchV3)
1875
 
        self.assertHandlerEqual('PackRepository.autopack',
1876
 
            smart_packrepo.SmartServerPackRepositoryAutopack)
1877
 
        self.assertHandlerEqual('Repository.gather_stats',
1878
 
            smart_repo.SmartServerRepositoryGatherStats)
1879
 
        self.assertHandlerEqual('Repository.get_parent_map',
1880
 
            smart_repo.SmartServerRepositoryGetParentMap)
1881
 
        self.assertHandlerEqual('Repository.get_rev_id_for_revno',
1882
 
            smart_repo.SmartServerRepositoryGetRevIdForRevno)
1883
 
        self.assertHandlerEqual('Repository.get_revision_graph',
1884
 
            smart_repo.SmartServerRepositoryGetRevisionGraph)
1885
 
        self.assertHandlerEqual('Repository.get_stream',
1886
 
            smart_repo.SmartServerRepositoryGetStream)
1887
 
        self.assertHandlerEqual('Repository.has_revision',
1888
 
            smart_repo.SmartServerRequestHasRevision)
1889
 
        self.assertHandlerEqual('Repository.insert_stream',
1890
 
            smart_repo.SmartServerRepositoryInsertStream)
1891
 
        self.assertHandlerEqual('Repository.insert_stream_locked',
1892
 
            smart_repo.SmartServerRepositoryInsertStreamLocked)
1893
 
        self.assertHandlerEqual('Repository.is_shared',
1894
 
            smart_repo.SmartServerRepositoryIsShared)
1895
 
        self.assertHandlerEqual('Repository.lock_write',
1896
 
            smart_repo.SmartServerRepositoryLockWrite)
1897
 
        self.assertHandlerEqual('Repository.tarball',
1898
 
            smart_repo.SmartServerRepositoryTarball)
1899
 
        self.assertHandlerEqual('Repository.unlock',
1900
 
            smart_repo.SmartServerRepositoryUnlock)
1901
 
        self.assertHandlerEqual('Transport.is_readonly',
1902
 
            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, True)
 
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))