/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test_smart.py

  • Committer: Jelmer Vernooij
  • Date: 2019-01-01 21:38:07 UTC
  • mfrom: (7228 work)
  • mto: This revision was merged to the branch mainline in revision 7233.
  • Revision ID: jelmer@jelmer.uk-20190101213807-ay6uqghz0nnrgjvx
Merge trunk.

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_simple(self):
 
909
        backing = self.get_transport()
 
910
        request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
 
911
            backing)
 
912
        tree = self.make_branch_and_memory_tree('.')
 
913
        tree.lock_write()
 
914
        tree.add('')
734
915
        r1 = tree.commit('1st commit')
735
 
        r2 = tree.commit('2nd commit', rev_id=rev_id_utf8)
736
916
        tree.unlock()
737
917
        self.assertEqual(
738
 
            smart_req.SmartServerResponse(('ok', '2', rev_id_utf8)),
739
 
            request.execute(''))
 
918
            smart_req.SmartServerResponse((b'ok', b'1')),
 
919
            request.execute(b'', r1))
 
920
 
 
921
    def test_not_found(self):
 
922
        backing = self.get_transport()
 
923
        request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
 
924
            backing)
 
925
        self.make_branch('.')
 
926
        self.assertEqual(
 
927
            smart_req.FailedSmartServerResponse(
 
928
                (b'NoSuchRevision', b'idontexist')),
 
929
            request.execute(b'', b'idontexist'))
740
930
 
741
931
 
742
932
class TestSmartServerBranchRequestGetConfigFile(
743
 
    tests.TestCaseWithMemoryTransport):
 
933
        tests.TestCaseWithMemoryTransport):
744
934
 
745
935
    def test_default(self):
746
936
        """With no file, we get empty content."""
747
937
        backing = self.get_transport()
748
938
        request = smart_branch.SmartServerBranchGetConfigFile(backing)
749
 
        branch = self.make_branch('.')
 
939
        self.make_branch('.')
750
940
        # there should be no file by default
751
 
        content = ''
752
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), content),
753
 
            request.execute(''))
 
941
        content = b''
 
942
        self.assertEqual(smart_req.SmartServerResponse((b'ok', ), content),
 
943
                         request.execute(b''))
754
944
 
755
945
    def test_with_content(self):
756
946
        # 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.
 
947
        # branch.control_files.get('branch.conf') for now - in the future it
 
948
        # may perform more complex processing.
759
949
        backing = self.get_transport()
760
950
        request = smart_branch.SmartServerBranchGetConfigFile(backing)
761
951
        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(''))
 
952
        branch._transport.put_bytes('branch.conf', b'foo bar baz')
 
953
        self.assertEqual(
 
954
            smart_req.SmartServerResponse((b'ok', ), b'foo bar baz'),
 
955
            request.execute(b''))
765
956
 
766
957
 
767
958
class TestLockedBranch(tests.TestCaseWithMemoryTransport):
768
959
 
769
960
    def get_lock_tokens(self, branch):
770
 
        branch_token = branch.lock_write()
771
 
        repo_token = branch.repository.lock_write()
 
961
        branch_token = branch.lock_write().token
 
962
        repo_token = branch.repository.lock_write().repository_token
772
963
        branch.repository.unlock()
773
964
        return branch_token, repo_token
774
965
 
775
966
 
 
967
class TestSmartServerBranchRequestPutConfigFile(TestLockedBranch):
 
968
 
 
969
    def test_with_content(self):
 
970
        backing = self.get_transport()
 
971
        request = smart_branch.SmartServerBranchPutConfigFile(backing)
 
972
        branch = self.make_branch('.')
 
973
        branch_token, repo_token = self.get_lock_tokens(branch)
 
974
        self.assertIs(None, request.execute(b'', branch_token, repo_token))
 
975
        self.assertEqual(
 
976
            smart_req.SmartServerResponse((b'ok', )),
 
977
            request.do_body(b'foo bar baz'))
 
978
        self.assertEqual(
 
979
            branch.control_transport.get_bytes('branch.conf'),
 
980
            b'foo bar baz')
 
981
        branch.unlock()
 
982
 
 
983
 
776
984
class TestSmartServerBranchRequestSetConfigOption(TestLockedBranch):
777
985
 
778
986
    def test_value_name(self):
779
987
        branch = self.make_branch('.')
780
988
        request = smart_branch.SmartServerBranchRequestSetConfigOption(
781
 
            branch.bzrdir.root_transport)
 
989
            branch.controldir.root_transport)
782
990
        branch_token, repo_token = self.get_lock_tokens(branch)
783
991
        config = branch._get_config()
784
 
        result = request.execute('', branch_token, repo_token, 'bar', 'foo',
785
 
            '')
 
992
        result = request.execute(b'', branch_token, repo_token, b'bar', b'foo',
 
993
                                 b'')
786
994
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
787
995
        self.assertEqual('bar', config.get_option('foo'))
788
996
        # Cleanup
791
999
    def test_value_name_section(self):
792
1000
        branch = self.make_branch('.')
793
1001
        request = smart_branch.SmartServerBranchRequestSetConfigOption(
794
 
            branch.bzrdir.root_transport)
 
1002
            branch.controldir.root_transport)
795
1003
        branch_token, repo_token = self.get_lock_tokens(branch)
796
1004
        config = branch._get_config()
797
 
        result = request.execute('', branch_token, repo_token, 'bar', 'foo',
798
 
            'gam')
 
1005
        result = request.execute(b'', branch_token, repo_token, b'bar', b'foo',
 
1006
                                 b'gam')
799
1007
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
800
1008
        self.assertEqual('bar', config.get_option('foo', 'gam'))
801
1009
        # Cleanup
802
1010
        branch.unlock()
803
1011
 
804
1012
 
 
1013
class TestSmartServerBranchRequestSetConfigOptionDict(TestLockedBranch):
 
1014
 
 
1015
    def setUp(self):
 
1016
        TestLockedBranch.setUp(self)
 
1017
        # A dict with non-ascii keys and values to exercise unicode
 
1018
        # roundtripping.
 
1019
        self.encoded_value_dict = (
 
1020
            b'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde')
 
1021
        self.value_dict = {
 
1022
            'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
 
1023
 
 
1024
    def test_value_name(self):
 
1025
        branch = self.make_branch('.')
 
1026
        request = smart_branch.SmartServerBranchRequestSetConfigOptionDict(
 
1027
            branch.controldir.root_transport)
 
1028
        branch_token, repo_token = self.get_lock_tokens(branch)
 
1029
        config = branch._get_config()
 
1030
        result = request.execute(b'', branch_token, repo_token,
 
1031
                                 self.encoded_value_dict, b'foo', b'')
 
1032
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
 
1033
        self.assertEqual(self.value_dict, config.get_option('foo'))
 
1034
        # Cleanup
 
1035
        branch.unlock()
 
1036
 
 
1037
    def test_value_name_section(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'gam')
 
1045
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
 
1046
        self.assertEqual(self.value_dict, config.get_option('foo', 'gam'))
 
1047
        # Cleanup
 
1048
        branch.unlock()
 
1049
 
 
1050
 
805
1051
class TestSmartServerBranchRequestSetTagsBytes(TestLockedBranch):
806
1052
    # Only called when the branch format and tags match [yay factory
807
1053
    # methods] so only need to test straight forward cases.
813
1059
        branch_token, repo_token = self.get_lock_tokens(base_branch)
814
1060
        request = smart_branch.SmartServerBranchSetTagsBytes(
815
1061
            self.get_transport())
816
 
        response = request.execute('base', branch_token, repo_token)
 
1062
        response = request.execute(b'base', branch_token, repo_token)
817
1063
        self.assertEqual(None, response)
818
1064
        response = request.do_chunk(tag_bytes)
819
1065
        self.assertEqual(None, response)
820
1066
        response = request.do_end()
821
 
        self.assertEquals(
 
1067
        self.assertEqual(
822
1068
            smart_req.SuccessfulSmartServerResponse(()), response)
823
1069
        base_branch.unlock()
824
1070
 
829
1075
        request = smart_branch.SmartServerBranchSetTagsBytes(
830
1076
            self.get_transport())
831
1077
        self.assertRaises(errors.TokenMismatch, request.execute,
832
 
            'base', 'wrong token', 'wrong token')
 
1078
                          b'base', b'wrong token', b'wrong token')
833
1079
        # The request handler will keep processing the message parts, so even
834
1080
        # if the request fails immediately do_chunk and do_end are still
835
1081
        # called.
838
1084
        base_branch.unlock()
839
1085
 
840
1086
 
841
 
 
842
1087
class SetLastRevisionTestBase(TestLockedBranch):
843
1088
    """Base test case for verbs that implement set_last_revision."""
844
1089
 
845
1090
    def setUp(self):
846
 
        tests.TestCaseWithMemoryTransport.setUp(self)
 
1091
        super(SetLastRevisionTestBase, self).setUp()
847
1092
        backing_transport = self.get_transport()
848
1093
        self.request = self.request_class(backing_transport)
849
1094
        self.tree = self.make_branch_and_memory_tree('.')
863
1108
 
864
1109
    def assertRequestSucceeds(self, revision_id, revno):
865
1110
        response = self.set_last_revision(revision_id, revno)
866
 
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
 
1111
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
867
1112
                         response)
868
1113
 
869
1114
 
871
1116
    """Mixin test case for verbs that implement set_last_revision."""
872
1117
 
873
1118
    def test_set_null_to_null(self):
874
 
        """An empty branch can have its last revision set to 'null:'."""
875
 
        self.assertRequestSucceeds('null:', 0)
 
1119
        """An empty branch can have its last revision set to b'null:'."""
 
1120
        self.assertRequestSucceeds(b'null:', 0)
876
1121
 
877
1122
    def test_NoSuchRevision(self):
878
1123
        """If the revision_id is not present, the verb returns NoSuchRevision.
879
1124
        """
880
 
        revision_id = 'non-existent revision'
881
 
        self.assertEqual(smart_req.FailedSmartServerResponse(('NoSuchRevision',
882
 
                                                              revision_id)),
883
 
                         self.set_last_revision(revision_id, 1))
 
1125
        revision_id = b'non-existent revision'
 
1126
        self.assertEqual(
 
1127
            smart_req.FailedSmartServerResponse(
 
1128
                (b'NoSuchRevision', revision_id)),
 
1129
            self.set_last_revision(revision_id, 1))
884
1130
 
885
1131
    def make_tree_with_two_commits(self):
886
1132
        self.tree.lock_write()
887
1133
        self.tree.add('')
888
1134
        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')
 
1135
        self.tree.commit('1st commit', rev_id=rev_id_utf8)
 
1136
        self.tree.commit('2nd commit', rev_id=b'rev-2')
891
1137
        self.tree.unlock()
892
1138
 
893
1139
    def test_branch_last_revision_info_is_updated(self):
898
1144
        # its repository.
899
1145
        self.make_tree_with_two_commits()
900
1146
        rev_id_utf8 = u'\xc8'.encode('utf-8')
901
 
        self.tree.branch.set_revision_history([])
 
1147
        self.tree.branch.set_last_revision_info(0, b'null:')
902
1148
        self.assertEqual(
903
 
            (0, 'null:'), self.tree.branch.last_revision_info())
 
1149
            (0, b'null:'), self.tree.branch.last_revision_info())
904
1150
        # We can update the branch to a revision that is present in the
905
1151
        # repository.
906
1152
        self.assertRequestSucceeds(rev_id_utf8, 1)
914
1160
        self.make_tree_with_two_commits()
915
1161
        rev_id_utf8 = u'\xc8'.encode('utf-8')
916
1162
        self.assertEqual(
917
 
            (2, 'rev-2'), self.tree.branch.last_revision_info())
 
1163
            (2, b'rev-2'), self.tree.branch.last_revision_info())
918
1164
        self.assertRequestSucceeds(rev_id_utf8, 1)
919
1165
        self.assertEqual(
920
1166
            (1, rev_id_utf8), self.tree.branch.last_revision_info())
924
1170
        returns TipChangeRejected.
925
1171
        """
926
1172
        rejection_message = u'rejection message\N{INTERROBANG}'
 
1173
 
927
1174
        def hook_that_rejects(params):
928
1175
            raise errors.TipChangeRejected(rejection_message)
929
1176
        _mod_branch.Branch.hooks.install_named_hook(
930
1177
            'pre_change_branch_tip', hook_that_rejects, None)
931
1178
        self.assertEqual(
932
1179
            smart_req.FailedSmartServerResponse(
933
 
                ('TipChangeRejected', rejection_message.encode('utf-8'))),
934
 
            self.set_last_revision('null:', 0))
 
1180
                (b'TipChangeRejected', rejection_message.encode('utf-8'))),
 
1181
            self.set_last_revision(b'null:', 0))
935
1182
 
936
1183
 
937
1184
class TestSmartServerBranchRequestSetLastRevision(
942
1189
 
943
1190
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
944
1191
        return self.request.execute(
945
 
            '', branch_token, repo_token, revision_id)
 
1192
            b'', branch_token, repo_token, revision_id)
946
1193
 
947
1194
 
948
1195
class TestSmartServerBranchRequestSetLastRevisionInfo(
953
1200
 
954
1201
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
955
1202
        return self.request.execute(
956
 
            '', branch_token, repo_token, revno, revision_id)
 
1203
            b'', branch_token, repo_token, revno, revision_id)
957
1204
 
958
1205
    def test_NoSuchRevision(self):
959
1206
        """Branch.set_last_revision_info does not have to return
970
1217
 
971
1218
    def _set_last_revision(self, revision_id, revno, branch_token, repo_token):
972
1219
        return self.request.execute(
973
 
            '', branch_token, repo_token, revision_id, 0, 0)
 
1220
            b'', branch_token, repo_token, revision_id, 0, 0)
974
1221
 
975
1222
    def assertRequestSucceeds(self, revision_id, revno):
976
1223
        response = self.set_last_revision(revision_id, revno)
977
1224
        self.assertEqual(
978
 
            smart_req.SuccessfulSmartServerResponse(('ok', revno, revision_id)),
 
1225
            smart_req.SuccessfulSmartServerResponse(
 
1226
                (b'ok', revno, revision_id)),
979
1227
            response)
980
1228
 
981
1229
    def test_branch_last_revision_info_rewind(self):
985
1233
        self.make_tree_with_two_commits()
986
1234
        rev_id_utf8 = u'\xc8'.encode('utf-8')
987
1235
        self.assertEqual(
988
 
            (2, 'rev-2'), self.tree.branch.last_revision_info())
 
1236
            (2, b'rev-2'), self.tree.branch.last_revision_info())
989
1237
        # If allow_overwrite_descendant flag is 0, then trying to set the tip
990
1238
        # to an older revision ID has no effect.
991
1239
        branch_token, repo_token = self.lock_branch()
992
1240
        response = self.request.execute(
993
 
            '', branch_token, repo_token, rev_id_utf8, 0, 0)
 
1241
            b'', branch_token, repo_token, rev_id_utf8, 0, 0)
994
1242
        self.assertEqual(
995
 
            smart_req.SuccessfulSmartServerResponse(('ok', 2, 'rev-2')),
 
1243
            smart_req.SuccessfulSmartServerResponse((b'ok', 2, b'rev-2')),
996
1244
            response)
997
1245
        self.assertEqual(
998
 
            (2, 'rev-2'), self.tree.branch.last_revision_info())
 
1246
            (2, b'rev-2'), self.tree.branch.last_revision_info())
999
1247
 
1000
1248
        # If allow_overwrite_descendant flag is 1, then setting the tip to an
1001
1249
        # ancestor works.
1002
1250
        response = self.request.execute(
1003
 
            '', branch_token, repo_token, rev_id_utf8, 0, 1)
 
1251
            b'', branch_token, repo_token, rev_id_utf8, 0, 1)
1004
1252
        self.assertEqual(
1005
 
            smart_req.SuccessfulSmartServerResponse(('ok', 1, rev_id_utf8)),
 
1253
            smart_req.SuccessfulSmartServerResponse((b'ok', 1, rev_id_utf8)),
1006
1254
            response)
1007
1255
        self.unlock_branch()
1008
1256
        self.assertEqual(
1016
1264
        """
1017
1265
        self.tree.lock_write()
1018
1266
        self.tree.add('')
1019
 
        r1 = self.tree.commit('1st commit')
 
1267
        self.tree.commit('1st commit')
1020
1268
        revno_1, revid_1 = self.tree.branch.last_revision_info()
1021
 
        r2 = self.tree.commit('2nd commit', rev_id='child-1')
 
1269
        self.tree.commit('2nd commit', rev_id=b'child-1')
1022
1270
        # Undo the second commit
1023
1271
        self.tree.branch.set_last_revision_info(revno_1, revid_1)
1024
1272
        self.tree.set_parent_ids([revid_1])
1025
1273
        # Make a new second commit, child-2.  child-2 has diverged from
1026
1274
        # child-1.
1027
 
        new_r2 = self.tree.commit('2nd commit', rev_id='child-2')
 
1275
        self.tree.commit('2nd commit', rev_id=b'child-2')
1028
1276
        self.tree.unlock()
1029
1277
 
1030
1278
    def test_not_allow_diverged(self):
1033
1281
        """
1034
1282
        self.make_branch_with_divergent_history()
1035
1283
        self.assertEqual(
1036
 
            smart_req.FailedSmartServerResponse(('Diverged',)),
1037
 
            self.set_last_revision('child-1', 2))
 
1284
            smart_req.FailedSmartServerResponse((b'Diverged',)),
 
1285
            self.set_last_revision(b'child-1', 2))
1038
1286
        # The branch tip was not changed.
1039
 
        self.assertEqual('child-2', self.tree.branch.last_revision())
 
1287
        self.assertEqual(b'child-2', self.tree.branch.last_revision())
1040
1288
 
1041
1289
    def test_allow_diverged(self):
1042
1290
        """If allow_diverged is passed, then setting a divergent history
1045
1293
        self.make_branch_with_divergent_history()
1046
1294
        branch_token, repo_token = self.lock_branch()
1047
1295
        response = self.request.execute(
1048
 
            '', branch_token, repo_token, 'child-1', 1, 0)
 
1296
            b'', branch_token, repo_token, b'child-1', 1, 0)
1049
1297
        self.assertEqual(
1050
 
            smart_req.SuccessfulSmartServerResponse(('ok', 2, 'child-1')),
 
1298
            smart_req.SuccessfulSmartServerResponse((b'ok', 2, b'child-1')),
1051
1299
            response)
1052
1300
        self.unlock_branch()
1053
1301
        # The branch tip was changed.
1054
 
        self.assertEqual('child-1', self.tree.branch.last_revision())
 
1302
        self.assertEqual(b'child-1', self.tree.branch.last_revision())
 
1303
 
 
1304
 
 
1305
class TestSmartServerBranchBreakLock(tests.TestCaseWithMemoryTransport):
 
1306
 
 
1307
    def test_lock_to_break(self):
 
1308
        base_branch = self.make_branch('base')
 
1309
        request = smart_branch.SmartServerBranchBreakLock(
 
1310
            self.get_transport())
 
1311
        base_branch.lock_write()
 
1312
        self.assertEqual(
 
1313
            smart_req.SuccessfulSmartServerResponse((b'ok', ), None),
 
1314
            request.execute(b'base'))
 
1315
 
 
1316
    def test_nothing_to_break(self):
 
1317
        self.make_branch('base')
 
1318
        request = smart_branch.SmartServerBranchBreakLock(
 
1319
            self.get_transport())
 
1320
        self.assertEqual(
 
1321
            smart_req.SuccessfulSmartServerResponse((b'ok', ), None),
 
1322
            request.execute(b'base'))
1055
1323
 
1056
1324
 
1057
1325
class TestSmartServerBranchRequestGetParent(tests.TestCaseWithMemoryTransport):
1058
1326
 
1059
1327
    def test_get_parent_none(self):
1060
 
        base_branch = self.make_branch('base')
 
1328
        self.make_branch('base')
1061
1329
        request = smart_branch.SmartServerBranchGetParent(self.get_transport())
1062
 
        response = request.execute('base')
1063
 
        self.assertEquals(
1064
 
            smart_req.SuccessfulSmartServerResponse(('',)), response)
 
1330
        response = request.execute(b'base')
 
1331
        self.assertEqual(
 
1332
            smart_req.SuccessfulSmartServerResponse((b'',)), response)
1065
1333
 
1066
1334
    def test_get_parent_something(self):
1067
1335
        base_branch = self.make_branch('base')
1068
1336
        base_branch.set_parent(self.get_url('foo'))
1069
1337
        request = smart_branch.SmartServerBranchGetParent(self.get_transport())
1070
 
        response = request.execute('base')
1071
 
        self.assertEquals(
1072
 
            smart_req.SuccessfulSmartServerResponse(("../foo",)),
 
1338
        response = request.execute(b'base')
 
1339
        self.assertEqual(
 
1340
            smart_req.SuccessfulSmartServerResponse((b"../foo",)),
1073
1341
            response)
1074
1342
 
1075
1343
 
1076
 
class TestSmartServerBranchRequestSetParent(tests.TestCaseWithMemoryTransport):
 
1344
class TestSmartServerBranchRequestSetParent(TestLockedBranch):
1077
1345
 
1078
1346
    def test_set_parent_none(self):
1079
1347
        branch = self.make_branch('base', format="1.9")
1082
1350
        branch.unlock()
1083
1351
        request = smart_branch.SmartServerBranchRequestSetParentLocation(
1084
1352
            self.get_transport())
1085
 
        branch_token = branch.lock_write()
1086
 
        repo_token = branch.repository.lock_write()
 
1353
        branch_token, repo_token = self.get_lock_tokens(branch)
1087
1354
        try:
1088
 
            response = request.execute('base', branch_token, repo_token, '')
 
1355
            response = request.execute(b'base', branch_token, repo_token, b'')
1089
1356
        finally:
1090
 
            branch.repository.unlock()
1091
1357
            branch.unlock()
1092
1358
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
 
1359
        # Refresh branch as SetParentLocation modified it
 
1360
        branch = branch.controldir.open_branch()
1093
1361
        self.assertEqual(None, branch.get_parent())
1094
1362
 
1095
1363
    def test_set_parent_something(self):
1096
1364
        branch = self.make_branch('base', format="1.9")
1097
1365
        request = smart_branch.SmartServerBranchRequestSetParentLocation(
1098
1366
            self.get_transport())
1099
 
        branch_token = branch.lock_write()
1100
 
        repo_token = branch.repository.lock_write()
 
1367
        branch_token, repo_token = self.get_lock_tokens(branch)
1101
1368
        try:
1102
 
            response = request.execute('base', branch_token, repo_token,
1103
 
            'http://bar/')
 
1369
            response = request.execute(b'base', branch_token, repo_token,
 
1370
                                       b'http://bar/')
1104
1371
        finally:
1105
 
            branch.repository.unlock()
1106
1372
            branch.unlock()
1107
1373
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
1108
 
        self.assertEqual('http://bar/', branch.get_parent())
 
1374
        refreshed = _mod_branch.Branch.open(branch.base)
 
1375
        self.assertEqual('http://bar/', refreshed.get_parent())
1109
1376
 
1110
1377
 
1111
1378
class TestSmartServerBranchRequestGetTagsBytes(
1112
 
    tests.TestCaseWithMemoryTransport):
 
1379
        tests.TestCaseWithMemoryTransport):
1113
1380
    # Only called when the branch format and tags match [yay factory
1114
1381
    # methods] so only need to test straight forward cases.
1115
1382
 
1116
1383
    def test_get_bytes(self):
1117
 
        base_branch = self.make_branch('base')
 
1384
        self.make_branch('base')
1118
1385
        request = smart_branch.SmartServerBranchGetTagsBytes(
1119
1386
            self.get_transport())
1120
 
        response = request.execute('base')
1121
 
        self.assertEquals(
1122
 
            smart_req.SuccessfulSmartServerResponse(('',)), response)
1123
 
 
1124
 
 
1125
 
class TestSmartServerBranchRequestGetStackedOnURL(tests.TestCaseWithMemoryTransport):
 
1387
        response = request.execute(b'base')
 
1388
        self.assertEqual(
 
1389
            smart_req.SuccessfulSmartServerResponse((b'',)), response)
 
1390
 
 
1391
 
 
1392
class TestSmartServerBranchRequestGetStackedOnURL(
 
1393
        tests.TestCaseWithMemoryTransport):
1126
1394
 
1127
1395
    def test_get_stacked_on_url(self):
1128
 
        base_branch = self.make_branch('base', format='1.6')
 
1396
        self.make_branch('base', format='1.6')
1129
1397
        stacked_branch = self.make_branch('stacked', format='1.6')
1130
1398
        # typically should be relative
1131
1399
        stacked_branch.set_stacked_on_url('../base')
1132
1400
        request = smart_branch.SmartServerBranchRequestGetStackedOnURL(
1133
1401
            self.get_transport())
1134
 
        response = request.execute('stacked')
1135
 
        self.assertEquals(
1136
 
            smart_req.SmartServerResponse(('ok', '../base')),
 
1402
        response = request.execute(b'stacked')
 
1403
        self.assertEqual(
 
1404
            smart_req.SmartServerResponse((b'ok', b'../base')),
1137
1405
            response)
1138
1406
 
1139
1407
 
1140
 
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithMemoryTransport):
1141
 
 
1142
 
    def setUp(self):
1143
 
        tests.TestCaseWithMemoryTransport.setUp(self)
 
1408
class TestSmartServerBranchRequestLockWrite(TestLockedBranch):
1144
1409
 
1145
1410
    def test_lock_write_on_unlocked_branch(self):
1146
1411
        backing = self.get_transport()
1147
1412
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1148
1413
        branch = self.make_branch('.', format='knit')
1149
1414
        repository = branch.repository
1150
 
        response = request.execute('')
 
1415
        response = request.execute(b'')
1151
1416
        branch_nonce = branch.control_files._lock.peek().get('nonce')
1152
1417
        repository_nonce = repository.control_files._lock.peek().get('nonce')
1153
1418
        self.assertEqual(smart_req.SmartServerResponse(
1154
 
                ('ok', branch_nonce, repository_nonce)),
1155
 
                         response)
 
1419
            (b'ok', branch_nonce, repository_nonce)),
 
1420
            response)
1156
1421
        # The branch (and associated repository) is now locked.  Verify that
1157
1422
        # with a new branch object.
1158
 
        new_branch = repository.bzrdir.open_branch()
 
1423
        new_branch = repository.controldir.open_branch()
1159
1424
        self.assertRaises(errors.LockContention, new_branch.lock_write)
1160
1425
        # Cleanup
1161
1426
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1162
 
        response = request.execute('', branch_nonce, repository_nonce)
 
1427
        response = request.execute(b'', branch_nonce, repository_nonce)
1163
1428
 
1164
1429
    def test_lock_write_on_locked_branch(self):
1165
1430
        backing = self.get_transport()
1166
1431
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1167
1432
        branch = self.make_branch('.')
1168
 
        branch_token = branch.lock_write()
 
1433
        branch_token = branch.lock_write().token
1169
1434
        branch.leave_lock_in_place()
1170
1435
        branch.unlock()
1171
 
        response = request.execute('')
 
1436
        response = request.execute(b'')
1172
1437
        self.assertEqual(
1173
 
            smart_req.SmartServerResponse(('LockContention',)), response)
 
1438
            smart_req.SmartServerResponse((b'LockContention',)), response)
1174
1439
        # Cleanup
1175
1440
        branch.lock_write(branch_token)
1176
1441
        branch.dont_leave_lock_in_place()
1180
1445
        backing = self.get_transport()
1181
1446
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1182
1447
        branch = self.make_branch('.', format='knit')
1183
 
        branch_token = branch.lock_write()
1184
 
        repo_token = branch.repository.lock_write()
1185
 
        branch.repository.unlock()
 
1448
        branch_token, repo_token = self.get_lock_tokens(branch)
1186
1449
        branch.leave_lock_in_place()
1187
1450
        branch.repository.leave_lock_in_place()
1188
1451
        branch.unlock()
1189
 
        response = request.execute('',
 
1452
        response = request.execute(b'',
1190
1453
                                   branch_token, repo_token)
1191
1454
        self.assertEqual(
1192
 
            smart_req.SmartServerResponse(('ok', branch_token, repo_token)),
 
1455
            smart_req.SmartServerResponse((b'ok', branch_token, repo_token)),
1193
1456
            response)
1194
1457
        # Cleanup
1195
1458
        branch.repository.lock_write(repo_token)
1203
1466
        backing = self.get_transport()
1204
1467
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1205
1468
        branch = self.make_branch('.', format='knit')
1206
 
        branch_token = branch.lock_write()
1207
 
        repo_token = branch.repository.lock_write()
1208
 
        branch.repository.unlock()
 
1469
        branch_token, repo_token = self.get_lock_tokens(branch)
1209
1470
        branch.leave_lock_in_place()
1210
1471
        branch.repository.leave_lock_in_place()
1211
1472
        branch.unlock()
1212
 
        response = request.execute('',
1213
 
                                   branch_token+'xxx', repo_token)
 
1473
        response = request.execute(b'',
 
1474
                                   branch_token + b'xxx', repo_token)
1214
1475
        self.assertEqual(
1215
 
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
 
1476
            smart_req.SmartServerResponse((b'TokenMismatch',)), response)
1216
1477
        # Cleanup
1217
1478
        branch.repository.lock_write(repo_token)
1218
1479
        branch.repository.dont_leave_lock_in_place()
1226
1487
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1227
1488
        branch = self.make_branch('.', format='knit')
1228
1489
        repo = branch.repository
1229
 
        repo_token = repo.lock_write()
 
1490
        repo_token = repo.lock_write().repository_token
1230
1491
        repo.leave_lock_in_place()
1231
1492
        repo.unlock()
1232
 
        response = request.execute('')
 
1493
        response = request.execute(b'')
1233
1494
        self.assertEqual(
1234
 
            smart_req.SmartServerResponse(('LockContention',)), response)
 
1495
            smart_req.SmartServerResponse((b'LockContention',)), response)
1235
1496
        # Cleanup
1236
1497
        repo.lock_write(repo_token)
1237
1498
        repo.dont_leave_lock_in_place()
1240
1501
    def test_lock_write_on_readonly_transport(self):
1241
1502
        backing = self.get_readonly_transport()
1242
1503
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1243
 
        branch = self.make_branch('.')
 
1504
        self.make_branch('.')
1244
1505
        root = self.get_transport().clone('/')
1245
1506
        path = urlutils.relative_url(root.base, self.get_transport().base)
1246
 
        response = request.execute(path)
 
1507
        response = request.execute(path.encode('utf-8'))
1247
1508
        error_name, lock_str, why_str = response.args
1248
1509
        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)
 
1510
        self.assertEqual(b'LockFailed', error_name)
 
1511
 
 
1512
 
 
1513
class TestSmartServerBranchRequestGetPhysicalLockStatus(TestLockedBranch):
 
1514
 
 
1515
    def test_true(self):
 
1516
        backing = self.get_transport()
 
1517
        request = smart_branch.SmartServerBranchRequestGetPhysicalLockStatus(
 
1518
            backing)
 
1519
        branch = self.make_branch('.')
 
1520
        branch_token, repo_token = self.get_lock_tokens(branch)
 
1521
        self.assertEqual(True, branch.get_physical_lock_status())
 
1522
        response = request.execute(b'')
 
1523
        self.assertEqual(
 
1524
            smart_req.SmartServerResponse((b'yes',)), response)
 
1525
        branch.unlock()
 
1526
 
 
1527
    def test_false(self):
 
1528
        backing = self.get_transport()
 
1529
        request = smart_branch.SmartServerBranchRequestGetPhysicalLockStatus(
 
1530
            backing)
 
1531
        branch = self.make_branch('.')
 
1532
        self.assertEqual(False, branch.get_physical_lock_status())
 
1533
        response = request.execute(b'')
 
1534
        self.assertEqual(
 
1535
            smart_req.SmartServerResponse((b'no',)), response)
 
1536
 
 
1537
 
 
1538
class TestSmartServerBranchRequestUnlock(TestLockedBranch):
1256
1539
 
1257
1540
    def test_unlock_on_locked_branch_and_repo(self):
1258
1541
        backing = self.get_transport()
1259
1542
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1260
1543
        branch = self.make_branch('.', format='knit')
1261
1544
        # Lock the branch
1262
 
        branch_token = branch.lock_write()
1263
 
        repo_token = branch.repository.lock_write()
1264
 
        branch.repository.unlock()
 
1545
        branch_token, repo_token = self.get_lock_tokens(branch)
1265
1546
        # Unlock the branch (and repo) object, leaving the physical locks
1266
1547
        # in place.
1267
1548
        branch.leave_lock_in_place()
1268
1549
        branch.repository.leave_lock_in_place()
1269
1550
        branch.unlock()
1270
 
        response = request.execute('',
 
1551
        response = request.execute(b'',
1271
1552
                                   branch_token, repo_token)
1272
1553
        self.assertEqual(
1273
 
            smart_req.SmartServerResponse(('ok',)), response)
 
1554
            smart_req.SmartServerResponse((b'ok',)), response)
1274
1555
        # The branch is now unlocked.  Verify that with a new branch
1275
1556
        # object.
1276
 
        new_branch = branch.bzrdir.open_branch()
 
1557
        new_branch = branch.controldir.open_branch()
1277
1558
        new_branch.lock_write()
1278
1559
        new_branch.unlock()
1279
1560
 
1280
1561
    def test_unlock_on_unlocked_branch_unlocked_repo(self):
1281
1562
        backing = self.get_transport()
1282
1563
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1283
 
        branch = self.make_branch('.', format='knit')
 
1564
        self.make_branch('.', format='knit')
1284
1565
        response = request.execute(
1285
 
            '', 'branch token', 'repo token')
 
1566
            b'', b'branch token', b'repo token')
1286
1567
        self.assertEqual(
1287
 
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
 
1568
            smart_req.SmartServerResponse((b'TokenMismatch',)), response)
1288
1569
 
1289
1570
    def test_unlock_on_unlocked_branch_locked_repo(self):
1290
1571
        backing = self.get_transport()
1291
1572
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1292
1573
        branch = self.make_branch('.', format='knit')
1293
1574
        # Lock the repository.
1294
 
        repo_token = branch.repository.lock_write()
 
1575
        repo_token = branch.repository.lock_write().repository_token
1295
1576
        branch.repository.leave_lock_in_place()
1296
1577
        branch.repository.unlock()
1297
1578
        # Issue branch lock_write request on the unlocked branch (with locked
1298
1579
        # repo).
1299
 
        response = request.execute(
1300
 
            '', 'branch token', repo_token)
 
1580
        response = request.execute(b'', b'branch token', repo_token)
1301
1581
        self.assertEqual(
1302
 
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
 
1582
            smart_req.SmartServerResponse((b'TokenMismatch',)), response)
1303
1583
        # Cleanup
1304
1584
        branch.repository.lock_write(repo_token)
1305
1585
        branch.repository.dont_leave_lock_in_place()
1317
1597
        backing = self.get_transport()
1318
1598
        request = smart_repo.SmartServerRepositoryRequest(backing)
1319
1599
        self.make_repository('.', shared=True)
1320
 
        self.make_bzrdir('subdir')
 
1600
        self.make_controldir('subdir')
1321
1601
        self.assertRaises(errors.NoRepositoryPresent,
1322
 
            request.execute, 'subdir')
 
1602
                          request.execute, b'subdir')
 
1603
 
 
1604
 
 
1605
class TestSmartServerRepositoryAddSignatureText(
 
1606
        tests.TestCaseWithMemoryTransport):
 
1607
 
 
1608
    def test_add_text(self):
 
1609
        backing = self.get_transport()
 
1610
        request = smart_repo.SmartServerRepositoryAddSignatureText(backing)
 
1611
        tree = self.make_branch_and_memory_tree('.')
 
1612
        write_token = tree.lock_write()
 
1613
        self.addCleanup(tree.unlock)
 
1614
        tree.add('')
 
1615
        tree.commit("Message", rev_id=b'rev1')
 
1616
        tree.branch.repository.start_write_group()
 
1617
        write_group_tokens = tree.branch.repository.suspend_write_group()
 
1618
        self.assertEqual(
 
1619
            None, request.execute(
 
1620
                b'', write_token, b'rev1',
 
1621
                *[token.encode('utf-8') for token in write_group_tokens]))
 
1622
        response = request.do_body(b'somesignature')
 
1623
        self.assertTrue(response.is_successful())
 
1624
        self.assertEqual(response.args[0], b'ok')
 
1625
        write_group_tokens = [token.decode('utf-8')
 
1626
                              for token in response.args[1:]]
 
1627
        tree.branch.repository.resume_write_group(write_group_tokens)
 
1628
        tree.branch.repository.commit_write_group()
 
1629
        tree.unlock()
 
1630
        self.assertEqual(b"somesignature",
 
1631
                         tree.branch.repository.get_signature_text(b"rev1"))
 
1632
 
 
1633
 
 
1634
class TestSmartServerRepositoryAllRevisionIds(
 
1635
        tests.TestCaseWithMemoryTransport):
 
1636
 
 
1637
    def test_empty(self):
 
1638
        """An empty body should be returned for an empty repository."""
 
1639
        backing = self.get_transport()
 
1640
        request = smart_repo.SmartServerRepositoryAllRevisionIds(backing)
 
1641
        self.make_repository('.')
 
1642
        self.assertEqual(
 
1643
            smart_req.SuccessfulSmartServerResponse((b"ok", ), b""),
 
1644
            request.execute(b''))
 
1645
 
 
1646
    def test_some_revisions(self):
 
1647
        """An empty body should be returned for an empty repository."""
 
1648
        backing = self.get_transport()
 
1649
        request = smart_repo.SmartServerRepositoryAllRevisionIds(backing)
 
1650
        tree = self.make_branch_and_memory_tree('.')
 
1651
        tree.lock_write()
 
1652
        tree.add('')
 
1653
        tree.commit(rev_id=b'origineel', message="message")
 
1654
        tree.commit(rev_id=b'nog-een-revisie', message="message")
 
1655
        tree.unlock()
 
1656
        self.assertIn(
 
1657
            request.execute(b''),
 
1658
            [smart_req.SuccessfulSmartServerResponse(
 
1659
                (b"ok", ), b"origineel\nnog-een-revisie"),
 
1660
             smart_req.SuccessfulSmartServerResponse(
 
1661
                 (b"ok", ), b"nog-een-revisie\norigineel")])
 
1662
 
 
1663
 
 
1664
class TestSmartServerRepositoryBreakLock(tests.TestCaseWithMemoryTransport):
 
1665
 
 
1666
    def test_lock_to_break(self):
 
1667
        backing = self.get_transport()
 
1668
        request = smart_repo.SmartServerRepositoryBreakLock(backing)
 
1669
        tree = self.make_branch_and_memory_tree('.')
 
1670
        tree.branch.repository.lock_write()
 
1671
        self.assertEqual(
 
1672
            smart_req.SuccessfulSmartServerResponse((b'ok', ), None),
 
1673
            request.execute(b''))
 
1674
 
 
1675
    def test_nothing_to_break(self):
 
1676
        backing = self.get_transport()
 
1677
        request = smart_repo.SmartServerRepositoryBreakLock(backing)
 
1678
        self.make_branch_and_memory_tree('.')
 
1679
        self.assertEqual(
 
1680
            smart_req.SuccessfulSmartServerResponse((b'ok', ), None),
 
1681
            request.execute(b''))
1323
1682
 
1324
1683
 
1325
1684
class TestSmartServerRepositoryGetParentMap(tests.TestCaseWithMemoryTransport):
1328
1687
        # This tests that the wire encoding is actually bzipped
1329
1688
        backing = self.get_transport()
1330
1689
        request = smart_repo.SmartServerRepositoryGetParentMap(backing)
1331
 
        tree = self.make_branch_and_memory_tree('.')
 
1690
        self.make_branch_and_memory_tree('.')
1332
1691
 
1333
1692
        self.assertEqual(None,
1334
 
            request.execute('', 'missing-id'))
 
1693
                         request.execute(b'', b'missing-id'))
1335
1694
        # Note that it returns a body that is bzipped.
1336
1695
        self.assertEqual(
1337
 
            smart_req.SuccessfulSmartServerResponse(('ok', ), bz2.compress('')),
1338
 
            request.do_body('\n\n0\n'))
 
1696
            smart_req.SuccessfulSmartServerResponse(
 
1697
                (b'ok', ), bz2.compress(b'')),
 
1698
            request.do_body(b'\n\n0\n'))
1339
1699
 
1340
1700
    def test_trivial_include_missing(self):
1341
1701
        backing = self.get_transport()
1342
1702
        request = smart_repo.SmartServerRepositoryGetParentMap(backing)
1343
 
        tree = self.make_branch_and_memory_tree('.')
 
1703
        self.make_branch_and_memory_tree('.')
1344
1704
 
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'))
 
1705
        self.assertEqual(
 
1706
            None, request.execute(b'', b'missing-id', b'include-missing:'))
 
1707
        self.assertEqual(
 
1708
            smart_req.SuccessfulSmartServerResponse(
 
1709
                (b'ok', ), bz2.compress(b'missing:missing-id')),
 
1710
            request.do_body(b'\n\n0\n'))
1351
1711
 
1352
1712
 
1353
1713
class TestSmartServerRepositoryGetRevisionGraph(
1354
 
    tests.TestCaseWithMemoryTransport):
 
1714
        tests.TestCaseWithMemoryTransport):
1355
1715
 
1356
1716
    def test_none_argument(self):
1357
1717
        backing = self.get_transport()
1365
1725
 
1366
1726
        # the lines of revision_id->revision_parent_list has no guaranteed
1367
1727
        # 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')))
 
1728
        lines = sorted([b' '.join([r2, r1]), r1])
 
1729
        response = request.execute(b'', b'')
 
1730
        response.body = b'\n'.join(sorted(response.body.split(b'\n')))
1371
1731
 
1372
1732
        self.assertEqual(
1373
 
            smart_req.SmartServerResponse(('ok', ), '\n'.join(lines)), response)
 
1733
            smart_req.SmartServerResponse((b'ok', ), b'\n'.join(lines)),
 
1734
            response)
1374
1735
 
1375
1736
    def test_specific_revision_argument(self):
1376
1737
        backing = self.get_transport()
1379
1740
        tree.lock_write()
1380
1741
        tree.add('')
1381
1742
        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'))
 
1743
        tree.commit('1st commit', rev_id=rev_id_utf8)
 
1744
        tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
1384
1745
        tree.unlock()
1385
1746
 
1386
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', ), rev_id_utf8),
1387
 
            request.execute('', rev_id_utf8))
 
1747
        self.assertEqual(smart_req.SmartServerResponse((b'ok', ), rev_id_utf8),
 
1748
                         request.execute(b'', rev_id_utf8))
1388
1749
 
1389
1750
    def test_no_such_revision(self):
1390
1751
        backing = self.get_transport()
1392
1753
        tree = self.make_branch_and_memory_tree('.')
1393
1754
        tree.lock_write()
1394
1755
        tree.add('')
1395
 
        r1 = tree.commit('1st commit')
 
1756
        tree.commit('1st commit')
1396
1757
        tree.unlock()
1397
1758
 
1398
1759
        # Note that it still returns body (of zero bytes).
1399
1760
        self.assertEqual(smart_req.SmartServerResponse(
1400
 
                ('nosuchrevision', 'missingrevision', ), ''),
1401
 
                         request.execute('', 'missingrevision'))
 
1761
            (b'nosuchrevision', b'missingrevision', ), b''),
 
1762
            request.execute(b'', b'missingrevision'))
1402
1763
 
1403
1764
 
1404
1765
class TestSmartServerRepositoryGetRevIdForRevno(
1405
 
    tests.TestCaseWithMemoryTransport):
 
1766
        tests.TestCaseWithMemoryTransport):
1406
1767
 
1407
1768
    def test_revno_found(self):
1408
1769
        backing = self.get_transport()
1416
1777
        tree.commit('2nd commit', rev_id=rev2_id_utf8)
1417
1778
        tree.unlock()
1418
1779
 
1419
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', rev1_id_utf8)),
1420
 
            request.execute('', 1, (2, rev2_id_utf8)))
 
1780
        self.assertEqual(smart_req.SmartServerResponse((b'ok', rev1_id_utf8)),
 
1781
                         request.execute(b'', 1, (2, rev2_id_utf8)))
1421
1782
 
1422
1783
    def test_known_revid_missing(self):
1423
1784
        backing = self.get_transport()
1424
1785
        request = smart_repo.SmartServerRepositoryGetRevIdForRevno(backing)
1425
 
        repo = self.make_repository('.')
 
1786
        self.make_repository('.')
1426
1787
        self.assertEqual(
1427
 
            smart_req.FailedSmartServerResponse(('nosuchrevision', 'ghost')),
1428
 
            request.execute('', 1, (2, 'ghost')))
 
1788
            smart_req.FailedSmartServerResponse((b'nosuchrevision', b'ghost')),
 
1789
            request.execute(b'', 1, (2, b'ghost')))
1429
1790
 
1430
1791
    def test_history_incomplete(self):
1431
1792
        backing = self.get_transport()
1432
1793
        request = smart_repo.SmartServerRepositoryGetRevIdForRevno(backing)
1433
1794
        parent = self.make_branch_and_memory_tree('parent', format='1.9')
1434
1795
        parent.lock_write()
1435
 
        parent.add([''], ['TREE_ROOT'])
1436
 
        r1 = parent.commit(message='first commit')
 
1796
        parent.add([''], [b'TREE_ROOT'])
 
1797
        parent.commit(message='first commit')
1437
1798
        r2 = parent.commit(message='second commit')
1438
1799
        parent.unlock()
1439
1800
        local = self.make_branch_and_memory_tree('local', format='1.9')
1443
1804
        local.branch.create_clone_on_transport(
1444
1805
            self.get_transport('stacked'), stacked_on=self.get_url('parent'))
1445
1806
        self.assertEqual(
1446
 
            smart_req.SmartServerResponse(('history-incomplete', 2, r2)),
1447
 
            request.execute('stacked', 1, (3, r3)))
1448
 
 
1449
 
 
1450
 
class TestSmartServerRepositoryGetStream(tests.TestCaseWithMemoryTransport):
 
1807
            smart_req.SmartServerResponse((b'history-incomplete', 2, r2)),
 
1808
            request.execute(b'stacked', 1, (3, r3)))
 
1809
 
 
1810
 
 
1811
class TestSmartServerRepositoryIterRevisions(
 
1812
        tests.TestCaseWithMemoryTransport):
 
1813
 
 
1814
    def test_basic(self):
 
1815
        backing = self.get_transport()
 
1816
        request = smart_repo.SmartServerRepositoryIterRevisions(backing)
 
1817
        tree = self.make_branch_and_memory_tree('.', format='2a')
 
1818
        tree.lock_write()
 
1819
        tree.add('')
 
1820
        tree.commit('1st commit', rev_id=b"rev1")
 
1821
        tree.commit('2nd commit', rev_id=b"rev2")
 
1822
        tree.unlock()
 
1823
 
 
1824
        self.assertIs(None, request.execute(b''))
 
1825
        response = request.do_body(b"rev1\nrev2")
 
1826
        self.assertTrue(response.is_successful())
 
1827
        # Format 2a uses serializer format 10
 
1828
        self.assertEqual(response.args, (b"ok", b"10"))
 
1829
 
 
1830
        self.addCleanup(tree.branch.lock_read().unlock)
 
1831
        entries = [zlib.compress(record.get_bytes_as("fulltext")) for record in
 
1832
                   tree.branch.repository.revisions.get_record_stream(
 
1833
            [(b"rev1", ), (b"rev2", )], "unordered", True)]
 
1834
 
 
1835
        contents = b"".join(response.body_stream)
 
1836
        self.assertTrue(contents in (
 
1837
            b"".join([entries[0], entries[1]]),
 
1838
            b"".join([entries[1], entries[0]])))
 
1839
 
 
1840
    def test_missing(self):
 
1841
        backing = self.get_transport()
 
1842
        request = smart_repo.SmartServerRepositoryIterRevisions(backing)
 
1843
        self.make_branch_and_memory_tree('.', format='2a')
 
1844
 
 
1845
        self.assertIs(None, request.execute(b''))
 
1846
        response = request.do_body(b"rev1\nrev2")
 
1847
        self.assertTrue(response.is_successful())
 
1848
        # Format 2a uses serializer format 10
 
1849
        self.assertEqual(response.args, (b"ok", b"10"))
 
1850
 
 
1851
        contents = b"".join(response.body_stream)
 
1852
        self.assertEqual(contents, b"")
 
1853
 
 
1854
 
 
1855
class GetStreamTestBase(tests.TestCaseWithMemoryTransport):
1451
1856
 
1452
1857
    def make_two_commit_repo(self):
1453
1858
        tree = self.make_branch_and_memory_tree('.')
1459
1864
        repo = tree.branch.repository
1460
1865
        return repo, r1, r2
1461
1866
 
 
1867
 
 
1868
class TestSmartServerRepositoryGetStream(GetStreamTestBase):
 
1869
 
1462
1870
    def test_ancestry_of(self):
1463
1871
        """The search argument may be a 'ancestry-of' some heads'."""
1464
1872
        backing = self.get_transport()
1465
1873
        request = smart_repo.SmartServerRepositoryGetStream(backing)
1466
1874
        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())
 
1875
        fetch_spec = [b'ancestry-of', r2]
 
1876
        lines = b'\n'.join(fetch_spec)
 
1877
        request.execute(b'', repo._format.network_name())
1470
1878
        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')
 
1879
        self.assertEqual((b'ok',), response.args)
 
1880
        stream_bytes = b''.join(response.body_stream)
 
1881
        self.assertStartsWith(stream_bytes, b'Bazaar pack format 1')
1474
1882
 
1475
1883
    def test_search(self):
1476
1884
        """The search argument may be a 'search' of some explicit keys."""
1477
1885
        backing = self.get_transport()
1478
1886
        request = smart_repo.SmartServerRepositoryGetStream(backing)
1479
1887
        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())
 
1888
        fetch_spec = [b'search', r1 + b' ' + r2, b'null:', b'2']
 
1889
        lines = b'\n'.join(fetch_spec)
 
1890
        request.execute(b'', repo._format.network_name())
1483
1891
        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')
 
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')
 
1895
 
 
1896
    def test_search_everything(self):
 
1897
        """A search of 'everything' returns a stream."""
 
1898
        backing = self.get_transport()
 
1899
        request = smart_repo.SmartServerRepositoryGetStream_1_19(backing)
 
1900
        repo, r1, r2 = self.make_two_commit_repo()
 
1901
        serialised_fetch_spec = b'everything'
 
1902
        request.execute(b'', repo._format.network_name())
 
1903
        response = request.do_body(serialised_fetch_spec)
 
1904
        self.assertEqual((b'ok',), response.args)
 
1905
        stream_bytes = b''.join(response.body_stream)
 
1906
        self.assertStartsWith(stream_bytes, b'Bazaar pack format 1')
1487
1907
 
1488
1908
 
1489
1909
class TestSmartServerRequestHasRevision(tests.TestCaseWithMemoryTransport):
1493
1913
        backing = self.get_transport()
1494
1914
        request = smart_repo.SmartServerRequestHasRevision(backing)
1495
1915
        self.make_repository('.')
1496
 
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
1497
 
            request.execute('', 'revid'))
 
1916
        self.assertEqual(smart_req.SmartServerResponse((b'no', )),
 
1917
                         request.execute(b'', b'revid'))
1498
1918
 
1499
1919
    def test_present_revision(self):
1500
1920
        """For a present revision, ('yes', ) is returned."""
1504
1924
        tree.lock_write()
1505
1925
        tree.add('')
1506
1926
        rev_id_utf8 = u'\xc8abc'.encode('utf-8')
1507
 
        r1 = tree.commit('a commit', rev_id=rev_id_utf8)
 
1927
        tree.commit('a commit', rev_id=rev_id_utf8)
1508
1928
        tree.unlock()
1509
1929
        self.assertTrue(tree.branch.repository.has_revision(rev_id_utf8))
1510
 
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
1511
 
            request.execute('', rev_id_utf8))
 
1930
        self.assertEqual(smart_req.SmartServerResponse((b'yes', )),
 
1931
                         request.execute(b'', rev_id_utf8))
 
1932
 
 
1933
 
 
1934
class TestSmartServerRepositoryIterFilesBytes(tests.TestCaseWithTransport):
 
1935
 
 
1936
    def test_single(self):
 
1937
        backing = self.get_transport()
 
1938
        request = smart_repo.SmartServerRepositoryIterFilesBytes(backing)
 
1939
        t = self.make_branch_and_tree('.')
 
1940
        self.addCleanup(t.lock_write().unlock)
 
1941
        self.build_tree_contents([("file", b"somecontents")])
 
1942
        t.add(["file"], [b"thefileid"])
 
1943
        t.commit(rev_id=b'somerev', message="add file")
 
1944
        self.assertIs(None, request.execute(b''))
 
1945
        response = request.do_body(b"thefileid\0somerev\n")
 
1946
        self.assertTrue(response.is_successful())
 
1947
        self.assertEqual(response.args, (b"ok", ))
 
1948
        self.assertEqual(b"".join(response.body_stream),
 
1949
                         b"ok\x000\n" + zlib.compress(b"somecontents"))
 
1950
 
 
1951
    def test_missing(self):
 
1952
        backing = self.get_transport()
 
1953
        request = smart_repo.SmartServerRepositoryIterFilesBytes(backing)
 
1954
        t = self.make_branch_and_tree('.')
 
1955
        self.addCleanup(t.lock_write().unlock)
 
1956
        self.assertIs(None, request.execute(b''))
 
1957
        response = request.do_body(b"thefileid\0revision\n")
 
1958
        self.assertTrue(response.is_successful())
 
1959
        self.assertEqual(response.args, (b"ok", ))
 
1960
        self.assertEqual(b"".join(response.body_stream),
 
1961
                         b"absent\x00thefileid\x00revision\x000\n")
 
1962
 
 
1963
 
 
1964
class TestSmartServerRequestHasSignatureForRevisionId(
 
1965
        tests.TestCaseWithMemoryTransport):
 
1966
 
 
1967
    def test_missing_revision(self):
 
1968
        """For a missing revision, NoSuchRevision is returned."""
 
1969
        backing = self.get_transport()
 
1970
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1971
            backing)
 
1972
        self.make_repository('.')
 
1973
        self.assertEqual(
 
1974
            smart_req.FailedSmartServerResponse(
 
1975
                (b'nosuchrevision', b'revid'), None),
 
1976
            request.execute(b'', b'revid'))
 
1977
 
 
1978
    def test_missing_signature(self):
 
1979
        """For a missing signature, ('no', ) is returned."""
 
1980
        backing = self.get_transport()
 
1981
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1982
            backing)
 
1983
        tree = self.make_branch_and_memory_tree('.')
 
1984
        tree.lock_write()
 
1985
        tree.add('')
 
1986
        tree.commit('a commit', rev_id=b'A')
 
1987
        tree.unlock()
 
1988
        self.assertTrue(tree.branch.repository.has_revision(b'A'))
 
1989
        self.assertEqual(smart_req.SmartServerResponse((b'no', )),
 
1990
                         request.execute(b'', b'A'))
 
1991
 
 
1992
    def test_present_signature(self):
 
1993
        """For a present signature, ('yes', ) is returned."""
 
1994
        backing = self.get_transport()
 
1995
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1996
            backing)
 
1997
        strategy = gpg.LoopbackGPGStrategy(None)
 
1998
        tree = self.make_branch_and_memory_tree('.')
 
1999
        tree.lock_write()
 
2000
        tree.add('')
 
2001
        tree.commit('a commit', rev_id=b'A')
 
2002
        tree.branch.repository.start_write_group()
 
2003
        tree.branch.repository.sign_revision(b'A', strategy)
 
2004
        tree.branch.repository.commit_write_group()
 
2005
        tree.unlock()
 
2006
        self.assertTrue(tree.branch.repository.has_revision(b'A'))
 
2007
        self.assertEqual(smart_req.SmartServerResponse((b'yes', )),
 
2008
                         request.execute(b'', b'A'))
1512
2009
 
1513
2010
 
1514
2011
class TestSmartServerRepositoryGatherStats(tests.TestCaseWithMemoryTransport):
1518
2015
        backing = self.get_transport()
1519
2016
        request = smart_repo.SmartServerRepositoryGatherStats(backing)
1520
2017
        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'))
 
2018
        repository.gather_stats()
 
2019
        expected_body = b'revisions: 0\n'
 
2020
        self.assertEqual(
 
2021
            smart_req.SmartServerResponse((b'ok', ), expected_body),
 
2022
            request.execute(b'', b'', b'no'))
1525
2023
 
1526
2024
    def test_revid_with_committers(self):
1527
2025
        """For a revid we get more infos."""
1537
2035
                    rev_id=rev_id_utf8)
1538
2036
        tree.unlock()
1539
2037
 
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'))
 
2038
        tree.branch.repository.gather_stats()
 
2039
        expected_body = (b'firstrev: 123456.200 3600\n'
 
2040
                         b'latestrev: 654321.400 0\n'
 
2041
                         b'revisions: 2\n')
 
2042
        self.assertEqual(
 
2043
            smart_req.SmartServerResponse((b'ok', ), expected_body),
 
2044
            request.execute(b'', rev_id_utf8, b'no'))
1547
2045
 
1548
2046
    def test_not_empty_repository_with_committers(self):
1549
2047
        """For a revid and requesting committers we get the whole thing."""
1559
2057
        tree.commit('a commit', timestamp=654321.4, timezone=0,
1560
2058
                    committer='bar', rev_id=rev_id_utf8)
1561
2059
        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'))
 
2060
        tree.branch.repository.gather_stats()
 
2061
 
 
2062
        expected_body = (b'committers: 2\n'
 
2063
                         b'firstrev: 123456.200 3600\n'
 
2064
                         b'latestrev: 654321.400 0\n'
 
2065
                         b'revisions: 2\n')
 
2066
        self.assertEqual(
 
2067
            smart_req.SmartServerResponse((b'ok', ), expected_body),
 
2068
            request.execute(b'', rev_id_utf8, b'yes'))
 
2069
 
 
2070
    def test_unknown_revid(self):
 
2071
        """An unknown revision id causes a 'nosuchrevision' error."""
 
2072
        backing = self.get_transport()
 
2073
        request = smart_repo.SmartServerRepositoryGatherStats(backing)
 
2074
        self.make_repository('.')
 
2075
        self.assertEqual(
 
2076
            smart_req.FailedSmartServerResponse(
 
2077
                (b'nosuchrevision', b'mia'), None),
 
2078
            request.execute(b'', b'mia', b'yes'))
1571
2079
 
1572
2080
 
1573
2081
class TestSmartServerRepositoryIsShared(tests.TestCaseWithMemoryTransport):
1577
2085
        backing = self.get_transport()
1578
2086
        request = smart_repo.SmartServerRepositoryIsShared(backing)
1579
2087
        self.make_repository('.', shared=True)
1580
 
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
1581
 
            request.execute('', ))
 
2088
        self.assertEqual(smart_req.SmartServerResponse((b'yes', )),
 
2089
                         request.execute(b'', ))
1582
2090
 
1583
2091
    def test_is_not_shared(self):
1584
2092
        """For a shared repository, ('no', ) is returned."""
1585
2093
        backing = self.get_transport()
1586
2094
        request = smart_repo.SmartServerRepositoryIsShared(backing)
1587
2095
        self.make_repository('.', shared=False)
1588
 
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
1589
 
            request.execute('', ))
 
2096
        self.assertEqual(smart_req.SmartServerResponse((b'no', )),
 
2097
                         request.execute(b'', ))
 
2098
 
 
2099
 
 
2100
class TestSmartServerRepositoryGetRevisionSignatureText(
 
2101
        tests.TestCaseWithMemoryTransport):
 
2102
 
 
2103
    def test_get_signature(self):
 
2104
        backing = self.get_transport()
 
2105
        request = smart_repo.SmartServerRepositoryGetRevisionSignatureText(
 
2106
            backing)
 
2107
        bb = self.make_branch_builder('.')
 
2108
        bb.build_commit(rev_id=b'A')
 
2109
        repo = bb.get_branch().repository
 
2110
        strategy = gpg.LoopbackGPGStrategy(None)
 
2111
        self.addCleanup(repo.lock_write().unlock)
 
2112
        repo.start_write_group()
 
2113
        repo.sign_revision(b'A', strategy)
 
2114
        repo.commit_write_group()
 
2115
        expected_body = (
 
2116
            b'-----BEGIN PSEUDO-SIGNED CONTENT-----\n' +
 
2117
            Testament.from_revision(repo, b'A').as_short_text() +
 
2118
            b'-----END PSEUDO-SIGNED CONTENT-----\n')
 
2119
        self.assertEqual(
 
2120
            smart_req.SmartServerResponse((b'ok', ), expected_body),
 
2121
            request.execute(b'', b'A'))
 
2122
 
 
2123
 
 
2124
class TestSmartServerRepositoryMakeWorkingTrees(
 
2125
        tests.TestCaseWithMemoryTransport):
 
2126
 
 
2127
    def test_make_working_trees(self):
 
2128
        """For a repository with working trees, ('yes', ) is returned."""
 
2129
        backing = self.get_transport()
 
2130
        request = smart_repo.SmartServerRepositoryMakeWorkingTrees(backing)
 
2131
        r = self.make_repository('.')
 
2132
        r.set_make_working_trees(True)
 
2133
        self.assertEqual(smart_req.SmartServerResponse((b'yes', )),
 
2134
                         request.execute(b'', ))
 
2135
 
 
2136
    def test_is_not_shared(self):
 
2137
        """For a repository with working trees, ('no', ) is returned."""
 
2138
        backing = self.get_transport()
 
2139
        request = smart_repo.SmartServerRepositoryMakeWorkingTrees(backing)
 
2140
        r = self.make_repository('.')
 
2141
        r.set_make_working_trees(False)
 
2142
        self.assertEqual(smart_req.SmartServerResponse((b'no', )),
 
2143
                         request.execute(b'', ))
1590
2144
 
1591
2145
 
1592
2146
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
1595
2149
        backing = self.get_transport()
1596
2150
        request = smart_repo.SmartServerRepositoryLockWrite(backing)
1597
2151
        repository = self.make_repository('.', format='knit')
1598
 
        response = request.execute('')
 
2152
        response = request.execute(b'')
1599
2153
        nonce = repository.control_files._lock.peek().get('nonce')
1600
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', nonce)), response)
 
2154
        self.assertEqual(smart_req.SmartServerResponse(
 
2155
            (b'ok', nonce)), response)
1601
2156
        # The repository is now locked.  Verify that with a new repository
1602
2157
        # object.
1603
 
        new_repo = repository.bzrdir.open_repository()
 
2158
        new_repo = repository.controldir.open_repository()
1604
2159
        self.assertRaises(errors.LockContention, new_repo.lock_write)
1605
2160
        # Cleanup
1606
2161
        request = smart_repo.SmartServerRepositoryUnlock(backing)
1607
 
        response = request.execute('', nonce)
 
2162
        response = request.execute(b'', nonce)
1608
2163
 
1609
2164
    def test_lock_write_on_locked_repo(self):
1610
2165
        backing = self.get_transport()
1611
2166
        request = smart_repo.SmartServerRepositoryLockWrite(backing)
1612
2167
        repository = self.make_repository('.', format='knit')
1613
 
        repo_token = repository.lock_write()
 
2168
        repo_token = repository.lock_write().repository_token
1614
2169
        repository.leave_lock_in_place()
1615
2170
        repository.unlock()
1616
 
        response = request.execute('')
 
2171
        response = request.execute(b'')
1617
2172
        self.assertEqual(
1618
 
            smart_req.SmartServerResponse(('LockContention',)), response)
 
2173
            smart_req.SmartServerResponse((b'LockContention',)), response)
1619
2174
        # Cleanup
1620
2175
        repository.lock_write(repo_token)
1621
2176
        repository.dont_leave_lock_in_place()
1624
2179
    def test_lock_write_on_readonly_transport(self):
1625
2180
        backing = self.get_readonly_transport()
1626
2181
        request = smart_repo.SmartServerRepositoryLockWrite(backing)
1627
 
        repository = self.make_repository('.', format='knit')
1628
 
        response = request.execute('')
 
2182
        self.make_repository('.', format='knit')
 
2183
        response = request.execute(b'')
1629
2184
        self.assertFalse(response.is_successful())
1630
 
        self.assertEqual('LockFailed', response.args[0])
 
2185
        self.assertEqual(b'LockFailed', response.args[0])
1631
2186
 
1632
2187
 
1633
2188
class TestInsertStreamBase(tests.TestCaseWithMemoryTransport):
1634
2189
 
1635
2190
    def make_empty_byte_stream(self, repo):
1636
2191
        byte_stream = smart_repo._stream_to_byte_stream([], repo._format)
1637
 
        return ''.join(byte_stream)
 
2192
        return b''.join(byte_stream)
1638
2193
 
1639
2194
 
1640
2195
class TestSmartServerRepositoryInsertStream(TestInsertStreamBase):
1643
2198
        backing = self.get_transport()
1644
2199
        request = smart_repo.SmartServerRepositoryInsertStream(backing)
1645
2200
        repository = self.make_repository('.')
1646
 
        response = request.execute('', '')
 
2201
        response = request.execute(b'', b'')
1647
2202
        self.assertEqual(None, response)
1648
2203
        response = request.do_chunk(self.make_empty_byte_stream(repository))
1649
2204
        self.assertEqual(None, response)
1650
2205
        response = request.do_end()
1651
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', )), response)
 
2206
        self.assertEqual(smart_req.SmartServerResponse((b'ok', )), response)
1652
2207
 
1653
2208
 
1654
2209
class TestSmartServerRepositoryInsertStreamLocked(TestInsertStreamBase):
1658
2213
        request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1659
2214
            backing)
1660
2215
        repository = self.make_repository('.', format='knit')
1661
 
        lock_token = repository.lock_write()
1662
 
        response = request.execute('', '', lock_token)
 
2216
        lock_token = repository.lock_write().repository_token
 
2217
        response = request.execute(b'', b'', lock_token)
1663
2218
        self.assertEqual(None, response)
1664
2219
        response = request.do_chunk(self.make_empty_byte_stream(repository))
1665
2220
        self.assertEqual(None, response)
1666
2221
        response = request.do_end()
1667
 
        self.assertEqual(smart_req.SmartServerResponse(('ok', )), response)
 
2222
        self.assertEqual(smart_req.SmartServerResponse((b'ok', )), response)
1668
2223
        repository.unlock()
1669
2224
 
1670
2225
    def test_insert_stream_with_wrong_lock_token(self):
1672
2227
        request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1673
2228
            backing)
1674
2229
        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()
 
2230
        with repository.lock_write():
 
2231
            self.assertRaises(
 
2232
                errors.TokenMismatch, request.execute, b'', b'',
 
2233
                b'wrong-token')
1679
2234
 
1680
2235
 
1681
2236
class TestSmartServerRepositoryUnlock(tests.TestCaseWithMemoryTransport):
1682
2237
 
1683
 
    def setUp(self):
1684
 
        tests.TestCaseWithMemoryTransport.setUp(self)
1685
 
 
1686
2238
    def test_unlock_on_locked_repo(self):
1687
2239
        backing = self.get_transport()
1688
2240
        request = smart_repo.SmartServerRepositoryUnlock(backing)
1689
2241
        repository = self.make_repository('.', format='knit')
1690
 
        token = repository.lock_write()
 
2242
        token = repository.lock_write().repository_token
1691
2243
        repository.leave_lock_in_place()
1692
2244
        repository.unlock()
1693
 
        response = request.execute('', token)
 
2245
        response = request.execute(b'', token)
1694
2246
        self.assertEqual(
1695
 
            smart_req.SmartServerResponse(('ok',)), response)
 
2247
            smart_req.SmartServerResponse((b'ok',)), response)
1696
2248
        # The repository is now unlocked.  Verify that with a new repository
1697
2249
        # object.
1698
 
        new_repo = repository.bzrdir.open_repository()
 
2250
        new_repo = repository.controldir.open_repository()
1699
2251
        new_repo.lock_write()
1700
2252
        new_repo.unlock()
1701
2253
 
1702
2254
    def test_unlock_on_unlocked_repo(self):
1703
2255
        backing = self.get_transport()
1704
2256
        request = smart_repo.SmartServerRepositoryUnlock(backing)
1705
 
        repository = self.make_repository('.', format='knit')
1706
 
        response = request.execute('', 'some token')
 
2257
        self.make_repository('.', format='knit')
 
2258
        response = request.execute(b'', b'some token')
1707
2259
        self.assertEqual(
1708
 
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
 
2260
            smart_req.SmartServerResponse((b'TokenMismatch',)), response)
 
2261
 
 
2262
 
 
2263
class TestSmartServerRepositoryGetPhysicalLockStatus(
 
2264
        tests.TestCaseWithTransport):
 
2265
 
 
2266
    def test_with_write_lock(self):
 
2267
        backing = self.get_transport()
 
2268
        repo = self.make_repository('.')
 
2269
        self.addCleanup(repo.lock_write().unlock)
 
2270
        # lock_write() doesn't necessarily actually take a physical
 
2271
        # lock out.
 
2272
        if repo.get_physical_lock_status():
 
2273
            expected = b'yes'
 
2274
        else:
 
2275
            expected = b'no'
 
2276
        request_class = smart_repo.SmartServerRepositoryGetPhysicalLockStatus
 
2277
        request = request_class(backing)
 
2278
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((expected,)),
 
2279
                         request.execute(b'', ))
 
2280
 
 
2281
    def test_without_write_lock(self):
 
2282
        backing = self.get_transport()
 
2283
        repo = self.make_repository('.')
 
2284
        self.assertEqual(False, repo.get_physical_lock_status())
 
2285
        request_class = smart_repo.SmartServerRepositoryGetPhysicalLockStatus
 
2286
        request = request_class(backing)
 
2287
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'no',)),
 
2288
                         request.execute(b'', ))
 
2289
 
 
2290
 
 
2291
class TestSmartServerRepositoryReconcile(tests.TestCaseWithTransport):
 
2292
 
 
2293
    def test_reconcile(self):
 
2294
        backing = self.get_transport()
 
2295
        repo = self.make_repository('.')
 
2296
        token = repo.lock_write().repository_token
 
2297
        self.addCleanup(repo.unlock)
 
2298
        request_class = smart_repo.SmartServerRepositoryReconcile
 
2299
        request = request_class(backing)
 
2300
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(
 
2301
            (b'ok', ),
 
2302
            b'garbage_inventories: 0\n'
 
2303
            b'inconsistent_parents: 0\n'),
 
2304
            request.execute(b'', token))
1709
2305
 
1710
2306
 
1711
2307
class TestSmartServerIsReadonly(tests.TestCaseWithMemoryTransport):
1715
2311
        request = smart_req.SmartServerIsReadonly(backing)
1716
2312
        response = request.execute()
1717
2313
        self.assertEqual(
1718
 
            smart_req.SmartServerResponse(('no',)), response)
 
2314
            smart_req.SmartServerResponse((b'no',)), response)
1719
2315
 
1720
2316
    def test_is_readonly_yes(self):
1721
2317
        backing = self.get_readonly_transport()
1722
2318
        request = smart_req.SmartServerIsReadonly(backing)
1723
2319
        response = request.execute()
1724
2320
        self.assertEqual(
1725
 
            smart_req.SmartServerResponse(('yes',)), response)
 
2321
            smart_req.SmartServerResponse((b'yes',)), response)
1726
2322
 
1727
2323
 
1728
2324
class TestSmartServerRepositorySetMakeWorkingTrees(
1729
 
    tests.TestCaseWithMemoryTransport):
 
2325
        tests.TestCaseWithMemoryTransport):
1730
2326
 
1731
2327
    def test_set_false(self):
1732
2328
        backing = self.get_transport()
1734
2330
        repo.set_make_working_trees(True)
1735
2331
        request_class = smart_repo.SmartServerRepositorySetMakeWorkingTrees
1736
2332
        request = request_class(backing)
1737
 
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
1738
 
            request.execute('', 'False'))
1739
 
        repo = repo.bzrdir.open_repository()
 
2333
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
 
2334
                         request.execute(b'', b'False'))
 
2335
        repo = repo.controldir.open_repository()
1740
2336
        self.assertFalse(repo.make_working_trees())
1741
2337
 
1742
2338
    def test_set_true(self):
1745
2341
        repo.set_make_working_trees(False)
1746
2342
        request_class = smart_repo.SmartServerRepositorySetMakeWorkingTrees
1747
2343
        request = request_class(backing)
1748
 
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
1749
 
            request.execute('', 'True'))
1750
 
        repo = repo.bzrdir.open_repository()
 
2344
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
 
2345
                         request.execute(b'', b'True'))
 
2346
        repo = repo.controldir.open_repository()
1751
2347
        self.assertTrue(repo.make_working_trees())
1752
2348
 
1753
2349
 
 
2350
class TestSmartServerRepositoryGetSerializerFormat(
 
2351
        tests.TestCaseWithMemoryTransport):
 
2352
 
 
2353
    def test_get_serializer_format(self):
 
2354
        backing = self.get_transport()
 
2355
        repo = self.make_repository('.', format='2a')
 
2356
        request_class = smart_repo.SmartServerRepositoryGetSerializerFormat
 
2357
        request = request_class(backing)
 
2358
        self.assertEqual(
 
2359
            smart_req.SuccessfulSmartServerResponse((b'ok', b'10')),
 
2360
            request.execute(b''))
 
2361
 
 
2362
 
 
2363
class TestSmartServerRepositoryWriteGroup(
 
2364
        tests.TestCaseWithMemoryTransport):
 
2365
 
 
2366
    def test_start_write_group(self):
 
2367
        backing = self.get_transport()
 
2368
        repo = self.make_repository('.')
 
2369
        lock_token = repo.lock_write().repository_token
 
2370
        self.addCleanup(repo.unlock)
 
2371
        request_class = smart_repo.SmartServerRepositoryStartWriteGroup
 
2372
        request = request_class(backing)
 
2373
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok', [])),
 
2374
                         request.execute(b'', lock_token))
 
2375
 
 
2376
    def test_start_write_group_unsuspendable(self):
 
2377
        backing = self.get_transport()
 
2378
        repo = self.make_repository('.', format='knit')
 
2379
        lock_token = repo.lock_write().repository_token
 
2380
        self.addCleanup(repo.unlock)
 
2381
        request_class = smart_repo.SmartServerRepositoryStartWriteGroup
 
2382
        request = request_class(backing)
 
2383
        self.assertEqual(
 
2384
            smart_req.FailedSmartServerResponse((b'UnsuspendableWriteGroup',)),
 
2385
            request.execute(b'', lock_token))
 
2386
 
 
2387
    def test_commit_write_group(self):
 
2388
        backing = self.get_transport()
 
2389
        repo = self.make_repository('.')
 
2390
        lock_token = repo.lock_write().repository_token
 
2391
        self.addCleanup(repo.unlock)
 
2392
        repo.start_write_group()
 
2393
        tokens = repo.suspend_write_group()
 
2394
        request_class = smart_repo.SmartServerRepositoryCommitWriteGroup
 
2395
        request = request_class(backing)
 
2396
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
 
2397
                         request.execute(b'', lock_token, tokens))
 
2398
 
 
2399
    def test_abort_write_group(self):
 
2400
        backing = self.get_transport()
 
2401
        repo = self.make_repository('.')
 
2402
        lock_token = repo.lock_write().repository_token
 
2403
        repo.start_write_group()
 
2404
        tokens = repo.suspend_write_group()
 
2405
        self.addCleanup(repo.unlock)
 
2406
        request_class = smart_repo.SmartServerRepositoryAbortWriteGroup
 
2407
        request = request_class(backing)
 
2408
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
 
2409
                         request.execute(b'', lock_token, tokens))
 
2410
 
 
2411
    def test_check_write_group(self):
 
2412
        backing = self.get_transport()
 
2413
        repo = self.make_repository('.')
 
2414
        lock_token = repo.lock_write().repository_token
 
2415
        repo.start_write_group()
 
2416
        tokens = repo.suspend_write_group()
 
2417
        self.addCleanup(repo.unlock)
 
2418
        request_class = smart_repo.SmartServerRepositoryCheckWriteGroup
 
2419
        request = request_class(backing)
 
2420
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((b'ok',)),
 
2421
                         request.execute(b'', lock_token, tokens))
 
2422
 
 
2423
    def test_check_write_group_invalid(self):
 
2424
        backing = self.get_transport()
 
2425
        repo = self.make_repository('.')
 
2426
        lock_token = repo.lock_write().repository_token
 
2427
        self.addCleanup(repo.unlock)
 
2428
        request_class = smart_repo.SmartServerRepositoryCheckWriteGroup
 
2429
        request = request_class(backing)
 
2430
        self.assertEqual(smart_req.FailedSmartServerResponse(
 
2431
            (b'UnresumableWriteGroup', [b'random'],
 
2432
                b'Malformed write group token')),
 
2433
            request.execute(b'', lock_token, [b"random"]))
 
2434
 
 
2435
 
1754
2436
class TestSmartServerPackRepositoryAutopack(tests.TestCaseWithTransport):
1755
2437
 
1756
2438
    def make_repo_needing_autopacking(self, path='.'):
1772
2454
        backing = self.get_transport()
1773
2455
        request = smart_packrepo.SmartServerPackRepositoryAutopack(
1774
2456
            backing)
1775
 
        response = request.execute('')
1776
 
        self.assertEqual(smart_req.SmartServerResponse(('ok',)), response)
 
2457
        response = request.execute(b'')
 
2458
        self.assertEqual(smart_req.SmartServerResponse((b'ok',)), response)
1777
2459
        repo._pack_collection.reload_pack_names()
1778
2460
        self.assertEqual(1, len(repo._pack_collection.names()))
1779
2461
 
1787
2469
        backing = self.get_transport()
1788
2470
        request = smart_packrepo.SmartServerPackRepositoryAutopack(
1789
2471
            backing)
1790
 
        response = request.execute('')
1791
 
        self.assertEqual(smart_req.SmartServerResponse(('ok',)), response)
 
2472
        response = request.execute(b'')
 
2473
        self.assertEqual(smart_req.SmartServerResponse((b'ok',)), response)
1792
2474
        repo._pack_collection.reload_pack_names()
1793
2475
        self.assertEqual(9, len(repo._pack_collection.names()))
1794
2476
 
1798
2480
        backing = self.get_transport()
1799
2481
        request = smart_packrepo.SmartServerPackRepositoryAutopack(
1800
2482
            backing)
1801
 
        response = request.execute('')
1802
 
        self.assertEqual(smart_req.SmartServerResponse(('ok',)), response)
 
2483
        response = request.execute(b'')
 
2484
        self.assertEqual(smart_req.SmartServerResponse((b'ok',)), response)
1803
2485
 
1804
2486
 
1805
2487
class TestSmartServerVfsGet(tests.TestCaseWithMemoryTransport):
1810
2492
        filename_escaped = urlutils.escape(filename)
1811
2493
        backing = self.get_transport()
1812
2494
        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))
 
2495
        backing.put_bytes_non_atomic(filename_escaped, b'contents')
 
2496
        self.assertEqual(smart_req.SmartServerResponse((b'ok', ), b'contents'),
 
2497
                         request.execute(filename_escaped.encode('ascii')))
1816
2498
 
1817
2499
 
1818
2500
class TestHandlers(tests.TestCase):
1822
2504
        """All registered request_handlers can be found."""
1823
2505
        # If there's a typo in a register_lazy call, this loop will fail with
1824
2506
        # an AttributeError.
1825
 
        for key, item in smart_req.request_handlers.iteritems():
1826
 
            pass
 
2507
        for key in smart_req.request_handlers.keys():
 
2508
            try:
 
2509
                item = smart_req.request_handlers.get(key)
 
2510
            except AttributeError as e:
 
2511
                raise AttributeError('failed to get %s: %s' % (key, e))
1827
2512
 
1828
2513
    def assertHandlerEqual(self, verb, handler):
1829
2514
        self.assertEqual(smart_req.request_handlers.get(verb), handler)
1830
2515
 
1831
2516
    def test_registered_methods(self):
1832
2517
        """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)
 
2518
        self.assertHandlerEqual(b'Branch.break_lock',
 
2519
                                smart_branch.SmartServerBranchBreakLock)
 
2520
        self.assertHandlerEqual(b'Branch.get_config_file',
 
2521
                                smart_branch.SmartServerBranchGetConfigFile)
 
2522
        self.assertHandlerEqual(b'Branch.put_config_file',
 
2523
                                smart_branch.SmartServerBranchPutConfigFile)
 
2524
        self.assertHandlerEqual(b'Branch.get_parent',
 
2525
                                smart_branch.SmartServerBranchGetParent)
 
2526
        self.assertHandlerEqual(b'Branch.get_physical_lock_status',
 
2527
                                smart_branch.SmartServerBranchRequestGetPhysicalLockStatus)
 
2528
        self.assertHandlerEqual(b'Branch.get_tags_bytes',
 
2529
                                smart_branch.SmartServerBranchGetTagsBytes)
 
2530
        self.assertHandlerEqual(b'Branch.lock_write',
 
2531
                                smart_branch.SmartServerBranchRequestLockWrite)
 
2532
        self.assertHandlerEqual(b'Branch.last_revision_info',
 
2533
                                smart_branch.SmartServerBranchRequestLastRevisionInfo)
 
2534
        self.assertHandlerEqual(b'Branch.revision_history',
 
2535
                                smart_branch.SmartServerRequestRevisionHistory)
 
2536
        self.assertHandlerEqual(b'Branch.revision_id_to_revno',
 
2537
                                smart_branch.SmartServerBranchRequestRevisionIdToRevno)
 
2538
        self.assertHandlerEqual(b'Branch.set_config_option',
 
2539
                                smart_branch.SmartServerBranchRequestSetConfigOption)
 
2540
        self.assertHandlerEqual(b'Branch.set_last_revision',
 
2541
                                smart_branch.SmartServerBranchRequestSetLastRevision)
 
2542
        self.assertHandlerEqual(b'Branch.set_last_revision_info',
 
2543
                                smart_branch.SmartServerBranchRequestSetLastRevisionInfo)
 
2544
        self.assertHandlerEqual(b'Branch.set_last_revision_ex',
 
2545
                                smart_branch.SmartServerBranchRequestSetLastRevisionEx)
 
2546
        self.assertHandlerEqual(b'Branch.set_parent_location',
 
2547
                                smart_branch.SmartServerBranchRequestSetParentLocation)
 
2548
        self.assertHandlerEqual(b'Branch.unlock',
 
2549
                                smart_branch.SmartServerBranchRequestUnlock)
 
2550
        self.assertHandlerEqual(b'BzrDir.destroy_branch',
 
2551
                                smart_dir.SmartServerBzrDirRequestDestroyBranch)
 
2552
        self.assertHandlerEqual(b'BzrDir.find_repository',
 
2553
                                smart_dir.SmartServerRequestFindRepositoryV1)
 
2554
        self.assertHandlerEqual(b'BzrDir.find_repositoryV2',
 
2555
                                smart_dir.SmartServerRequestFindRepositoryV2)
 
2556
        self.assertHandlerEqual(b'BzrDirFormat.initialize',
 
2557
                                smart_dir.SmartServerRequestInitializeBzrDir)
 
2558
        self.assertHandlerEqual(b'BzrDirFormat.initialize_ex_1.16',
 
2559
                                smart_dir.SmartServerRequestBzrDirInitializeEx)
 
2560
        self.assertHandlerEqual(b'BzrDir.checkout_metadir',
 
2561
                                smart_dir.SmartServerBzrDirRequestCheckoutMetaDir)
 
2562
        self.assertHandlerEqual(b'BzrDir.cloning_metadir',
 
2563
                                smart_dir.SmartServerBzrDirRequestCloningMetaDir)
 
2564
        self.assertHandlerEqual(b'BzrDir.get_branches',
 
2565
                                smart_dir.SmartServerBzrDirRequestGetBranches)
 
2566
        self.assertHandlerEqual(b'BzrDir.get_config_file',
 
2567
                                smart_dir.SmartServerBzrDirRequestConfigFile)
 
2568
        self.assertHandlerEqual(b'BzrDir.open_branch',
 
2569
                                smart_dir.SmartServerRequestOpenBranch)
 
2570
        self.assertHandlerEqual(b'BzrDir.open_branchV2',
 
2571
                                smart_dir.SmartServerRequestOpenBranchV2)
 
2572
        self.assertHandlerEqual(b'BzrDir.open_branchV3',
 
2573
                                smart_dir.SmartServerRequestOpenBranchV3)
 
2574
        self.assertHandlerEqual(b'PackRepository.autopack',
 
2575
                                smart_packrepo.SmartServerPackRepositoryAutopack)
 
2576
        self.assertHandlerEqual(b'Repository.add_signature_text',
 
2577
                                smart_repo.SmartServerRepositoryAddSignatureText)
 
2578
        self.assertHandlerEqual(b'Repository.all_revision_ids',
 
2579
                                smart_repo.SmartServerRepositoryAllRevisionIds)
 
2580
        self.assertHandlerEqual(b'Repository.break_lock',
 
2581
                                smart_repo.SmartServerRepositoryBreakLock)
 
2582
        self.assertHandlerEqual(b'Repository.gather_stats',
 
2583
                                smart_repo.SmartServerRepositoryGatherStats)
 
2584
        self.assertHandlerEqual(b'Repository.get_parent_map',
 
2585
                                smart_repo.SmartServerRepositoryGetParentMap)
 
2586
        self.assertHandlerEqual(b'Repository.get_physical_lock_status',
 
2587
                                smart_repo.SmartServerRepositoryGetPhysicalLockStatus)
 
2588
        self.assertHandlerEqual(b'Repository.get_rev_id_for_revno',
 
2589
                                smart_repo.SmartServerRepositoryGetRevIdForRevno)
 
2590
        self.assertHandlerEqual(b'Repository.get_revision_graph',
 
2591
                                smart_repo.SmartServerRepositoryGetRevisionGraph)
 
2592
        self.assertHandlerEqual(b'Repository.get_revision_signature_text',
 
2593
                                smart_repo.SmartServerRepositoryGetRevisionSignatureText)
 
2594
        self.assertHandlerEqual(b'Repository.get_stream',
 
2595
                                smart_repo.SmartServerRepositoryGetStream)
 
2596
        self.assertHandlerEqual(b'Repository.get_stream_1.19',
 
2597
                                smart_repo.SmartServerRepositoryGetStream_1_19)
 
2598
        self.assertHandlerEqual(b'Repository.iter_revisions',
 
2599
                                smart_repo.SmartServerRepositoryIterRevisions)
 
2600
        self.assertHandlerEqual(b'Repository.has_revision',
 
2601
                                smart_repo.SmartServerRequestHasRevision)
 
2602
        self.assertHandlerEqual(b'Repository.insert_stream',
 
2603
                                smart_repo.SmartServerRepositoryInsertStream)
 
2604
        self.assertHandlerEqual(b'Repository.insert_stream_locked',
 
2605
                                smart_repo.SmartServerRepositoryInsertStreamLocked)
 
2606
        self.assertHandlerEqual(b'Repository.is_shared',
 
2607
                                smart_repo.SmartServerRepositoryIsShared)
 
2608
        self.assertHandlerEqual(b'Repository.iter_files_bytes',
 
2609
                                smart_repo.SmartServerRepositoryIterFilesBytes)
 
2610
        self.assertHandlerEqual(b'Repository.lock_write',
 
2611
                                smart_repo.SmartServerRepositoryLockWrite)
 
2612
        self.assertHandlerEqual(b'Repository.make_working_trees',
 
2613
                                smart_repo.SmartServerRepositoryMakeWorkingTrees)
 
2614
        self.assertHandlerEqual(b'Repository.pack',
 
2615
                                smart_repo.SmartServerRepositoryPack)
 
2616
        self.assertHandlerEqual(b'Repository.reconcile',
 
2617
                                smart_repo.SmartServerRepositoryReconcile)
 
2618
        self.assertHandlerEqual(b'Repository.tarball',
 
2619
                                smart_repo.SmartServerRepositoryTarball)
 
2620
        self.assertHandlerEqual(b'Repository.unlock',
 
2621
                                smart_repo.SmartServerRepositoryUnlock)
 
2622
        self.assertHandlerEqual(b'Repository.start_write_group',
 
2623
                                smart_repo.SmartServerRepositoryStartWriteGroup)
 
2624
        self.assertHandlerEqual(b'Repository.check_write_group',
 
2625
                                smart_repo.SmartServerRepositoryCheckWriteGroup)
 
2626
        self.assertHandlerEqual(b'Repository.commit_write_group',
 
2627
                                smart_repo.SmartServerRepositoryCommitWriteGroup)
 
2628
        self.assertHandlerEqual(b'Repository.abort_write_group',
 
2629
                                smart_repo.SmartServerRepositoryAbortWriteGroup)
 
2630
        self.assertHandlerEqual(b'VersionedFileRepository.get_serializer_format',
 
2631
                                smart_repo.SmartServerRepositoryGetSerializerFormat)
 
2632
        self.assertHandlerEqual(b'VersionedFileRepository.get_inventories',
 
2633
                                smart_repo.SmartServerRepositoryGetInventories)
 
2634
        self.assertHandlerEqual(b'Transport.is_readonly',
 
2635
                                smart_req.SmartServerIsReadonly)
 
2636
 
 
2637
 
 
2638
class SmartTCPServerHookTests(tests.TestCaseWithMemoryTransport):
 
2639
    """Tests for SmartTCPServer hooks."""
 
2640
 
 
2641
    def setUp(self):
 
2642
        super(SmartTCPServerHookTests, self).setUp()
 
2643
        self.server = server.SmartTCPServer(self.get_transport())
 
2644
 
 
2645
    def test_run_server_started_hooks(self):
 
2646
        """Test the server started hooks get fired properly."""
 
2647
        started_calls = []
 
2648
        server.SmartTCPServer.hooks.install_named_hook('server_started',
 
2649
                                                       lambda backing_urls, url: started_calls.append(
 
2650
                                                           (backing_urls, url)),
 
2651
                                                       None)
 
2652
        started_ex_calls = []
 
2653
        server.SmartTCPServer.hooks.install_named_hook('server_started_ex',
 
2654
                                                       lambda backing_urls, url: started_ex_calls.append(
 
2655
                                                           (backing_urls, url)),
 
2656
                                                       None)
 
2657
        self.server._sockname = ('example.com', 42)
 
2658
        self.server.run_server_started_hooks()
 
2659
        self.assertEqual(started_calls,
 
2660
                         [([self.get_transport().base], 'bzr://example.com:42/')])
 
2661
        self.assertEqual(started_ex_calls,
 
2662
                         [([self.get_transport().base], self.server)])
 
2663
 
 
2664
    def test_run_server_started_hooks_ipv6(self):
 
2665
        """Test that socknames can contain 4-tuples."""
 
2666
        self.server._sockname = ('::', 42, 0, 0)
 
2667
        started_calls = []
 
2668
        server.SmartTCPServer.hooks.install_named_hook('server_started',
 
2669
                                                       lambda backing_urls, url: started_calls.append(
 
2670
                                                           (backing_urls, url)),
 
2671
                                                       None)
 
2672
        self.server.run_server_started_hooks()
 
2673
        self.assertEqual(started_calls,
 
2674
                         [([self.get_transport().base], 'bzr://:::42/')])
 
2675
 
 
2676
    def test_run_server_stopped_hooks(self):
 
2677
        """Test the server stopped hooks."""
 
2678
        self.server._sockname = ('example.com', 42)
 
2679
        stopped_calls = []
 
2680
        server.SmartTCPServer.hooks.install_named_hook('server_stopped',
 
2681
                                                       lambda backing_urls, url: stopped_calls.append(
 
2682
                                                           (backing_urls, url)),
 
2683
                                                       None)
 
2684
        self.server.run_server_stopped_hooks()
 
2685
        self.assertEqual(stopped_calls,
 
2686
                         [([self.get_transport().base], 'bzr://example.com:42/')])
 
2687
 
 
2688
 
 
2689
class TestSmartServerRepositoryPack(tests.TestCaseWithMemoryTransport):
 
2690
 
 
2691
    def test_pack(self):
 
2692
        backing = self.get_transport()
 
2693
        request = smart_repo.SmartServerRepositoryPack(backing)
 
2694
        tree = self.make_branch_and_memory_tree('.')
 
2695
        repo_token = tree.branch.repository.lock_write().repository_token
 
2696
 
 
2697
        self.assertIs(None, request.execute(b'', repo_token, False))
 
2698
 
 
2699
        self.assertEqual(
 
2700
            smart_req.SuccessfulSmartServerResponse((b'ok', ), ),
 
2701
            request.do_body(b''))
 
2702
 
 
2703
 
 
2704
class TestSmartServerRepositoryGetInventories(tests.TestCaseWithTransport):
 
2705
 
 
2706
    def _get_serialized_inventory_delta(self, repository, base_revid, revid):
 
2707
        base_inv = repository.revision_tree(base_revid).root_inventory
 
2708
        inv = repository.revision_tree(revid).root_inventory
 
2709
        inv_delta = inv._make_delta(base_inv)
 
2710
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
 
2711
        return b"".join(serializer.delta_to_lines(base_revid, revid, inv_delta))
 
2712
 
 
2713
    def test_single(self):
 
2714
        backing = self.get_transport()
 
2715
        request = smart_repo.SmartServerRepositoryGetInventories(backing)
 
2716
        t = self.make_branch_and_tree('.', format='2a')
 
2717
        self.addCleanup(t.lock_write().unlock)
 
2718
        self.build_tree_contents([("file", b"somecontents")])
 
2719
        t.add(["file"], [b"thefileid"])
 
2720
        t.commit(rev_id=b'somerev', message="add file")
 
2721
        self.assertIs(None, request.execute(b'', b'unordered'))
 
2722
        response = request.do_body(b"somerev\n")
 
2723
        self.assertTrue(response.is_successful())
 
2724
        self.assertEqual(response.args, (b"ok", ))
 
2725
        stream = [('inventory-deltas', [
 
2726
            versionedfile.FulltextContentFactory(b'somerev', None, None,
 
2727
                                                 self._get_serialized_inventory_delta(
 
2728
                                                     t.branch.repository, b'null:', b'somerev'))])]
 
2729
        fmt = controldir.format_registry.get('2a')().repository_format
 
2730
        self.assertEqual(
 
2731
            b"".join(response.body_stream),
 
2732
            b"".join(smart_repo._stream_to_byte_stream(stream, fmt)))
 
2733
 
 
2734
    def test_empty(self):
 
2735
        backing = self.get_transport()
 
2736
        request = smart_repo.SmartServerRepositoryGetInventories(backing)
 
2737
        t = self.make_branch_and_tree('.', format='2a')
 
2738
        self.addCleanup(t.lock_write().unlock)
 
2739
        self.build_tree_contents([("file", b"somecontents")])
 
2740
        t.add(["file"], [b"thefileid"])
 
2741
        t.commit(rev_id=b'somerev', message="add file")
 
2742
        self.assertIs(None, request.execute(b'', b'unordered'))
 
2743
        response = request.do_body(b"")
 
2744
        self.assertTrue(response.is_successful())
 
2745
        self.assertEqual(response.args, (b"ok", ))
 
2746
        self.assertEqual(b"".join(response.body_stream),
 
2747
                         b"Bazaar pack format 1 (introduced in 0.18)\nB54\n\nBazaar repository format 2a (needs bzr 1.16 or later)\nE")
 
2748
 
 
2749
 
 
2750
class TestSmartServerRepositoryGetStreamForMissingKeys(GetStreamTestBase):
 
2751
 
 
2752
    def test_missing(self):
 
2753
        """The search argument may be a 'ancestry-of' some heads'."""
 
2754
        backing = self.get_transport()
 
2755
        request = smart_repo.SmartServerRepositoryGetStreamForMissingKeys(
 
2756
            backing)
 
2757
        repo, r1, r2 = self.make_two_commit_repo()
 
2758
        request.execute(b'', repo._format.network_name())
 
2759
        lines = b'inventories\t' + r1
 
2760
        response = request.do_body(lines)
 
2761
        self.assertEqual((b'ok',), response.args)
 
2762
        stream_bytes = b''.join(response.body_stream)
 
2763
        self.assertStartsWith(stream_bytes, b'Bazaar pack format 1')
 
2764
 
 
2765
    def test_unknown_format(self):
 
2766
        """The format may not be known by the remote server."""
 
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'', b'yada yada yada')
 
2772
        expected = smart_req.FailedSmartServerResponse(
 
2773
            (b'UnknownFormat', b'repository', b'yada yada yada'))
 
2774
 
 
2775
 
 
2776
class TestSmartServerRepositoryRevisionArchive(tests.TestCaseWithTransport):
 
2777
    def test_get(self):
 
2778
        backing = self.get_transport()
 
2779
        request = smart_repo.SmartServerRepositoryRevisionArchive(backing)
 
2780
        t = self.make_branch_and_tree('.')
 
2781
        self.addCleanup(t.lock_write().unlock)
 
2782
        self.build_tree_contents([("file", b"somecontents")])
 
2783
        t.add(["file"], [b"thefileid"])
 
2784
        t.commit(rev_id=b'somerev', message="add file")
 
2785
        response = request.execute(b'', b"somerev", b"tar", b"foo.tar", b"foo")
 
2786
        self.assertTrue(response.is_successful())
 
2787
        self.assertEqual(response.args, (b"ok", ))
 
2788
        b = BytesIO(b"".join(response.body_stream))
 
2789
        with tarfile.open(mode='r', fileobj=b) as tf:
 
2790
            self.assertEqual(['foo/file'], tf.getnames())
 
2791
 
 
2792
 
 
2793
class TestSmartServerRepositoryAnnotateFileRevision(tests.TestCaseWithTransport):
 
2794
 
 
2795
    def test_get(self):
 
2796
        backing = self.get_transport()
 
2797
        request = smart_repo.SmartServerRepositoryAnnotateFileRevision(backing)
 
2798
        t = self.make_branch_and_tree('.')
 
2799
        self.addCleanup(t.lock_write().unlock)
 
2800
        self.build_tree_contents([("file", b"somecontents\nmorecontents\n")])
 
2801
        t.add(["file"], [b"thefileid"])
 
2802
        t.commit(rev_id=b'somerev', message="add file")
 
2803
        response = request.execute(b'', b"somerev", b"file")
 
2804
        self.assertTrue(response.is_successful())
 
2805
        self.assertEqual(response.args, (b"ok", ))
 
2806
        self.assertEqual(
 
2807
            [[b'somerev', b'somecontents\n'], [b'somerev', b'morecontents\n']],
 
2808
            bencode.bdecode(response.body))