~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

  • Committer: Martin Pool
  • Date: 2010-01-29 14:09:05 UTC
  • mto: This revision was merged to the branch mainline in revision 4992.
  • Revision ID: mbp@sourcefrog.net-20100129140905-2uiarb6p8di1ywsr
Correction to url

from review: https://code.edge.launchpad.net/~mbp/bzr/doc/+merge/18250

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
from cStringIO import StringIO
28
28
 
29
29
from bzrlib import (
 
30
    branch,
30
31
    bzrdir,
31
32
    config,
32
33
    errors,
36
37
    pack,
37
38
    remote,
38
39
    repository,
39
 
    smart,
40
40
    tests,
41
41
    treebuilder,
42
42
    urlutils,
61
61
    condition_isinstance,
62
62
    split_suite_by_condition,
63
63
    multiply_tests,
64
 
    KnownFailure,
65
64
    )
66
 
from bzrlib.transport import get_transport, http
 
65
from bzrlib.transport import get_transport
67
66
from bzrlib.transport.memory import MemoryTransport
68
67
from bzrlib.transport.remote import (
69
68
    RemoteTransport,
135
134
        b = BzrDir.open_from_transport(self.transport).open_branch()
136
135
        self.assertStartsWith(str(b), 'RemoteBranch(')
137
136
 
 
137
    def test_remote_bzrdir_repr(self):
 
138
        b = BzrDir.open_from_transport(self.transport)
 
139
        self.assertStartsWith(str(b), 'RemoteBzrDir(')
 
140
 
138
141
    def test_remote_branch_format_supports_stacking(self):
139
142
        t = self.transport
140
143
        self.make_branch('unstackable', format='pack-0.92')
280
283
        self.expecting_body = True
281
284
        return result[1], FakeProtocol(result[2], self)
282
285
 
 
286
    def call_with_body_bytes(self, method, args, body):
 
287
        self._check_call(method, args)
 
288
        self._calls.append(('call_with_body_bytes', method, args, body))
 
289
        result = self._get_next_response()
 
290
        return result[1], FakeProtocol(result[2], self)
 
291
 
283
292
    def call_with_body_bytes_expecting_body(self, method, args, body):
284
293
        self._check_call(method, args)
285
294
        self._calls.append(('call_with_body_bytes_expecting_body', method,
435
444
            'BzrDir.cloning_metadir', ('quack/', 'False'),
436
445
            'error', ('BranchReference',)),
437
446
        client.add_expected_call(
438
 
            'BzrDir.open_branchV2', ('quack/',),
 
447
            'BzrDir.open_branchV3', ('quack/',),
439
448
            'success', ('ref', self.get_url('referenced'))),
440
449
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
441
450
            _client=client)
468
477
        self.assertFinished(client)
469
478
 
470
479
 
 
480
class TestBzrDirOpen(TestRemote):
 
481
 
 
482
    def make_fake_client_and_transport(self, path='quack'):
 
483
        transport = MemoryTransport()
 
484
        transport.mkdir(path)
 
485
        transport = transport.clone(path)
 
486
        client = FakeClient(transport.base)
 
487
        return client, transport
 
488
 
 
489
    def test_absent(self):
 
490
        client, transport = self.make_fake_client_and_transport()
 
491
        client.add_expected_call(
 
492
            'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
 
493
        self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
 
494
                remote.RemoteBzrDirFormat(), _client=client, _force_probe=True)
 
495
        self.assertFinished(client)
 
496
 
 
497
    def test_present_without_workingtree(self):
 
498
        client, transport = self.make_fake_client_and_transport()
 
499
        client.add_expected_call(
 
500
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
 
501
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
502
            _client=client, _force_probe=True)
 
503
        self.assertIsInstance(bd, RemoteBzrDir)
 
504
        self.assertFalse(bd.has_workingtree())
 
505
        self.assertRaises(errors.NoWorkingTree, bd.open_workingtree)
 
506
        self.assertFinished(client)
 
507
 
 
508
    def test_present_with_workingtree(self):
 
509
        client, transport = self.make_fake_client_and_transport()
 
510
        client.add_expected_call(
 
511
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
 
512
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
513
            _client=client, _force_probe=True)
 
514
        self.assertIsInstance(bd, RemoteBzrDir)
 
515
        self.assertTrue(bd.has_workingtree())
 
516
        self.assertRaises(errors.NotLocalUrl, bd.open_workingtree)
 
517
        self.assertFinished(client)
 
518
 
 
519
    def test_backwards_compat(self):
 
520
        client, transport = self.make_fake_client_and_transport()
 
521
        client.add_expected_call(
 
522
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
 
523
        client.add_expected_call(
 
524
            'BzrDir.open', ('quack/',), 'success', ('yes',))
 
525
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
526
            _client=client, _force_probe=True)
 
527
        self.assertIsInstance(bd, RemoteBzrDir)
 
528
        self.assertFinished(client)
 
529
 
 
530
 
471
531
class TestBzrDirOpenBranch(TestRemote):
472
532
 
473
533
    def test_backwards_compat(self):
475
535
        self.make_branch('.')
476
536
        a_dir = BzrDir.open(self.get_url('.'))
477
537
        self.reset_smart_call_log()
478
 
        verb = 'BzrDir.open_branchV2'
 
538
        verb = 'BzrDir.open_branchV3'
479
539
        self.disable_verb(verb)
480
540
        format = a_dir.open_branch()
481
541
        call_count = len([call for call in self.hpss_calls if
491
551
        transport = transport.clone('quack')
492
552
        client = FakeClient(transport.base)
493
553
        client.add_expected_call(
494
 
            'BzrDir.open_branchV2', ('quack/',),
 
554
            'BzrDir.open_branchV3', ('quack/',),
495
555
            'success', ('branch', branch_network_name))
496
556
        client.add_expected_call(
497
557
            'BzrDir.find_repositoryV3', ('quack/',),
516
576
            _client=client)
517
577
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
518
578
        self.assertEqual(
519
 
            [('call', 'BzrDir.open_branchV2', ('quack/',))],
 
579
            [('call', 'BzrDir.open_branchV3', ('quack/',))],
520
580
            client._calls)
521
581
 
522
582
    def test__get_tree_branch(self):
546
606
        network_name = reference_format.network_name()
547
607
        branch_network_name = self.get_branch_format().network_name()
548
608
        client.add_expected_call(
549
 
            'BzrDir.open_branchV2', ('~hello/',),
 
609
            'BzrDir.open_branchV3', ('~hello/',),
550
610
            'success', ('branch', branch_network_name))
551
611
        client.add_expected_call(
552
612
            'BzrDir.find_repositoryV3', ('~hello/',),
661
721
        network_name = reference_format.network_name()
662
722
        client.add_expected_call(
663
723
            'BzrDir.create_repository', ('quack/',
664
 
                'Bazaar pack repository format 1 (needs bzr 0.92)\n', 'False'),
665
 
            'success', ('ok', 'no', 'no', 'no', network_name))
 
724
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
 
725
                'False'),
 
726
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
666
727
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
667
728
            _client=client)
668
729
        repo = a_bzrdir.create_repository()
670
731
        self.assertIsInstance(repo, remote.RemoteRepository)
671
732
        # its format should have the settings from the response
672
733
        format = repo._format
673
 
        self.assertFalse(format.rich_root_data)
674
 
        self.assertFalse(format.supports_tree_reference)
675
 
        self.assertFalse(format.supports_external_lookups)
 
734
        self.assertTrue(format.rich_root_data)
 
735
        self.assertTrue(format.supports_tree_reference)
 
736
        self.assertTrue(format.supports_external_lookups)
676
737
        self.assertEqual(network_name, format.network_name())
677
738
 
678
739
 
682
743
        # fallback all the way to the first version.
683
744
        reference_format = self.get_repo_format()
684
745
        network_name = reference_format.network_name()
685
 
        client = FakeClient('bzr://example.com/')
 
746
        server_url = 'bzr://example.com/'
 
747
        self.permit_url(server_url)
 
748
        client = FakeClient(server_url)
686
749
        client.add_unknown_method_response('BzrDir.find_repositoryV3')
687
750
        client.add_unknown_method_response('BzrDir.find_repositoryV2')
688
751
        client.add_success_response('ok', '', 'no', 'no')
694
757
            reference_format.get_format_string(), 'ok')
695
758
        # PackRepository wants to do a stat
696
759
        client.add_success_response('stat', '0', '65535')
697
 
        remote_transport = RemoteTransport('bzr://example.com/quack/', medium=False,
 
760
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
698
761
            _client=client)
699
762
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
700
763
            _client=client)
714
777
        # fallback to find_repositoryV2
715
778
        reference_format = self.get_repo_format()
716
779
        network_name = reference_format.network_name()
717
 
        client = FakeClient('bzr://example.com/')
 
780
        server_url = 'bzr://example.com/'
 
781
        self.permit_url(server_url)
 
782
        client = FakeClient(server_url)
718
783
        client.add_unknown_method_response('BzrDir.find_repositoryV3')
719
784
        client.add_success_response('ok', '', 'no', 'no', 'no')
720
785
        # A real repository instance will be created to determine the network
725
790
            reference_format.get_format_string(), 'ok')
726
791
        # PackRepository wants to do a stat
727
792
        client.add_success_response('stat', '0', '65535')
728
 
        remote_transport = RemoteTransport('bzr://example.com/quack/', medium=False,
 
793
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
729
794
            _client=client)
730
795
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
731
796
            _client=client)
850
915
 
851
916
class RemoteBranchTestCase(RemoteBzrDirTestCase):
852
917
 
 
918
    def lock_remote_branch(self, branch):
 
919
        """Trick a RemoteBranch into thinking it is locked."""
 
920
        branch._lock_mode = 'w'
 
921
        branch._lock_count = 2
 
922
        branch._lock_token = 'branch token'
 
923
        branch._repo_lock_token = 'repo token'
 
924
        branch.repository._lock_mode = 'w'
 
925
        branch.repository._lock_count = 2
 
926
        branch.repository._lock_token = 'repo token'
 
927
 
853
928
    def make_remote_branch(self, transport, client):
854
929
        """Make a RemoteBranch using 'client' as its _SmartClient.
855
930
 
994
1069
        self.assertEqual({}, result)
995
1070
 
996
1071
 
 
1072
class TestBranchSetTagsBytes(RemoteBranchTestCase):
 
1073
 
 
1074
    def test_trivial(self):
 
1075
        transport = MemoryTransport()
 
1076
        client = FakeClient(transport.base)
 
1077
        client.add_expected_call(
 
1078
            'Branch.get_stacked_on_url', ('quack/',),
 
1079
            'error', ('NotStacked',))
 
1080
        client.add_expected_call(
 
1081
            'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
 
1082
            'success', ('',))
 
1083
        transport.mkdir('quack')
 
1084
        transport = transport.clone('quack')
 
1085
        branch = self.make_remote_branch(transport, client)
 
1086
        self.lock_remote_branch(branch)
 
1087
        branch._set_tags_bytes('tags bytes')
 
1088
        self.assertFinished(client)
 
1089
        self.assertEqual('tags bytes', client._calls[-1][-1])
 
1090
 
 
1091
    def test_backwards_compatible(self):
 
1092
        transport = MemoryTransport()
 
1093
        client = FakeClient(transport.base)
 
1094
        client.add_expected_call(
 
1095
            'Branch.get_stacked_on_url', ('quack/',),
 
1096
            'error', ('NotStacked',))
 
1097
        client.add_expected_call(
 
1098
            'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
 
1099
            'unknown', ('Branch.set_tags_bytes',))
 
1100
        transport.mkdir('quack')
 
1101
        transport = transport.clone('quack')
 
1102
        branch = self.make_remote_branch(transport, client)
 
1103
        self.lock_remote_branch(branch)
 
1104
        class StubRealBranch(object):
 
1105
            def __init__(self):
 
1106
                self.calls = []
 
1107
            def _set_tags_bytes(self, bytes):
 
1108
                self.calls.append(('set_tags_bytes', bytes))
 
1109
        real_branch = StubRealBranch()
 
1110
        branch._real_branch = real_branch
 
1111
        branch._set_tags_bytes('tags bytes')
 
1112
        # Call a second time, to exercise the 'remote version already inferred'
 
1113
        # code path.
 
1114
        branch._set_tags_bytes('tags bytes')
 
1115
        self.assertFinished(client)
 
1116
        self.assertEqual(
 
1117
            [('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
 
1118
 
 
1119
 
997
1120
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
998
1121
 
999
1122
    def test_empty_branch(self):
1071
1194
        client = FakeClient(self.get_url())
1072
1195
        branch_network_name = self.get_branch_format().network_name()
1073
1196
        client.add_expected_call(
1074
 
            'BzrDir.open_branchV2', ('stacked/',),
 
1197
            'BzrDir.open_branchV3', ('stacked/',),
1075
1198
            'success', ('branch', branch_network_name))
1076
1199
        client.add_expected_call(
1077
1200
            'BzrDir.find_repositoryV3', ('stacked/',),
1107
1230
        client = FakeClient(self.get_url())
1108
1231
        branch_network_name = self.get_branch_format().network_name()
1109
1232
        client.add_expected_call(
1110
 
            'BzrDir.open_branchV2', ('stacked/',),
 
1233
            'BzrDir.open_branchV3', ('stacked/',),
1111
1234
            'success', ('branch', branch_network_name))
1112
1235
        client.add_expected_call(
1113
1236
            'BzrDir.find_repositoryV3', ('stacked/',),
1341
1464
            errors.NoSuchRevision, branch.set_last_revision_info, 123, 'revid')
1342
1465
        branch.unlock()
1343
1466
 
1344
 
    def lock_remote_branch(self, branch):
1345
 
        """Trick a RemoteBranch into thinking it is locked."""
1346
 
        branch._lock_mode = 'w'
1347
 
        branch._lock_count = 2
1348
 
        branch._lock_token = 'branch token'
1349
 
        branch._repo_lock_token = 'repo token'
1350
 
        branch.repository._lock_mode = 'w'
1351
 
        branch.repository._lock_count = 2
1352
 
        branch.repository._lock_token = 'repo token'
1353
 
 
1354
1467
    def test_backwards_compatibility(self):
1355
1468
        """If the server does not support the Branch.set_last_revision_info
1356
1469
        verb (which is new in 1.4), then the client falls back to VFS methods.
1672
1785
        return repo, client
1673
1786
 
1674
1787
 
 
1788
def remoted_description(format):
 
1789
    return 'Remote: ' + format.get_format_description()
 
1790
 
 
1791
 
 
1792
class TestBranchFormat(tests.TestCase):
 
1793
 
 
1794
    def test_get_format_description(self):
 
1795
        remote_format = RemoteBranchFormat()
 
1796
        real_format = branch.BranchFormat.get_default_format()
 
1797
        remote_format._network_name = real_format.network_name()
 
1798
        self.assertEqual(remoted_description(real_format),
 
1799
            remote_format.get_format_description())
 
1800
 
 
1801
 
1675
1802
class TestRepositoryFormat(TestRemoteRepository):
1676
1803
 
1677
1804
    def test_fast_delta(self):
1684
1811
        false_format._network_name = false_name
1685
1812
        self.assertEqual(False, false_format.fast_deltas)
1686
1813
 
 
1814
    def test_get_format_description(self):
 
1815
        remote_repo_format = RemoteRepositoryFormat()
 
1816
        real_format = repository.RepositoryFormat.get_default_format()
 
1817
        remote_repo_format._network_name = real_format.network_name()
 
1818
        self.assertEqual(remoted_description(real_format),
 
1819
            remote_repo_format.get_format_description())
 
1820
 
1687
1821
 
1688
1822
class TestRepositoryGatherStats(TestRemoteRepository):
1689
1823
 
1874
2008
        self.assertLength(1, self.hpss_calls)
1875
2009
 
1876
2010
    def disableExtraResults(self):
1877
 
        old_flag = SmartServerRepositoryGetParentMap.no_extra_results
1878
 
        SmartServerRepositoryGetParentMap.no_extra_results = True
1879
 
        def reset_values():
1880
 
            SmartServerRepositoryGetParentMap.no_extra_results = old_flag
1881
 
        self.addCleanup(reset_values)
 
2011
        self.overrideAttr(SmartServerRepositoryGetParentMap,
 
2012
                          'no_extra_results', True)
1882
2013
 
1883
2014
    def test_null_cached_missing_and_stop_key(self):
1884
2015
        self.setup_smart_server_with_call_log()
1944
2075
    def test_allows_new_revisions(self):
1945
2076
        """get_parent_map's results can be updated by commit."""
1946
2077
        smart_server = server.SmartTCPServer_for_testing()
1947
 
        smart_server.setUp()
1948
 
        self.addCleanup(smart_server.tearDown)
 
2078
        self.start_server(smart_server)
1949
2079
        self.make_branch('branch')
1950
2080
        branch = Branch.open(smart_server.get_url() + '/branch')
1951
2081
        tree = branch.create_checkout('tree', lightweight=True)
2092
2222
            repo.get_rev_id_for_revno, 5, (42, 'rev-foo'))
2093
2223
        self.assertFinished(client)
2094
2224
 
 
2225
    def test_branch_fallback_locking(self):
 
2226
        """RemoteBranch.get_rev_id takes a read lock, and tries to call the
 
2227
        get_rev_id_for_revno verb.  If the verb is unknown the VFS fallback
 
2228
        will be invoked, which will fail if the repo is unlocked.
 
2229
        """
 
2230
        self.setup_smart_server_with_call_log()
 
2231
        tree = self.make_branch_and_memory_tree('.')
 
2232
        tree.lock_write()
 
2233
        rev1 = tree.commit('First')
 
2234
        rev2 = tree.commit('Second')
 
2235
        tree.unlock()
 
2236
        branch = tree.branch
 
2237
        self.assertFalse(branch.is_locked())
 
2238
        self.reset_smart_call_log()
 
2239
        verb = 'Repository.get_rev_id_for_revno'
 
2240
        self.disable_verb(verb)
 
2241
        self.assertEqual(rev1, branch.get_rev_id(1))
 
2242
        self.assertLength(1, [call for call in self.hpss_calls if
 
2243
                              call.call.method == verb])
 
2244
 
2095
2245
 
2096
2246
class TestRepositoryIsShared(TestRemoteRepository):
2097
2247
 
2325
2475
        class FakeRealRepository:
2326
2476
            def _get_sink(self):
2327
2477
                return fake_real_sink
 
2478
            def is_in_write_group(self):
 
2479
                return False
 
2480
            def refresh_data(self):
 
2481
                return True
2328
2482
        repo._real_repository = FakeRealRepository()
2329
2483
        sink = repo._get_sink()
2330
2484
        fmt = repository.RepositoryFormat.get_default_format()
2354
2508
        """
2355
2509
        # Define a stream using generators so that it isn't rewindable.
2356
2510
        inv = inventory.Inventory(revision_id='rev1')
 
2511
        inv.root.revision = 'rev1'
2357
2512
        def stream_with_inv_delta():
2358
2513
            yield ('inventories', inventories_substream())
2359
2514
            yield ('inventory-deltas', inventory_delta_substream())
2621
2776
        expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
2622
2777
        self.assertEqual(expected_error, translated_error)
2623
2778
 
 
2779
    def test_nobranch_one_arg(self):
 
2780
        bzrdir = self.make_bzrdir('')
 
2781
        translated_error = self.translateTuple(
 
2782
            ('nobranch', 'extra detail'), bzrdir=bzrdir)
 
2783
        expected_error = errors.NotBranchError(
 
2784
            path=bzrdir.root_transport.base,
 
2785
            detail='extra detail')
 
2786
        self.assertEqual(expected_error, translated_error)
 
2787
 
2624
2788
    def test_LockContention(self):
2625
2789
        translated_error = self.translateTuple(('LockContention',))
2626
2790
        expected_error = errors.LockContention('(remote lock)')
2666
2830
        expected_error = errors.ReadError(path)
2667
2831
        self.assertEqual(expected_error, translated_error)
2668
2832
 
 
2833
    def test_IncompatibleRepositories(self):
 
2834
        translated_error = self.translateTuple(('IncompatibleRepositories',
 
2835
            "repo1", "repo2", "details here"))
 
2836
        expected_error = errors.IncompatibleRepositories("repo1", "repo2",
 
2837
            "details here")
 
2838
        self.assertEqual(expected_error, translated_error)
 
2839
 
2669
2840
    def test_PermissionDenied_no_args(self):
2670
2841
        path = 'a path'
2671
2842
        translated_error = self.translateTuple(('PermissionDenied',), path=path)
2732
2903
        # In addition to re-raising ErrorFromSmartServer, some debug info has
2733
2904
        # been muttered to the log file for developer to look at.
2734
2905
        self.assertContainsRe(
2735
 
            self._get_log(keep_log_file=True),
 
2906
            self.get_log(),
2736
2907
            "Missing key 'branch' in context")
2737
2908
 
2738
2909
    def test_path_missing(self):
2746
2917
        self.assertEqual(server_error, translated_error)
2747
2918
        # In addition to re-raising ErrorFromSmartServer, some debug info has
2748
2919
        # been muttered to the log file for developer to look at.
2749
 
        self.assertContainsRe(
2750
 
            self._get_log(keep_log_file=True), "Missing key 'path' in context")
 
2920
        self.assertContainsRe(self.get_log(), "Missing key 'path' in context")
2751
2921
 
2752
2922
 
2753
2923
class TestStacking(tests.TestCaseWithTransport):
2772
2942
        stacked_branch.set_stacked_on_url('../base')
2773
2943
        # start a server looking at this
2774
2944
        smart_server = server.SmartTCPServer_for_testing()
2775
 
        smart_server.setUp()
2776
 
        self.addCleanup(smart_server.tearDown)
 
2945
        self.start_server(smart_server)
2777
2946
        remote_bzrdir = BzrDir.open(smart_server.get_url() + '/stacked')
2778
2947
        # can get its branch and repository
2779
2948
        remote_branch = remote_bzrdir.open_branch()
2882
3051
            local_tree.commit('more local changes are better')
2883
3052
            branch = Branch.open(self.get_url('tree3'))
2884
3053
            branch.lock_read()
 
3054
            self.addCleanup(branch.unlock)
2885
3055
            return None, branch
2886
3056
        rev_ord, expected_revs = self.get_ordered_revs('1.9', 'unordered',
2887
3057
            branch_factory=make_stacked_stacked)
2934
3104
        # Create a smart server that publishes whatever the backing VFS server
2935
3105
        # does.
2936
3106
        self.smart_server = server.SmartTCPServer_for_testing()
2937
 
        self.smart_server.setUp(self.get_server())
2938
 
        self.addCleanup(self.smart_server.tearDown)
 
3107
        self.start_server(self.smart_server, self.get_server())
2939
3108
        # Log all HPSS calls into self.hpss_calls.
2940
3109
        _SmartClient.hooks.install_named_hook(
2941
3110
            'call', self.capture_hpss_call, None)