~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_smart.py

  • Committer: Patch Queue Manager
  • Date: 2016-02-01 19:56:05 UTC
  • mfrom: (6615.1.1 trunk)
  • Revision ID: pqm@pqm.ubuntu.com-20160201195605-o7rl92wf6uyum3fk
(vila) Open trunk again as 2.8b1 (Vincent Ladeuil)

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
29
 
import tarfile
 
28
import zlib
30
29
 
31
30
from bzrlib import (
32
31
    bencode,
33
32
    branch as _mod_branch,
34
 
    bzrdir,
 
33
    controldir,
35
34
    errors,
36
 
    pack,
 
35
    gpg,
 
36
    inventory_delta,
37
37
    tests,
38
38
    transport,
39
39
    urlutils,
48
48
    server,
49
49
    vfs,
50
50
    )
 
51
from bzrlib.testament import Testament
51
52
from bzrlib.tests import test_server
52
53
from bzrlib.transport import (
53
54
    chroot,
81
82
 
82
83
    def setUp(self):
83
84
        self.vfs_transport_factory = memory.MemoryServer
84
 
        tests.TestCaseWithTransport.setUp(self)
 
85
        super(TestCaseWithChrootedTransport, self).setUp()
85
86
        self._chroot_server = None
86
87
 
87
88
    def get_transport(self, relpath=None):
89
90
            backing_transport = tests.TestCaseWithTransport.get_transport(self)
90
91
            self._chroot_server = chroot.ChrootServer(backing_transport)
91
92
            self.start_server(self._chroot_server)
92
 
        t = transport.get_transport(self._chroot_server.get_url())
 
93
        t = transport.get_transport_from_url(self._chroot_server.get_url())
93
94
        if relpath is not None:
94
95
            t = t.clone(relpath)
95
96
        return t
103
104
        # the default or a parameterized class, but rather use the
104
105
        # TestCaseWithTransport infrastructure to set up a smart server and
105
106
        # transport.
106
 
        self.transport_server = self.make_transport_server
 
107
        self.overrideAttr(self, "transport_server", self.make_transport_server)
107
108
 
108
109
    def make_transport_server(self):
109
110
        return test_server.SmartTCPServer_for_testing('-' + self.id())
120
121
        stream = [('text', [versionedfile.FulltextContentFactory(('k1',), None,
121
122
            None, 'foo')]),('text', [
122
123
            versionedfile.FulltextContentFactory(('k2',), None, None, 'bar')])]
123
 
        fmt = bzrdir.format_registry.get('pack-0.92')().repository_format
 
124
        fmt = controldir.format_registry.get('pack-0.92')().repository_format
124
125
        bytes = smart_repo._stream_to_byte_stream(stream, fmt)
125
126
        streams = []
126
127
        # Iterate the resulting iterable; checking that we get only one stream
214
215
        dir = self.make_bzrdir('.')
215
216
        local_result = dir.cloning_metadir()
216
217
        reference = _mod_branch.BranchReferenceFormat().initialize(
217
 
            dir, referenced_branch)
 
218
            dir, target_branch=referenced_branch)
218
219
        reference_url = _mod_branch.BranchReferenceFormat().get_reference(dir)
219
220
        # The server shouldn't try to follow the branch reference, so it's fine
220
221
        # if the referenced branch isn't reachable.
225
226
        self.assertEqual(expected, request.execute('', 'False'))
226
227
 
227
228
 
 
229
class TestSmartServerBzrDirRequestCloningMetaDir(
 
230
    tests.TestCaseWithMemoryTransport):
 
231
    """Tests for BzrDir.checkout_metadir."""
 
232
 
 
233
    def test_checkout_metadir(self):
 
234
        backing = self.get_transport()
 
235
        request = smart_dir.SmartServerBzrDirRequestCheckoutMetaDir(
 
236
            backing)
 
237
        branch = self.make_branch('.', format='2a')
 
238
        response = request.execute('')
 
239
        self.assertEqual(
 
240
            smart_req.SmartServerResponse(
 
241
                ('Bazaar-NG meta directory, format 1\n',
 
242
                 'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
 
243
                 'Bazaar Branch Format 7 (needs bzr 1.6)\n')),
 
244
            response)
 
245
 
 
246
 
 
247
class TestSmartServerBzrDirRequestDestroyBranch(
 
248
    tests.TestCaseWithMemoryTransport):
 
249
    """Tests for BzrDir.destroy_branch."""
 
250
 
 
251
    def test_destroy_branch_default(self):
 
252
        """The default branch can be removed."""
 
253
        backing = self.get_transport()
 
254
        dir = self.make_branch('.').bzrdir
 
255
        request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
 
256
        request = request_class(backing)
 
257
        expected = smart_req.SuccessfulSmartServerResponse(('ok',))
 
258
        self.assertEqual(expected, request.execute('', None))
 
259
 
 
260
    def test_destroy_branch_named(self):
 
261
        """A named branch can be removed."""
 
262
        backing = self.get_transport()
 
263
        dir = self.make_repository('.', format="development-colo").bzrdir
 
264
        dir.create_branch(name="branchname")
 
265
        request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
 
266
        request = request_class(backing)
 
267
        expected = smart_req.SuccessfulSmartServerResponse(('ok',))
 
268
        self.assertEqual(expected, request.execute('', "branchname"))
 
269
 
 
270
    def test_destroy_branch_missing(self):
 
271
        """An error is raised if the branch didn't exist."""
 
272
        backing = self.get_transport()
 
273
        dir = self.make_bzrdir('.', format="development-colo")
 
274
        request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
 
275
        request = request_class(backing)
 
276
        expected = smart_req.FailedSmartServerResponse(('nobranch',), None)
 
277
        self.assertEqual(expected, request.execute('', "branchname"))
 
278
 
 
279
 
 
280
class TestSmartServerBzrDirRequestHasWorkingTree(
 
281
    tests.TestCaseWithTransport):
 
282
    """Tests for BzrDir.has_workingtree."""
 
283
 
 
284
    def test_has_workingtree_yes(self):
 
285
        """A working tree is present."""
 
286
        backing = self.get_transport()
 
287
        dir = self.make_branch_and_tree('.').bzrdir
 
288
        request_class = smart_dir.SmartServerBzrDirRequestHasWorkingTree
 
289
        request = request_class(backing)
 
290
        expected = smart_req.SuccessfulSmartServerResponse(('yes',))
 
291
        self.assertEqual(expected, request.execute(''))
 
292
 
 
293
    def test_has_workingtree_no(self):
 
294
        """A working tree is missing."""
 
295
        backing = self.get_transport()
 
296
        dir = self.make_bzrdir('.')
 
297
        request_class = smart_dir.SmartServerBzrDirRequestHasWorkingTree
 
298
        request = request_class(backing)
 
299
        expected = smart_req.SuccessfulSmartServerResponse(('no',))
 
300
        self.assertEqual(expected, request.execute(''))
 
301
 
 
302
 
 
303
class TestSmartServerBzrDirRequestDestroyRepository(
 
304
    tests.TestCaseWithMemoryTransport):
 
305
    """Tests for BzrDir.destroy_repository."""
 
306
 
 
307
    def test_destroy_repository_default(self):
 
308
        """The repository can be removed."""
 
309
        backing = self.get_transport()
 
310
        dir = self.make_repository('.').bzrdir
 
311
        request_class = smart_dir.SmartServerBzrDirRequestDestroyRepository
 
312
        request = request_class(backing)
 
313
        expected = smart_req.SuccessfulSmartServerResponse(('ok',))
 
314
        self.assertEqual(expected, request.execute(''))
 
315
 
 
316
    def test_destroy_repository_missing(self):
 
317
        """An error is raised if the repository didn't exist."""
 
318
        backing = self.get_transport()
 
319
        dir = self.make_bzrdir('.')
 
320
        request_class = smart_dir.SmartServerBzrDirRequestDestroyRepository
 
321
        request = request_class(backing)
 
322
        expected = smart_req.FailedSmartServerResponse(
 
323
            ('norepository',), None)
 
324
        self.assertEqual(expected, request.execute(''))
 
325
 
 
326
 
228
327
class TestSmartServerRequestCreateRepository(tests.TestCaseWithMemoryTransport):
229
328
    """Tests for BzrDir.create_repository."""
230
329
 
234
333
        self.make_bzrdir('.')
235
334
        request_class = smart_dir.SmartServerRequestCreateRepository
236
335
        request = request_class(backing)
237
 
        reference_bzrdir_format = bzrdir.format_registry.get('pack-0.92')()
 
336
        reference_bzrdir_format = controldir.format_registry.get('pack-0.92')()
238
337
        reference_format = reference_bzrdir_format.repository_format
239
338
        network_name = reference_format.network_name()
240
339
        expected = smart_req.SuccessfulSmartServerResponse(
320
419
        backing = self.get_transport()
321
420
        request = self._request_class(backing)
322
421
        result = self._make_repository_and_result(
323
 
            format='dirstate-with-subtree')
 
422
            format='development-subtree')
324
423
        # check the test will be valid
325
424
        self.assertEqual('yes', result.args[2])
326
425
        self.assertEqual('yes', result.args[3])
331
430
        backing = self.get_transport()
332
431
        request = self._request_class(backing)
333
432
        result = self._make_repository_and_result(
334
 
            format='dirstate-with-subtree')
 
433
            format='development-subtree')
335
434
        # check the test will be valid
336
 
        self.assertEqual('no', result.args[4])
 
435
        self.assertEqual('yes', result.args[4])
337
436
        self.assertEqual(result, request.execute(''))
338
437
 
339
438
 
360
459
        self.assertEqual(expected, request.execute(''))
361
460
 
362
461
 
 
462
class TestSmartServerBzrDirRequestGetBranches(
 
463
    tests.TestCaseWithMemoryTransport):
 
464
    """Tests for BzrDir.get_branches."""
 
465
 
 
466
    def test_simple(self):
 
467
        backing = self.get_transport()
 
468
        branch = self.make_branch('.')
 
469
        request_class = smart_dir.SmartServerBzrDirRequestGetBranches
 
470
        request = request_class(backing)
 
471
        local_result = bencode.bencode(
 
472
            {"": ("branch", branch._format.network_name())})
 
473
        expected = smart_req.SuccessfulSmartServerResponse(
 
474
            ("success", ), local_result)
 
475
        self.assertEqual(expected, request.execute(''))
 
476
 
 
477
    def test_empty(self):
 
478
        backing = self.get_transport()
 
479
        dir = self.make_bzrdir('.')
 
480
        request_class = smart_dir.SmartServerBzrDirRequestGetBranches
 
481
        request = request_class(backing)
 
482
        local_result = bencode.bencode({})
 
483
        expected = smart_req.SuccessfulSmartServerResponse(
 
484
            ('success',), local_result)
 
485
        self.assertEqual(expected, request.execute(''))
 
486
 
 
487
 
363
488
class TestSmartServerRequestInitializeBzrDir(tests.TestCaseWithMemoryTransport):
364
489
 
365
490
    def test_empty_dir(self):
368
493
        request = smart_dir.SmartServerRequestInitializeBzrDir(backing)
369
494
        self.assertEqual(smart_req.SmartServerResponse(('ok', )),
370
495
            request.execute(''))
371
 
        made_dir = bzrdir.BzrDir.open_from_transport(backing)
 
496
        made_dir = controldir.ControlDir.open_from_transport(backing)
372
497
        # no branch, tree or repository is expected with the current
373
498
        # default formart.
374
499
        self.assertRaises(errors.NoWorkingTree, made_dir.open_workingtree)
387
512
        backing = self.get_transport()
388
513
        request = smart_dir.SmartServerRequestInitializeBzrDir(backing)
389
514
        self.make_bzrdir('subdir')
390
 
        self.assertRaises(errors.FileExists,
 
515
        self.assertRaises(errors.AlreadyControlDirError,
391
516
            request.execute, 'subdir')
392
517
 
393
518
 
408
533
                                           'False', '', '', '')),
409
534
            request.execute(name, '', 'True', 'False', 'False', '', '', '', '',
410
535
                            'False'))
411
 
        made_dir = bzrdir.BzrDir.open_from_transport(backing)
 
536
        made_dir = controldir.ControlDir.open_from_transport(backing)
412
537
        # no branch, tree or repository is expected with the current
413
538
        # default format.
414
539
        self.assertRaises(errors.NoWorkingTree, made_dir.open_workingtree)
739
864
            request.execute(''))
740
865
 
741
866
 
 
867
class TestSmartServerBranchRequestRevisionIdToRevno(
 
868
    tests.TestCaseWithMemoryTransport):
 
869
 
 
870
    def test_null(self):
 
871
        backing = self.get_transport()
 
872
        request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
 
873
            backing)
 
874
        self.make_branch('.')
 
875
        self.assertEqual(smart_req.SmartServerResponse(('ok', '0')),
 
876
            request.execute('', 'null:'))
 
877
 
 
878
    def test_simple(self):
 
879
        backing = self.get_transport()
 
880
        request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
 
881
            backing)
 
882
        tree = self.make_branch_and_memory_tree('.')
 
883
        tree.lock_write()
 
884
        tree.add('')
 
885
        r1 = tree.commit('1st commit')
 
886
        tree.unlock()
 
887
        self.assertEqual(
 
888
            smart_req.SmartServerResponse(('ok', '1')),
 
889
            request.execute('', r1))
 
890
 
 
891
    def test_not_found(self):
 
892
        backing = self.get_transport()
 
893
        request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
 
894
            backing)
 
895
        branch = self.make_branch('.')
 
896
        self.assertEqual(
 
897
            smart_req.FailedSmartServerResponse(
 
898
                ('NoSuchRevision', 'idontexist')),
 
899
            request.execute('', 'idontexist'))
 
900
 
 
901
 
742
902
class TestSmartServerBranchRequestGetConfigFile(
743
903
    tests.TestCaseWithMemoryTransport):
744
904
 
767
927
class TestLockedBranch(tests.TestCaseWithMemoryTransport):
768
928
 
769
929
    def get_lock_tokens(self, branch):
770
 
        branch_token = branch.lock_write()
771
 
        repo_token = branch.repository.lock_write()
 
930
        branch_token = branch.lock_write().branch_token
 
931
        repo_token = branch.repository.lock_write().repository_token
772
932
        branch.repository.unlock()
773
933
        return branch_token, repo_token
774
934
 
775
935
 
 
936
class TestSmartServerBranchRequestPutConfigFile(TestLockedBranch):
 
937
 
 
938
    def test_with_content(self):
 
939
        backing = self.get_transport()
 
940
        request = smart_branch.SmartServerBranchPutConfigFile(backing)
 
941
        branch = self.make_branch('.')
 
942
        branch_token, repo_token = self.get_lock_tokens(branch)
 
943
        self.assertIs(None, request.execute('', branch_token, repo_token))
 
944
        self.assertEqual(
 
945
            smart_req.SmartServerResponse(('ok', )),
 
946
            request.do_body('foo bar baz'))
 
947
        self.assertEqual(
 
948
            branch.control_transport.get_bytes('branch.conf'),
 
949
            'foo bar baz')
 
950
        branch.unlock()
 
951
 
 
952
 
776
953
class TestSmartServerBranchRequestSetConfigOption(TestLockedBranch):
777
954
 
778
955
    def test_value_name(self):
802
979
        branch.unlock()
803
980
 
804
981
 
 
982
class TestSmartServerBranchRequestSetConfigOptionDict(TestLockedBranch):
 
983
 
 
984
    def setUp(self):
 
985
        TestLockedBranch.setUp(self)
 
986
        # A dict with non-ascii keys and values to exercise unicode
 
987
        # roundtripping.
 
988
        self.encoded_value_dict = (
 
989
            'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde')
 
990
        self.value_dict = {
 
991
            'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
 
992
 
 
993
    def test_value_name(self):
 
994
        branch = self.make_branch('.')
 
995
        request = smart_branch.SmartServerBranchRequestSetConfigOptionDict(
 
996
            branch.bzrdir.root_transport)
 
997
        branch_token, repo_token = self.get_lock_tokens(branch)
 
998
        config = branch._get_config()
 
999
        result = request.execute('', branch_token, repo_token,
 
1000
            self.encoded_value_dict, 'foo', '')
 
1001
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
 
1002
        self.assertEqual(self.value_dict, config.get_option('foo'))
 
1003
        # Cleanup
 
1004
        branch.unlock()
 
1005
 
 
1006
    def test_value_name_section(self):
 
1007
        branch = self.make_branch('.')
 
1008
        request = smart_branch.SmartServerBranchRequestSetConfigOptionDict(
 
1009
            branch.bzrdir.root_transport)
 
1010
        branch_token, repo_token = self.get_lock_tokens(branch)
 
1011
        config = branch._get_config()
 
1012
        result = request.execute('', branch_token, repo_token,
 
1013
            self.encoded_value_dict, 'foo', 'gam')
 
1014
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
 
1015
        self.assertEqual(self.value_dict, config.get_option('foo', 'gam'))
 
1016
        # Cleanup
 
1017
        branch.unlock()
 
1018
 
 
1019
 
805
1020
class TestSmartServerBranchRequestSetTagsBytes(TestLockedBranch):
806
1021
    # Only called when the branch format and tags match [yay factory
807
1022
    # methods] so only need to test straight forward cases.
818
1033
        response = request.do_chunk(tag_bytes)
819
1034
        self.assertEqual(None, response)
820
1035
        response = request.do_end()
821
 
        self.assertEquals(
 
1036
        self.assertEqual(
822
1037
            smart_req.SuccessfulSmartServerResponse(()), response)
823
1038
        base_branch.unlock()
824
1039
 
843
1058
    """Base test case for verbs that implement set_last_revision."""
844
1059
 
845
1060
    def setUp(self):
846
 
        tests.TestCaseWithMemoryTransport.setUp(self)
 
1061
        super(SetLastRevisionTestBase, self).setUp()
847
1062
        backing_transport = self.get_transport()
848
1063
        self.request = self.request_class(backing_transport)
849
1064
        self.tree = self.make_branch_and_memory_tree('.')
898
1113
        # its repository.
899
1114
        self.make_tree_with_two_commits()
900
1115
        rev_id_utf8 = u'\xc8'.encode('utf-8')
901
 
        self.tree.branch.set_revision_history([])
 
1116
        self.tree.branch.set_last_revision_info(0, 'null:')
902
1117
        self.assertEqual(
903
1118
            (0, 'null:'), self.tree.branch.last_revision_info())
904
1119
        # We can update the branch to a revision that is present in the
1054
1269
        self.assertEqual('child-1', self.tree.branch.last_revision())
1055
1270
 
1056
1271
 
 
1272
class TestSmartServerBranchBreakLock(tests.TestCaseWithMemoryTransport):
 
1273
 
 
1274
    def test_lock_to_break(self):
 
1275
        base_branch = self.make_branch('base')
 
1276
        request = smart_branch.SmartServerBranchBreakLock(
 
1277
            self.get_transport())
 
1278
        base_branch.lock_write()
 
1279
        self.assertEqual(
 
1280
            smart_req.SuccessfulSmartServerResponse(('ok', ), None),
 
1281
            request.execute('base'))
 
1282
 
 
1283
    def test_nothing_to_break(self):
 
1284
        base_branch = self.make_branch('base')
 
1285
        request = smart_branch.SmartServerBranchBreakLock(
 
1286
            self.get_transport())
 
1287
        self.assertEqual(
 
1288
            smart_req.SuccessfulSmartServerResponse(('ok', ), None),
 
1289
            request.execute('base'))
 
1290
 
 
1291
 
1057
1292
class TestSmartServerBranchRequestGetParent(tests.TestCaseWithMemoryTransport):
1058
1293
 
1059
1294
    def test_get_parent_none(self):
1060
1295
        base_branch = self.make_branch('base')
1061
1296
        request = smart_branch.SmartServerBranchGetParent(self.get_transport())
1062
1297
        response = request.execute('base')
1063
 
        self.assertEquals(
 
1298
        self.assertEqual(
1064
1299
            smart_req.SuccessfulSmartServerResponse(('',)), response)
1065
1300
 
1066
1301
    def test_get_parent_something(self):
1068
1303
        base_branch.set_parent(self.get_url('foo'))
1069
1304
        request = smart_branch.SmartServerBranchGetParent(self.get_transport())
1070
1305
        response = request.execute('base')
1071
 
        self.assertEquals(
 
1306
        self.assertEqual(
1072
1307
            smart_req.SuccessfulSmartServerResponse(("../foo",)),
1073
1308
            response)
1074
1309
 
1075
1310
 
1076
 
class TestSmartServerBranchRequestSetParent(tests.TestCaseWithMemoryTransport):
 
1311
class TestSmartServerBranchRequestSetParent(TestLockedBranch):
1077
1312
 
1078
1313
    def test_set_parent_none(self):
1079
1314
        branch = self.make_branch('base', format="1.9")
1082
1317
        branch.unlock()
1083
1318
        request = smart_branch.SmartServerBranchRequestSetParentLocation(
1084
1319
            self.get_transport())
1085
 
        branch_token = branch.lock_write()
1086
 
        repo_token = branch.repository.lock_write()
 
1320
        branch_token, repo_token = self.get_lock_tokens(branch)
1087
1321
        try:
1088
1322
            response = request.execute('base', branch_token, repo_token, '')
1089
1323
        finally:
1090
 
            branch.repository.unlock()
1091
1324
            branch.unlock()
1092
1325
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
 
1326
        # Refresh branch as SetParentLocation modified it
 
1327
        branch = branch.bzrdir.open_branch()
1093
1328
        self.assertEqual(None, branch.get_parent())
1094
1329
 
1095
1330
    def test_set_parent_something(self):
1096
1331
        branch = self.make_branch('base', format="1.9")
1097
1332
        request = smart_branch.SmartServerBranchRequestSetParentLocation(
1098
1333
            self.get_transport())
1099
 
        branch_token = branch.lock_write()
1100
 
        repo_token = branch.repository.lock_write()
 
1334
        branch_token, repo_token = self.get_lock_tokens(branch)
1101
1335
        try:
1102
1336
            response = request.execute('base', branch_token, repo_token,
1103
 
            'http://bar/')
 
1337
                                       'http://bar/')
1104
1338
        finally:
1105
 
            branch.repository.unlock()
1106
1339
            branch.unlock()
1107
1340
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
1108
 
        self.assertEqual('http://bar/', branch.get_parent())
 
1341
        refreshed = _mod_branch.Branch.open(branch.base)
 
1342
        self.assertEqual('http://bar/', refreshed.get_parent())
1109
1343
 
1110
1344
 
1111
1345
class TestSmartServerBranchRequestGetTagsBytes(
1118
1352
        request = smart_branch.SmartServerBranchGetTagsBytes(
1119
1353
            self.get_transport())
1120
1354
        response = request.execute('base')
1121
 
        self.assertEquals(
 
1355
        self.assertEqual(
1122
1356
            smart_req.SuccessfulSmartServerResponse(('',)), response)
1123
1357
 
1124
1358
 
1132
1366
        request = smart_branch.SmartServerBranchRequestGetStackedOnURL(
1133
1367
            self.get_transport())
1134
1368
        response = request.execute('stacked')
1135
 
        self.assertEquals(
 
1369
        self.assertEqual(
1136
1370
            smart_req.SmartServerResponse(('ok', '../base')),
1137
1371
            response)
1138
1372
 
1139
1373
 
1140
 
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithMemoryTransport):
1141
 
 
1142
 
    def setUp(self):
1143
 
        tests.TestCaseWithMemoryTransport.setUp(self)
 
1374
class TestSmartServerBranchRequestLockWrite(TestLockedBranch):
1144
1375
 
1145
1376
    def test_lock_write_on_unlocked_branch(self):
1146
1377
        backing = self.get_transport()
1165
1396
        backing = self.get_transport()
1166
1397
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1167
1398
        branch = self.make_branch('.')
1168
 
        branch_token = branch.lock_write()
 
1399
        branch_token = branch.lock_write().branch_token
1169
1400
        branch.leave_lock_in_place()
1170
1401
        branch.unlock()
1171
1402
        response = request.execute('')
1180
1411
        backing = self.get_transport()
1181
1412
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1182
1413
        branch = self.make_branch('.', format='knit')
1183
 
        branch_token = branch.lock_write()
1184
 
        repo_token = branch.repository.lock_write()
1185
 
        branch.repository.unlock()
 
1414
        branch_token, repo_token = self.get_lock_tokens(branch)
1186
1415
        branch.leave_lock_in_place()
1187
1416
        branch.repository.leave_lock_in_place()
1188
1417
        branch.unlock()
1203
1432
        backing = self.get_transport()
1204
1433
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1205
1434
        branch = self.make_branch('.', format='knit')
1206
 
        branch_token = branch.lock_write()
1207
 
        repo_token = branch.repository.lock_write()
1208
 
        branch.repository.unlock()
 
1435
        branch_token, repo_token = self.get_lock_tokens(branch)
1209
1436
        branch.leave_lock_in_place()
1210
1437
        branch.repository.leave_lock_in_place()
1211
1438
        branch.unlock()
1226
1453
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1227
1454
        branch = self.make_branch('.', format='knit')
1228
1455
        repo = branch.repository
1229
 
        repo_token = repo.lock_write()
 
1456
        repo_token = repo.lock_write().repository_token
1230
1457
        repo.leave_lock_in_place()
1231
1458
        repo.unlock()
1232
1459
        response = request.execute('')
1249
1476
        self.assertEqual('LockFailed', error_name)
1250
1477
 
1251
1478
 
1252
 
class TestSmartServerBranchRequestUnlock(tests.TestCaseWithMemoryTransport):
1253
 
 
1254
 
    def setUp(self):
1255
 
        tests.TestCaseWithMemoryTransport.setUp(self)
 
1479
class TestSmartServerBranchRequestGetPhysicalLockStatus(TestLockedBranch):
 
1480
 
 
1481
    def test_true(self):
 
1482
        backing = self.get_transport()
 
1483
        request = smart_branch.SmartServerBranchRequestGetPhysicalLockStatus(
 
1484
            backing)
 
1485
        branch = self.make_branch('.')
 
1486
        branch_token, repo_token = self.get_lock_tokens(branch)
 
1487
        self.assertEqual(True, branch.get_physical_lock_status())
 
1488
        response = request.execute('')
 
1489
        self.assertEqual(
 
1490
            smart_req.SmartServerResponse(('yes',)), response)
 
1491
        branch.unlock()
 
1492
 
 
1493
    def test_false(self):
 
1494
        backing = self.get_transport()
 
1495
        request = smart_branch.SmartServerBranchRequestGetPhysicalLockStatus(
 
1496
            backing)
 
1497
        branch = self.make_branch('.')
 
1498
        self.assertEqual(False, branch.get_physical_lock_status())
 
1499
        response = request.execute('')
 
1500
        self.assertEqual(
 
1501
            smart_req.SmartServerResponse(('no',)), response)
 
1502
 
 
1503
 
 
1504
class TestSmartServerBranchRequestUnlock(TestLockedBranch):
1256
1505
 
1257
1506
    def test_unlock_on_locked_branch_and_repo(self):
1258
1507
        backing = self.get_transport()
1259
1508
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1260
1509
        branch = self.make_branch('.', format='knit')
1261
1510
        # Lock the branch
1262
 
        branch_token = branch.lock_write()
1263
 
        repo_token = branch.repository.lock_write()
1264
 
        branch.repository.unlock()
 
1511
        branch_token, repo_token = self.get_lock_tokens(branch)
1265
1512
        # Unlock the branch (and repo) object, leaving the physical locks
1266
1513
        # in place.
1267
1514
        branch.leave_lock_in_place()
1291
1538
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1292
1539
        branch = self.make_branch('.', format='knit')
1293
1540
        # Lock the repository.
1294
 
        repo_token = branch.repository.lock_write()
 
1541
        repo_token = branch.repository.lock_write().repository_token
1295
1542
        branch.repository.leave_lock_in_place()
1296
1543
        branch.repository.unlock()
1297
1544
        # Issue branch lock_write request on the unlocked branch (with locked
1298
1545
        # repo).
1299
 
        response = request.execute(
1300
 
            '', 'branch token', repo_token)
 
1546
        response = request.execute('', 'branch token', repo_token)
1301
1547
        self.assertEqual(
1302
1548
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
1303
1549
        # Cleanup
1322
1568
            request.execute, 'subdir')
1323
1569
 
1324
1570
 
 
1571
class TestSmartServerRepositoryAddSignatureText(tests.TestCaseWithMemoryTransport):
 
1572
 
 
1573
    def test_add_text(self):
 
1574
        backing = self.get_transport()
 
1575
        request = smart_repo.SmartServerRepositoryAddSignatureText(backing)
 
1576
        tree = self.make_branch_and_memory_tree('.')
 
1577
        write_token = tree.lock_write()
 
1578
        self.addCleanup(tree.unlock)
 
1579
        tree.add('')
 
1580
        tree.commit("Message", rev_id='rev1')
 
1581
        tree.branch.repository.start_write_group()
 
1582
        write_group_tokens = tree.branch.repository.suspend_write_group()
 
1583
        self.assertEqual(None, request.execute('', write_token,
 
1584
            'rev1', *write_group_tokens))
 
1585
        response = request.do_body('somesignature')
 
1586
        self.assertTrue(response.is_successful())
 
1587
        self.assertEqual(response.args[0], 'ok')
 
1588
        write_group_tokens = response.args[1:]
 
1589
        tree.branch.repository.resume_write_group(write_group_tokens)
 
1590
        tree.branch.repository.commit_write_group()
 
1591
        tree.unlock()
 
1592
        self.assertEqual("somesignature",
 
1593
            tree.branch.repository.get_signature_text("rev1"))
 
1594
 
 
1595
 
 
1596
class TestSmartServerRepositoryAllRevisionIds(
 
1597
    tests.TestCaseWithMemoryTransport):
 
1598
 
 
1599
    def test_empty(self):
 
1600
        """An empty body should be returned for an empty repository."""
 
1601
        backing = self.get_transport()
 
1602
        request = smart_repo.SmartServerRepositoryAllRevisionIds(backing)
 
1603
        self.make_repository('.')
 
1604
        self.assertEqual(
 
1605
            smart_req.SuccessfulSmartServerResponse(("ok", ), ""),
 
1606
            request.execute(''))
 
1607
 
 
1608
    def test_some_revisions(self):
 
1609
        """An empty body should be returned for an empty repository."""
 
1610
        backing = self.get_transport()
 
1611
        request = smart_repo.SmartServerRepositoryAllRevisionIds(backing)
 
1612
        tree = self.make_branch_and_memory_tree('.')
 
1613
        tree.lock_write()
 
1614
        tree.add('')
 
1615
        tree.commit(rev_id='origineel', message="message")
 
1616
        tree.commit(rev_id='nog-een-revisie', message="message")
 
1617
        tree.unlock()
 
1618
        self.assertEqual(
 
1619
            smart_req.SuccessfulSmartServerResponse(("ok", ),
 
1620
                "origineel\nnog-een-revisie"),
 
1621
            request.execute(''))
 
1622
 
 
1623
 
 
1624
class TestSmartServerRepositoryBreakLock(tests.TestCaseWithMemoryTransport):
 
1625
 
 
1626
    def test_lock_to_break(self):
 
1627
        backing = self.get_transport()
 
1628
        request = smart_repo.SmartServerRepositoryBreakLock(backing)
 
1629
        tree = self.make_branch_and_memory_tree('.')
 
1630
        tree.branch.repository.lock_write()
 
1631
        self.assertEqual(
 
1632
            smart_req.SuccessfulSmartServerResponse(('ok', ), None),
 
1633
            request.execute(''))
 
1634
 
 
1635
    def test_nothing_to_break(self):
 
1636
        backing = self.get_transport()
 
1637
        request = smart_repo.SmartServerRepositoryBreakLock(backing)
 
1638
        tree = self.make_branch_and_memory_tree('.')
 
1639
        self.assertEqual(
 
1640
            smart_req.SuccessfulSmartServerResponse(('ok', ), None),
 
1641
            request.execute(''))
 
1642
 
 
1643
 
1325
1644
class TestSmartServerRepositoryGetParentMap(tests.TestCaseWithMemoryTransport):
1326
1645
 
1327
1646
    def test_trivial_bzipped(self):
1447
1766
            request.execute('stacked', 1, (3, r3)))
1448
1767
 
1449
1768
 
1450
 
class TestSmartServerRepositoryGetStream(tests.TestCaseWithMemoryTransport):
 
1769
class TestSmartServerRepositoryIterRevisions(
 
1770
    tests.TestCaseWithMemoryTransport):
 
1771
 
 
1772
    def test_basic(self):
 
1773
        backing = self.get_transport()
 
1774
        request = smart_repo.SmartServerRepositoryIterRevisions(backing)
 
1775
        tree = self.make_branch_and_memory_tree('.', format='2a')
 
1776
        tree.lock_write()
 
1777
        tree.add('')
 
1778
        tree.commit('1st commit', rev_id="rev1")
 
1779
        tree.commit('2nd commit', rev_id="rev2")
 
1780
        tree.unlock()
 
1781
 
 
1782
        self.assertIs(None, request.execute(''))
 
1783
        response = request.do_body("rev1\nrev2")
 
1784
        self.assertTrue(response.is_successful())
 
1785
        # Format 2a uses serializer format 10
 
1786
        self.assertEqual(response.args, ("ok", "10"))
 
1787
 
 
1788
        self.addCleanup(tree.branch.lock_read().unlock)
 
1789
        entries = [zlib.compress(record.get_bytes_as("fulltext")) for record in
 
1790
            tree.branch.repository.revisions.get_record_stream(
 
1791
            [("rev1", ), ("rev2", )], "unordered", True)]
 
1792
 
 
1793
        contents = "".join(response.body_stream)
 
1794
        self.assertTrue(contents in (
 
1795
            "".join([entries[0], entries[1]]),
 
1796
            "".join([entries[1], entries[0]])))
 
1797
 
 
1798
    def test_missing(self):
 
1799
        backing = self.get_transport()
 
1800
        request = smart_repo.SmartServerRepositoryIterRevisions(backing)
 
1801
        tree = self.make_branch_and_memory_tree('.', format='2a')
 
1802
 
 
1803
        self.assertIs(None, request.execute(''))
 
1804
        response = request.do_body("rev1\nrev2")
 
1805
        self.assertTrue(response.is_successful())
 
1806
        # Format 2a uses serializer format 10
 
1807
        self.assertEqual(response.args, ("ok", "10"))
 
1808
 
 
1809
        contents = "".join(response.body_stream)
 
1810
        self.assertEqual(contents, "")
 
1811
 
 
1812
 
 
1813
class GetStreamTestBase(tests.TestCaseWithMemoryTransport):
1451
1814
 
1452
1815
    def make_two_commit_repo(self):
1453
1816
        tree = self.make_branch_and_memory_tree('.')
1459
1822
        repo = tree.branch.repository
1460
1823
        return repo, r1, r2
1461
1824
 
 
1825
 
 
1826
class TestSmartServerRepositoryGetStream(GetStreamTestBase):
 
1827
 
1462
1828
    def test_ancestry_of(self):
1463
1829
        """The search argument may be a 'ancestry-of' some heads'."""
1464
1830
        backing = self.get_transport()
1485
1851
        stream_bytes = ''.join(response.body_stream)
1486
1852
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
1487
1853
 
 
1854
    def test_search_everything(self):
 
1855
        """A search of 'everything' returns a stream."""
 
1856
        backing = self.get_transport()
 
1857
        request = smart_repo.SmartServerRepositoryGetStream_1_19(backing)
 
1858
        repo, r1, r2 = self.make_two_commit_repo()
 
1859
        serialised_fetch_spec = 'everything'
 
1860
        request.execute('', repo._format.network_name())
 
1861
        response = request.do_body(serialised_fetch_spec)
 
1862
        self.assertEqual(('ok',), response.args)
 
1863
        stream_bytes = ''.join(response.body_stream)
 
1864
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
 
1865
 
1488
1866
 
1489
1867
class TestSmartServerRequestHasRevision(tests.TestCaseWithMemoryTransport):
1490
1868
 
1511
1889
            request.execute('', rev_id_utf8))
1512
1890
 
1513
1891
 
 
1892
class TestSmartServerRepositoryIterFilesBytes(tests.TestCaseWithTransport):
 
1893
 
 
1894
    def test_single(self):
 
1895
        backing = self.get_transport()
 
1896
        request = smart_repo.SmartServerRepositoryIterFilesBytes(backing)
 
1897
        t = self.make_branch_and_tree('.')
 
1898
        self.addCleanup(t.lock_write().unlock)
 
1899
        self.build_tree_contents([("file", "somecontents")])
 
1900
        t.add(["file"], ["thefileid"])
 
1901
        t.commit(rev_id='somerev', message="add file")
 
1902
        self.assertIs(None, request.execute(''))
 
1903
        response = request.do_body("thefileid\0somerev\n")
 
1904
        self.assertTrue(response.is_successful())
 
1905
        self.assertEqual(response.args, ("ok", ))
 
1906
        self.assertEqual("".join(response.body_stream),
 
1907
            "ok\x000\n" + zlib.compress("somecontents"))
 
1908
 
 
1909
    def test_missing(self):
 
1910
        backing = self.get_transport()
 
1911
        request = smart_repo.SmartServerRepositoryIterFilesBytes(backing)
 
1912
        t = self.make_branch_and_tree('.')
 
1913
        self.addCleanup(t.lock_write().unlock)
 
1914
        self.assertIs(None, request.execute(''))
 
1915
        response = request.do_body("thefileid\0revision\n")
 
1916
        self.assertTrue(response.is_successful())
 
1917
        self.assertEqual(response.args, ("ok", ))
 
1918
        self.assertEqual("".join(response.body_stream),
 
1919
            "absent\x00thefileid\x00revision\x000\n")
 
1920
 
 
1921
 
 
1922
class TestSmartServerRequestHasSignatureForRevisionId(
 
1923
        tests.TestCaseWithMemoryTransport):
 
1924
 
 
1925
    def test_missing_revision(self):
 
1926
        """For a missing revision, NoSuchRevision is returned."""
 
1927
        backing = self.get_transport()
 
1928
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1929
            backing)
 
1930
        self.make_repository('.')
 
1931
        self.assertEqual(
 
1932
            smart_req.FailedSmartServerResponse(
 
1933
                ('nosuchrevision', 'revid'), None),
 
1934
            request.execute('', 'revid'))
 
1935
 
 
1936
    def test_missing_signature(self):
 
1937
        """For a missing signature, ('no', ) is returned."""
 
1938
        backing = self.get_transport()
 
1939
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1940
            backing)
 
1941
        tree = self.make_branch_and_memory_tree('.')
 
1942
        tree.lock_write()
 
1943
        tree.add('')
 
1944
        r1 = tree.commit('a commit', rev_id='A')
 
1945
        tree.unlock()
 
1946
        self.assertTrue(tree.branch.repository.has_revision('A'))
 
1947
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
 
1948
            request.execute('', 'A'))
 
1949
 
 
1950
    def test_present_signature(self):
 
1951
        """For a present signature, ('yes', ) is returned."""
 
1952
        backing = self.get_transport()
 
1953
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1954
            backing)
 
1955
        strategy = gpg.LoopbackGPGStrategy(None)
 
1956
        tree = self.make_branch_and_memory_tree('.')
 
1957
        tree.lock_write()
 
1958
        tree.add('')
 
1959
        r1 = tree.commit('a commit', rev_id='A')
 
1960
        tree.branch.repository.start_write_group()
 
1961
        tree.branch.repository.sign_revision('A', strategy)
 
1962
        tree.branch.repository.commit_write_group()
 
1963
        tree.unlock()
 
1964
        self.assertTrue(tree.branch.repository.has_revision('A'))
 
1965
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
 
1966
            request.execute('', 'A'))
 
1967
 
 
1968
 
1514
1969
class TestSmartServerRepositoryGatherStats(tests.TestCaseWithMemoryTransport):
1515
1970
 
1516
1971
    def test_empty_revid(self):
1569
2024
                         request.execute('',
1570
2025
                                         rev_id_utf8, 'yes'))
1571
2026
 
 
2027
    def test_unknown_revid(self):
 
2028
        """An unknown revision id causes a 'nosuchrevision' error."""
 
2029
        backing = self.get_transport()
 
2030
        request = smart_repo.SmartServerRepositoryGatherStats(backing)
 
2031
        repository = self.make_repository('.')
 
2032
        expected_body = 'revisions: 0\n'
 
2033
        self.assertEqual(
 
2034
            smart_req.FailedSmartServerResponse(
 
2035
                ('nosuchrevision', 'mia'), None),
 
2036
            request.execute('', 'mia', 'yes'))
 
2037
 
1572
2038
 
1573
2039
class TestSmartServerRepositoryIsShared(tests.TestCaseWithMemoryTransport):
1574
2040
 
1589
2055
            request.execute('', ))
1590
2056
 
1591
2057
 
 
2058
class TestSmartServerRepositoryGetRevisionSignatureText(
 
2059
        tests.TestCaseWithMemoryTransport):
 
2060
 
 
2061
    def test_get_signature(self):
 
2062
        backing = self.get_transport()
 
2063
        request = smart_repo.SmartServerRepositoryGetRevisionSignatureText(
 
2064
            backing)
 
2065
        bb = self.make_branch_builder('.')
 
2066
        bb.build_commit(rev_id='A')
 
2067
        repo = bb.get_branch().repository
 
2068
        strategy = gpg.LoopbackGPGStrategy(None)
 
2069
        self.addCleanup(repo.lock_write().unlock)
 
2070
        repo.start_write_group()
 
2071
        repo.sign_revision('A', strategy)
 
2072
        repo.commit_write_group()
 
2073
        expected_body = (
 
2074
            '-----BEGIN PSEUDO-SIGNED CONTENT-----\n' +
 
2075
            Testament.from_revision(repo, 'A').as_short_text() +
 
2076
            '-----END PSEUDO-SIGNED CONTENT-----\n')
 
2077
        self.assertEqual(
 
2078
            smart_req.SmartServerResponse(('ok', ), expected_body),
 
2079
            request.execute('', 'A'))
 
2080
 
 
2081
 
 
2082
class TestSmartServerRepositoryMakeWorkingTrees(
 
2083
        tests.TestCaseWithMemoryTransport):
 
2084
 
 
2085
    def test_make_working_trees(self):
 
2086
        """For a repository with working trees, ('yes', ) is returned."""
 
2087
        backing = self.get_transport()
 
2088
        request = smart_repo.SmartServerRepositoryMakeWorkingTrees(backing)
 
2089
        r = self.make_repository('.')
 
2090
        r.set_make_working_trees(True)
 
2091
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
 
2092
            request.execute('', ))
 
2093
 
 
2094
    def test_is_not_shared(self):
 
2095
        """For a repository with working trees, ('no', ) is returned."""
 
2096
        backing = self.get_transport()
 
2097
        request = smart_repo.SmartServerRepositoryMakeWorkingTrees(backing)
 
2098
        r = self.make_repository('.')
 
2099
        r.set_make_working_trees(False)
 
2100
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
 
2101
            request.execute('', ))
 
2102
 
 
2103
 
1592
2104
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
1593
2105
 
1594
2106
    def test_lock_write_on_unlocked_repo(self):
1610
2122
        backing = self.get_transport()
1611
2123
        request = smart_repo.SmartServerRepositoryLockWrite(backing)
1612
2124
        repository = self.make_repository('.', format='knit')
1613
 
        repo_token = repository.lock_write()
 
2125
        repo_token = repository.lock_write().repository_token
1614
2126
        repository.leave_lock_in_place()
1615
2127
        repository.unlock()
1616
2128
        response = request.execute('')
1658
2170
        request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1659
2171
            backing)
1660
2172
        repository = self.make_repository('.', format='knit')
1661
 
        lock_token = repository.lock_write()
 
2173
        lock_token = repository.lock_write().repository_token
1662
2174
        response = request.execute('', '', lock_token)
1663
2175
        self.assertEqual(None, response)
1664
2176
        response = request.do_chunk(self.make_empty_byte_stream(repository))
1672
2184
        request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1673
2185
            backing)
1674
2186
        repository = self.make_repository('.', format='knit')
1675
 
        lock_token = repository.lock_write()
 
2187
        lock_token = repository.lock_write().repository_token
1676
2188
        self.assertRaises(
1677
2189
            errors.TokenMismatch, request.execute, '', '', 'wrong-token')
1678
2190
        repository.unlock()
1680
2192
 
1681
2193
class TestSmartServerRepositoryUnlock(tests.TestCaseWithMemoryTransport):
1682
2194
 
1683
 
    def setUp(self):
1684
 
        tests.TestCaseWithMemoryTransport.setUp(self)
1685
 
 
1686
2195
    def test_unlock_on_locked_repo(self):
1687
2196
        backing = self.get_transport()
1688
2197
        request = smart_repo.SmartServerRepositoryUnlock(backing)
1689
2198
        repository = self.make_repository('.', format='knit')
1690
 
        token = repository.lock_write()
 
2199
        token = repository.lock_write().repository_token
1691
2200
        repository.leave_lock_in_place()
1692
2201
        repository.unlock()
1693
2202
        response = request.execute('', token)
1708
2217
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
1709
2218
 
1710
2219
 
 
2220
class TestSmartServerRepositoryGetPhysicalLockStatus(
 
2221
    tests.TestCaseWithTransport):
 
2222
 
 
2223
    def test_with_write_lock(self):
 
2224
        backing = self.get_transport()
 
2225
        repo = self.make_repository('.')
 
2226
        self.addCleanup(repo.lock_write().unlock)
 
2227
        # lock_write() doesn't necessarily actually take a physical
 
2228
        # lock out.
 
2229
        if repo.get_physical_lock_status():
 
2230
            expected = 'yes'
 
2231
        else:
 
2232
            expected = 'no'
 
2233
        request_class = smart_repo.SmartServerRepositoryGetPhysicalLockStatus
 
2234
        request = request_class(backing)
 
2235
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((expected,)),
 
2236
            request.execute('', ))
 
2237
 
 
2238
    def test_without_write_lock(self):
 
2239
        backing = self.get_transport()
 
2240
        repo = self.make_repository('.')
 
2241
        self.assertEqual(False, repo.get_physical_lock_status())
 
2242
        request_class = smart_repo.SmartServerRepositoryGetPhysicalLockStatus
 
2243
        request = request_class(backing)
 
2244
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('no',)),
 
2245
            request.execute('', ))
 
2246
 
 
2247
 
 
2248
class TestSmartServerRepositoryReconcile(tests.TestCaseWithTransport):
 
2249
 
 
2250
    def test_reconcile(self):
 
2251
        backing = self.get_transport()
 
2252
        repo = self.make_repository('.')
 
2253
        token = repo.lock_write().repository_token
 
2254
        self.addCleanup(repo.unlock)
 
2255
        request_class = smart_repo.SmartServerRepositoryReconcile
 
2256
        request = request_class(backing)
 
2257
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(
 
2258
            ('ok', ),
 
2259
             'garbage_inventories: 0\n'
 
2260
             'inconsistent_parents: 0\n'),
 
2261
            request.execute('', token))
 
2262
 
 
2263
 
1711
2264
class TestSmartServerIsReadonly(tests.TestCaseWithMemoryTransport):
1712
2265
 
1713
2266
    def test_is_readonly_no(self):
1751
2304
        self.assertTrue(repo.make_working_trees())
1752
2305
 
1753
2306
 
 
2307
class TestSmartServerRepositoryGetSerializerFormat(
 
2308
    tests.TestCaseWithMemoryTransport):
 
2309
 
 
2310
    def test_get_serializer_format(self):
 
2311
        backing = self.get_transport()
 
2312
        repo = self.make_repository('.', format='2a')
 
2313
        request_class = smart_repo.SmartServerRepositoryGetSerializerFormat
 
2314
        request = request_class(backing)
 
2315
        self.assertEqual(
 
2316
            smart_req.SuccessfulSmartServerResponse(('ok', '10')),
 
2317
            request.execute(''))
 
2318
 
 
2319
 
 
2320
class TestSmartServerRepositoryWriteGroup(
 
2321
    tests.TestCaseWithMemoryTransport):
 
2322
 
 
2323
    def test_start_write_group(self):
 
2324
        backing = self.get_transport()
 
2325
        repo = self.make_repository('.')
 
2326
        lock_token = repo.lock_write().repository_token
 
2327
        self.addCleanup(repo.unlock)
 
2328
        request_class = smart_repo.SmartServerRepositoryStartWriteGroup
 
2329
        request = request_class(backing)
 
2330
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok', [])),
 
2331
            request.execute('', lock_token))
 
2332
 
 
2333
    def test_start_write_group_unsuspendable(self):
 
2334
        backing = self.get_transport()
 
2335
        repo = self.make_repository('.', format='knit')
 
2336
        lock_token = repo.lock_write().repository_token
 
2337
        self.addCleanup(repo.unlock)
 
2338
        request_class = smart_repo.SmartServerRepositoryStartWriteGroup
 
2339
        request = request_class(backing)
 
2340
        self.assertEqual(
 
2341
            smart_req.FailedSmartServerResponse(('UnsuspendableWriteGroup',)),
 
2342
            request.execute('', lock_token))
 
2343
 
 
2344
    def test_commit_write_group(self):
 
2345
        backing = self.get_transport()
 
2346
        repo = self.make_repository('.')
 
2347
        lock_token = repo.lock_write().repository_token
 
2348
        self.addCleanup(repo.unlock)
 
2349
        repo.start_write_group()
 
2350
        tokens = repo.suspend_write_group()
 
2351
        request_class = smart_repo.SmartServerRepositoryCommitWriteGroup
 
2352
        request = request_class(backing)
 
2353
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
 
2354
            request.execute('', lock_token, tokens))
 
2355
 
 
2356
    def test_abort_write_group(self):
 
2357
        backing = self.get_transport()
 
2358
        repo = self.make_repository('.')
 
2359
        lock_token = repo.lock_write().repository_token
 
2360
        repo.start_write_group()
 
2361
        tokens = repo.suspend_write_group()
 
2362
        self.addCleanup(repo.unlock)
 
2363
        request_class = smart_repo.SmartServerRepositoryAbortWriteGroup
 
2364
        request = request_class(backing)
 
2365
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
 
2366
            request.execute('', lock_token, tokens))
 
2367
 
 
2368
    def test_check_write_group(self):
 
2369
        backing = self.get_transport()
 
2370
        repo = self.make_repository('.')
 
2371
        lock_token = repo.lock_write().repository_token
 
2372
        repo.start_write_group()
 
2373
        tokens = repo.suspend_write_group()
 
2374
        self.addCleanup(repo.unlock)
 
2375
        request_class = smart_repo.SmartServerRepositoryCheckWriteGroup
 
2376
        request = request_class(backing)
 
2377
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
 
2378
            request.execute('', lock_token, tokens))
 
2379
 
 
2380
    def test_check_write_group_invalid(self):
 
2381
        backing = self.get_transport()
 
2382
        repo = self.make_repository('.')
 
2383
        lock_token = repo.lock_write().repository_token
 
2384
        self.addCleanup(repo.unlock)
 
2385
        request_class = smart_repo.SmartServerRepositoryCheckWriteGroup
 
2386
        request = request_class(backing)
 
2387
        self.assertEqual(smart_req.FailedSmartServerResponse(
 
2388
            ('UnresumableWriteGroup', ['random'],
 
2389
                'Malformed write group token')),
 
2390
            request.execute('', lock_token, ["random"]))
 
2391
 
 
2392
 
1754
2393
class TestSmartServerPackRepositoryAutopack(tests.TestCaseWithTransport):
1755
2394
 
1756
2395
    def make_repo_needing_autopacking(self, path='.'):
1822
2461
        """All registered request_handlers can be found."""
1823
2462
        # If there's a typo in a register_lazy call, this loop will fail with
1824
2463
        # an AttributeError.
1825
 
        for key, item in smart_req.request_handlers.iteritems():
1826
 
            pass
 
2464
        for key in smart_req.request_handlers.keys():
 
2465
            try:
 
2466
                item = smart_req.request_handlers.get(key)
 
2467
            except AttributeError, e:
 
2468
                raise AttributeError('failed to get %s: %s' % (key, e))
1827
2469
 
1828
2470
    def assertHandlerEqual(self, verb, handler):
1829
2471
        self.assertEqual(smart_req.request_handlers.get(verb), handler)
1830
2472
 
1831
2473
    def test_registered_methods(self):
1832
2474
        """Test that known methods are registered to the correct object."""
 
2475
        self.assertHandlerEqual('Branch.break_lock',
 
2476
            smart_branch.SmartServerBranchBreakLock)
1833
2477
        self.assertHandlerEqual('Branch.get_config_file',
1834
2478
            smart_branch.SmartServerBranchGetConfigFile)
 
2479
        self.assertHandlerEqual('Branch.put_config_file',
 
2480
            smart_branch.SmartServerBranchPutConfigFile)
1835
2481
        self.assertHandlerEqual('Branch.get_parent',
1836
2482
            smart_branch.SmartServerBranchGetParent)
 
2483
        self.assertHandlerEqual('Branch.get_physical_lock_status',
 
2484
            smart_branch.SmartServerBranchRequestGetPhysicalLockStatus)
1837
2485
        self.assertHandlerEqual('Branch.get_tags_bytes',
1838
2486
            smart_branch.SmartServerBranchGetTagsBytes)
1839
2487
        self.assertHandlerEqual('Branch.lock_write',
1842
2490
            smart_branch.SmartServerBranchRequestLastRevisionInfo)
1843
2491
        self.assertHandlerEqual('Branch.revision_history',
1844
2492
            smart_branch.SmartServerRequestRevisionHistory)
 
2493
        self.assertHandlerEqual('Branch.revision_id_to_revno',
 
2494
            smart_branch.SmartServerBranchRequestRevisionIdToRevno)
1845
2495
        self.assertHandlerEqual('Branch.set_config_option',
1846
2496
            smart_branch.SmartServerBranchRequestSetConfigOption)
1847
2497
        self.assertHandlerEqual('Branch.set_last_revision',
1854
2504
            smart_branch.SmartServerBranchRequestSetParentLocation)
1855
2505
        self.assertHandlerEqual('Branch.unlock',
1856
2506
            smart_branch.SmartServerBranchRequestUnlock)
 
2507
        self.assertHandlerEqual('BzrDir.destroy_branch',
 
2508
            smart_dir.SmartServerBzrDirRequestDestroyBranch)
1857
2509
        self.assertHandlerEqual('BzrDir.find_repository',
1858
2510
            smart_dir.SmartServerRequestFindRepositoryV1)
1859
2511
        self.assertHandlerEqual('BzrDir.find_repositoryV2',
1862
2514
            smart_dir.SmartServerRequestInitializeBzrDir)
1863
2515
        self.assertHandlerEqual('BzrDirFormat.initialize_ex_1.16',
1864
2516
            smart_dir.SmartServerRequestBzrDirInitializeEx)
 
2517
        self.assertHandlerEqual('BzrDir.checkout_metadir',
 
2518
            smart_dir.SmartServerBzrDirRequestCheckoutMetaDir)
1865
2519
        self.assertHandlerEqual('BzrDir.cloning_metadir',
1866
2520
            smart_dir.SmartServerBzrDirRequestCloningMetaDir)
 
2521
        self.assertHandlerEqual('BzrDir.get_branches',
 
2522
            smart_dir.SmartServerBzrDirRequestGetBranches)
1867
2523
        self.assertHandlerEqual('BzrDir.get_config_file',
1868
2524
            smart_dir.SmartServerBzrDirRequestConfigFile)
1869
2525
        self.assertHandlerEqual('BzrDir.open_branch',
1874
2530
            smart_dir.SmartServerRequestOpenBranchV3)
1875
2531
        self.assertHandlerEqual('PackRepository.autopack',
1876
2532
            smart_packrepo.SmartServerPackRepositoryAutopack)
 
2533
        self.assertHandlerEqual('Repository.add_signature_text',
 
2534
            smart_repo.SmartServerRepositoryAddSignatureText)
 
2535
        self.assertHandlerEqual('Repository.all_revision_ids',
 
2536
            smart_repo.SmartServerRepositoryAllRevisionIds)
 
2537
        self.assertHandlerEqual('Repository.break_lock',
 
2538
            smart_repo.SmartServerRepositoryBreakLock)
1877
2539
        self.assertHandlerEqual('Repository.gather_stats',
1878
2540
            smart_repo.SmartServerRepositoryGatherStats)
1879
2541
        self.assertHandlerEqual('Repository.get_parent_map',
1880
2542
            smart_repo.SmartServerRepositoryGetParentMap)
 
2543
        self.assertHandlerEqual('Repository.get_physical_lock_status',
 
2544
            smart_repo.SmartServerRepositoryGetPhysicalLockStatus)
1881
2545
        self.assertHandlerEqual('Repository.get_rev_id_for_revno',
1882
2546
            smart_repo.SmartServerRepositoryGetRevIdForRevno)
1883
2547
        self.assertHandlerEqual('Repository.get_revision_graph',
1884
2548
            smart_repo.SmartServerRepositoryGetRevisionGraph)
 
2549
        self.assertHandlerEqual('Repository.get_revision_signature_text',
 
2550
            smart_repo.SmartServerRepositoryGetRevisionSignatureText)
1885
2551
        self.assertHandlerEqual('Repository.get_stream',
1886
2552
            smart_repo.SmartServerRepositoryGetStream)
 
2553
        self.assertHandlerEqual('Repository.get_stream_1.19',
 
2554
            smart_repo.SmartServerRepositoryGetStream_1_19)
 
2555
        self.assertHandlerEqual('Repository.iter_revisions',
 
2556
            smart_repo.SmartServerRepositoryIterRevisions)
1887
2557
        self.assertHandlerEqual('Repository.has_revision',
1888
2558
            smart_repo.SmartServerRequestHasRevision)
1889
2559
        self.assertHandlerEqual('Repository.insert_stream',
1892
2562
            smart_repo.SmartServerRepositoryInsertStreamLocked)
1893
2563
        self.assertHandlerEqual('Repository.is_shared',
1894
2564
            smart_repo.SmartServerRepositoryIsShared)
 
2565
        self.assertHandlerEqual('Repository.iter_files_bytes',
 
2566
            smart_repo.SmartServerRepositoryIterFilesBytes)
1895
2567
        self.assertHandlerEqual('Repository.lock_write',
1896
2568
            smart_repo.SmartServerRepositoryLockWrite)
 
2569
        self.assertHandlerEqual('Repository.make_working_trees',
 
2570
            smart_repo.SmartServerRepositoryMakeWorkingTrees)
 
2571
        self.assertHandlerEqual('Repository.pack',
 
2572
            smart_repo.SmartServerRepositoryPack)
 
2573
        self.assertHandlerEqual('Repository.reconcile',
 
2574
            smart_repo.SmartServerRepositoryReconcile)
1897
2575
        self.assertHandlerEqual('Repository.tarball',
1898
2576
            smart_repo.SmartServerRepositoryTarball)
1899
2577
        self.assertHandlerEqual('Repository.unlock',
1900
2578
            smart_repo.SmartServerRepositoryUnlock)
 
2579
        self.assertHandlerEqual('Repository.start_write_group',
 
2580
            smart_repo.SmartServerRepositoryStartWriteGroup)
 
2581
        self.assertHandlerEqual('Repository.check_write_group',
 
2582
            smart_repo.SmartServerRepositoryCheckWriteGroup)
 
2583
        self.assertHandlerEqual('Repository.commit_write_group',
 
2584
            smart_repo.SmartServerRepositoryCommitWriteGroup)
 
2585
        self.assertHandlerEqual('Repository.abort_write_group',
 
2586
            smart_repo.SmartServerRepositoryAbortWriteGroup)
 
2587
        self.assertHandlerEqual('VersionedFileRepository.get_serializer_format',
 
2588
            smart_repo.SmartServerRepositoryGetSerializerFormat)
 
2589
        self.assertHandlerEqual('VersionedFileRepository.get_inventories',
 
2590
            smart_repo.SmartServerRepositoryGetInventories)
1901
2591
        self.assertHandlerEqual('Transport.is_readonly',
1902
2592
            smart_req.SmartServerIsReadonly)
 
2593
 
 
2594
 
 
2595
class SmartTCPServerHookTests(tests.TestCaseWithMemoryTransport):
 
2596
    """Tests for SmartTCPServer hooks."""
 
2597
 
 
2598
    def setUp(self):
 
2599
        super(SmartTCPServerHookTests, self).setUp()
 
2600
        self.server = server.SmartTCPServer(self.get_transport())
 
2601
 
 
2602
    def test_run_server_started_hooks(self):
 
2603
        """Test the server started hooks get fired properly."""
 
2604
        started_calls = []
 
2605
        server.SmartTCPServer.hooks.install_named_hook('server_started',
 
2606
            lambda backing_urls, url: started_calls.append((backing_urls, url)),
 
2607
            None)
 
2608
        started_ex_calls = []
 
2609
        server.SmartTCPServer.hooks.install_named_hook('server_started_ex',
 
2610
            lambda backing_urls, url: started_ex_calls.append((backing_urls, url)),
 
2611
            None)
 
2612
        self.server._sockname = ('example.com', 42)
 
2613
        self.server.run_server_started_hooks()
 
2614
        self.assertEqual(started_calls,
 
2615
            [([self.get_transport().base], 'bzr://example.com:42/')])
 
2616
        self.assertEqual(started_ex_calls,
 
2617
            [([self.get_transport().base], self.server)])
 
2618
 
 
2619
    def test_run_server_started_hooks_ipv6(self):
 
2620
        """Test that socknames can contain 4-tuples."""
 
2621
        self.server._sockname = ('::', 42, 0, 0)
 
2622
        started_calls = []
 
2623
        server.SmartTCPServer.hooks.install_named_hook('server_started',
 
2624
            lambda backing_urls, url: started_calls.append((backing_urls, url)),
 
2625
            None)
 
2626
        self.server.run_server_started_hooks()
 
2627
        self.assertEqual(started_calls,
 
2628
                [([self.get_transport().base], 'bzr://:::42/')])
 
2629
 
 
2630
    def test_run_server_stopped_hooks(self):
 
2631
        """Test the server stopped hooks."""
 
2632
        self.server._sockname = ('example.com', 42)
 
2633
        stopped_calls = []
 
2634
        server.SmartTCPServer.hooks.install_named_hook('server_stopped',
 
2635
            lambda backing_urls, url: stopped_calls.append((backing_urls, url)),
 
2636
            None)
 
2637
        self.server.run_server_stopped_hooks()
 
2638
        self.assertEqual(stopped_calls,
 
2639
            [([self.get_transport().base], 'bzr://example.com:42/')])
 
2640
 
 
2641
 
 
2642
class TestSmartServerRepositoryPack(tests.TestCaseWithMemoryTransport):
 
2643
 
 
2644
    def test_pack(self):
 
2645
        backing = self.get_transport()
 
2646
        request = smart_repo.SmartServerRepositoryPack(backing)
 
2647
        tree = self.make_branch_and_memory_tree('.')
 
2648
        repo_token = tree.branch.repository.lock_write().repository_token
 
2649
 
 
2650
        self.assertIs(None, request.execute('', repo_token, False))
 
2651
 
 
2652
        self.assertEqual(
 
2653
            smart_req.SuccessfulSmartServerResponse(('ok', ), ),
 
2654
            request.do_body(''))
 
2655
 
 
2656
 
 
2657
class TestSmartServerRepositoryGetInventories(tests.TestCaseWithTransport):
 
2658
 
 
2659
    def _get_serialized_inventory_delta(self, repository, base_revid, revid):
 
2660
        base_inv = repository.revision_tree(base_revid).root_inventory
 
2661
        inv = repository.revision_tree(revid).root_inventory
 
2662
        inv_delta = inv._make_delta(base_inv)
 
2663
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
 
2664
        return "".join(serializer.delta_to_lines(base_revid, revid, inv_delta))
 
2665
 
 
2666
    def test_single(self):
 
2667
        backing = self.get_transport()
 
2668
        request = smart_repo.SmartServerRepositoryGetInventories(backing)
 
2669
        t = self.make_branch_and_tree('.', format='2a')
 
2670
        self.addCleanup(t.lock_write().unlock)
 
2671
        self.build_tree_contents([("file", "somecontents")])
 
2672
        t.add(["file"], ["thefileid"])
 
2673
        t.commit(rev_id='somerev', message="add file")
 
2674
        self.assertIs(None, request.execute('', 'unordered'))
 
2675
        response = request.do_body("somerev\n")
 
2676
        self.assertTrue(response.is_successful())
 
2677
        self.assertEqual(response.args, ("ok", ))
 
2678
        stream = [('inventory-deltas', [
 
2679
            versionedfile.FulltextContentFactory('somerev', None, None,
 
2680
                self._get_serialized_inventory_delta(
 
2681
                    t.branch.repository, 'null:', 'somerev'))])]
 
2682
        fmt = controldir.format_registry.get('2a')().repository_format
 
2683
        self.assertEqual(
 
2684
            "".join(response.body_stream),
 
2685
            "".join(smart_repo._stream_to_byte_stream(stream, fmt)))
 
2686
 
 
2687
    def test_empty(self):
 
2688
        backing = self.get_transport()
 
2689
        request = smart_repo.SmartServerRepositoryGetInventories(backing)
 
2690
        t = self.make_branch_and_tree('.', format='2a')
 
2691
        self.addCleanup(t.lock_write().unlock)
 
2692
        self.build_tree_contents([("file", "somecontents")])
 
2693
        t.add(["file"], ["thefileid"])
 
2694
        t.commit(rev_id='somerev', message="add file")
 
2695
        self.assertIs(None, request.execute('', 'unordered'))
 
2696
        response = request.do_body("")
 
2697
        self.assertTrue(response.is_successful())
 
2698
        self.assertEqual(response.args, ("ok", ))
 
2699
        self.assertEqual("".join(response.body_stream),
 
2700
            "Bazaar pack format 1 (introduced in 0.18)\nB54\n\nBazaar repository format 2a (needs bzr 1.16 or later)\nE")