~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_smart.py

  • Committer: Jelmer Vernooij
  • Date: 2012-03-15 02:42:48 UTC
  • mto: This revision was merged to the branch mainline in revision 6510.
  • Revision ID: jelmer@samba.org-20120315024248-7nyk2zxc52i1u8gj
extention -> extension.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006-2012 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,
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.assertEquals(
 
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.
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):
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(
1137
1371
            response)
1138
1372
 
1139
1373
 
1140
 
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithMemoryTransport):
 
1374
class TestSmartServerBranchRequestLockWrite(TestLockedBranch):
1141
1375
 
1142
1376
    def setUp(self):
1143
1377
        tests.TestCaseWithMemoryTransport.setUp(self)
1165
1399
        backing = self.get_transport()
1166
1400
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1167
1401
        branch = self.make_branch('.')
1168
 
        branch_token = branch.lock_write()
 
1402
        branch_token = branch.lock_write().branch_token
1169
1403
        branch.leave_lock_in_place()
1170
1404
        branch.unlock()
1171
1405
        response = request.execute('')
1180
1414
        backing = self.get_transport()
1181
1415
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1182
1416
        branch = self.make_branch('.', format='knit')
1183
 
        branch_token = branch.lock_write()
1184
 
        repo_token = branch.repository.lock_write()
1185
 
        branch.repository.unlock()
 
1417
        branch_token, repo_token = self.get_lock_tokens(branch)
1186
1418
        branch.leave_lock_in_place()
1187
1419
        branch.repository.leave_lock_in_place()
1188
1420
        branch.unlock()
1203
1435
        backing = self.get_transport()
1204
1436
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1205
1437
        branch = self.make_branch('.', format='knit')
1206
 
        branch_token = branch.lock_write()
1207
 
        repo_token = branch.repository.lock_write()
1208
 
        branch.repository.unlock()
 
1438
        branch_token, repo_token = self.get_lock_tokens(branch)
1209
1439
        branch.leave_lock_in_place()
1210
1440
        branch.repository.leave_lock_in_place()
1211
1441
        branch.unlock()
1226
1456
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1227
1457
        branch = self.make_branch('.', format='knit')
1228
1458
        repo = branch.repository
1229
 
        repo_token = repo.lock_write()
 
1459
        repo_token = repo.lock_write().repository_token
1230
1460
        repo.leave_lock_in_place()
1231
1461
        repo.unlock()
1232
1462
        response = request.execute('')
1249
1479
        self.assertEqual('LockFailed', error_name)
1250
1480
 
1251
1481
 
1252
 
class TestSmartServerBranchRequestUnlock(tests.TestCaseWithMemoryTransport):
 
1482
class TestSmartServerBranchRequestGetPhysicalLockStatus(TestLockedBranch):
 
1483
 
 
1484
    def setUp(self):
 
1485
        tests.TestCaseWithMemoryTransport.setUp(self)
 
1486
 
 
1487
    def test_true(self):
 
1488
        backing = self.get_transport()
 
1489
        request = smart_branch.SmartServerBranchRequestGetPhysicalLockStatus(
 
1490
            backing)
 
1491
        branch = self.make_branch('.')
 
1492
        branch_token, repo_token = self.get_lock_tokens(branch)
 
1493
        self.assertEquals(True, branch.get_physical_lock_status())
 
1494
        response = request.execute('')
 
1495
        self.assertEqual(
 
1496
            smart_req.SmartServerResponse(('yes',)), response)
 
1497
        branch.unlock()
 
1498
 
 
1499
    def test_false(self):
 
1500
        backing = self.get_transport()
 
1501
        request = smart_branch.SmartServerBranchRequestGetPhysicalLockStatus(
 
1502
            backing)
 
1503
        branch = self.make_branch('.')
 
1504
        self.assertEquals(False, branch.get_physical_lock_status())
 
1505
        response = request.execute('')
 
1506
        self.assertEqual(
 
1507
            smart_req.SmartServerResponse(('no',)), response)
 
1508
 
 
1509
 
 
1510
class TestSmartServerBranchRequestUnlock(TestLockedBranch):
1253
1511
 
1254
1512
    def setUp(self):
1255
1513
        tests.TestCaseWithMemoryTransport.setUp(self)
1259
1517
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1260
1518
        branch = self.make_branch('.', format='knit')
1261
1519
        # Lock the branch
1262
 
        branch_token = branch.lock_write()
1263
 
        repo_token = branch.repository.lock_write()
1264
 
        branch.repository.unlock()
 
1520
        branch_token, repo_token = self.get_lock_tokens(branch)
1265
1521
        # Unlock the branch (and repo) object, leaving the physical locks
1266
1522
        # in place.
1267
1523
        branch.leave_lock_in_place()
1291
1547
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1292
1548
        branch = self.make_branch('.', format='knit')
1293
1549
        # Lock the repository.
1294
 
        repo_token = branch.repository.lock_write()
 
1550
        repo_token = branch.repository.lock_write().repository_token
1295
1551
        branch.repository.leave_lock_in_place()
1296
1552
        branch.repository.unlock()
1297
1553
        # Issue branch lock_write request on the unlocked branch (with locked
1298
1554
        # repo).
1299
 
        response = request.execute(
1300
 
            '', 'branch token', repo_token)
 
1555
        response = request.execute('', 'branch token', repo_token)
1301
1556
        self.assertEqual(
1302
1557
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
1303
1558
        # Cleanup
1322
1577
            request.execute, 'subdir')
1323
1578
 
1324
1579
 
 
1580
class TestSmartServerRepositoryAddSignatureText(tests.TestCaseWithMemoryTransport):
 
1581
 
 
1582
    def test_add_text(self):
 
1583
        backing = self.get_transport()
 
1584
        request = smart_repo.SmartServerRepositoryAddSignatureText(backing)
 
1585
        tree = self.make_branch_and_memory_tree('.')
 
1586
        write_token = tree.lock_write()
 
1587
        self.addCleanup(tree.unlock)
 
1588
        tree.add('')
 
1589
        tree.commit("Message", rev_id='rev1')
 
1590
        tree.branch.repository.start_write_group()
 
1591
        write_group_tokens = tree.branch.repository.suspend_write_group()
 
1592
        self.assertEqual(None, request.execute('', write_token,
 
1593
            'rev1', *write_group_tokens))
 
1594
        response = request.do_body('somesignature')
 
1595
        self.assertTrue(response.is_successful())
 
1596
        self.assertEqual(response.args[0], 'ok')
 
1597
        write_group_tokens = response.args[1:]
 
1598
        tree.branch.repository.resume_write_group(write_group_tokens)
 
1599
        tree.branch.repository.commit_write_group()
 
1600
        tree.unlock()
 
1601
        self.assertEqual("somesignature",
 
1602
            tree.branch.repository.get_signature_text("rev1"))
 
1603
 
 
1604
 
 
1605
class TestSmartServerRepositoryAllRevisionIds(
 
1606
    tests.TestCaseWithMemoryTransport):
 
1607
 
 
1608
    def test_empty(self):
 
1609
        """An empty body should be returned for an empty repository."""
 
1610
        backing = self.get_transport()
 
1611
        request = smart_repo.SmartServerRepositoryAllRevisionIds(backing)
 
1612
        self.make_repository('.')
 
1613
        self.assertEquals(
 
1614
            smart_req.SuccessfulSmartServerResponse(("ok", ), ""),
 
1615
            request.execute(''))
 
1616
 
 
1617
    def test_some_revisions(self):
 
1618
        """An empty body should be returned for an empty repository."""
 
1619
        backing = self.get_transport()
 
1620
        request = smart_repo.SmartServerRepositoryAllRevisionIds(backing)
 
1621
        tree = self.make_branch_and_memory_tree('.')
 
1622
        tree.lock_write()
 
1623
        tree.add('')
 
1624
        tree.commit(rev_id='origineel', message="message")
 
1625
        tree.commit(rev_id='nog-een-revisie', message="message")
 
1626
        tree.unlock()
 
1627
        self.assertEquals(
 
1628
            smart_req.SuccessfulSmartServerResponse(("ok", ),
 
1629
                "origineel\nnog-een-revisie"),
 
1630
            request.execute(''))
 
1631
 
 
1632
 
 
1633
class TestSmartServerRepositoryBreakLock(tests.TestCaseWithMemoryTransport):
 
1634
 
 
1635
    def test_lock_to_break(self):
 
1636
        backing = self.get_transport()
 
1637
        request = smart_repo.SmartServerRepositoryBreakLock(backing)
 
1638
        tree = self.make_branch_and_memory_tree('.')
 
1639
        tree.branch.repository.lock_write()
 
1640
        self.assertEqual(
 
1641
            smart_req.SuccessfulSmartServerResponse(('ok', ), None),
 
1642
            request.execute(''))
 
1643
 
 
1644
    def test_nothing_to_break(self):
 
1645
        backing = self.get_transport()
 
1646
        request = smart_repo.SmartServerRepositoryBreakLock(backing)
 
1647
        tree = self.make_branch_and_memory_tree('.')
 
1648
        self.assertEqual(
 
1649
            smart_req.SuccessfulSmartServerResponse(('ok', ), None),
 
1650
            request.execute(''))
 
1651
 
 
1652
 
1325
1653
class TestSmartServerRepositoryGetParentMap(tests.TestCaseWithMemoryTransport):
1326
1654
 
1327
1655
    def test_trivial_bzipped(self):
1447
1775
            request.execute('stacked', 1, (3, r3)))
1448
1776
 
1449
1777
 
1450
 
class TestSmartServerRepositoryGetStream(tests.TestCaseWithMemoryTransport):
 
1778
class TestSmartServerRepositoryIterRevisions(
 
1779
    tests.TestCaseWithMemoryTransport):
 
1780
 
 
1781
    def test_basic(self):
 
1782
        backing = self.get_transport()
 
1783
        request = smart_repo.SmartServerRepositoryIterRevisions(backing)
 
1784
        tree = self.make_branch_and_memory_tree('.', format='2a')
 
1785
        tree.lock_write()
 
1786
        tree.add('')
 
1787
        tree.commit('1st commit', rev_id="rev1")
 
1788
        tree.commit('2nd commit', rev_id="rev2")
 
1789
        tree.unlock()
 
1790
 
 
1791
        self.assertIs(None, request.execute(''))
 
1792
        response = request.do_body("rev1\nrev2")
 
1793
        self.assertTrue(response.is_successful())
 
1794
        # Format 2a uses serializer format 10
 
1795
        self.assertEquals(response.args, ("ok", "10"))
 
1796
 
 
1797
        self.addCleanup(tree.branch.lock_read().unlock)
 
1798
        entries = [zlib.compress(record.get_bytes_as("fulltext")) for record in
 
1799
            tree.branch.repository.revisions.get_record_stream(
 
1800
            [("rev1", ), ("rev2", )], "unordered", True)]
 
1801
 
 
1802
        contents = "".join(response.body_stream)
 
1803
        self.assertTrue(contents in (
 
1804
            "".join([entries[0], entries[1]]),
 
1805
            "".join([entries[1], entries[0]])))
 
1806
 
 
1807
    def test_missing(self):
 
1808
        backing = self.get_transport()
 
1809
        request = smart_repo.SmartServerRepositoryIterRevisions(backing)
 
1810
        tree = self.make_branch_and_memory_tree('.', format='2a')
 
1811
 
 
1812
        self.assertIs(None, request.execute(''))
 
1813
        response = request.do_body("rev1\nrev2")
 
1814
        self.assertTrue(response.is_successful())
 
1815
        # Format 2a uses serializer format 10
 
1816
        self.assertEquals(response.args, ("ok", "10"))
 
1817
 
 
1818
        contents = "".join(response.body_stream)
 
1819
        self.assertEquals(contents, "")
 
1820
 
 
1821
 
 
1822
class GetStreamTestBase(tests.TestCaseWithMemoryTransport):
1451
1823
 
1452
1824
    def make_two_commit_repo(self):
1453
1825
        tree = self.make_branch_and_memory_tree('.')
1459
1831
        repo = tree.branch.repository
1460
1832
        return repo, r1, r2
1461
1833
 
 
1834
 
 
1835
class TestSmartServerRepositoryGetStream(GetStreamTestBase):
 
1836
 
1462
1837
    def test_ancestry_of(self):
1463
1838
        """The search argument may be a 'ancestry-of' some heads'."""
1464
1839
        backing = self.get_transport()
1485
1860
        stream_bytes = ''.join(response.body_stream)
1486
1861
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
1487
1862
 
 
1863
    def test_search_everything(self):
 
1864
        """A search of 'everything' returns a stream."""
 
1865
        backing = self.get_transport()
 
1866
        request = smart_repo.SmartServerRepositoryGetStream_1_19(backing)
 
1867
        repo, r1, r2 = self.make_two_commit_repo()
 
1868
        serialised_fetch_spec = 'everything'
 
1869
        request.execute('', repo._format.network_name())
 
1870
        response = request.do_body(serialised_fetch_spec)
 
1871
        self.assertEqual(('ok',), response.args)
 
1872
        stream_bytes = ''.join(response.body_stream)
 
1873
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
 
1874
 
1488
1875
 
1489
1876
class TestSmartServerRequestHasRevision(tests.TestCaseWithMemoryTransport):
1490
1877
 
1511
1898
            request.execute('', rev_id_utf8))
1512
1899
 
1513
1900
 
 
1901
class TestSmartServerRepositoryIterFilesBytes(tests.TestCaseWithTransport):
 
1902
 
 
1903
    def test_single(self):
 
1904
        backing = self.get_transport()
 
1905
        request = smart_repo.SmartServerRepositoryIterFilesBytes(backing)
 
1906
        t = self.make_branch_and_tree('.')
 
1907
        self.addCleanup(t.lock_write().unlock)
 
1908
        self.build_tree_contents([("file", "somecontents")])
 
1909
        t.add(["file"], ["thefileid"])
 
1910
        t.commit(rev_id='somerev', message="add file")
 
1911
        self.assertIs(None, request.execute(''))
 
1912
        response = request.do_body("thefileid\0somerev\n")
 
1913
        self.assertTrue(response.is_successful())
 
1914
        self.assertEquals(response.args, ("ok", ))
 
1915
        self.assertEquals("".join(response.body_stream),
 
1916
            "ok\x000\n" + zlib.compress("somecontents"))
 
1917
 
 
1918
    def test_missing(self):
 
1919
        backing = self.get_transport()
 
1920
        request = smart_repo.SmartServerRepositoryIterFilesBytes(backing)
 
1921
        t = self.make_branch_and_tree('.')
 
1922
        self.addCleanup(t.lock_write().unlock)
 
1923
        self.assertIs(None, request.execute(''))
 
1924
        response = request.do_body("thefileid\0revision\n")
 
1925
        self.assertTrue(response.is_successful())
 
1926
        self.assertEquals(response.args, ("ok", ))
 
1927
        self.assertEquals("".join(response.body_stream),
 
1928
            "absent\x00thefileid\x00revision\x000\n")
 
1929
 
 
1930
 
 
1931
class TestSmartServerRequestHasSignatureForRevisionId(
 
1932
        tests.TestCaseWithMemoryTransport):
 
1933
 
 
1934
    def test_missing_revision(self):
 
1935
        """For a missing revision, NoSuchRevision is returned."""
 
1936
        backing = self.get_transport()
 
1937
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1938
            backing)
 
1939
        self.make_repository('.')
 
1940
        self.assertEqual(
 
1941
            smart_req.FailedSmartServerResponse(
 
1942
                ('nosuchrevision', 'revid'), None),
 
1943
            request.execute('', 'revid'))
 
1944
 
 
1945
    def test_missing_signature(self):
 
1946
        """For a missing signature, ('no', ) is returned."""
 
1947
        backing = self.get_transport()
 
1948
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1949
            backing)
 
1950
        tree = self.make_branch_and_memory_tree('.')
 
1951
        tree.lock_write()
 
1952
        tree.add('')
 
1953
        r1 = tree.commit('a commit', rev_id='A')
 
1954
        tree.unlock()
 
1955
        self.assertTrue(tree.branch.repository.has_revision('A'))
 
1956
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
 
1957
            request.execute('', 'A'))
 
1958
 
 
1959
    def test_present_signature(self):
 
1960
        """For a present signature, ('yes', ) is returned."""
 
1961
        backing = self.get_transport()
 
1962
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1963
            backing)
 
1964
        strategy = gpg.LoopbackGPGStrategy(None)
 
1965
        tree = self.make_branch_and_memory_tree('.')
 
1966
        tree.lock_write()
 
1967
        tree.add('')
 
1968
        r1 = tree.commit('a commit', rev_id='A')
 
1969
        tree.branch.repository.start_write_group()
 
1970
        tree.branch.repository.sign_revision('A', strategy)
 
1971
        tree.branch.repository.commit_write_group()
 
1972
        tree.unlock()
 
1973
        self.assertTrue(tree.branch.repository.has_revision('A'))
 
1974
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
 
1975
            request.execute('', 'A'))
 
1976
 
 
1977
 
1514
1978
class TestSmartServerRepositoryGatherStats(tests.TestCaseWithMemoryTransport):
1515
1979
 
1516
1980
    def test_empty_revid(self):
1569
2033
                         request.execute('',
1570
2034
                                         rev_id_utf8, 'yes'))
1571
2035
 
 
2036
    def test_unknown_revid(self):
 
2037
        """An unknown revision id causes a 'nosuchrevision' error."""
 
2038
        backing = self.get_transport()
 
2039
        request = smart_repo.SmartServerRepositoryGatherStats(backing)
 
2040
        repository = self.make_repository('.')
 
2041
        expected_body = 'revisions: 0\n'
 
2042
        self.assertEqual(
 
2043
            smart_req.FailedSmartServerResponse(
 
2044
                ('nosuchrevision', 'mia'), None),
 
2045
            request.execute('', 'mia', 'yes'))
 
2046
 
1572
2047
 
1573
2048
class TestSmartServerRepositoryIsShared(tests.TestCaseWithMemoryTransport):
1574
2049
 
1589
2064
            request.execute('', ))
1590
2065
 
1591
2066
 
 
2067
class TestSmartServerRepositoryGetRevisionSignatureText(
 
2068
        tests.TestCaseWithMemoryTransport):
 
2069
 
 
2070
    def test_get_signature(self):
 
2071
        backing = self.get_transport()
 
2072
        request = smart_repo.SmartServerRepositoryGetRevisionSignatureText(
 
2073
            backing)
 
2074
        bb = self.make_branch_builder('.')
 
2075
        bb.build_commit(rev_id='A')
 
2076
        repo = bb.get_branch().repository
 
2077
        strategy = gpg.LoopbackGPGStrategy(None)
 
2078
        self.addCleanup(repo.lock_write().unlock)
 
2079
        repo.start_write_group()
 
2080
        repo.sign_revision('A', strategy)
 
2081
        repo.commit_write_group()
 
2082
        expected_body = (
 
2083
            '-----BEGIN PSEUDO-SIGNED CONTENT-----\n' +
 
2084
            Testament.from_revision(repo, 'A').as_short_text() +
 
2085
            '-----END PSEUDO-SIGNED CONTENT-----\n')
 
2086
        self.assertEqual(
 
2087
            smart_req.SmartServerResponse(('ok', ), expected_body),
 
2088
            request.execute('', 'A'))
 
2089
 
 
2090
 
 
2091
class TestSmartServerRepositoryMakeWorkingTrees(
 
2092
        tests.TestCaseWithMemoryTransport):
 
2093
 
 
2094
    def test_make_working_trees(self):
 
2095
        """For a repository with working trees, ('yes', ) is returned."""
 
2096
        backing = self.get_transport()
 
2097
        request = smart_repo.SmartServerRepositoryMakeWorkingTrees(backing)
 
2098
        r = self.make_repository('.')
 
2099
        r.set_make_working_trees(True)
 
2100
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
 
2101
            request.execute('', ))
 
2102
 
 
2103
    def test_is_not_shared(self):
 
2104
        """For a repository with working trees, ('no', ) is returned."""
 
2105
        backing = self.get_transport()
 
2106
        request = smart_repo.SmartServerRepositoryMakeWorkingTrees(backing)
 
2107
        r = self.make_repository('.')
 
2108
        r.set_make_working_trees(False)
 
2109
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
 
2110
            request.execute('', ))
 
2111
 
 
2112
 
1592
2113
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
1593
2114
 
1594
2115
    def test_lock_write_on_unlocked_repo(self):
1610
2131
        backing = self.get_transport()
1611
2132
        request = smart_repo.SmartServerRepositoryLockWrite(backing)
1612
2133
        repository = self.make_repository('.', format='knit')
1613
 
        repo_token = repository.lock_write()
 
2134
        repo_token = repository.lock_write().repository_token
1614
2135
        repository.leave_lock_in_place()
1615
2136
        repository.unlock()
1616
2137
        response = request.execute('')
1658
2179
        request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1659
2180
            backing)
1660
2181
        repository = self.make_repository('.', format='knit')
1661
 
        lock_token = repository.lock_write()
 
2182
        lock_token = repository.lock_write().repository_token
1662
2183
        response = request.execute('', '', lock_token)
1663
2184
        self.assertEqual(None, response)
1664
2185
        response = request.do_chunk(self.make_empty_byte_stream(repository))
1672
2193
        request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1673
2194
            backing)
1674
2195
        repository = self.make_repository('.', format='knit')
1675
 
        lock_token = repository.lock_write()
 
2196
        lock_token = repository.lock_write().repository_token
1676
2197
        self.assertRaises(
1677
2198
            errors.TokenMismatch, request.execute, '', '', 'wrong-token')
1678
2199
        repository.unlock()
1687
2208
        backing = self.get_transport()
1688
2209
        request = smart_repo.SmartServerRepositoryUnlock(backing)
1689
2210
        repository = self.make_repository('.', format='knit')
1690
 
        token = repository.lock_write()
 
2211
        token = repository.lock_write().repository_token
1691
2212
        repository.leave_lock_in_place()
1692
2213
        repository.unlock()
1693
2214
        response = request.execute('', token)
1708
2229
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
1709
2230
 
1710
2231
 
 
2232
class TestSmartServerRepositoryGetPhysicalLockStatus(
 
2233
    tests.TestCaseWithTransport):
 
2234
 
 
2235
    def test_with_write_lock(self):
 
2236
        backing = self.get_transport()
 
2237
        repo = self.make_repository('.')
 
2238
        self.addCleanup(repo.lock_write().unlock)
 
2239
        # lock_write() doesn't necessarily actually take a physical
 
2240
        # lock out.
 
2241
        if repo.get_physical_lock_status():
 
2242
            expected = 'yes'
 
2243
        else:
 
2244
            expected = 'no'
 
2245
        request_class = smart_repo.SmartServerRepositoryGetPhysicalLockStatus
 
2246
        request = request_class(backing)
 
2247
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((expected,)),
 
2248
            request.execute('', ))
 
2249
 
 
2250
    def test_without_write_lock(self):
 
2251
        backing = self.get_transport()
 
2252
        repo = self.make_repository('.')
 
2253
        self.assertEquals(False, repo.get_physical_lock_status())
 
2254
        request_class = smart_repo.SmartServerRepositoryGetPhysicalLockStatus
 
2255
        request = request_class(backing)
 
2256
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('no',)),
 
2257
            request.execute('', ))
 
2258
 
 
2259
 
 
2260
class TestSmartServerRepositoryReconcile(tests.TestCaseWithTransport):
 
2261
 
 
2262
    def test_reconcile(self):
 
2263
        backing = self.get_transport()
 
2264
        repo = self.make_repository('.')
 
2265
        token = repo.lock_write().repository_token
 
2266
        self.addCleanup(repo.unlock)
 
2267
        request_class = smart_repo.SmartServerRepositoryReconcile
 
2268
        request = request_class(backing)
 
2269
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(
 
2270
            ('ok', ),
 
2271
             'garbage_inventories: 0\n'
 
2272
             'inconsistent_parents: 0\n'),
 
2273
            request.execute('', token))
 
2274
 
 
2275
 
1711
2276
class TestSmartServerIsReadonly(tests.TestCaseWithMemoryTransport):
1712
2277
 
1713
2278
    def test_is_readonly_no(self):
1751
2316
        self.assertTrue(repo.make_working_trees())
1752
2317
 
1753
2318
 
 
2319
class TestSmartServerRepositoryGetSerializerFormat(
 
2320
    tests.TestCaseWithMemoryTransport):
 
2321
 
 
2322
    def test_get_serializer_format(self):
 
2323
        backing = self.get_transport()
 
2324
        repo = self.make_repository('.', format='2a')
 
2325
        request_class = smart_repo.SmartServerRepositoryGetSerializerFormat
 
2326
        request = request_class(backing)
 
2327
        self.assertEqual(
 
2328
            smart_req.SuccessfulSmartServerResponse(('ok', '10')),
 
2329
            request.execute(''))
 
2330
 
 
2331
 
 
2332
class TestSmartServerRepositoryWriteGroup(
 
2333
    tests.TestCaseWithMemoryTransport):
 
2334
 
 
2335
    def test_start_write_group(self):
 
2336
        backing = self.get_transport()
 
2337
        repo = self.make_repository('.')
 
2338
        lock_token = repo.lock_write().repository_token
 
2339
        self.addCleanup(repo.unlock)
 
2340
        request_class = smart_repo.SmartServerRepositoryStartWriteGroup
 
2341
        request = request_class(backing)
 
2342
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok', [])),
 
2343
            request.execute('', lock_token))
 
2344
 
 
2345
    def test_start_write_group_unsuspendable(self):
 
2346
        backing = self.get_transport()
 
2347
        repo = self.make_repository('.', format='knit')
 
2348
        lock_token = repo.lock_write().repository_token
 
2349
        self.addCleanup(repo.unlock)
 
2350
        request_class = smart_repo.SmartServerRepositoryStartWriteGroup
 
2351
        request = request_class(backing)
 
2352
        self.assertEqual(
 
2353
            smart_req.FailedSmartServerResponse(('UnsuspendableWriteGroup',)),
 
2354
            request.execute('', lock_token))
 
2355
 
 
2356
    def test_commit_write_group(self):
 
2357
        backing = self.get_transport()
 
2358
        repo = self.make_repository('.')
 
2359
        lock_token = repo.lock_write().repository_token
 
2360
        self.addCleanup(repo.unlock)
 
2361
        repo.start_write_group()
 
2362
        tokens = repo.suspend_write_group()
 
2363
        request_class = smart_repo.SmartServerRepositoryCommitWriteGroup
 
2364
        request = request_class(backing)
 
2365
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
 
2366
            request.execute('', lock_token, tokens))
 
2367
 
 
2368
    def test_abort_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.SmartServerRepositoryAbortWriteGroup
 
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(self):
 
2381
        backing = self.get_transport()
 
2382
        repo = self.make_repository('.')
 
2383
        lock_token = repo.lock_write().repository_token
 
2384
        repo.start_write_group()
 
2385
        tokens = repo.suspend_write_group()
 
2386
        self.addCleanup(repo.unlock)
 
2387
        request_class = smart_repo.SmartServerRepositoryCheckWriteGroup
 
2388
        request = request_class(backing)
 
2389
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
 
2390
            request.execute('', lock_token, tokens))
 
2391
 
 
2392
    def test_check_write_group_invalid(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.SmartServerRepositoryCheckWriteGroup
 
2398
        request = request_class(backing)
 
2399
        self.assertEqual(smart_req.FailedSmartServerResponse(
 
2400
            ('UnresumableWriteGroup', ['random'],
 
2401
                'Malformed write group token')),
 
2402
            request.execute('', lock_token, ["random"]))
 
2403
 
 
2404
 
1754
2405
class TestSmartServerPackRepositoryAutopack(tests.TestCaseWithTransport):
1755
2406
 
1756
2407
    def make_repo_needing_autopacking(self, path='.'):
1822
2473
        """All registered request_handlers can be found."""
1823
2474
        # If there's a typo in a register_lazy call, this loop will fail with
1824
2475
        # an AttributeError.
1825
 
        for key, item in smart_req.request_handlers.iteritems():
1826
 
            pass
 
2476
        for key in smart_req.request_handlers.keys():
 
2477
            try:
 
2478
                item = smart_req.request_handlers.get(key)
 
2479
            except AttributeError, e:
 
2480
                raise AttributeError('failed to get %s: %s' % (key, e))
1827
2481
 
1828
2482
    def assertHandlerEqual(self, verb, handler):
1829
2483
        self.assertEqual(smart_req.request_handlers.get(verb), handler)
1830
2484
 
1831
2485
    def test_registered_methods(self):
1832
2486
        """Test that known methods are registered to the correct object."""
 
2487
        self.assertHandlerEqual('Branch.break_lock',
 
2488
            smart_branch.SmartServerBranchBreakLock)
1833
2489
        self.assertHandlerEqual('Branch.get_config_file',
1834
2490
            smart_branch.SmartServerBranchGetConfigFile)
 
2491
        self.assertHandlerEqual('Branch.put_config_file',
 
2492
            smart_branch.SmartServerBranchPutConfigFile)
1835
2493
        self.assertHandlerEqual('Branch.get_parent',
1836
2494
            smart_branch.SmartServerBranchGetParent)
 
2495
        self.assertHandlerEqual('Branch.get_physical_lock_status',
 
2496
            smart_branch.SmartServerBranchRequestGetPhysicalLockStatus)
1837
2497
        self.assertHandlerEqual('Branch.get_tags_bytes',
1838
2498
            smart_branch.SmartServerBranchGetTagsBytes)
1839
2499
        self.assertHandlerEqual('Branch.lock_write',
1842
2502
            smart_branch.SmartServerBranchRequestLastRevisionInfo)
1843
2503
        self.assertHandlerEqual('Branch.revision_history',
1844
2504
            smart_branch.SmartServerRequestRevisionHistory)
 
2505
        self.assertHandlerEqual('Branch.revision_id_to_revno',
 
2506
            smart_branch.SmartServerBranchRequestRevisionIdToRevno)
1845
2507
        self.assertHandlerEqual('Branch.set_config_option',
1846
2508
            smart_branch.SmartServerBranchRequestSetConfigOption)
1847
2509
        self.assertHandlerEqual('Branch.set_last_revision',
1854
2516
            smart_branch.SmartServerBranchRequestSetParentLocation)
1855
2517
        self.assertHandlerEqual('Branch.unlock',
1856
2518
            smart_branch.SmartServerBranchRequestUnlock)
 
2519
        self.assertHandlerEqual('BzrDir.destroy_branch',
 
2520
            smart_dir.SmartServerBzrDirRequestDestroyBranch)
1857
2521
        self.assertHandlerEqual('BzrDir.find_repository',
1858
2522
            smart_dir.SmartServerRequestFindRepositoryV1)
1859
2523
        self.assertHandlerEqual('BzrDir.find_repositoryV2',
1862
2526
            smart_dir.SmartServerRequestInitializeBzrDir)
1863
2527
        self.assertHandlerEqual('BzrDirFormat.initialize_ex_1.16',
1864
2528
            smart_dir.SmartServerRequestBzrDirInitializeEx)
 
2529
        self.assertHandlerEqual('BzrDir.checkout_metadir',
 
2530
            smart_dir.SmartServerBzrDirRequestCheckoutMetaDir)
1865
2531
        self.assertHandlerEqual('BzrDir.cloning_metadir',
1866
2532
            smart_dir.SmartServerBzrDirRequestCloningMetaDir)
 
2533
        self.assertHandlerEqual('BzrDir.get_branches',
 
2534
            smart_dir.SmartServerBzrDirRequestGetBranches)
1867
2535
        self.assertHandlerEqual('BzrDir.get_config_file',
1868
2536
            smart_dir.SmartServerBzrDirRequestConfigFile)
1869
2537
        self.assertHandlerEqual('BzrDir.open_branch',
1874
2542
            smart_dir.SmartServerRequestOpenBranchV3)
1875
2543
        self.assertHandlerEqual('PackRepository.autopack',
1876
2544
            smart_packrepo.SmartServerPackRepositoryAutopack)
 
2545
        self.assertHandlerEqual('Repository.add_signature_text',
 
2546
            smart_repo.SmartServerRepositoryAddSignatureText)
 
2547
        self.assertHandlerEqual('Repository.all_revision_ids',
 
2548
            smart_repo.SmartServerRepositoryAllRevisionIds)
 
2549
        self.assertHandlerEqual('Repository.break_lock',
 
2550
            smart_repo.SmartServerRepositoryBreakLock)
1877
2551
        self.assertHandlerEqual('Repository.gather_stats',
1878
2552
            smart_repo.SmartServerRepositoryGatherStats)
1879
2553
        self.assertHandlerEqual('Repository.get_parent_map',
1880
2554
            smart_repo.SmartServerRepositoryGetParentMap)
 
2555
        self.assertHandlerEqual('Repository.get_physical_lock_status',
 
2556
            smart_repo.SmartServerRepositoryGetPhysicalLockStatus)
1881
2557
        self.assertHandlerEqual('Repository.get_rev_id_for_revno',
1882
2558
            smart_repo.SmartServerRepositoryGetRevIdForRevno)
1883
2559
        self.assertHandlerEqual('Repository.get_revision_graph',
1884
2560
            smart_repo.SmartServerRepositoryGetRevisionGraph)
 
2561
        self.assertHandlerEqual('Repository.get_revision_signature_text',
 
2562
            smart_repo.SmartServerRepositoryGetRevisionSignatureText)
1885
2563
        self.assertHandlerEqual('Repository.get_stream',
1886
2564
            smart_repo.SmartServerRepositoryGetStream)
 
2565
        self.assertHandlerEqual('Repository.get_stream_1.19',
 
2566
            smart_repo.SmartServerRepositoryGetStream_1_19)
 
2567
        self.assertHandlerEqual('Repository.iter_revisions',
 
2568
            smart_repo.SmartServerRepositoryIterRevisions)
1887
2569
        self.assertHandlerEqual('Repository.has_revision',
1888
2570
            smart_repo.SmartServerRequestHasRevision)
1889
2571
        self.assertHandlerEqual('Repository.insert_stream',
1892
2574
            smart_repo.SmartServerRepositoryInsertStreamLocked)
1893
2575
        self.assertHandlerEqual('Repository.is_shared',
1894
2576
            smart_repo.SmartServerRepositoryIsShared)
 
2577
        self.assertHandlerEqual('Repository.iter_files_bytes',
 
2578
            smart_repo.SmartServerRepositoryIterFilesBytes)
1895
2579
        self.assertHandlerEqual('Repository.lock_write',
1896
2580
            smart_repo.SmartServerRepositoryLockWrite)
 
2581
        self.assertHandlerEqual('Repository.make_working_trees',
 
2582
            smart_repo.SmartServerRepositoryMakeWorkingTrees)
 
2583
        self.assertHandlerEqual('Repository.pack',
 
2584
            smart_repo.SmartServerRepositoryPack)
 
2585
        self.assertHandlerEqual('Repository.reconcile',
 
2586
            smart_repo.SmartServerRepositoryReconcile)
1897
2587
        self.assertHandlerEqual('Repository.tarball',
1898
2588
            smart_repo.SmartServerRepositoryTarball)
1899
2589
        self.assertHandlerEqual('Repository.unlock',
1900
2590
            smart_repo.SmartServerRepositoryUnlock)
 
2591
        self.assertHandlerEqual('Repository.start_write_group',
 
2592
            smart_repo.SmartServerRepositoryStartWriteGroup)
 
2593
        self.assertHandlerEqual('Repository.check_write_group',
 
2594
            smart_repo.SmartServerRepositoryCheckWriteGroup)
 
2595
        self.assertHandlerEqual('Repository.commit_write_group',
 
2596
            smart_repo.SmartServerRepositoryCommitWriteGroup)
 
2597
        self.assertHandlerEqual('Repository.abort_write_group',
 
2598
            smart_repo.SmartServerRepositoryAbortWriteGroup)
 
2599
        self.assertHandlerEqual('VersionedFileRepository.get_serializer_format',
 
2600
            smart_repo.SmartServerRepositoryGetSerializerFormat)
 
2601
        self.assertHandlerEqual('VersionedFileRepository.get_inventories',
 
2602
            smart_repo.SmartServerRepositoryGetInventories)
1901
2603
        self.assertHandlerEqual('Transport.is_readonly',
1902
2604
            smart_req.SmartServerIsReadonly)
 
2605
 
 
2606
 
 
2607
class SmartTCPServerHookTests(tests.TestCaseWithMemoryTransport):
 
2608
    """Tests for SmartTCPServer hooks."""
 
2609
 
 
2610
    def setUp(self):
 
2611
        super(SmartTCPServerHookTests, self).setUp()
 
2612
        self.server = server.SmartTCPServer(self.get_transport())
 
2613
 
 
2614
    def test_run_server_started_hooks(self):
 
2615
        """Test the server started hooks get fired properly."""
 
2616
        started_calls = []
 
2617
        server.SmartTCPServer.hooks.install_named_hook('server_started',
 
2618
            lambda backing_urls, url: started_calls.append((backing_urls, url)),
 
2619
            None)
 
2620
        started_ex_calls = []
 
2621
        server.SmartTCPServer.hooks.install_named_hook('server_started_ex',
 
2622
            lambda backing_urls, url: started_ex_calls.append((backing_urls, url)),
 
2623
            None)
 
2624
        self.server._sockname = ('example.com', 42)
 
2625
        self.server.run_server_started_hooks()
 
2626
        self.assertEquals(started_calls,
 
2627
            [([self.get_transport().base], 'bzr://example.com:42/')])
 
2628
        self.assertEquals(started_ex_calls,
 
2629
            [([self.get_transport().base], self.server)])
 
2630
 
 
2631
    def test_run_server_started_hooks_ipv6(self):
 
2632
        """Test that socknames can contain 4-tuples."""
 
2633
        self.server._sockname = ('::', 42, 0, 0)
 
2634
        started_calls = []
 
2635
        server.SmartTCPServer.hooks.install_named_hook('server_started',
 
2636
            lambda backing_urls, url: started_calls.append((backing_urls, url)),
 
2637
            None)
 
2638
        self.server.run_server_started_hooks()
 
2639
        self.assertEquals(started_calls,
 
2640
                [([self.get_transport().base], 'bzr://:::42/')])
 
2641
 
 
2642
    def test_run_server_stopped_hooks(self):
 
2643
        """Test the server stopped hooks."""
 
2644
        self.server._sockname = ('example.com', 42)
 
2645
        stopped_calls = []
 
2646
        server.SmartTCPServer.hooks.install_named_hook('server_stopped',
 
2647
            lambda backing_urls, url: stopped_calls.append((backing_urls, url)),
 
2648
            None)
 
2649
        self.server.run_server_stopped_hooks()
 
2650
        self.assertEquals(stopped_calls,
 
2651
            [([self.get_transport().base], 'bzr://example.com:42/')])
 
2652
 
 
2653
 
 
2654
class TestSmartServerRepositoryPack(tests.TestCaseWithMemoryTransport):
 
2655
 
 
2656
    def test_pack(self):
 
2657
        backing = self.get_transport()
 
2658
        request = smart_repo.SmartServerRepositoryPack(backing)
 
2659
        tree = self.make_branch_and_memory_tree('.')
 
2660
        repo_token = tree.branch.repository.lock_write().repository_token
 
2661
 
 
2662
        self.assertIs(None, request.execute('', repo_token, False))
 
2663
 
 
2664
        self.assertEqual(
 
2665
            smart_req.SuccessfulSmartServerResponse(('ok', ), ),
 
2666
            request.do_body(''))
 
2667
 
 
2668
 
 
2669
class TestSmartServerRepositoryGetInventories(tests.TestCaseWithTransport):
 
2670
 
 
2671
    def _get_serialized_inventory_delta(self, repository, base_revid, revid):
 
2672
        base_inv = repository.revision_tree(base_revid).root_inventory
 
2673
        inv = repository.revision_tree(revid).root_inventory
 
2674
        inv_delta = inv._make_delta(base_inv)
 
2675
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
 
2676
        return "".join(serializer.delta_to_lines(base_revid, revid, inv_delta))
 
2677
 
 
2678
    def test_single(self):
 
2679
        backing = self.get_transport()
 
2680
        request = smart_repo.SmartServerRepositoryGetInventories(backing)
 
2681
        t = self.make_branch_and_tree('.', format='2a')
 
2682
        self.addCleanup(t.lock_write().unlock)
 
2683
        self.build_tree_contents([("file", "somecontents")])
 
2684
        t.add(["file"], ["thefileid"])
 
2685
        t.commit(rev_id='somerev', message="add file")
 
2686
        self.assertIs(None, request.execute('', 'unordered'))
 
2687
        response = request.do_body("somerev\n")
 
2688
        self.assertTrue(response.is_successful())
 
2689
        self.assertEquals(response.args, ("ok", ))
 
2690
        stream = [('inventory-deltas', [
 
2691
            versionedfile.FulltextContentFactory('somerev', None, None,
 
2692
                self._get_serialized_inventory_delta(
 
2693
                    t.branch.repository, 'null:', 'somerev'))])]
 
2694
        fmt = controldir.format_registry.get('2a')().repository_format
 
2695
        self.assertEquals(
 
2696
            "".join(response.body_stream),
 
2697
            "".join(smart_repo._stream_to_byte_stream(stream, fmt)))
 
2698
 
 
2699
    def test_empty(self):
 
2700
        backing = self.get_transport()
 
2701
        request = smart_repo.SmartServerRepositoryGetInventories(backing)
 
2702
        t = self.make_branch_and_tree('.', format='2a')
 
2703
        self.addCleanup(t.lock_write().unlock)
 
2704
        self.build_tree_contents([("file", "somecontents")])
 
2705
        t.add(["file"], ["thefileid"])
 
2706
        t.commit(rev_id='somerev', message="add file")
 
2707
        self.assertIs(None, request.execute('', 'unordered'))
 
2708
        response = request.do_body("")
 
2709
        self.assertTrue(response.is_successful())
 
2710
        self.assertEquals(response.args, ("ok", ))
 
2711
        self.assertEquals("".join(response.body_stream),
 
2712
            "Bazaar pack format 1 (introduced in 0.18)\nB54\n\nBazaar repository format 2a (needs bzr 1.16 or later)\nE")