/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to breezy/tests/test_smart.py

  • Committer: Jelmer Vernooij
  • Date: 2020-04-05 19:11:34 UTC
  • mto: (7490.7.16 work)
  • mto: This revision was merged to the branch mainline in revision 7501.
  • Revision ID: jelmer@jelmer.uk-20200405191134-0aebh8ikiwygxma5
Populate the .gitignore file.

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