~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_smart.py

  • Committer: Wouter van Heyst
  • Date: 2012-01-25 19:07:22 UTC
  • mfrom: (6437.19.2 2.5)
  • mto: (6437.3.27 2.5)
  • mto: This revision was merged to the branch mainline in revision 6451.
  • Revision ID: larstiq@larstiq.dyndns.org-20120125190722-1bf3j0d6my1zd8v1
ensure files actually hit the disk under pypy

Show diffs side-by-side

added added

removed removed

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