/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_smart.py

  • Committer: Vincent Ladeuil
  • Date: 2012-01-05 14:26:58 UTC
  • mto: This revision was merged to the branch mainline in revision 6468.
  • Revision ID: v.ladeuil+lp@free.fr-20120105142658-vek3v6pzlxb751s2
Tests passing for a first rough version of a cached branch config store. The changes here are too invasive and several parallel proposals have been made. 

@only_raises is evil and gave a hard time since any exception during
save_changes() was swallowed.

Possible improvements: 

- add some needs_write_lock decorators to crucial
  methods (_set_config_location ?) but keep locking the branch at higher levels

- decorate branch.unlock to call stack.save if last_lock() it True
  outside of @only_raises scope (evil decorator)

- add @needs_write_lock to stack.set and stack.remove (will probably get
  rid of most testing issues) we probably need a specialized decorator
  that can relay to the store and from there to the branch or whatever is
  needed. This will also helps bzr config to get it right. The
  get_mutable_section trick should not be needed anymore either.

- decorate branch.unlock to call stack.save if last_lock() it True outside
  of @only_raises scope (evil decorator)

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
 
    bencode,
33
31
    branch as _mod_branch,
34
32
    bzrdir,
35
33
    errors,
36
 
    pack,
 
34
    gpg,
 
35
    inventory_delta,
37
36
    tests,
38
37
    transport,
39
38
    urlutils,
48
47
    server,
49
48
    vfs,
50
49
    )
 
50
from bzrlib.testament import Testament
51
51
from bzrlib.tests import test_server
52
52
from bzrlib.transport import (
53
53
    chroot,
89
89
            backing_transport = tests.TestCaseWithTransport.get_transport(self)
90
90
            self._chroot_server = chroot.ChrootServer(backing_transport)
91
91
            self.start_server(self._chroot_server)
92
 
        t = transport.get_transport(self._chroot_server.get_url())
 
92
        t = transport.get_transport_from_url(self._chroot_server.get_url())
93
93
        if relpath is not None:
94
94
            t = t.clone(relpath)
95
95
        return t
103
103
        # the default or a parameterized class, but rather use the
104
104
        # TestCaseWithTransport infrastructure to set up a smart server and
105
105
        # transport.
106
 
        self.transport_server = self.make_transport_server
 
106
        self.overrideAttr(self, "transport_server", self.make_transport_server)
107
107
 
108
108
    def make_transport_server(self):
109
109
        return test_server.SmartTCPServer_for_testing('-' + self.id())
225
225
        self.assertEqual(expected, request.execute('', 'False'))
226
226
 
227
227
 
 
228
class TestSmartServerBzrDirRequestCloningMetaDir(
 
229
    tests.TestCaseWithMemoryTransport):
 
230
    """Tests for BzrDir.checkout_metadir."""
 
231
 
 
232
    def test_checkout_metadir(self):
 
233
        backing = self.get_transport()
 
234
        request = smart_dir.SmartServerBzrDirRequestCheckoutMetaDir(
 
235
            backing)
 
236
        branch = self.make_branch('.', format='2a')
 
237
        response = request.execute('')
 
238
        self.assertEqual(
 
239
            smart_req.SmartServerResponse(
 
240
                ('Bazaar-NG meta directory, format 1\n',
 
241
                 'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
 
242
                 'Bazaar Branch Format 7 (needs bzr 1.6)\n')),
 
243
            response)
 
244
 
 
245
 
 
246
class TestSmartServerBzrDirRequestDestroyBranch(
 
247
    tests.TestCaseWithMemoryTransport):
 
248
    """Tests for BzrDir.destroy_branch."""
 
249
 
 
250
    def test_destroy_branch_default(self):
 
251
        """The default branch can be removed."""
 
252
        backing = self.get_transport()
 
253
        dir = self.make_branch('.').bzrdir
 
254
        request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
 
255
        request = request_class(backing)
 
256
        expected = smart_req.SuccessfulSmartServerResponse(('ok',))
 
257
        self.assertEqual(expected, request.execute('', None))
 
258
 
 
259
    def test_destroy_branch_named(self):
 
260
        """A named branch can be removed."""
 
261
        backing = self.get_transport()
 
262
        dir = self.make_repository('.', format="development-colo").bzrdir
 
263
        dir.create_branch(name="branchname")
 
264
        request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
 
265
        request = request_class(backing)
 
266
        expected = smart_req.SuccessfulSmartServerResponse(('ok',))
 
267
        self.assertEqual(expected, request.execute('', "branchname"))
 
268
 
 
269
    def test_destroy_branch_missing(self):
 
270
        """An error is raised if the branch didn't exist."""
 
271
        backing = self.get_transport()
 
272
        dir = self.make_bzrdir('.', format="development-colo")
 
273
        request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
 
274
        request = request_class(backing)
 
275
        expected = smart_req.FailedSmartServerResponse(('nobranch',), None)
 
276
        self.assertEqual(expected, request.execute('', "branchname"))
 
277
 
 
278
 
 
279
class TestSmartServerBzrDirRequestHasWorkingTree(
 
280
    tests.TestCaseWithTransport):
 
281
    """Tests for BzrDir.has_workingtree."""
 
282
 
 
283
    def test_has_workingtree_yes(self):
 
284
        """A working tree is present."""
 
285
        backing = self.get_transport()
 
286
        dir = self.make_branch_and_tree('.').bzrdir
 
287
        request_class = smart_dir.SmartServerBzrDirRequestHasWorkingTree
 
288
        request = request_class(backing)
 
289
        expected = smart_req.SuccessfulSmartServerResponse(('yes',))
 
290
        self.assertEqual(expected, request.execute(''))
 
291
 
 
292
    def test_has_workingtree_no(self):
 
293
        """A working tree is missing."""
 
294
        backing = self.get_transport()
 
295
        dir = self.make_bzrdir('.')
 
296
        request_class = smart_dir.SmartServerBzrDirRequestHasWorkingTree
 
297
        request = request_class(backing)
 
298
        expected = smart_req.SuccessfulSmartServerResponse(('no',))
 
299
        self.assertEqual(expected, request.execute(''))
 
300
 
 
301
 
 
302
class TestSmartServerBzrDirRequestDestroyRepository(
 
303
    tests.TestCaseWithMemoryTransport):
 
304
    """Tests for BzrDir.destroy_repository."""
 
305
 
 
306
    def test_destroy_repository_default(self):
 
307
        """The repository can be removed."""
 
308
        backing = self.get_transport()
 
309
        dir = self.make_repository('.').bzrdir
 
310
        request_class = smart_dir.SmartServerBzrDirRequestDestroyRepository
 
311
        request = request_class(backing)
 
312
        expected = smart_req.SuccessfulSmartServerResponse(('ok',))
 
313
        self.assertEqual(expected, request.execute(''))
 
314
 
 
315
    def test_destroy_repository_missing(self):
 
316
        """An error is raised if the repository didn't exist."""
 
317
        backing = self.get_transport()
 
318
        dir = self.make_bzrdir('.')
 
319
        request_class = smart_dir.SmartServerBzrDirRequestDestroyRepository
 
320
        request = request_class(backing)
 
321
        expected = smart_req.FailedSmartServerResponse(
 
322
            ('norepository',), None)
 
323
        self.assertEqual(expected, request.execute(''))
 
324
 
 
325
 
228
326
class TestSmartServerRequestCreateRepository(tests.TestCaseWithMemoryTransport):
229
327
    """Tests for BzrDir.create_repository."""
230
328
 
739
837
            request.execute(''))
740
838
 
741
839
 
 
840
class TestSmartServerBranchRequestRevisionIdToRevno(
 
841
    tests.TestCaseWithMemoryTransport):
 
842
 
 
843
    def test_null(self):
 
844
        backing = self.get_transport()
 
845
        request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
 
846
            backing)
 
847
        self.make_branch('.')
 
848
        self.assertEqual(smart_req.SmartServerResponse(('ok', '0')),
 
849
            request.execute('', 'null:'))
 
850
 
 
851
    def test_simple(self):
 
852
        backing = self.get_transport()
 
853
        request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
 
854
            backing)
 
855
        tree = self.make_branch_and_memory_tree('.')
 
856
        tree.lock_write()
 
857
        tree.add('')
 
858
        r1 = tree.commit('1st commit')
 
859
        tree.unlock()
 
860
        self.assertEqual(
 
861
            smart_req.SmartServerResponse(('ok', '1')),
 
862
            request.execute('', r1))
 
863
 
 
864
    def test_not_found(self):
 
865
        backing = self.get_transport()
 
866
        request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
 
867
            backing)
 
868
        branch = self.make_branch('.')
 
869
        self.assertEqual(
 
870
            smart_req.FailedSmartServerResponse(
 
871
                ('NoSuchRevision', 'idontexist')),
 
872
            request.execute('', 'idontexist'))
 
873
 
 
874
 
742
875
class TestSmartServerBranchRequestGetConfigFile(
743
876
    tests.TestCaseWithMemoryTransport):
744
877
 
767
900
class TestLockedBranch(tests.TestCaseWithMemoryTransport):
768
901
 
769
902
    def get_lock_tokens(self, branch):
770
 
        branch_token = branch.lock_write()
771
 
        repo_token = branch.repository.lock_write()
 
903
        branch_token = branch.lock_write().branch_token
 
904
        repo_token = branch.repository.lock_write().repository_token
772
905
        branch.repository.unlock()
773
906
        return branch_token, repo_token
774
907
 
775
908
 
 
909
class TestSmartServerBranchRequestPutConfigFile(TestLockedBranch):
 
910
 
 
911
    def test_with_content(self):
 
912
        backing = self.get_transport()
 
913
        request = smart_branch.SmartServerBranchPutConfigFile(backing)
 
914
        branch = self.make_branch('.')
 
915
        branch_token, repo_token = self.get_lock_tokens(branch)
 
916
        self.assertIs(None, request.execute('', branch_token, repo_token))
 
917
        self.assertEqual(
 
918
            smart_req.SmartServerResponse(('ok', )),
 
919
            request.do_body('foo bar baz'))
 
920
        self.assertEquals(
 
921
            branch.control_transport.get_bytes('branch.conf'),
 
922
            'foo bar baz')
 
923
        branch.unlock()
 
924
 
 
925
 
776
926
class TestSmartServerBranchRequestSetConfigOption(TestLockedBranch):
777
927
 
778
928
    def test_value_name(self):
802
952
        branch.unlock()
803
953
 
804
954
 
 
955
class TestSmartServerBranchRequestSetConfigOptionDict(TestLockedBranch):
 
956
 
 
957
    def setUp(self):
 
958
        TestLockedBranch.setUp(self)
 
959
        # A dict with non-ascii keys and values to exercise unicode
 
960
        # roundtripping.
 
961
        self.encoded_value_dict = (
 
962
            'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde')
 
963
        self.value_dict = {
 
964
            'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
 
965
 
 
966
    def test_value_name(self):
 
967
        branch = self.make_branch('.')
 
968
        request = smart_branch.SmartServerBranchRequestSetConfigOptionDict(
 
969
            branch.bzrdir.root_transport)
 
970
        branch_token, repo_token = self.get_lock_tokens(branch)
 
971
        config = branch._get_config()
 
972
        result = request.execute('', branch_token, repo_token,
 
973
            self.encoded_value_dict, 'foo', '')
 
974
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
 
975
        self.assertEqual(self.value_dict, config.get_option('foo'))
 
976
        # Cleanup
 
977
        branch.unlock()
 
978
 
 
979
    def test_value_name_section(self):
 
980
        branch = self.make_branch('.')
 
981
        request = smart_branch.SmartServerBranchRequestSetConfigOptionDict(
 
982
            branch.bzrdir.root_transport)
 
983
        branch_token, repo_token = self.get_lock_tokens(branch)
 
984
        config = branch._get_config()
 
985
        result = request.execute('', branch_token, repo_token,
 
986
            self.encoded_value_dict, 'foo', 'gam')
 
987
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
 
988
        self.assertEqual(self.value_dict, config.get_option('foo', 'gam'))
 
989
        # Cleanup
 
990
        branch.unlock()
 
991
 
 
992
 
805
993
class TestSmartServerBranchRequestSetTagsBytes(TestLockedBranch):
806
994
    # Only called when the branch format and tags match [yay factory
807
995
    # methods] so only need to test straight forward cases.
898
1086
        # its repository.
899
1087
        self.make_tree_with_two_commits()
900
1088
        rev_id_utf8 = u'\xc8'.encode('utf-8')
901
 
        self.tree.branch.set_revision_history([])
 
1089
        self.tree.branch.set_last_revision_info(0, 'null:')
902
1090
        self.assertEqual(
903
1091
            (0, 'null:'), self.tree.branch.last_revision_info())
904
1092
        # We can update the branch to a revision that is present in the
1054
1242
        self.assertEqual('child-1', self.tree.branch.last_revision())
1055
1243
 
1056
1244
 
 
1245
class TestSmartServerBranchBreakLock(tests.TestCaseWithMemoryTransport):
 
1246
 
 
1247
    def test_lock_to_break(self):
 
1248
        base_branch = self.make_branch('base')
 
1249
        request = smart_branch.SmartServerBranchBreakLock(
 
1250
            self.get_transport())
 
1251
        base_branch.lock_write()
 
1252
        self.assertEqual(
 
1253
            smart_req.SuccessfulSmartServerResponse(('ok', ), None),
 
1254
            request.execute('base'))
 
1255
 
 
1256
    def test_nothing_to_break(self):
 
1257
        base_branch = self.make_branch('base')
 
1258
        request = smart_branch.SmartServerBranchBreakLock(
 
1259
            self.get_transport())
 
1260
        self.assertEqual(
 
1261
            smart_req.SuccessfulSmartServerResponse(('ok', ), None),
 
1262
            request.execute('base'))
 
1263
 
 
1264
 
1057
1265
class TestSmartServerBranchRequestGetParent(tests.TestCaseWithMemoryTransport):
1058
1266
 
1059
1267
    def test_get_parent_none(self):
1073
1281
            response)
1074
1282
 
1075
1283
 
1076
 
class TestSmartServerBranchRequestSetParent(tests.TestCaseWithMemoryTransport):
 
1284
class TestSmartServerBranchRequestSetParent(TestLockedBranch):
1077
1285
 
1078
1286
    def test_set_parent_none(self):
1079
1287
        branch = self.make_branch('base', format="1.9")
1082
1290
        branch.unlock()
1083
1291
        request = smart_branch.SmartServerBranchRequestSetParentLocation(
1084
1292
            self.get_transport())
1085
 
        branch_token = branch.lock_write()
1086
 
        repo_token = branch.repository.lock_write()
 
1293
        branch_token, repo_token = self.get_lock_tokens(branch)
1087
1294
        try:
1088
1295
            response = request.execute('base', branch_token, repo_token, '')
1089
1296
        finally:
1090
 
            branch.repository.unlock()
1091
1297
            branch.unlock()
1092
1298
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
1093
 
        self.assertEqual(None, branch.get_parent())
 
1299
        refreshed = _mod_branch.Branch.open(branch.base)
 
1300
        self.assertEqual(None, refreshed.get_parent())
1094
1301
 
1095
1302
    def test_set_parent_something(self):
1096
1303
        branch = self.make_branch('base', format="1.9")
1097
1304
        request = smart_branch.SmartServerBranchRequestSetParentLocation(
1098
1305
            self.get_transport())
1099
 
        branch_token = branch.lock_write()
1100
 
        repo_token = branch.repository.lock_write()
 
1306
        branch_token, repo_token = self.get_lock_tokens(branch)
1101
1307
        try:
1102
1308
            response = request.execute('base', branch_token, repo_token,
1103
 
            'http://bar/')
 
1309
                                       'http://bar/')
1104
1310
        finally:
1105
 
            branch.repository.unlock()
1106
1311
            branch.unlock()
1107
1312
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
1108
 
        self.assertEqual('http://bar/', branch.get_parent())
 
1313
        refreshed = _mod_branch.Branch.open(branch.base)
 
1314
        self.assertEqual('http://bar/', refreshed.get_parent())
1109
1315
 
1110
1316
 
1111
1317
class TestSmartServerBranchRequestGetTagsBytes(
1137
1343
            response)
1138
1344
 
1139
1345
 
1140
 
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithMemoryTransport):
 
1346
class TestSmartServerBranchRequestLockWrite(TestLockedBranch):
1141
1347
 
1142
1348
    def setUp(self):
1143
1349
        tests.TestCaseWithMemoryTransport.setUp(self)
1165
1371
        backing = self.get_transport()
1166
1372
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1167
1373
        branch = self.make_branch('.')
1168
 
        branch_token = branch.lock_write()
 
1374
        branch_token = branch.lock_write().branch_token
1169
1375
        branch.leave_lock_in_place()
1170
1376
        branch.unlock()
1171
1377
        response = request.execute('')
1180
1386
        backing = self.get_transport()
1181
1387
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1182
1388
        branch = self.make_branch('.', format='knit')
1183
 
        branch_token = branch.lock_write()
1184
 
        repo_token = branch.repository.lock_write()
1185
 
        branch.repository.unlock()
 
1389
        branch_token, repo_token = self.get_lock_tokens(branch)
1186
1390
        branch.leave_lock_in_place()
1187
1391
        branch.repository.leave_lock_in_place()
1188
1392
        branch.unlock()
1203
1407
        backing = self.get_transport()
1204
1408
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1205
1409
        branch = self.make_branch('.', format='knit')
1206
 
        branch_token = branch.lock_write()
1207
 
        repo_token = branch.repository.lock_write()
1208
 
        branch.repository.unlock()
 
1410
        branch_token, repo_token = self.get_lock_tokens(branch)
1209
1411
        branch.leave_lock_in_place()
1210
1412
        branch.repository.leave_lock_in_place()
1211
1413
        branch.unlock()
1226
1428
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1227
1429
        branch = self.make_branch('.', format='knit')
1228
1430
        repo = branch.repository
1229
 
        repo_token = repo.lock_write()
 
1431
        repo_token = repo.lock_write().repository_token
1230
1432
        repo.leave_lock_in_place()
1231
1433
        repo.unlock()
1232
1434
        response = request.execute('')
1249
1451
        self.assertEqual('LockFailed', error_name)
1250
1452
 
1251
1453
 
1252
 
class TestSmartServerBranchRequestUnlock(tests.TestCaseWithMemoryTransport):
 
1454
class TestSmartServerBranchRequestGetPhysicalLockStatus(TestLockedBranch):
 
1455
 
 
1456
    def setUp(self):
 
1457
        tests.TestCaseWithMemoryTransport.setUp(self)
 
1458
 
 
1459
    def test_true(self):
 
1460
        backing = self.get_transport()
 
1461
        request = smart_branch.SmartServerBranchRequestGetPhysicalLockStatus(
 
1462
            backing)
 
1463
        branch = self.make_branch('.')
 
1464
        branch_token, repo_token = self.get_lock_tokens(branch)
 
1465
        self.assertEquals(True, branch.get_physical_lock_status())
 
1466
        response = request.execute('')
 
1467
        self.assertEqual(
 
1468
            smart_req.SmartServerResponse(('yes',)), response)
 
1469
        branch.unlock()
 
1470
 
 
1471
    def test_false(self):
 
1472
        backing = self.get_transport()
 
1473
        request = smart_branch.SmartServerBranchRequestGetPhysicalLockStatus(
 
1474
            backing)
 
1475
        branch = self.make_branch('.')
 
1476
        self.assertEquals(False, branch.get_physical_lock_status())
 
1477
        response = request.execute('')
 
1478
        self.assertEqual(
 
1479
            smart_req.SmartServerResponse(('no',)), response)
 
1480
 
 
1481
 
 
1482
class TestSmartServerBranchRequestUnlock(TestLockedBranch):
1253
1483
 
1254
1484
    def setUp(self):
1255
1485
        tests.TestCaseWithMemoryTransport.setUp(self)
1259
1489
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1260
1490
        branch = self.make_branch('.', format='knit')
1261
1491
        # Lock the branch
1262
 
        branch_token = branch.lock_write()
1263
 
        repo_token = branch.repository.lock_write()
1264
 
        branch.repository.unlock()
 
1492
        branch_token, repo_token = self.get_lock_tokens(branch)
1265
1493
        # Unlock the branch (and repo) object, leaving the physical locks
1266
1494
        # in place.
1267
1495
        branch.leave_lock_in_place()
1291
1519
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1292
1520
        branch = self.make_branch('.', format='knit')
1293
1521
        # Lock the repository.
1294
 
        repo_token = branch.repository.lock_write()
 
1522
        repo_token = branch.repository.lock_write().repository_token
1295
1523
        branch.repository.leave_lock_in_place()
1296
1524
        branch.repository.unlock()
1297
1525
        # Issue branch lock_write request on the unlocked branch (with locked
1298
1526
        # repo).
1299
 
        response = request.execute(
1300
 
            '', 'branch token', repo_token)
 
1527
        response = request.execute('', 'branch token', repo_token)
1301
1528
        self.assertEqual(
1302
1529
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
1303
1530
        # Cleanup
1322
1549
            request.execute, 'subdir')
1323
1550
 
1324
1551
 
 
1552
class TestSmartServerRepositoryAddSignatureText(tests.TestCaseWithMemoryTransport):
 
1553
 
 
1554
    def test_add_text(self):
 
1555
        backing = self.get_transport()
 
1556
        request = smart_repo.SmartServerRepositoryAddSignatureText(backing)
 
1557
        tree = self.make_branch_and_memory_tree('.')
 
1558
        write_token = tree.lock_write()
 
1559
        self.addCleanup(tree.unlock)
 
1560
        tree.add('')
 
1561
        tree.commit("Message", rev_id='rev1')
 
1562
        tree.branch.repository.start_write_group()
 
1563
        write_group_tokens = tree.branch.repository.suspend_write_group()
 
1564
        self.assertEqual(None, request.execute('', write_token,
 
1565
            'rev1', *write_group_tokens))
 
1566
        response = request.do_body('somesignature')
 
1567
        self.assertTrue(response.is_successful())
 
1568
        self.assertEqual(response.args[0], 'ok')
 
1569
        write_group_tokens = response.args[1:]
 
1570
        tree.branch.repository.resume_write_group(write_group_tokens)
 
1571
        tree.branch.repository.commit_write_group()
 
1572
        tree.unlock()
 
1573
        self.assertEqual("somesignature",
 
1574
            tree.branch.repository.get_signature_text("rev1"))
 
1575
 
 
1576
 
 
1577
class TestSmartServerRepositoryAllRevisionIds(
 
1578
    tests.TestCaseWithMemoryTransport):
 
1579
 
 
1580
    def test_empty(self):
 
1581
        """An empty body should be returned for an empty repository."""
 
1582
        backing = self.get_transport()
 
1583
        request = smart_repo.SmartServerRepositoryAllRevisionIds(backing)
 
1584
        self.make_repository('.')
 
1585
        self.assertEquals(
 
1586
            smart_req.SuccessfulSmartServerResponse(("ok", ), ""),
 
1587
            request.execute(''))
 
1588
 
 
1589
    def test_some_revisions(self):
 
1590
        """An empty body should be returned for an empty repository."""
 
1591
        backing = self.get_transport()
 
1592
        request = smart_repo.SmartServerRepositoryAllRevisionIds(backing)
 
1593
        tree = self.make_branch_and_memory_tree('.')
 
1594
        tree.lock_write()
 
1595
        tree.add('')
 
1596
        tree.commit(rev_id='origineel', message="message")
 
1597
        tree.commit(rev_id='nog-een-revisie', message="message")
 
1598
        tree.unlock()
 
1599
        self.assertEquals(
 
1600
            smart_req.SuccessfulSmartServerResponse(("ok", ),
 
1601
                "origineel\nnog-een-revisie"),
 
1602
            request.execute(''))
 
1603
 
 
1604
 
 
1605
class TestSmartServerRepositoryBreakLock(tests.TestCaseWithMemoryTransport):
 
1606
 
 
1607
    def test_lock_to_break(self):
 
1608
        backing = self.get_transport()
 
1609
        request = smart_repo.SmartServerRepositoryBreakLock(backing)
 
1610
        tree = self.make_branch_and_memory_tree('.')
 
1611
        tree.branch.repository.lock_write()
 
1612
        self.assertEqual(
 
1613
            smart_req.SuccessfulSmartServerResponse(('ok', ), None),
 
1614
            request.execute(''))
 
1615
 
 
1616
    def test_nothing_to_break(self):
 
1617
        backing = self.get_transport()
 
1618
        request = smart_repo.SmartServerRepositoryBreakLock(backing)
 
1619
        tree = self.make_branch_and_memory_tree('.')
 
1620
        self.assertEqual(
 
1621
            smart_req.SuccessfulSmartServerResponse(('ok', ), None),
 
1622
            request.execute(''))
 
1623
 
 
1624
 
1325
1625
class TestSmartServerRepositoryGetParentMap(tests.TestCaseWithMemoryTransport):
1326
1626
 
1327
1627
    def test_trivial_bzipped(self):
1447
1747
            request.execute('stacked', 1, (3, r3)))
1448
1748
 
1449
1749
 
1450
 
class TestSmartServerRepositoryGetStream(tests.TestCaseWithMemoryTransport):
 
1750
class TestSmartServerRepositoryIterRevisions(
 
1751
    tests.TestCaseWithMemoryTransport):
 
1752
 
 
1753
    def test_basic(self):
 
1754
        backing = self.get_transport()
 
1755
        request = smart_repo.SmartServerRepositoryIterRevisions(backing)
 
1756
        tree = self.make_branch_and_memory_tree('.', format='2a')
 
1757
        tree.lock_write()
 
1758
        tree.add('')
 
1759
        tree.commit('1st commit', rev_id="rev1")
 
1760
        tree.commit('2nd commit', rev_id="rev2")
 
1761
        tree.unlock()
 
1762
 
 
1763
        self.assertIs(None, request.execute(''))
 
1764
        response = request.do_body("rev1\nrev2")
 
1765
        self.assertTrue(response.is_successful())
 
1766
        # Format 2a uses serializer format 10
 
1767
        self.assertEquals(response.args, ("ok", "10"))
 
1768
 
 
1769
        self.addCleanup(tree.branch.lock_read().unlock)
 
1770
        entries = [zlib.compress(record.get_bytes_as("fulltext")) for record in
 
1771
            tree.branch.repository.revisions.get_record_stream(
 
1772
            [("rev1", ), ("rev2", )], "unordered", True)]
 
1773
 
 
1774
        contents = "".join(response.body_stream)
 
1775
        self.assertTrue(contents in (
 
1776
            "".join([entries[0], entries[1]]),
 
1777
            "".join([entries[1], entries[0]])))
 
1778
 
 
1779
    def test_missing(self):
 
1780
        backing = self.get_transport()
 
1781
        request = smart_repo.SmartServerRepositoryIterRevisions(backing)
 
1782
        tree = self.make_branch_and_memory_tree('.', format='2a')
 
1783
 
 
1784
        self.assertIs(None, request.execute(''))
 
1785
        response = request.do_body("rev1\nrev2")
 
1786
        self.assertTrue(response.is_successful())
 
1787
        # Format 2a uses serializer format 10
 
1788
        self.assertEquals(response.args, ("ok", "10"))
 
1789
 
 
1790
        contents = "".join(response.body_stream)
 
1791
        self.assertEquals(contents, "")
 
1792
 
 
1793
 
 
1794
class GetStreamTestBase(tests.TestCaseWithMemoryTransport):
1451
1795
 
1452
1796
    def make_two_commit_repo(self):
1453
1797
        tree = self.make_branch_and_memory_tree('.')
1459
1803
        repo = tree.branch.repository
1460
1804
        return repo, r1, r2
1461
1805
 
 
1806
 
 
1807
class TestSmartServerRepositoryGetStream(GetStreamTestBase):
 
1808
 
1462
1809
    def test_ancestry_of(self):
1463
1810
        """The search argument may be a 'ancestry-of' some heads'."""
1464
1811
        backing = self.get_transport()
1485
1832
        stream_bytes = ''.join(response.body_stream)
1486
1833
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
1487
1834
 
 
1835
    def test_search_everything(self):
 
1836
        """A search of 'everything' returns a stream."""
 
1837
        backing = self.get_transport()
 
1838
        request = smart_repo.SmartServerRepositoryGetStream_1_19(backing)
 
1839
        repo, r1, r2 = self.make_two_commit_repo()
 
1840
        serialised_fetch_spec = 'everything'
 
1841
        request.execute('', repo._format.network_name())
 
1842
        response = request.do_body(serialised_fetch_spec)
 
1843
        self.assertEqual(('ok',), response.args)
 
1844
        stream_bytes = ''.join(response.body_stream)
 
1845
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
 
1846
 
1488
1847
 
1489
1848
class TestSmartServerRequestHasRevision(tests.TestCaseWithMemoryTransport):
1490
1849
 
1511
1870
            request.execute('', rev_id_utf8))
1512
1871
 
1513
1872
 
 
1873
class TestSmartServerRepositoryIterFilesBytes(tests.TestCaseWithTransport):
 
1874
 
 
1875
    def test_single(self):
 
1876
        backing = self.get_transport()
 
1877
        request = smart_repo.SmartServerRepositoryIterFilesBytes(backing)
 
1878
        t = self.make_branch_and_tree('.')
 
1879
        self.addCleanup(t.lock_write().unlock)
 
1880
        self.build_tree_contents([("file", "somecontents")])
 
1881
        t.add(["file"], ["thefileid"])
 
1882
        t.commit(rev_id='somerev', message="add file")
 
1883
        self.assertIs(None, request.execute(''))
 
1884
        response = request.do_body("thefileid\0somerev\n")
 
1885
        self.assertTrue(response.is_successful())
 
1886
        self.assertEquals(response.args, ("ok", ))
 
1887
        self.assertEquals("".join(response.body_stream),
 
1888
            "ok\x000\n" + zlib.compress("somecontents"))
 
1889
 
 
1890
    def test_missing(self):
 
1891
        backing = self.get_transport()
 
1892
        request = smart_repo.SmartServerRepositoryIterFilesBytes(backing)
 
1893
        t = self.make_branch_and_tree('.')
 
1894
        self.addCleanup(t.lock_write().unlock)
 
1895
        self.assertIs(None, request.execute(''))
 
1896
        response = request.do_body("thefileid\0revision\n")
 
1897
        self.assertTrue(response.is_successful())
 
1898
        self.assertEquals(response.args, ("ok", ))
 
1899
        self.assertEquals("".join(response.body_stream),
 
1900
            "absent\x00thefileid\x00revision\x000\n")
 
1901
 
 
1902
 
 
1903
class TestSmartServerRequestHasSignatureForRevisionId(
 
1904
        tests.TestCaseWithMemoryTransport):
 
1905
 
 
1906
    def test_missing_revision(self):
 
1907
        """For a missing revision, NoSuchRevision is returned."""
 
1908
        backing = self.get_transport()
 
1909
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1910
            backing)
 
1911
        self.make_repository('.')
 
1912
        self.assertEqual(
 
1913
            smart_req.FailedSmartServerResponse(
 
1914
                ('nosuchrevision', 'revid'), None),
 
1915
            request.execute('', 'revid'))
 
1916
 
 
1917
    def test_missing_signature(self):
 
1918
        """For a missing signature, ('no', ) is returned."""
 
1919
        backing = self.get_transport()
 
1920
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1921
            backing)
 
1922
        tree = self.make_branch_and_memory_tree('.')
 
1923
        tree.lock_write()
 
1924
        tree.add('')
 
1925
        r1 = tree.commit('a commit', rev_id='A')
 
1926
        tree.unlock()
 
1927
        self.assertTrue(tree.branch.repository.has_revision('A'))
 
1928
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
 
1929
            request.execute('', 'A'))
 
1930
 
 
1931
    def test_present_signature(self):
 
1932
        """For a present signature, ('yes', ) is returned."""
 
1933
        backing = self.get_transport()
 
1934
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1935
            backing)
 
1936
        strategy = gpg.LoopbackGPGStrategy(None)
 
1937
        tree = self.make_branch_and_memory_tree('.')
 
1938
        tree.lock_write()
 
1939
        tree.add('')
 
1940
        r1 = tree.commit('a commit', rev_id='A')
 
1941
        tree.branch.repository.start_write_group()
 
1942
        tree.branch.repository.sign_revision('A', strategy)
 
1943
        tree.branch.repository.commit_write_group()
 
1944
        tree.unlock()
 
1945
        self.assertTrue(tree.branch.repository.has_revision('A'))
 
1946
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
 
1947
            request.execute('', 'A'))
 
1948
 
 
1949
 
1514
1950
class TestSmartServerRepositoryGatherStats(tests.TestCaseWithMemoryTransport):
1515
1951
 
1516
1952
    def test_empty_revid(self):
1569
2005
                         request.execute('',
1570
2006
                                         rev_id_utf8, 'yes'))
1571
2007
 
 
2008
    def test_unknown_revid(self):
 
2009
        """An unknown revision id causes a 'nosuchrevision' error."""
 
2010
        backing = self.get_transport()
 
2011
        request = smart_repo.SmartServerRepositoryGatherStats(backing)
 
2012
        repository = self.make_repository('.')
 
2013
        expected_body = 'revisions: 0\n'
 
2014
        self.assertEqual(
 
2015
            smart_req.FailedSmartServerResponse(
 
2016
                ('nosuchrevision', 'mia'), None),
 
2017
            request.execute('', 'mia', 'yes'))
 
2018
 
1572
2019
 
1573
2020
class TestSmartServerRepositoryIsShared(tests.TestCaseWithMemoryTransport):
1574
2021
 
1589
2036
            request.execute('', ))
1590
2037
 
1591
2038
 
 
2039
class TestSmartServerRepositoryGetRevisionSignatureText(
 
2040
        tests.TestCaseWithMemoryTransport):
 
2041
 
 
2042
    def test_get_signature(self):
 
2043
        backing = self.get_transport()
 
2044
        request = smart_repo.SmartServerRepositoryGetRevisionSignatureText(
 
2045
            backing)
 
2046
        bb = self.make_branch_builder('.')
 
2047
        bb.build_commit(rev_id='A')
 
2048
        repo = bb.get_branch().repository
 
2049
        strategy = gpg.LoopbackGPGStrategy(None)
 
2050
        self.addCleanup(repo.lock_write().unlock)
 
2051
        repo.start_write_group()
 
2052
        repo.sign_revision('A', strategy)
 
2053
        repo.commit_write_group()
 
2054
        expected_body = (
 
2055
            '-----BEGIN PSEUDO-SIGNED CONTENT-----\n' +
 
2056
            Testament.from_revision(repo, 'A').as_short_text() +
 
2057
            '-----END PSEUDO-SIGNED CONTENT-----\n')
 
2058
        self.assertEqual(
 
2059
            smart_req.SmartServerResponse(('ok', ), expected_body),
 
2060
            request.execute('', 'A'))
 
2061
 
 
2062
 
 
2063
class TestSmartServerRepositoryMakeWorkingTrees(
 
2064
        tests.TestCaseWithMemoryTransport):
 
2065
 
 
2066
    def test_make_working_trees(self):
 
2067
        """For a repository with working trees, ('yes', ) is returned."""
 
2068
        backing = self.get_transport()
 
2069
        request = smart_repo.SmartServerRepositoryMakeWorkingTrees(backing)
 
2070
        r = self.make_repository('.')
 
2071
        r.set_make_working_trees(True)
 
2072
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
 
2073
            request.execute('', ))
 
2074
 
 
2075
    def test_is_not_shared(self):
 
2076
        """For a repository with working trees, ('no', ) is returned."""
 
2077
        backing = self.get_transport()
 
2078
        request = smart_repo.SmartServerRepositoryMakeWorkingTrees(backing)
 
2079
        r = self.make_repository('.')
 
2080
        r.set_make_working_trees(False)
 
2081
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
 
2082
            request.execute('', ))
 
2083
 
 
2084
 
1592
2085
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
1593
2086
 
1594
2087
    def test_lock_write_on_unlocked_repo(self):
1610
2103
        backing = self.get_transport()
1611
2104
        request = smart_repo.SmartServerRepositoryLockWrite(backing)
1612
2105
        repository = self.make_repository('.', format='knit')
1613
 
        repo_token = repository.lock_write()
 
2106
        repo_token = repository.lock_write().repository_token
1614
2107
        repository.leave_lock_in_place()
1615
2108
        repository.unlock()
1616
2109
        response = request.execute('')
1658
2151
        request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1659
2152
            backing)
1660
2153
        repository = self.make_repository('.', format='knit')
1661
 
        lock_token = repository.lock_write()
 
2154
        lock_token = repository.lock_write().repository_token
1662
2155
        response = request.execute('', '', lock_token)
1663
2156
        self.assertEqual(None, response)
1664
2157
        response = request.do_chunk(self.make_empty_byte_stream(repository))
1672
2165
        request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1673
2166
            backing)
1674
2167
        repository = self.make_repository('.', format='knit')
1675
 
        lock_token = repository.lock_write()
 
2168
        lock_token = repository.lock_write().repository_token
1676
2169
        self.assertRaises(
1677
2170
            errors.TokenMismatch, request.execute, '', '', 'wrong-token')
1678
2171
        repository.unlock()
1687
2180
        backing = self.get_transport()
1688
2181
        request = smart_repo.SmartServerRepositoryUnlock(backing)
1689
2182
        repository = self.make_repository('.', format='knit')
1690
 
        token = repository.lock_write()
 
2183
        token = repository.lock_write().repository_token
1691
2184
        repository.leave_lock_in_place()
1692
2185
        repository.unlock()
1693
2186
        response = request.execute('', token)
1708
2201
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
1709
2202
 
1710
2203
 
 
2204
class TestSmartServerRepositoryGetPhysicalLockStatus(
 
2205
    tests.TestCaseWithTransport):
 
2206
 
 
2207
    def test_with_write_lock(self):
 
2208
        backing = self.get_transport()
 
2209
        repo = self.make_repository('.')
 
2210
        self.addCleanup(repo.lock_write().unlock)
 
2211
        # lock_write() doesn't necessarily actually take a physical
 
2212
        # lock out.
 
2213
        if repo.get_physical_lock_status():
 
2214
            expected = 'yes'
 
2215
        else:
 
2216
            expected = 'no'
 
2217
        request_class = smart_repo.SmartServerRepositoryGetPhysicalLockStatus
 
2218
        request = request_class(backing)
 
2219
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((expected,)),
 
2220
            request.execute('', ))
 
2221
 
 
2222
    def test_without_write_lock(self):
 
2223
        backing = self.get_transport()
 
2224
        repo = self.make_repository('.')
 
2225
        self.assertEquals(False, repo.get_physical_lock_status())
 
2226
        request_class = smart_repo.SmartServerRepositoryGetPhysicalLockStatus
 
2227
        request = request_class(backing)
 
2228
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('no',)),
 
2229
            request.execute('', ))
 
2230
 
 
2231
 
 
2232
class TestSmartServerRepositoryReconcile(tests.TestCaseWithTransport):
 
2233
 
 
2234
    def test_reconcile(self):
 
2235
        backing = self.get_transport()
 
2236
        repo = self.make_repository('.')
 
2237
        token = repo.lock_write().repository_token
 
2238
        self.addCleanup(repo.unlock)
 
2239
        request_class = smart_repo.SmartServerRepositoryReconcile
 
2240
        request = request_class(backing)
 
2241
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(
 
2242
            ('ok', ),
 
2243
             'garbage_inventories: 0\n'
 
2244
             'inconsistent_parents: 0\n'),
 
2245
            request.execute('', token))
 
2246
 
 
2247
 
1711
2248
class TestSmartServerIsReadonly(tests.TestCaseWithMemoryTransport):
1712
2249
 
1713
2250
    def test_is_readonly_no(self):
1751
2288
        self.assertTrue(repo.make_working_trees())
1752
2289
 
1753
2290
 
 
2291
class TestSmartServerRepositoryGetSerializerFormat(
 
2292
    tests.TestCaseWithMemoryTransport):
 
2293
 
 
2294
    def test_get_serializer_format(self):
 
2295
        backing = self.get_transport()
 
2296
        repo = self.make_repository('.', format='2a')
 
2297
        request_class = smart_repo.SmartServerRepositoryGetSerializerFormat
 
2298
        request = request_class(backing)
 
2299
        self.assertEqual(
 
2300
            smart_req.SuccessfulSmartServerResponse(('ok', '10')),
 
2301
            request.execute(''))
 
2302
 
 
2303
 
 
2304
class TestSmartServerRepositoryWriteGroup(
 
2305
    tests.TestCaseWithMemoryTransport):
 
2306
 
 
2307
    def test_start_write_group(self):
 
2308
        backing = self.get_transport()
 
2309
        repo = self.make_repository('.')
 
2310
        lock_token = repo.lock_write().repository_token
 
2311
        self.addCleanup(repo.unlock)
 
2312
        request_class = smart_repo.SmartServerRepositoryStartWriteGroup
 
2313
        request = request_class(backing)
 
2314
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok', [])),
 
2315
            request.execute('', lock_token))
 
2316
 
 
2317
    def test_start_write_group_unsuspendable(self):
 
2318
        backing = self.get_transport()
 
2319
        repo = self.make_repository('.', format='knit')
 
2320
        lock_token = repo.lock_write().repository_token
 
2321
        self.addCleanup(repo.unlock)
 
2322
        request_class = smart_repo.SmartServerRepositoryStartWriteGroup
 
2323
        request = request_class(backing)
 
2324
        self.assertEqual(
 
2325
            smart_req.FailedSmartServerResponse(('UnsuspendableWriteGroup',)),
 
2326
            request.execute('', lock_token))
 
2327
 
 
2328
    def test_commit_write_group(self):
 
2329
        backing = self.get_transport()
 
2330
        repo = self.make_repository('.')
 
2331
        lock_token = repo.lock_write().repository_token
 
2332
        self.addCleanup(repo.unlock)
 
2333
        repo.start_write_group()
 
2334
        tokens = repo.suspend_write_group()
 
2335
        request_class = smart_repo.SmartServerRepositoryCommitWriteGroup
 
2336
        request = request_class(backing)
 
2337
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
 
2338
            request.execute('', lock_token, tokens))
 
2339
 
 
2340
    def test_abort_write_group(self):
 
2341
        backing = self.get_transport()
 
2342
        repo = self.make_repository('.')
 
2343
        lock_token = repo.lock_write().repository_token
 
2344
        repo.start_write_group()
 
2345
        tokens = repo.suspend_write_group()
 
2346
        self.addCleanup(repo.unlock)
 
2347
        request_class = smart_repo.SmartServerRepositoryAbortWriteGroup
 
2348
        request = request_class(backing)
 
2349
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
 
2350
            request.execute('', lock_token, tokens))
 
2351
 
 
2352
    def test_check_write_group(self):
 
2353
        backing = self.get_transport()
 
2354
        repo = self.make_repository('.')
 
2355
        lock_token = repo.lock_write().repository_token
 
2356
        repo.start_write_group()
 
2357
        tokens = repo.suspend_write_group()
 
2358
        self.addCleanup(repo.unlock)
 
2359
        request_class = smart_repo.SmartServerRepositoryCheckWriteGroup
 
2360
        request = request_class(backing)
 
2361
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
 
2362
            request.execute('', lock_token, tokens))
 
2363
 
 
2364
    def test_check_write_group_invalid(self):
 
2365
        backing = self.get_transport()
 
2366
        repo = self.make_repository('.')
 
2367
        lock_token = repo.lock_write().repository_token
 
2368
        self.addCleanup(repo.unlock)
 
2369
        request_class = smart_repo.SmartServerRepositoryCheckWriteGroup
 
2370
        request = request_class(backing)
 
2371
        self.assertEqual(smart_req.FailedSmartServerResponse(
 
2372
            ('UnresumableWriteGroup', ['random'],
 
2373
                'Malformed write group token')),
 
2374
            request.execute('', lock_token, ["random"]))
 
2375
 
 
2376
 
1754
2377
class TestSmartServerPackRepositoryAutopack(tests.TestCaseWithTransport):
1755
2378
 
1756
2379
    def make_repo_needing_autopacking(self, path='.'):
1822
2445
        """All registered request_handlers can be found."""
1823
2446
        # If there's a typo in a register_lazy call, this loop will fail with
1824
2447
        # an AttributeError.
1825
 
        for key, item in smart_req.request_handlers.iteritems():
1826
 
            pass
 
2448
        for key in smart_req.request_handlers.keys():
 
2449
            try:
 
2450
                item = smart_req.request_handlers.get(key)
 
2451
            except AttributeError, e:
 
2452
                raise AttributeError('failed to get %s: %s' % (key, e))
1827
2453
 
1828
2454
    def assertHandlerEqual(self, verb, handler):
1829
2455
        self.assertEqual(smart_req.request_handlers.get(verb), handler)
1830
2456
 
1831
2457
    def test_registered_methods(self):
1832
2458
        """Test that known methods are registered to the correct object."""
 
2459
        self.assertHandlerEqual('Branch.break_lock',
 
2460
            smart_branch.SmartServerBranchBreakLock)
1833
2461
        self.assertHandlerEqual('Branch.get_config_file',
1834
2462
            smart_branch.SmartServerBranchGetConfigFile)
 
2463
        self.assertHandlerEqual('Branch.put_config_file',
 
2464
            smart_branch.SmartServerBranchPutConfigFile)
1835
2465
        self.assertHandlerEqual('Branch.get_parent',
1836
2466
            smart_branch.SmartServerBranchGetParent)
 
2467
        self.assertHandlerEqual('Branch.get_physical_lock_status',
 
2468
            smart_branch.SmartServerBranchRequestGetPhysicalLockStatus)
1837
2469
        self.assertHandlerEqual('Branch.get_tags_bytes',
1838
2470
            smart_branch.SmartServerBranchGetTagsBytes)
1839
2471
        self.assertHandlerEqual('Branch.lock_write',
1842
2474
            smart_branch.SmartServerBranchRequestLastRevisionInfo)
1843
2475
        self.assertHandlerEqual('Branch.revision_history',
1844
2476
            smart_branch.SmartServerRequestRevisionHistory)
 
2477
        self.assertHandlerEqual('Branch.revision_id_to_revno',
 
2478
            smart_branch.SmartServerBranchRequestRevisionIdToRevno)
1845
2479
        self.assertHandlerEqual('Branch.set_config_option',
1846
2480
            smart_branch.SmartServerBranchRequestSetConfigOption)
1847
2481
        self.assertHandlerEqual('Branch.set_last_revision',
1854
2488
            smart_branch.SmartServerBranchRequestSetParentLocation)
1855
2489
        self.assertHandlerEqual('Branch.unlock',
1856
2490
            smart_branch.SmartServerBranchRequestUnlock)
 
2491
        self.assertHandlerEqual('BzrDir.destroy_branch',
 
2492
            smart_dir.SmartServerBzrDirRequestDestroyBranch)
1857
2493
        self.assertHandlerEqual('BzrDir.find_repository',
1858
2494
            smart_dir.SmartServerRequestFindRepositoryV1)
1859
2495
        self.assertHandlerEqual('BzrDir.find_repositoryV2',
1862
2498
            smart_dir.SmartServerRequestInitializeBzrDir)
1863
2499
        self.assertHandlerEqual('BzrDirFormat.initialize_ex_1.16',
1864
2500
            smart_dir.SmartServerRequestBzrDirInitializeEx)
 
2501
        self.assertHandlerEqual('BzrDir.checkout_metadir',
 
2502
            smart_dir.SmartServerBzrDirRequestCheckoutMetaDir)
1865
2503
        self.assertHandlerEqual('BzrDir.cloning_metadir',
1866
2504
            smart_dir.SmartServerBzrDirRequestCloningMetaDir)
1867
2505
        self.assertHandlerEqual('BzrDir.get_config_file',
1874
2512
            smart_dir.SmartServerRequestOpenBranchV3)
1875
2513
        self.assertHandlerEqual('PackRepository.autopack',
1876
2514
            smart_packrepo.SmartServerPackRepositoryAutopack)
 
2515
        self.assertHandlerEqual('Repository.add_signature_text',
 
2516
            smart_repo.SmartServerRepositoryAddSignatureText)
 
2517
        self.assertHandlerEqual('Repository.all_revision_ids',
 
2518
            smart_repo.SmartServerRepositoryAllRevisionIds)
 
2519
        self.assertHandlerEqual('Repository.break_lock',
 
2520
            smart_repo.SmartServerRepositoryBreakLock)
1877
2521
        self.assertHandlerEqual('Repository.gather_stats',
1878
2522
            smart_repo.SmartServerRepositoryGatherStats)
1879
2523
        self.assertHandlerEqual('Repository.get_parent_map',
1880
2524
            smart_repo.SmartServerRepositoryGetParentMap)
 
2525
        self.assertHandlerEqual('Repository.get_physical_lock_status',
 
2526
            smart_repo.SmartServerRepositoryGetPhysicalLockStatus)
1881
2527
        self.assertHandlerEqual('Repository.get_rev_id_for_revno',
1882
2528
            smart_repo.SmartServerRepositoryGetRevIdForRevno)
1883
2529
        self.assertHandlerEqual('Repository.get_revision_graph',
1884
2530
            smart_repo.SmartServerRepositoryGetRevisionGraph)
 
2531
        self.assertHandlerEqual('Repository.get_revision_signature_text',
 
2532
            smart_repo.SmartServerRepositoryGetRevisionSignatureText)
1885
2533
        self.assertHandlerEqual('Repository.get_stream',
1886
2534
            smart_repo.SmartServerRepositoryGetStream)
 
2535
        self.assertHandlerEqual('Repository.get_stream_1.19',
 
2536
            smart_repo.SmartServerRepositoryGetStream_1_19)
 
2537
        self.assertHandlerEqual('Repository.iter_revisions',
 
2538
            smart_repo.SmartServerRepositoryIterRevisions)
1887
2539
        self.assertHandlerEqual('Repository.has_revision',
1888
2540
            smart_repo.SmartServerRequestHasRevision)
1889
2541
        self.assertHandlerEqual('Repository.insert_stream',
1892
2544
            smart_repo.SmartServerRepositoryInsertStreamLocked)
1893
2545
        self.assertHandlerEqual('Repository.is_shared',
1894
2546
            smart_repo.SmartServerRepositoryIsShared)
 
2547
        self.assertHandlerEqual('Repository.iter_files_bytes',
 
2548
            smart_repo.SmartServerRepositoryIterFilesBytes)
1895
2549
        self.assertHandlerEqual('Repository.lock_write',
1896
2550
            smart_repo.SmartServerRepositoryLockWrite)
 
2551
        self.assertHandlerEqual('Repository.make_working_trees',
 
2552
            smart_repo.SmartServerRepositoryMakeWorkingTrees)
 
2553
        self.assertHandlerEqual('Repository.pack',
 
2554
            smart_repo.SmartServerRepositoryPack)
 
2555
        self.assertHandlerEqual('Repository.reconcile',
 
2556
            smart_repo.SmartServerRepositoryReconcile)
1897
2557
        self.assertHandlerEqual('Repository.tarball',
1898
2558
            smart_repo.SmartServerRepositoryTarball)
1899
2559
        self.assertHandlerEqual('Repository.unlock',
1900
2560
            smart_repo.SmartServerRepositoryUnlock)
 
2561
        self.assertHandlerEqual('Repository.start_write_group',
 
2562
            smart_repo.SmartServerRepositoryStartWriteGroup)
 
2563
        self.assertHandlerEqual('Repository.check_write_group',
 
2564
            smart_repo.SmartServerRepositoryCheckWriteGroup)
 
2565
        self.assertHandlerEqual('Repository.commit_write_group',
 
2566
            smart_repo.SmartServerRepositoryCommitWriteGroup)
 
2567
        self.assertHandlerEqual('Repository.abort_write_group',
 
2568
            smart_repo.SmartServerRepositoryAbortWriteGroup)
 
2569
        self.assertHandlerEqual('VersionedFileRepository.get_serializer_format',
 
2570
            smart_repo.SmartServerRepositoryGetSerializerFormat)
 
2571
        self.assertHandlerEqual('VersionedFileRepository.get_inventories',
 
2572
            smart_repo.SmartServerRepositoryGetInventories)
1901
2573
        self.assertHandlerEqual('Transport.is_readonly',
1902
2574
            smart_req.SmartServerIsReadonly)
 
2575
 
 
2576
 
 
2577
class SmartTCPServerHookTests(tests.TestCaseWithMemoryTransport):
 
2578
    """Tests for SmartTCPServer hooks."""
 
2579
 
 
2580
    def setUp(self):
 
2581
        super(SmartTCPServerHookTests, self).setUp()
 
2582
        self.server = server.SmartTCPServer(self.get_transport())
 
2583
 
 
2584
    def test_run_server_started_hooks(self):
 
2585
        """Test the server started hooks get fired properly."""
 
2586
        started_calls = []
 
2587
        server.SmartTCPServer.hooks.install_named_hook('server_started',
 
2588
            lambda backing_urls, url: started_calls.append((backing_urls, url)),
 
2589
            None)
 
2590
        started_ex_calls = []
 
2591
        server.SmartTCPServer.hooks.install_named_hook('server_started_ex',
 
2592
            lambda backing_urls, url: started_ex_calls.append((backing_urls, url)),
 
2593
            None)
 
2594
        self.server._sockname = ('example.com', 42)
 
2595
        self.server.run_server_started_hooks()
 
2596
        self.assertEquals(started_calls,
 
2597
            [([self.get_transport().base], 'bzr://example.com:42/')])
 
2598
        self.assertEquals(started_ex_calls,
 
2599
            [([self.get_transport().base], self.server)])
 
2600
 
 
2601
    def test_run_server_started_hooks_ipv6(self):
 
2602
        """Test that socknames can contain 4-tuples."""
 
2603
        self.server._sockname = ('::', 42, 0, 0)
 
2604
        started_calls = []
 
2605
        server.SmartTCPServer.hooks.install_named_hook('server_started',
 
2606
            lambda backing_urls, url: started_calls.append((backing_urls, url)),
 
2607
            None)
 
2608
        self.server.run_server_started_hooks()
 
2609
        self.assertEquals(started_calls,
 
2610
                [([self.get_transport().base], 'bzr://:::42/')])
 
2611
 
 
2612
    def test_run_server_stopped_hooks(self):
 
2613
        """Test the server stopped hooks."""
 
2614
        self.server._sockname = ('example.com', 42)
 
2615
        stopped_calls = []
 
2616
        server.SmartTCPServer.hooks.install_named_hook('server_stopped',
 
2617
            lambda backing_urls, url: stopped_calls.append((backing_urls, url)),
 
2618
            None)
 
2619
        self.server.run_server_stopped_hooks()
 
2620
        self.assertEquals(stopped_calls,
 
2621
            [([self.get_transport().base], 'bzr://example.com:42/')])
 
2622
 
 
2623
 
 
2624
class TestSmartServerRepositoryPack(tests.TestCaseWithMemoryTransport):
 
2625
 
 
2626
    def test_pack(self):
 
2627
        backing = self.get_transport()
 
2628
        request = smart_repo.SmartServerRepositoryPack(backing)
 
2629
        tree = self.make_branch_and_memory_tree('.')
 
2630
        repo_token = tree.branch.repository.lock_write().repository_token
 
2631
 
 
2632
        self.assertIs(None, request.execute('', repo_token, False))
 
2633
 
 
2634
        self.assertEqual(
 
2635
            smart_req.SuccessfulSmartServerResponse(('ok', ), ),
 
2636
            request.do_body(''))
 
2637
 
 
2638
 
 
2639
class TestSmartServerRepositoryGetInventories(tests.TestCaseWithTransport):
 
2640
 
 
2641
    def _get_serialized_inventory_delta(self, repository, base_revid, revid):
 
2642
        base_inv = repository.revision_tree(base_revid).inventory
 
2643
        inv = repository.revision_tree(revid).inventory
 
2644
        inv_delta = inv._make_delta(base_inv)
 
2645
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
 
2646
        return "".join(serializer.delta_to_lines(base_revid, revid, inv_delta))
 
2647
 
 
2648
    def test_single(self):
 
2649
        backing = self.get_transport()
 
2650
        request = smart_repo.SmartServerRepositoryGetInventories(backing)
 
2651
        t = self.make_branch_and_tree('.', format='2a')
 
2652
        self.addCleanup(t.lock_write().unlock)
 
2653
        self.build_tree_contents([("file", "somecontents")])
 
2654
        t.add(["file"], ["thefileid"])
 
2655
        t.commit(rev_id='somerev', message="add file")
 
2656
        self.assertIs(None, request.execute('', 'unordered'))
 
2657
        response = request.do_body("somerev\n")
 
2658
        self.assertTrue(response.is_successful())
 
2659
        self.assertEquals(response.args, ("ok", ))
 
2660
        stream = [('inventory-deltas', [
 
2661
            versionedfile.FulltextContentFactory('somerev', None, None,
 
2662
                self._get_serialized_inventory_delta(
 
2663
                    t.branch.repository, 'null:', 'somerev'))])]
 
2664
        fmt = bzrdir.format_registry.get('2a')().repository_format
 
2665
        self.assertEquals(
 
2666
            "".join(response.body_stream),
 
2667
            "".join(smart_repo._stream_to_byte_stream(stream, fmt)))
 
2668
 
 
2669
    def test_empty(self):
 
2670
        backing = self.get_transport()
 
2671
        request = smart_repo.SmartServerRepositoryGetInventories(backing)
 
2672
        t = self.make_branch_and_tree('.', format='2a')
 
2673
        self.addCleanup(t.lock_write().unlock)
 
2674
        self.build_tree_contents([("file", "somecontents")])
 
2675
        t.add(["file"], ["thefileid"])
 
2676
        t.commit(rev_id='somerev', message="add file")
 
2677
        self.assertIs(None, request.execute('', 'unordered'))
 
2678
        response = request.do_body("")
 
2679
        self.assertTrue(response.is_successful())
 
2680
        self.assertEquals(response.args, ("ok", ))
 
2681
        self.assertEquals("".join(response.body_stream),
 
2682
            "Bazaar pack format 1 (introduced in 0.18)\nB54\n\nBazaar repository format 2a (needs bzr 1.16 or later)\nE")