~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

  • Committer: John Ferlito
  • Date: 2009-05-25 10:59:42 UTC
  • mto: (4665.4.1 ppa-doc)
  • mto: This revision was merged to the branch mainline in revision 4693.
  • Revision ID: johnf@inodes.org-20090525105942-5xkcbe37m1u5lp5z
Update packaging scripts to make deployment a bit easier
Update documentation for deploying to PPA

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,
31
30
    bzrdir,
32
31
    config,
33
32
    errors,
34
33
    graph,
35
 
    inventory,
36
 
    inventory_delta,
37
34
    pack,
38
35
    remote,
39
36
    repository,
 
37
    smart,
40
38
    tests,
41
39
    treebuilder,
42
40
    urlutils,
43
 
    versionedfile,
44
41
    )
45
42
from bzrlib.branch import Branch
46
43
from bzrlib.bzrdir import BzrDir, BzrDirFormat
62
59
    split_suite_by_condition,
63
60
    multiply_tests,
64
61
    )
65
 
from bzrlib.transport import get_transport
 
62
from bzrlib.transport import get_transport, http
66
63
from bzrlib.transport.memory import MemoryTransport
67
64
from bzrlib.transport.remote import (
68
65
    RemoteTransport,
134
131
        b = BzrDir.open_from_transport(self.transport).open_branch()
135
132
        self.assertStartsWith(str(b), 'RemoteBranch(')
136
133
 
137
 
    def test_remote_bzrdir_repr(self):
138
 
        b = BzrDir.open_from_transport(self.transport)
139
 
        self.assertStartsWith(str(b), 'RemoteBzrDir(')
140
 
 
141
134
    def test_remote_branch_format_supports_stacking(self):
142
135
        t = self.transport
143
136
        self.make_branch('unstackable', format='pack-0.92')
160
153
        r = BzrDir.open_from_transport(t.clone('stackable')).open_repository()
161
154
        self.assertTrue(r._format.supports_external_lookups)
162
155
 
163
 
    def test_remote_branch_set_append_revisions_only(self):
164
 
        # Make a format 1.9 branch, which supports append_revisions_only
165
 
        branch = self.make_branch('branch', format='1.9')
166
 
        config = branch.get_config()
167
 
        branch.set_append_revisions_only(True)
168
 
        self.assertEqual(
169
 
            'True', config.get_user_option('append_revisions_only'))
170
 
        branch.set_append_revisions_only(False)
171
 
        self.assertEqual(
172
 
            'False', config.get_user_option('append_revisions_only'))
173
 
 
174
 
    def test_remote_branch_set_append_revisions_only_upgrade_reqd(self):
175
 
        branch = self.make_branch('branch', format='knit')
176
 
        config = branch.get_config()
177
 
        self.assertRaises(
178
 
            errors.UpgradeRequired, branch.set_append_revisions_only, True)
179
 
 
180
156
 
181
157
class FakeProtocol(object):
182
158
    """Lookalike SmartClientRequestProtocolOne allowing body reading tests."""
283
259
        self.expecting_body = True
284
260
        return result[1], FakeProtocol(result[2], self)
285
261
 
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
 
 
292
262
    def call_with_body_bytes_expecting_body(self, method, args, body):
293
263
        self._check_call(method, args)
294
264
        self._calls.append(('call_with_body_bytes_expecting_body', method,
344
314
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
345
315
        return reference_bzrdir_format.repository_format
346
316
 
347
 
    def assertFinished(self, fake_client):
348
 
        """Assert that all of a FakeClient's expected calls have occurred."""
349
 
        fake_client.finished_test()
 
317
    def disable_verb(self, verb):
 
318
        """Disable a verb for one test."""
 
319
        request_handlers = smart.request.request_handlers
 
320
        orig_method = request_handlers.get(verb)
 
321
        request_handlers.remove(verb)
 
322
        def restoreVerb():
 
323
            request_handlers.register(verb, orig_method)
 
324
        self.addCleanup(restoreVerb)
350
325
 
351
326
 
352
327
class Test_ClientMedium_remote_path_from_transport(tests.TestCase):
444
419
            'BzrDir.cloning_metadir', ('quack/', 'False'),
445
420
            'error', ('BranchReference',)),
446
421
        client.add_expected_call(
447
 
            'BzrDir.open_branchV3', ('quack/',),
 
422
            'BzrDir.open_branchV2', ('quack/',),
448
423
            'success', ('ref', self.get_url('referenced'))),
449
424
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
450
425
            _client=client)
453
428
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
454
429
        self.assertEqual(expected._repository_format, result._repository_format)
455
430
        self.assertEqual(expected._branch_format, result._branch_format)
456
 
        self.assertFinished(client)
 
431
        client.finished_test()
457
432
 
458
433
    def test_current_server(self):
459
434
        transport = self.get_transport('.')
474
449
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
475
450
        self.assertEqual(None, result._repository_format)
476
451
        self.assertEqual(None, result._branch_format)
477
 
        self.assertFinished(client)
478
 
 
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)
 
452
        client.finished_test()
529
453
 
530
454
 
531
455
class TestBzrDirOpenBranch(TestRemote):
535
459
        self.make_branch('.')
536
460
        a_dir = BzrDir.open(self.get_url('.'))
537
461
        self.reset_smart_call_log()
538
 
        verb = 'BzrDir.open_branchV3'
 
462
        verb = 'BzrDir.open_branchV2'
539
463
        self.disable_verb(verb)
540
464
        format = a_dir.open_branch()
541
465
        call_count = len([call for call in self.hpss_calls if
551
475
        transport = transport.clone('quack')
552
476
        client = FakeClient(transport.base)
553
477
        client.add_expected_call(
554
 
            'BzrDir.open_branchV3', ('quack/',),
 
478
            'BzrDir.open_branchV2', ('quack/',),
555
479
            'success', ('branch', branch_network_name))
556
480
        client.add_expected_call(
557
481
            'BzrDir.find_repositoryV3', ('quack/',),
564
488
        result = bzrdir.open_branch()
565
489
        self.assertIsInstance(result, RemoteBranch)
566
490
        self.assertEqual(bzrdir, result.bzrdir)
567
 
        self.assertFinished(client)
 
491
        client.finished_test()
568
492
 
569
493
    def test_branch_missing(self):
570
494
        transport = MemoryTransport()
576
500
            _client=client)
577
501
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
578
502
        self.assertEqual(
579
 
            [('call', 'BzrDir.open_branchV3', ('quack/',))],
 
503
            [('call', 'BzrDir.open_branchV2', ('quack/',))],
580
504
            client._calls)
581
505
 
582
506
    def test__get_tree_branch(self):
606
530
        network_name = reference_format.network_name()
607
531
        branch_network_name = self.get_branch_format().network_name()
608
532
        client.add_expected_call(
609
 
            'BzrDir.open_branchV3', ('~hello/',),
 
533
            'BzrDir.open_branchV2', ('~hello/',),
610
534
            'success', ('branch', branch_network_name))
611
535
        client.add_expected_call(
612
536
            'BzrDir.find_repositoryV3', ('~hello/',),
617
541
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
618
542
            _client=client)
619
543
        result = bzrdir.open_branch()
620
 
        self.assertFinished(client)
 
544
        client.finished_test()
621
545
 
622
546
    def check_open_repository(self, rich_root, subtrees, external_lookup='no'):
623
547
        reference_format = self.get_repo_format()
721
645
        network_name = reference_format.network_name()
722
646
        client.add_expected_call(
723
647
            'BzrDir.create_repository', ('quack/',
724
 
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
725
 
                'False'),
726
 
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
 
648
                'Bazaar pack repository format 1 (needs bzr 0.92)\n', 'False'),
 
649
            'success', ('ok', 'no', 'no', 'no', network_name))
727
650
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
728
651
            _client=client)
729
652
        repo = a_bzrdir.create_repository()
731
654
        self.assertIsInstance(repo, remote.RemoteRepository)
732
655
        # its format should have the settings from the response
733
656
        format = repo._format
734
 
        self.assertTrue(format.rich_root_data)
735
 
        self.assertTrue(format.supports_tree_reference)
736
 
        self.assertTrue(format.supports_external_lookups)
 
657
        self.assertFalse(format.rich_root_data)
 
658
        self.assertFalse(format.supports_tree_reference)
 
659
        self.assertFalse(format.supports_external_lookups)
737
660
        self.assertEqual(network_name, format.network_name())
738
661
 
739
662
 
743
666
        # fallback all the way to the first version.
744
667
        reference_format = self.get_repo_format()
745
668
        network_name = reference_format.network_name()
746
 
        server_url = 'bzr://example.com/'
747
 
        self.permit_url(server_url)
748
 
        client = FakeClient(server_url)
 
669
        client = FakeClient('bzr://example.com/')
749
670
        client.add_unknown_method_response('BzrDir.find_repositoryV3')
750
671
        client.add_unknown_method_response('BzrDir.find_repositoryV2')
751
672
        client.add_success_response('ok', '', 'no', 'no')
757
678
            reference_format.get_format_string(), 'ok')
758
679
        # PackRepository wants to do a stat
759
680
        client.add_success_response('stat', '0', '65535')
760
 
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
 
681
        remote_transport = RemoteTransport('bzr://example.com/quack/', medium=False,
761
682
            _client=client)
762
683
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
763
684
            _client=client)
777
698
        # fallback to find_repositoryV2
778
699
        reference_format = self.get_repo_format()
779
700
        network_name = reference_format.network_name()
780
 
        server_url = 'bzr://example.com/'
781
 
        self.permit_url(server_url)
782
 
        client = FakeClient(server_url)
 
701
        client = FakeClient('bzr://example.com/')
783
702
        client.add_unknown_method_response('BzrDir.find_repositoryV3')
784
703
        client.add_success_response('ok', '', 'no', 'no', 'no')
785
704
        # A real repository instance will be created to determine the network
790
709
            reference_format.get_format_string(), 'ok')
791
710
        # PackRepository wants to do a stat
792
711
        client.add_success_response('stat', '0', '65535')
793
 
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
 
712
        remote_transport = RemoteTransport('bzr://example.com/quack/', medium=False,
794
713
            _client=client)
795
714
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
796
715
            _client=client)
822
741
        self.assertEqual(network_name, repo._format.network_name())
823
742
 
824
743
 
825
 
class TestBzrDirFormatInitializeEx(TestRemote):
826
 
 
827
 
    def test_success(self):
828
 
        """Simple test for typical successful call."""
829
 
        fmt = bzrdir.RemoteBzrDirFormat()
830
 
        default_format_name = BzrDirFormat.get_default_format().network_name()
831
 
        transport = self.get_transport()
832
 
        client = FakeClient(transport.base)
833
 
        client.add_expected_call(
834
 
            'BzrDirFormat.initialize_ex_1.16',
835
 
                (default_format_name, 'path', 'False', 'False', 'False', '',
836
 
                 '', '', '', 'False'),
837
 
            'success',
838
 
                ('.', 'no', 'no', 'yes', 'repo fmt', 'repo bzrdir fmt',
839
 
                 'bzrdir fmt', 'False', '', '', 'repo lock token'))
840
 
        # XXX: It would be better to call fmt.initialize_on_transport_ex, but
841
 
        # it's currently hard to test that without supplying a real remote
842
 
        # transport connected to a real server.
843
 
        result = fmt._initialize_on_transport_ex_rpc(client, 'path',
844
 
            transport, False, False, False, None, None, None, None, False)
845
 
        self.assertFinished(client)
846
 
 
847
 
    def test_error(self):
848
 
        """Error responses are translated, e.g. 'PermissionDenied' raises the
849
 
        corresponding error from the client.
850
 
        """
851
 
        fmt = bzrdir.RemoteBzrDirFormat()
852
 
        default_format_name = BzrDirFormat.get_default_format().network_name()
853
 
        transport = self.get_transport()
854
 
        client = FakeClient(transport.base)
855
 
        client.add_expected_call(
856
 
            'BzrDirFormat.initialize_ex_1.16',
857
 
                (default_format_name, 'path', 'False', 'False', 'False', '',
858
 
                 '', '', '', 'False'),
859
 
            'error',
860
 
                ('PermissionDenied', 'path', 'extra info'))
861
 
        # XXX: It would be better to call fmt.initialize_on_transport_ex, but
862
 
        # it's currently hard to test that without supplying a real remote
863
 
        # transport connected to a real server.
864
 
        err = self.assertRaises(errors.PermissionDenied,
865
 
            fmt._initialize_on_transport_ex_rpc, client, 'path', transport,
866
 
            False, False, False, None, None, None, None, False)
867
 
        self.assertEqual('path', err.path)
868
 
        self.assertEqual(': extra info', err.extra)
869
 
        self.assertFinished(client)
870
 
 
871
 
    def test_error_from_real_server(self):
872
 
        """Integration test for error translation."""
873
 
        transport = self.make_smart_server('foo')
874
 
        transport = transport.clone('no-such-path')
875
 
        fmt = bzrdir.RemoteBzrDirFormat()
876
 
        err = self.assertRaises(errors.NoSuchFile,
877
 
            fmt.initialize_on_transport_ex, transport, create_prefix=False)
878
 
 
879
 
 
880
744
class OldSmartClient(object):
881
745
    """A fake smart client for test_old_version that just returns a version one
882
746
    response to the 'hello' (query version) command.
915
779
 
916
780
class RemoteBranchTestCase(RemoteBzrDirTestCase):
917
781
 
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
 
 
928
782
    def make_remote_branch(self, transport, client):
929
783
        """Make a RemoteBranch using 'client' as its _SmartClient.
930
784
 
957
811
        transport = transport.clone('quack')
958
812
        branch = self.make_remote_branch(transport, client)
959
813
        result = branch.get_parent()
960
 
        self.assertFinished(client)
 
814
        client.finished_test()
961
815
        self.assertEqual(None, result)
962
816
 
963
817
    def test_parent_relative(self):
989
843
        branch = self.make_remote_branch(transport, client)
990
844
        result = branch.get_parent()
991
845
        self.assertEqual('http://foo/', result)
992
 
        self.assertFinished(client)
 
846
        client.finished_test()
993
847
 
994
848
 
995
849
class TestBranchSetParentLocation(RemoteBranchTestCase):
1010
864
        branch._lock_token = 'b'
1011
865
        branch._repo_lock_token = 'r'
1012
866
        branch._set_parent_location(None)
1013
 
        self.assertFinished(client)
 
867
        client.finished_test()
1014
868
 
1015
869
    def test_parent(self):
1016
870
        transport = MemoryTransport()
1027
881
        branch._lock_token = 'b'
1028
882
        branch._repo_lock_token = 'r'
1029
883
        branch._set_parent_location('foo')
1030
 
        self.assertFinished(client)
 
884
        client.finished_test()
1031
885
 
1032
886
    def test_backwards_compat(self):
1033
887
        self.setup_smart_server_with_call_log()
1065
919
        transport = transport.clone('quack')
1066
920
        branch = self.make_remote_branch(transport, client)
1067
921
        result = branch.tags.get_tag_dict()
1068
 
        self.assertFinished(client)
 
922
        client.finished_test()
1069
923
        self.assertEqual({}, result)
1070
924
 
1071
925
 
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
 
 
1120
926
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
1121
927
 
1122
928
    def test_empty_branch(self):
1133
939
        transport = transport.clone('quack')
1134
940
        branch = self.make_remote_branch(transport, client)
1135
941
        result = branch.last_revision_info()
1136
 
        self.assertFinished(client)
 
942
        client.finished_test()
1137
943
        self.assertEqual((0, NULL_REVISION), result)
1138
944
 
1139
945
    def test_non_empty_branch(self):
1194
1000
        client = FakeClient(self.get_url())
1195
1001
        branch_network_name = self.get_branch_format().network_name()
1196
1002
        client.add_expected_call(
1197
 
            'BzrDir.open_branchV3', ('stacked/',),
 
1003
            'BzrDir.open_branchV2', ('stacked/',),
1198
1004
            'success', ('branch', branch_network_name))
1199
1005
        client.add_expected_call(
1200
1006
            'BzrDir.find_repositoryV3', ('stacked/',),
1214
1020
        branch = bzrdir.open_branch()
1215
1021
        result = branch.get_stacked_on_url()
1216
1022
        self.assertEqual('../base', result)
1217
 
        self.assertFinished(client)
 
1023
        client.finished_test()
1218
1024
        # it's in the fallback list both for the RemoteRepository and its vfs
1219
1025
        # repository
1220
1026
        self.assertEqual(1, len(branch.repository._fallback_repositories))
1230
1036
        client = FakeClient(self.get_url())
1231
1037
        branch_network_name = self.get_branch_format().network_name()
1232
1038
        client.add_expected_call(
1233
 
            'BzrDir.open_branchV3', ('stacked/',),
 
1039
            'BzrDir.open_branchV2', ('stacked/',),
1234
1040
            'success', ('branch', branch_network_name))
1235
1041
        client.add_expected_call(
1236
1042
            'BzrDir.find_repositoryV3', ('stacked/',),
1247
1053
        branch = bzrdir.open_branch()
1248
1054
        result = branch.get_stacked_on_url()
1249
1055
        self.assertEqual('../base', result)
1250
 
        self.assertFinished(client)
 
1056
        client.finished_test()
1251
1057
        # it's in the fallback list both for the RemoteRepository.
1252
1058
        self.assertEqual(1, len(branch.repository._fallback_repositories))
1253
1059
        # And we haven't had to construct a real repository.
1288
1094
        result = branch.set_revision_history([])
1289
1095
        branch.unlock()
1290
1096
        self.assertEqual(None, result)
1291
 
        self.assertFinished(client)
 
1097
        client.finished_test()
1292
1098
 
1293
1099
    def test_set_nonempty(self):
1294
1100
        # set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
1326
1132
        result = branch.set_revision_history(['rev-id1', 'rev-id2'])
1327
1133
        branch.unlock()
1328
1134
        self.assertEqual(None, result)
1329
 
        self.assertFinished(client)
 
1135
        client.finished_test()
1330
1136
 
1331
1137
    def test_no_such_revision(self):
1332
1138
        transport = MemoryTransport()
1361
1167
        self.assertRaises(
1362
1168
            errors.NoSuchRevision, branch.set_revision_history, ['rev-id'])
1363
1169
        branch.unlock()
1364
 
        self.assertFinished(client)
 
1170
        client.finished_test()
1365
1171
 
1366
1172
    def test_tip_change_rejected(self):
1367
1173
        """TipChangeRejected responses cause a TipChangeRejected exception to
1404
1210
        self.assertIsInstance(err.msg, unicode)
1405
1211
        self.assertEqual(rejection_msg_unicode, err.msg)
1406
1212
        branch.unlock()
1407
 
        self.assertFinished(client)
 
1213
        client.finished_test()
1408
1214
 
1409
1215
 
1410
1216
class TestBranchSetLastRevisionInfo(RemoteBranchTestCase):
1464
1270
            errors.NoSuchRevision, branch.set_last_revision_info, 123, 'revid')
1465
1271
        branch.unlock()
1466
1272
 
 
1273
    def lock_remote_branch(self, branch):
 
1274
        """Trick a RemoteBranch into thinking it is locked."""
 
1275
        branch._lock_mode = 'w'
 
1276
        branch._lock_count = 2
 
1277
        branch._lock_token = 'branch token'
 
1278
        branch._repo_lock_token = 'repo token'
 
1279
        branch.repository._lock_mode = 'w'
 
1280
        branch.repository._lock_count = 2
 
1281
        branch.repository._lock_token = 'repo token'
 
1282
 
1467
1283
    def test_backwards_compatibility(self):
1468
1284
        """If the server does not support the Branch.set_last_revision_info
1469
1285
        verb (which is new in 1.4), then the client falls back to VFS methods.
1510
1326
        self.assertEqual(
1511
1327
            [('set_last_revision_info', 1234, 'a-revision-id')],
1512
1328
            real_branch.calls)
1513
 
        self.assertFinished(client)
 
1329
        client.finished_test()
1514
1330
 
1515
1331
    def test_unexpected_error(self):
1516
1332
        # If the server sends an error the client doesn't understand, it gets
1624
1440
        config = branch._get_config()
1625
1441
        config.set_option('foo', 'bar')
1626
1442
        branch.unlock()
1627
 
        self.assertFinished(client)
 
1443
        client.finished_test()
1628
1444
 
1629
1445
    def test_backwards_compat_set_option(self):
1630
1446
        self.setup_smart_server_with_call_log()
1654
1470
        transport = transport.clone('quack')
1655
1471
        branch = self.make_remote_branch(transport, client)
1656
1472
        self.assertRaises(errors.UnlockableTransport, branch.lock_write)
1657
 
        self.assertFinished(client)
 
1473
        client.finished_test()
1658
1474
 
1659
1475
 
1660
1476
class TestBzrDirGetSetConfig(RemoteBzrDirTestCase):
1785
1601
        return repo, client
1786
1602
 
1787
1603
 
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
 
 
1802
1604
class TestRepositoryFormat(TestRemoteRepository):
1803
1605
 
1804
1606
    def test_fast_delta(self):
1811
1613
        false_format._network_name = false_name
1812
1614
        self.assertEqual(False, false_format.fast_deltas)
1813
1615
 
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
 
 
1821
1616
 
1822
1617
class TestRepositoryGatherStats(TestRemoteRepository):
1823
1618
 
2008
1803
        self.assertLength(1, self.hpss_calls)
2009
1804
 
2010
1805
    def disableExtraResults(self):
2011
 
        self.overrideAttr(SmartServerRepositoryGetParentMap,
2012
 
                          'no_extra_results', True)
 
1806
        old_flag = SmartServerRepositoryGetParentMap.no_extra_results
 
1807
        SmartServerRepositoryGetParentMap.no_extra_results = True
 
1808
        def reset_values():
 
1809
            SmartServerRepositoryGetParentMap.no_extra_results = old_flag
 
1810
        self.addCleanup(reset_values)
2013
1811
 
2014
1812
    def test_null_cached_missing_and_stop_key(self):
2015
1813
        self.setup_smart_server_with_call_log()
2075
1873
    def test_allows_new_revisions(self):
2076
1874
        """get_parent_map's results can be updated by commit."""
2077
1875
        smart_server = server.SmartTCPServer_for_testing()
2078
 
        self.start_server(smart_server)
 
1876
        smart_server.setUp()
 
1877
        self.addCleanup(smart_server.tearDown)
2079
1878
        self.make_branch('branch')
2080
1879
        branch = Branch.open(smart_server.get_url() + '/branch')
2081
1880
        tree = branch.create_checkout('tree', lightweight=True)
2164
1963
        self.assertEqual(('AnUnexpectedError',), e.error_tuple)
2165
1964
 
2166
1965
 
2167
 
class TestRepositoryGetRevIdForRevno(TestRemoteRepository):
2168
 
 
2169
 
    def test_ok(self):
2170
 
        repo, client = self.setup_fake_client_and_repository('quack')
2171
 
        client.add_expected_call(
2172
 
            'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2173
 
            'success', ('ok', 'rev-five'))
2174
 
        result = repo.get_rev_id_for_revno(5, (42, 'rev-foo'))
2175
 
        self.assertEqual((True, 'rev-five'), result)
2176
 
        self.assertFinished(client)
2177
 
 
2178
 
    def test_history_incomplete(self):
2179
 
        repo, client = self.setup_fake_client_and_repository('quack')
2180
 
        client.add_expected_call(
2181
 
            'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2182
 
            'success', ('history-incomplete', 10, 'rev-ten'))
2183
 
        result = repo.get_rev_id_for_revno(5, (42, 'rev-foo'))
2184
 
        self.assertEqual((False, (10, 'rev-ten')), result)
2185
 
        self.assertFinished(client)
2186
 
 
2187
 
    def test_history_incomplete_with_fallback(self):
2188
 
        """A 'history-incomplete' response causes the fallback repository to be
2189
 
        queried too, if one is set.
2190
 
        """
2191
 
        # Make a repo with a fallback repo, both using a FakeClient.
2192
 
        format = remote.response_tuple_to_repo_format(
2193
 
            ('yes', 'no', 'yes', 'fake-network-name'))
2194
 
        repo, client = self.setup_fake_client_and_repository('quack')
2195
 
        repo._format = format
2196
 
        fallback_repo, ignored = self.setup_fake_client_and_repository(
2197
 
            'fallback')
2198
 
        fallback_repo._client = client
2199
 
        repo.add_fallback_repository(fallback_repo)
2200
 
        # First the client should ask the primary repo
2201
 
        client.add_expected_call(
2202
 
            'Repository.get_rev_id_for_revno', ('quack/', 1, (42, 'rev-foo')),
2203
 
            'success', ('history-incomplete', 2, 'rev-two'))
2204
 
        # Then it should ask the fallback, using revno/revid from the
2205
 
        # history-incomplete response as the known revno/revid.
2206
 
        client.add_expected_call(
2207
 
            'Repository.get_rev_id_for_revno',('fallback/', 1, (2, 'rev-two')),
2208
 
            'success', ('ok', 'rev-one'))
2209
 
        result = repo.get_rev_id_for_revno(1, (42, 'rev-foo'))
2210
 
        self.assertEqual((True, 'rev-one'), result)
2211
 
        self.assertFinished(client)
2212
 
 
2213
 
    def test_nosuchrevision(self):
2214
 
        # 'nosuchrevision' is returned when the known-revid is not found in the
2215
 
        # remote repo.  The client translates that response to NoSuchRevision.
2216
 
        repo, client = self.setup_fake_client_and_repository('quack')
2217
 
        client.add_expected_call(
2218
 
            'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2219
 
            'error', ('nosuchrevision', 'rev-foo'))
2220
 
        self.assertRaises(
2221
 
            errors.NoSuchRevision,
2222
 
            repo.get_rev_id_for_revno, 5, (42, 'rev-foo'))
2223
 
        self.assertFinished(client)
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
 
 
2245
 
 
2246
1966
class TestRepositoryIsShared(TestRemoteRepository):
2247
1967
 
2248
1968
    def test_is_shared(self):
2363
2083
        self.assertEqual([], client._calls)
2364
2084
 
2365
2085
 
2366
 
class TestRepositoryInsertStreamBase(TestRemoteRepository):
2367
 
    """Base class for Repository.insert_stream and .insert_stream_1.19
2368
 
    tests.
2369
 
    """
2370
 
    
2371
 
    def checkInsertEmptyStream(self, repo, client):
2372
 
        """Insert an empty stream, checking the result.
2373
 
 
2374
 
        This checks that there are no resume_tokens or missing_keys, and that
2375
 
        the client is finished.
2376
 
        """
2377
 
        sink = repo._get_sink()
2378
 
        fmt = repository.RepositoryFormat.get_default_format()
2379
 
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2380
 
        self.assertEqual([], resume_tokens)
2381
 
        self.assertEqual(set(), missing_keys)
2382
 
        self.assertFinished(client)
2383
 
 
2384
 
 
2385
 
class TestRepositoryInsertStream(TestRepositoryInsertStreamBase):
2386
 
    """Tests for using Repository.insert_stream verb when the _1.19 variant is
2387
 
    not available.
2388
 
 
2389
 
    This test case is very similar to TestRepositoryInsertStream_1_19.
2390
 
    """
2391
 
 
2392
 
    def setUp(self):
2393
 
        TestRemoteRepository.setUp(self)
2394
 
        self.disable_verb('Repository.insert_stream_1.19')
2395
 
 
2396
 
    def test_unlocked_repo(self):
2397
 
        transport_path = 'quack'
2398
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2399
 
        client.add_expected_call(
2400
 
            'Repository.insert_stream_1.19', ('quack/', ''),
2401
 
            'unknown', ('Repository.insert_stream_1.19',))
2402
 
        client.add_expected_call(
2403
 
            'Repository.insert_stream', ('quack/', ''),
2404
 
            'success', ('ok',))
2405
 
        client.add_expected_call(
2406
 
            'Repository.insert_stream', ('quack/', ''),
2407
 
            'success', ('ok',))
2408
 
        self.checkInsertEmptyStream(repo, client)
2409
 
 
2410
 
    def test_locked_repo_with_no_lock_token(self):
2411
 
        transport_path = 'quack'
2412
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2413
 
        client.add_expected_call(
2414
 
            'Repository.lock_write', ('quack/', ''),
2415
 
            'success', ('ok', ''))
2416
 
        client.add_expected_call(
2417
 
            'Repository.insert_stream_1.19', ('quack/', ''),
2418
 
            'unknown', ('Repository.insert_stream_1.19',))
2419
 
        client.add_expected_call(
2420
 
            'Repository.insert_stream', ('quack/', ''),
2421
 
            'success', ('ok',))
2422
 
        client.add_expected_call(
2423
 
            'Repository.insert_stream', ('quack/', ''),
2424
 
            'success', ('ok',))
2425
 
        repo.lock_write()
2426
 
        self.checkInsertEmptyStream(repo, client)
2427
 
 
2428
 
    def test_locked_repo_with_lock_token(self):
2429
 
        transport_path = 'quack'
2430
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2431
 
        client.add_expected_call(
2432
 
            'Repository.lock_write', ('quack/', ''),
2433
 
            'success', ('ok', 'a token'))
2434
 
        client.add_expected_call(
2435
 
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
2436
 
            'unknown', ('Repository.insert_stream_1.19',))
2437
 
        client.add_expected_call(
2438
 
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
2439
 
            'success', ('ok',))
2440
 
        client.add_expected_call(
2441
 
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
2442
 
            'success', ('ok',))
2443
 
        repo.lock_write()
2444
 
        self.checkInsertEmptyStream(repo, client)
2445
 
 
2446
 
    def test_stream_with_inventory_deltas(self):
2447
 
        """'inventory-deltas' substreams cannot be sent to the
2448
 
        Repository.insert_stream verb, because not all servers that implement
2449
 
        that verb will accept them.  So when one is encountered the RemoteSink
2450
 
        immediately stops using that verb and falls back to VFS insert_stream.
2451
 
        """
2452
 
        transport_path = 'quack'
2453
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2454
 
        client.add_expected_call(
2455
 
            'Repository.insert_stream_1.19', ('quack/', ''),
2456
 
            'unknown', ('Repository.insert_stream_1.19',))
2457
 
        client.add_expected_call(
2458
 
            'Repository.insert_stream', ('quack/', ''),
2459
 
            'success', ('ok',))
2460
 
        client.add_expected_call(
2461
 
            'Repository.insert_stream', ('quack/', ''),
2462
 
            'success', ('ok',))
2463
 
        # Create a fake real repository for insert_stream to fall back on, so
2464
 
        # that we can directly see the records the RemoteSink passes to the
2465
 
        # real sink.
2466
 
        class FakeRealSink:
2467
 
            def __init__(self):
2468
 
                self.records = []
2469
 
            def insert_stream(self, stream, src_format, resume_tokens):
2470
 
                for substream_kind, substream in stream:
2471
 
                    self.records.append(
2472
 
                        (substream_kind, [record.key for record in substream]))
2473
 
                return ['fake tokens'], ['fake missing keys']
2474
 
        fake_real_sink = FakeRealSink()
2475
 
        class FakeRealRepository:
2476
 
            def _get_sink(self):
2477
 
                return fake_real_sink
2478
 
            def is_in_write_group(self):
2479
 
                return False
2480
 
            def refresh_data(self):
2481
 
                return True
2482
 
        repo._real_repository = FakeRealRepository()
2483
 
        sink = repo._get_sink()
2484
 
        fmt = repository.RepositoryFormat.get_default_format()
2485
 
        stream = self.make_stream_with_inv_deltas(fmt)
2486
 
        resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
2487
 
        # Every record from the first inventory delta should have been sent to
2488
 
        # the VFS sink.
2489
 
        expected_records = [
2490
 
            ('inventory-deltas', [('rev2',), ('rev3',)]),
2491
 
            ('texts', [('some-rev', 'some-file')])]
2492
 
        self.assertEqual(expected_records, fake_real_sink.records)
2493
 
        # The return values from the real sink's insert_stream are propagated
2494
 
        # back to the original caller.
2495
 
        self.assertEqual(['fake tokens'], resume_tokens)
2496
 
        self.assertEqual(['fake missing keys'], missing_keys)
2497
 
        self.assertFinished(client)
2498
 
 
2499
 
    def make_stream_with_inv_deltas(self, fmt):
2500
 
        """Make a simple stream with an inventory delta followed by more
2501
 
        records and more substreams to test that all records and substreams
2502
 
        from that point on are used.
2503
 
 
2504
 
        This sends, in order:
2505
 
           * inventories substream: rev1, rev2, rev3.  rev2 and rev3 are
2506
 
             inventory-deltas.
2507
 
           * texts substream: (some-rev, some-file)
2508
 
        """
2509
 
        # Define a stream using generators so that it isn't rewindable.
2510
 
        inv = inventory.Inventory(revision_id='rev1')
2511
 
        inv.root.revision = 'rev1'
2512
 
        def stream_with_inv_delta():
2513
 
            yield ('inventories', inventories_substream())
2514
 
            yield ('inventory-deltas', inventory_delta_substream())
2515
 
            yield ('texts', [
2516
 
                versionedfile.FulltextContentFactory(
2517
 
                    ('some-rev', 'some-file'), (), None, 'content')])
2518
 
        def inventories_substream():
2519
 
            # An empty inventory fulltext.  This will be streamed normally.
2520
 
            text = fmt._serializer.write_inventory_to_string(inv)
2521
 
            yield versionedfile.FulltextContentFactory(
2522
 
                ('rev1',), (), None, text)
2523
 
        def inventory_delta_substream():
2524
 
            # An inventory delta.  This can't be streamed via this verb, so it
2525
 
            # will trigger a fallback to VFS insert_stream.
2526
 
            entry = inv.make_entry(
2527
 
                'directory', 'newdir', inv.root.file_id, 'newdir-id')
2528
 
            entry.revision = 'ghost'
2529
 
            delta = [(None, 'newdir', 'newdir-id', entry)]
2530
 
            serializer = inventory_delta.InventoryDeltaSerializer(
2531
 
                versioned_root=True, tree_references=False)
2532
 
            lines = serializer.delta_to_lines('rev1', 'rev2', delta)
2533
 
            yield versionedfile.ChunkedContentFactory(
2534
 
                ('rev2',), (('rev1',)), None, lines)
2535
 
            # Another delta.
2536
 
            lines = serializer.delta_to_lines('rev1', 'rev3', delta)
2537
 
            yield versionedfile.ChunkedContentFactory(
2538
 
                ('rev3',), (('rev1',)), None, lines)
2539
 
        return stream_with_inv_delta()
2540
 
 
2541
 
 
2542
 
class TestRepositoryInsertStream_1_19(TestRepositoryInsertStreamBase):
2543
 
 
2544
 
    def test_unlocked_repo(self):
2545
 
        transport_path = 'quack'
2546
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2547
 
        client.add_expected_call(
2548
 
            'Repository.insert_stream_1.19', ('quack/', ''),
2549
 
            'success', ('ok',))
2550
 
        client.add_expected_call(
2551
 
            'Repository.insert_stream_1.19', ('quack/', ''),
2552
 
            'success', ('ok',))
2553
 
        self.checkInsertEmptyStream(repo, client)
2554
 
 
2555
 
    def test_locked_repo_with_no_lock_token(self):
2556
 
        transport_path = 'quack'
2557
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2558
 
        client.add_expected_call(
2559
 
            'Repository.lock_write', ('quack/', ''),
2560
 
            'success', ('ok', ''))
2561
 
        client.add_expected_call(
2562
 
            'Repository.insert_stream_1.19', ('quack/', ''),
2563
 
            'success', ('ok',))
2564
 
        client.add_expected_call(
2565
 
            'Repository.insert_stream_1.19', ('quack/', ''),
2566
 
            'success', ('ok',))
2567
 
        repo.lock_write()
2568
 
        self.checkInsertEmptyStream(repo, client)
2569
 
 
2570
 
    def test_locked_repo_with_lock_token(self):
2571
 
        transport_path = 'quack'
2572
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2573
 
        client.add_expected_call(
2574
 
            'Repository.lock_write', ('quack/', ''),
2575
 
            'success', ('ok', 'a token'))
2576
 
        client.add_expected_call(
2577
 
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
2578
 
            'success', ('ok',))
2579
 
        client.add_expected_call(
2580
 
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
2581
 
            'success', ('ok',))
2582
 
        repo.lock_write()
2583
 
        self.checkInsertEmptyStream(repo, client)
 
2086
class TestRepositoryInsertStream(TestRemoteRepository):
 
2087
 
 
2088
    def test_unlocked_repo(self):
 
2089
        transport_path = 'quack'
 
2090
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2091
        client.add_expected_call(
 
2092
            'Repository.insert_stream', ('quack/', ''),
 
2093
            'success', ('ok',))
 
2094
        client.add_expected_call(
 
2095
            'Repository.insert_stream', ('quack/', ''),
 
2096
            'success', ('ok',))
 
2097
        sink = repo._get_sink()
 
2098
        fmt = repository.RepositoryFormat.get_default_format()
 
2099
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
 
2100
        self.assertEqual([], resume_tokens)
 
2101
        self.assertEqual(set(), missing_keys)
 
2102
        client.finished_test()
 
2103
 
 
2104
    def test_locked_repo_with_no_lock_token(self):
 
2105
        transport_path = 'quack'
 
2106
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2107
        client.add_expected_call(
 
2108
            'Repository.lock_write', ('quack/', ''),
 
2109
            'success', ('ok', ''))
 
2110
        client.add_expected_call(
 
2111
            'Repository.insert_stream', ('quack/', ''),
 
2112
            'success', ('ok',))
 
2113
        client.add_expected_call(
 
2114
            'Repository.insert_stream', ('quack/', ''),
 
2115
            'success', ('ok',))
 
2116
        repo.lock_write()
 
2117
        sink = repo._get_sink()
 
2118
        fmt = repository.RepositoryFormat.get_default_format()
 
2119
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
 
2120
        self.assertEqual([], resume_tokens)
 
2121
        self.assertEqual(set(), missing_keys)
 
2122
        client.finished_test()
 
2123
 
 
2124
    def test_locked_repo_with_lock_token(self):
 
2125
        transport_path = 'quack'
 
2126
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2127
        client.add_expected_call(
 
2128
            'Repository.lock_write', ('quack/', ''),
 
2129
            'success', ('ok', 'a token'))
 
2130
        client.add_expected_call(
 
2131
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
 
2132
            'success', ('ok',))
 
2133
        client.add_expected_call(
 
2134
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
 
2135
            'success', ('ok',))
 
2136
        repo.lock_write()
 
2137
        sink = repo._get_sink()
 
2138
        fmt = repository.RepositoryFormat.get_default_format()
 
2139
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
 
2140
        self.assertEqual([], resume_tokens)
 
2141
        self.assertEqual(set(), missing_keys)
 
2142
        client.finished_test()
2584
2143
 
2585
2144
 
2586
2145
class TestRepositoryTarball(TestRemoteRepository):
2671
2230
        client.add_expected_call(
2672
2231
            'PackRepository.autopack', ('quack/',), 'success', ('ok',))
2673
2232
        repo.autopack()
2674
 
        self.assertFinished(client)
 
2233
        client.finished_test()
2675
2234
 
2676
2235
    def test_ok_with_real_repo(self):
2677
2236
        """When the server returns 'ok' and there is a _real_repository, then
2776
2335
        expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
2777
2336
        self.assertEqual(expected_error, translated_error)
2778
2337
 
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
 
 
2788
2338
    def test_LockContention(self):
2789
2339
        translated_error = self.translateTuple(('LockContention',))
2790
2340
        expected_error = errors.LockContention('(remote lock)')
2830
2380
        expected_error = errors.ReadError(path)
2831
2381
        self.assertEqual(expected_error, translated_error)
2832
2382
 
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
 
 
2840
2383
    def test_PermissionDenied_no_args(self):
2841
2384
        path = 'a path'
2842
2385
        translated_error = self.translateTuple(('PermissionDenied',), path=path)
2903
2446
        # In addition to re-raising ErrorFromSmartServer, some debug info has
2904
2447
        # been muttered to the log file for developer to look at.
2905
2448
        self.assertContainsRe(
2906
 
            self.get_log(),
 
2449
            self._get_log(keep_log_file=True),
2907
2450
            "Missing key 'branch' in context")
2908
2451
 
2909
2452
    def test_path_missing(self):
2917
2460
        self.assertEqual(server_error, translated_error)
2918
2461
        # In addition to re-raising ErrorFromSmartServer, some debug info has
2919
2462
        # been muttered to the log file for developer to look at.
2920
 
        self.assertContainsRe(self.get_log(), "Missing key 'path' in context")
 
2463
        self.assertContainsRe(
 
2464
            self._get_log(keep_log_file=True), "Missing key 'path' in context")
2921
2465
 
2922
2466
 
2923
2467
class TestStacking(tests.TestCaseWithTransport):
2942
2486
        stacked_branch.set_stacked_on_url('../base')
2943
2487
        # start a server looking at this
2944
2488
        smart_server = server.SmartTCPServer_for_testing()
2945
 
        self.start_server(smart_server)
 
2489
        smart_server.setUp()
 
2490
        self.addCleanup(smart_server.tearDown)
2946
2491
        remote_bzrdir = BzrDir.open(smart_server.get_url() + '/stacked')
2947
2492
        # can get its branch and repository
2948
2493
        remote_branch = remote_bzrdir.open_branch()
2970
2515
        tree1.commit('rev1', rev_id='rev1')
2971
2516
        tree2 = tree1.branch.bzrdir.sprout('tree2', stacked=True
2972
2517
            ).open_workingtree()
2973
 
        local_tree = tree2.branch.create_checkout('local')
2974
 
        local_tree.commit('local changes make me feel good.')
 
2518
        tree2.commit('local changes make me feel good.')
2975
2519
        branch2 = Branch.open(self.get_url('tree2'))
2976
2520
        branch2.lock_read()
2977
2521
        self.addCleanup(branch2.unlock)
2999
2543
                    result.append(content.key[-1])
3000
2544
        return result
3001
2545
 
3002
 
    def get_ordered_revs(self, format, order, branch_factory=None):
 
2546
    def get_ordered_revs(self, format, order):
3003
2547
        """Get a list of the revisions in a stream to format format.
3004
2548
 
3005
2549
        :param format: The format of the target.
3006
2550
        :param order: the order that target should have requested.
3007
 
        :param branch_factory: A callable to create a trunk and stacked branch
3008
 
            to fetch from. If none, self.prepare_stacked_remote_branch is used.
3009
2551
        :result: The revision ids in the stream, in the order seen,
3010
2552
            the topological order of revisions in the source.
3011
2553
        """
3013
2555
        target_repository_format = unordered_format.repository_format
3014
2556
        # Cross check
3015
2557
        self.assertEqual(order, target_repository_format._fetch_order)
3016
 
        if branch_factory is None:
3017
 
            branch_factory = self.prepare_stacked_remote_branch
3018
 
        _, stacked = branch_factory()
 
2558
        trunk, stacked = self.prepare_stacked_remote_branch()
3019
2559
        source = stacked.repository._get_source(target_repository_format)
3020
2560
        tip = stacked.last_revision()
3021
2561
        revs = stacked.repository.get_ancestry(tip)
3040
2580
        # from the server, then one from the backing branch.
3041
2581
        self.assertLength(2, self.hpss_calls)
3042
2582
 
3043
 
    def test_stacked_on_stacked_get_stream_unordered(self):
3044
 
        # Repository._get_source.get_stream() from a stacked repository which
3045
 
        # is itself stacked yields the full data from all three sources.
3046
 
        def make_stacked_stacked():
3047
 
            _, stacked = self.prepare_stacked_remote_branch()
3048
 
            tree = stacked.bzrdir.sprout('tree3', stacked=True
3049
 
                ).open_workingtree()
3050
 
            local_tree = tree.branch.create_checkout('local-tree3')
3051
 
            local_tree.commit('more local changes are better')
3052
 
            branch = Branch.open(self.get_url('tree3'))
3053
 
            branch.lock_read()
3054
 
            self.addCleanup(branch.unlock)
3055
 
            return None, branch
3056
 
        rev_ord, expected_revs = self.get_ordered_revs('1.9', 'unordered',
3057
 
            branch_factory=make_stacked_stacked)
3058
 
        self.assertEqual(set(expected_revs), set(rev_ord))
3059
 
        # Getting unordered results should have made a streaming data request
3060
 
        # from the server, and one from each backing repo
3061
 
        self.assertLength(3, self.hpss_calls)
3062
 
 
3063
2583
    def test_stacked_get_stream_topological(self):
3064
2584
        # Repository._get_source.get_stream() from a stacked repository with
3065
2585
        # topological sorting yields the full data from both stacked and
3066
2586
        # stacked upon sources in topological order.
3067
2587
        rev_ord, expected_revs = self.get_ordered_revs('knit', 'topological')
3068
2588
        self.assertEqual(expected_revs, rev_ord)
3069
 
        # Getting topological sort requires VFS calls still - one of which is
3070
 
        # pushing up from the bound branch.
3071
 
        self.assertLength(13, self.hpss_calls)
 
2589
        # Getting topological sort requires VFS calls still
 
2590
        self.assertLength(12, self.hpss_calls)
3072
2591
 
3073
2592
    def test_stacked_get_stream_groupcompress(self):
3074
2593
        # Repository._get_source.get_stream() from a stacked repository with
3104
2623
        # Create a smart server that publishes whatever the backing VFS server
3105
2624
        # does.
3106
2625
        self.smart_server = server.SmartTCPServer_for_testing()
3107
 
        self.start_server(self.smart_server, self.get_server())
 
2626
        self.smart_server.setUp(self.get_server())
 
2627
        self.addCleanup(self.smart_server.tearDown)
3108
2628
        # Log all HPSS calls into self.hpss_calls.
3109
2629
        _SmartClient.hooks.install_named_hook(
3110
2630
            'call', self.capture_hpss_call, None)