/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

(jelmer) Make sure that a branch user URL uniquely identifies that branch,
 and can be used to open it. (Jelmer Vernooij)

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
30
28
 
31
29
from bzrlib import (
32
 
    bencode,
33
30
    branch as _mod_branch,
34
31
    bzrdir,
35
32
    errors,
36
 
    pack,
 
33
    gpg,
37
34
    tests,
38
35
    transport,
39
36
    urlutils,
89
86
            backing_transport = tests.TestCaseWithTransport.get_transport(self)
90
87
            self._chroot_server = chroot.ChrootServer(backing_transport)
91
88
            self.start_server(self._chroot_server)
92
 
        t = transport.get_transport(self._chroot_server.get_url())
 
89
        t = transport.get_transport_from_url(self._chroot_server.get_url())
93
90
        if relpath is not None:
94
91
            t = t.clone(relpath)
95
92
        return t
103
100
        # the default or a parameterized class, but rather use the
104
101
        # TestCaseWithTransport infrastructure to set up a smart server and
105
102
        # transport.
106
 
        self.transport_server = self.make_transport_server
 
103
        self.overrideAttr(self, "transport_server", self.make_transport_server)
107
104
 
108
105
    def make_transport_server(self):
109
106
        return test_server.SmartTCPServer_for_testing('-' + self.id())
767
764
class TestLockedBranch(tests.TestCaseWithMemoryTransport):
768
765
 
769
766
    def get_lock_tokens(self, branch):
770
 
        branch_token = branch.lock_write()
771
 
        repo_token = branch.repository.lock_write()
 
767
        branch_token = branch.lock_write().branch_token
 
768
        repo_token = branch.repository.lock_write().repository_token
772
769
        branch.repository.unlock()
773
770
        return branch_token, repo_token
774
771
 
802
799
        branch.unlock()
803
800
 
804
801
 
 
802
class TestSmartServerBranchRequestSetConfigOptionDict(TestLockedBranch):
 
803
 
 
804
    def setUp(self):
 
805
        TestLockedBranch.setUp(self)
 
806
        # A dict with non-ascii keys and values to exercise unicode
 
807
        # roundtripping.
 
808
        self.encoded_value_dict = (
 
809
            'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde')
 
810
        self.value_dict = {
 
811
            'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
 
812
 
 
813
    def test_value_name(self):
 
814
        branch = self.make_branch('.')
 
815
        request = smart_branch.SmartServerBranchRequestSetConfigOptionDict(
 
816
            branch.bzrdir.root_transport)
 
817
        branch_token, repo_token = self.get_lock_tokens(branch)
 
818
        config = branch._get_config()
 
819
        result = request.execute('', branch_token, repo_token,
 
820
            self.encoded_value_dict, 'foo', '')
 
821
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
 
822
        self.assertEqual(self.value_dict, config.get_option('foo'))
 
823
        # Cleanup
 
824
        branch.unlock()
 
825
 
 
826
    def test_value_name_section(self):
 
827
        branch = self.make_branch('.')
 
828
        request = smart_branch.SmartServerBranchRequestSetConfigOptionDict(
 
829
            branch.bzrdir.root_transport)
 
830
        branch_token, repo_token = self.get_lock_tokens(branch)
 
831
        config = branch._get_config()
 
832
        result = request.execute('', branch_token, repo_token,
 
833
            self.encoded_value_dict, 'foo', 'gam')
 
834
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
 
835
        self.assertEqual(self.value_dict, config.get_option('foo', 'gam'))
 
836
        # Cleanup
 
837
        branch.unlock()
 
838
 
 
839
 
805
840
class TestSmartServerBranchRequestSetTagsBytes(TestLockedBranch):
806
841
    # Only called when the branch format and tags match [yay factory
807
842
    # methods] so only need to test straight forward cases.
898
933
        # its repository.
899
934
        self.make_tree_with_two_commits()
900
935
        rev_id_utf8 = u'\xc8'.encode('utf-8')
901
 
        self.tree.branch.set_revision_history([])
 
936
        self.tree.branch.set_last_revision_info(0, 'null:')
902
937
        self.assertEqual(
903
938
            (0, 'null:'), self.tree.branch.last_revision_info())
904
939
        # We can update the branch to a revision that is present in the
1073
1108
            response)
1074
1109
 
1075
1110
 
1076
 
class TestSmartServerBranchRequestSetParent(tests.TestCaseWithMemoryTransport):
 
1111
class TestSmartServerBranchRequestSetParent(TestLockedBranch):
1077
1112
 
1078
1113
    def test_set_parent_none(self):
1079
1114
        branch = self.make_branch('base', format="1.9")
1082
1117
        branch.unlock()
1083
1118
        request = smart_branch.SmartServerBranchRequestSetParentLocation(
1084
1119
            self.get_transport())
1085
 
        branch_token = branch.lock_write()
1086
 
        repo_token = branch.repository.lock_write()
 
1120
        branch_token, repo_token = self.get_lock_tokens(branch)
1087
1121
        try:
1088
1122
            response = request.execute('base', branch_token, repo_token, '')
1089
1123
        finally:
1090
 
            branch.repository.unlock()
1091
1124
            branch.unlock()
1092
1125
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
1093
1126
        self.assertEqual(None, branch.get_parent())
1096
1129
        branch = self.make_branch('base', format="1.9")
1097
1130
        request = smart_branch.SmartServerBranchRequestSetParentLocation(
1098
1131
            self.get_transport())
1099
 
        branch_token = branch.lock_write()
1100
 
        repo_token = branch.repository.lock_write()
 
1132
        branch_token, repo_token = self.get_lock_tokens(branch)
1101
1133
        try:
1102
1134
            response = request.execute('base', branch_token, repo_token,
1103
1135
            'http://bar/')
1104
1136
        finally:
1105
 
            branch.repository.unlock()
1106
1137
            branch.unlock()
1107
1138
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
1108
1139
        self.assertEqual('http://bar/', branch.get_parent())
1137
1168
            response)
1138
1169
 
1139
1170
 
1140
 
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithMemoryTransport):
 
1171
class TestSmartServerBranchRequestLockWrite(TestLockedBranch):
1141
1172
 
1142
1173
    def setUp(self):
1143
1174
        tests.TestCaseWithMemoryTransport.setUp(self)
1165
1196
        backing = self.get_transport()
1166
1197
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1167
1198
        branch = self.make_branch('.')
1168
 
        branch_token = branch.lock_write()
 
1199
        branch_token = branch.lock_write().branch_token
1169
1200
        branch.leave_lock_in_place()
1170
1201
        branch.unlock()
1171
1202
        response = request.execute('')
1180
1211
        backing = self.get_transport()
1181
1212
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1182
1213
        branch = self.make_branch('.', format='knit')
1183
 
        branch_token = branch.lock_write()
1184
 
        repo_token = branch.repository.lock_write()
1185
 
        branch.repository.unlock()
 
1214
        branch_token, repo_token = self.get_lock_tokens(branch)
1186
1215
        branch.leave_lock_in_place()
1187
1216
        branch.repository.leave_lock_in_place()
1188
1217
        branch.unlock()
1203
1232
        backing = self.get_transport()
1204
1233
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1205
1234
        branch = self.make_branch('.', format='knit')
1206
 
        branch_token = branch.lock_write()
1207
 
        repo_token = branch.repository.lock_write()
1208
 
        branch.repository.unlock()
 
1235
        branch_token, repo_token = self.get_lock_tokens(branch)
1209
1236
        branch.leave_lock_in_place()
1210
1237
        branch.repository.leave_lock_in_place()
1211
1238
        branch.unlock()
1226
1253
        request = smart_branch.SmartServerBranchRequestLockWrite(backing)
1227
1254
        branch = self.make_branch('.', format='knit')
1228
1255
        repo = branch.repository
1229
 
        repo_token = repo.lock_write()
 
1256
        repo_token = repo.lock_write().repository_token
1230
1257
        repo.leave_lock_in_place()
1231
1258
        repo.unlock()
1232
1259
        response = request.execute('')
1249
1276
        self.assertEqual('LockFailed', error_name)
1250
1277
 
1251
1278
 
1252
 
class TestSmartServerBranchRequestUnlock(tests.TestCaseWithMemoryTransport):
 
1279
class TestSmartServerBranchRequestUnlock(TestLockedBranch):
1253
1280
 
1254
1281
    def setUp(self):
1255
1282
        tests.TestCaseWithMemoryTransport.setUp(self)
1259
1286
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1260
1287
        branch = self.make_branch('.', format='knit')
1261
1288
        # Lock the branch
1262
 
        branch_token = branch.lock_write()
1263
 
        repo_token = branch.repository.lock_write()
1264
 
        branch.repository.unlock()
 
1289
        branch_token, repo_token = self.get_lock_tokens(branch)
1265
1290
        # Unlock the branch (and repo) object, leaving the physical locks
1266
1291
        # in place.
1267
1292
        branch.leave_lock_in_place()
1291
1316
        request = smart_branch.SmartServerBranchRequestUnlock(backing)
1292
1317
        branch = self.make_branch('.', format='knit')
1293
1318
        # Lock the repository.
1294
 
        repo_token = branch.repository.lock_write()
 
1319
        repo_token = branch.repository.lock_write().repository_token
1295
1320
        branch.repository.leave_lock_in_place()
1296
1321
        branch.repository.unlock()
1297
1322
        # Issue branch lock_write request on the unlocked branch (with locked
1298
1323
        # repo).
1299
 
        response = request.execute(
1300
 
            '', 'branch token', repo_token)
 
1324
        response = request.execute('', 'branch token', repo_token)
1301
1325
        self.assertEqual(
1302
1326
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
1303
1327
        # Cleanup
1447
1471
            request.execute('stacked', 1, (3, r3)))
1448
1472
 
1449
1473
 
1450
 
class TestSmartServerRepositoryGetStream(tests.TestCaseWithMemoryTransport):
 
1474
class GetStreamTestBase(tests.TestCaseWithMemoryTransport):
1451
1475
 
1452
1476
    def make_two_commit_repo(self):
1453
1477
        tree = self.make_branch_and_memory_tree('.')
1459
1483
        repo = tree.branch.repository
1460
1484
        return repo, r1, r2
1461
1485
 
 
1486
 
 
1487
class TestSmartServerRepositoryGetStream(GetStreamTestBase):
 
1488
 
1462
1489
    def test_ancestry_of(self):
1463
1490
        """The search argument may be a 'ancestry-of' some heads'."""
1464
1491
        backing = self.get_transport()
1485
1512
        stream_bytes = ''.join(response.body_stream)
1486
1513
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
1487
1514
 
 
1515
    def test_search_everything(self):
 
1516
        """A search of 'everything' returns a stream."""
 
1517
        backing = self.get_transport()
 
1518
        request = smart_repo.SmartServerRepositoryGetStream_1_19(backing)
 
1519
        repo, r1, r2 = self.make_two_commit_repo()
 
1520
        serialised_fetch_spec = 'everything'
 
1521
        request.execute('', repo._format.network_name())
 
1522
        response = request.do_body(serialised_fetch_spec)
 
1523
        self.assertEqual(('ok',), response.args)
 
1524
        stream_bytes = ''.join(response.body_stream)
 
1525
        self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
 
1526
 
1488
1527
 
1489
1528
class TestSmartServerRequestHasRevision(tests.TestCaseWithMemoryTransport):
1490
1529
 
1511
1550
            request.execute('', rev_id_utf8))
1512
1551
 
1513
1552
 
 
1553
class TestSmartServerRequestHasSignatureForRevisionId(
 
1554
        tests.TestCaseWithMemoryTransport):
 
1555
 
 
1556
    def test_missing_revision(self):
 
1557
        """For a missing revision, NoSuchRevision is returned."""
 
1558
        backing = self.get_transport()
 
1559
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1560
            backing)
 
1561
        self.make_repository('.')
 
1562
        self.assertEqual(
 
1563
            smart_req.FailedSmartServerResponse(
 
1564
                ('nosuchrevision', 'revid'), None),
 
1565
            request.execute('', 'revid'))
 
1566
 
 
1567
    def test_missing_signature(self):
 
1568
        """For a missing signature, ('no', ) is returned."""
 
1569
        backing = self.get_transport()
 
1570
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1571
            backing)
 
1572
        tree = self.make_branch_and_memory_tree('.')
 
1573
        tree.lock_write()
 
1574
        tree.add('')
 
1575
        r1 = tree.commit('a commit', rev_id='A')
 
1576
        tree.unlock()
 
1577
        self.assertTrue(tree.branch.repository.has_revision('A'))
 
1578
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
 
1579
            request.execute('', 'A'))
 
1580
 
 
1581
    def test_present_signature(self):
 
1582
        """For a present signature, ('yes', ) is returned."""
 
1583
        backing = self.get_transport()
 
1584
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1585
            backing)
 
1586
        strategy = gpg.LoopbackGPGStrategy(None)
 
1587
        tree = self.make_branch_and_memory_tree('.')
 
1588
        tree.lock_write()
 
1589
        tree.add('')
 
1590
        r1 = tree.commit('a commit', rev_id='A')
 
1591
        tree.branch.repository.start_write_group()
 
1592
        tree.branch.repository.sign_revision('A', strategy)
 
1593
        tree.branch.repository.commit_write_group()
 
1594
        tree.unlock()
 
1595
        self.assertTrue(tree.branch.repository.has_revision('A'))
 
1596
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
 
1597
            request.execute('', 'A'))
 
1598
 
 
1599
 
1514
1600
class TestSmartServerRepositoryGatherStats(tests.TestCaseWithMemoryTransport):
1515
1601
 
1516
1602
    def test_empty_revid(self):
1589
1675
            request.execute('', ))
1590
1676
 
1591
1677
 
 
1678
class TestSmartServerRepositoryMakeWorkingTrees(
 
1679
        tests.TestCaseWithMemoryTransport):
 
1680
 
 
1681
    def test_make_working_trees(self):
 
1682
        """For a repository with working trees, ('yes', ) is returned."""
 
1683
        backing = self.get_transport()
 
1684
        request = smart_repo.SmartServerRepositoryMakeWorkingTrees(backing)
 
1685
        r = self.make_repository('.')
 
1686
        r.set_make_working_trees(True)
 
1687
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
 
1688
            request.execute('', ))
 
1689
 
 
1690
    def test_is_not_shared(self):
 
1691
        """For a repository with working trees, ('no', ) is returned."""
 
1692
        backing = self.get_transport()
 
1693
        request = smart_repo.SmartServerRepositoryMakeWorkingTrees(backing)
 
1694
        r = self.make_repository('.')
 
1695
        r.set_make_working_trees(False)
 
1696
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
 
1697
            request.execute('', ))
 
1698
 
 
1699
 
1592
1700
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
1593
1701
 
1594
1702
    def test_lock_write_on_unlocked_repo(self):
1610
1718
        backing = self.get_transport()
1611
1719
        request = smart_repo.SmartServerRepositoryLockWrite(backing)
1612
1720
        repository = self.make_repository('.', format='knit')
1613
 
        repo_token = repository.lock_write()
 
1721
        repo_token = repository.lock_write().repository_token
1614
1722
        repository.leave_lock_in_place()
1615
1723
        repository.unlock()
1616
1724
        response = request.execute('')
1658
1766
        request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1659
1767
            backing)
1660
1768
        repository = self.make_repository('.', format='knit')
1661
 
        lock_token = repository.lock_write()
 
1769
        lock_token = repository.lock_write().repository_token
1662
1770
        response = request.execute('', '', lock_token)
1663
1771
        self.assertEqual(None, response)
1664
1772
        response = request.do_chunk(self.make_empty_byte_stream(repository))
1672
1780
        request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1673
1781
            backing)
1674
1782
        repository = self.make_repository('.', format='knit')
1675
 
        lock_token = repository.lock_write()
 
1783
        lock_token = repository.lock_write().repository_token
1676
1784
        self.assertRaises(
1677
1785
            errors.TokenMismatch, request.execute, '', '', 'wrong-token')
1678
1786
        repository.unlock()
1687
1795
        backing = self.get_transport()
1688
1796
        request = smart_repo.SmartServerRepositoryUnlock(backing)
1689
1797
        repository = self.make_repository('.', format='knit')
1690
 
        token = repository.lock_write()
 
1798
        token = repository.lock_write().repository_token
1691
1799
        repository.leave_lock_in_place()
1692
1800
        repository.unlock()
1693
1801
        response = request.execute('', token)
1884
1992
            smart_repo.SmartServerRepositoryGetRevisionGraph)
1885
1993
        self.assertHandlerEqual('Repository.get_stream',
1886
1994
            smart_repo.SmartServerRepositoryGetStream)
 
1995
        self.assertHandlerEqual('Repository.get_stream_1.19',
 
1996
            smart_repo.SmartServerRepositoryGetStream_1_19)
1887
1997
        self.assertHandlerEqual('Repository.has_revision',
1888
1998
            smart_repo.SmartServerRequestHasRevision)
1889
1999
        self.assertHandlerEqual('Repository.insert_stream',
1894
2004
            smart_repo.SmartServerRepositoryIsShared)
1895
2005
        self.assertHandlerEqual('Repository.lock_write',
1896
2006
            smart_repo.SmartServerRepositoryLockWrite)
 
2007
        self.assertHandlerEqual('Repository.make_working_trees',
 
2008
            smart_repo.SmartServerRepositoryMakeWorkingTrees)
1897
2009
        self.assertHandlerEqual('Repository.tarball',
1898
2010
            smart_repo.SmartServerRepositoryTarball)
1899
2011
        self.assertHandlerEqual('Repository.unlock',
1900
2012
            smart_repo.SmartServerRepositoryUnlock)
1901
2013
        self.assertHandlerEqual('Transport.is_readonly',
1902
2014
            smart_req.SmartServerIsReadonly)
 
2015
 
 
2016
 
 
2017
class SmartTCPServerHookTests(tests.TestCaseWithMemoryTransport):
 
2018
    """Tests for SmartTCPServer hooks."""
 
2019
 
 
2020
    def setUp(self):
 
2021
        super(SmartTCPServerHookTests, self).setUp()
 
2022
        self.server = server.SmartTCPServer(self.get_transport())
 
2023
 
 
2024
    def test_run_server_started_hooks(self):
 
2025
        """Test the server started hooks get fired properly."""
 
2026
        started_calls = []
 
2027
        server.SmartTCPServer.hooks.install_named_hook('server_started',
 
2028
            lambda backing_urls, url: started_calls.append((backing_urls, url)),
 
2029
            None)
 
2030
        started_ex_calls = []
 
2031
        server.SmartTCPServer.hooks.install_named_hook('server_started_ex',
 
2032
            lambda backing_urls, url: started_ex_calls.append((backing_urls, url)),
 
2033
            None)
 
2034
        self.server._sockname = ('example.com', 42)
 
2035
        self.server.run_server_started_hooks()
 
2036
        self.assertEquals(started_calls,
 
2037
            [([self.get_transport().base], 'bzr://example.com:42/')])
 
2038
        self.assertEquals(started_ex_calls,
 
2039
            [([self.get_transport().base], self.server)])
 
2040
 
 
2041
    def test_run_server_started_hooks_ipv6(self):
 
2042
        """Test that socknames can contain 4-tuples."""
 
2043
        self.server._sockname = ('::', 42, 0, 0)
 
2044
        started_calls = []
 
2045
        server.SmartTCPServer.hooks.install_named_hook('server_started',
 
2046
            lambda backing_urls, url: started_calls.append((backing_urls, url)),
 
2047
            None)
 
2048
        self.server.run_server_started_hooks()
 
2049
        self.assertEquals(started_calls,
 
2050
                [([self.get_transport().base], 'bzr://:::42/')])
 
2051
 
 
2052
    def test_run_server_stopped_hooks(self):
 
2053
        """Test the server stopped hooks."""
 
2054
        self.server._sockname = ('example.com', 42)
 
2055
        stopped_calls = []
 
2056
        server.SmartTCPServer.hooks.install_named_hook('server_stopped',
 
2057
            lambda backing_urls, url: stopped_calls.append((backing_urls, url)),
 
2058
            None)
 
2059
        self.server.run_server_stopped_hooks()
 
2060
        self.assertEquals(stopped_calls,
 
2061
            [([self.get_transport().base], 'bzr://example.com:42/')])