~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-08-24 21:59:21 UTC
  • mfrom: (5363.2.22 controldir-1)
  • Revision ID: pqm@pqm.ubuntu.com-20100824215921-p4nheij9k4x6i1jw
(jelmer) Split generic interface code out of bzrlib.bzrdir.BzrDir into
 bzrlib.controldir.ControlDir. (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2007, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2006-2010 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
27
27
from cStringIO import StringIO
28
28
 
29
29
from bzrlib import (
 
30
    branch,
30
31
    bzrdir,
31
32
    config,
 
33
    controldir,
32
34
    errors,
33
35
    graph,
34
 
    pack,
 
36
    inventory,
 
37
    inventory_delta,
35
38
    remote,
36
39
    repository,
37
 
    smart,
38
40
    tests,
 
41
    transport,
39
42
    treebuilder,
40
 
    urlutils,
 
43
    versionedfile,
41
44
    )
42
45
from bzrlib.branch import Branch
43
 
from bzrlib.bzrdir import BzrDir, BzrDirFormat
 
46
from bzrlib.bzrdir import (
 
47
    BzrDir,
 
48
    BzrDirFormat,
 
49
    RemoteBzrProber,
 
50
    )
44
51
from bzrlib.remote import (
45
52
    RemoteBranch,
46
53
    RemoteBranchFormat,
47
54
    RemoteBzrDir,
48
 
    RemoteBzrDirFormat,
49
55
    RemoteRepository,
50
56
    RemoteRepositoryFormat,
51
57
    )
52
58
from bzrlib.repofmt import groupcompress_repo, pack_repo
53
59
from bzrlib.revision import NULL_REVISION
54
 
from bzrlib.smart import server, medium
 
60
from bzrlib.smart import medium
55
61
from bzrlib.smart.client import _SmartClient
56
62
from bzrlib.smart.repository import SmartServerRepositoryGetParentMap
57
63
from bzrlib.tests import (
58
64
    condition_isinstance,
59
65
    split_suite_by_condition,
60
66
    multiply_tests,
61
 
    KnownFailure,
 
67
    test_server,
62
68
    )
63
 
from bzrlib.transport import get_transport, http
64
69
from bzrlib.transport.memory import MemoryTransport
65
70
from bzrlib.transport.remote import (
66
71
    RemoteTransport,
73
78
        standard_tests, condition_isinstance(BasicRemoteObjectTests))
74
79
    smart_server_version_scenarios = [
75
80
        ('HPSS-v2',
76
 
            {'transport_server': server.SmartTCPServer_for_testing_v2_only}),
 
81
         {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
77
82
        ('HPSS-v3',
78
 
            {'transport_server': server.SmartTCPServer_for_testing})]
 
83
         {'transport_server': test_server.SmartTCPServer_for_testing})]
79
84
    return multiply_tests(to_adapt, smart_server_version_scenarios, result)
80
85
 
81
86
 
86
91
        self.transport = self.get_transport()
87
92
        # make a branch that can be opened over the smart transport
88
93
        self.local_wt = BzrDir.create_standalone_workingtree('.')
89
 
 
90
 
    def tearDown(self):
91
 
        self.transport.disconnect()
92
 
        tests.TestCaseWithTransport.tearDown(self)
 
94
        self.addCleanup(self.transport.disconnect)
93
95
 
94
96
    def test_create_remote_bzrdir(self):
95
97
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
119
121
    def test_find_correct_format(self):
120
122
        """Should open a RemoteBzrDir over a RemoteTransport"""
121
123
        fmt = BzrDirFormat.find_format(self.transport)
122
 
        self.assertTrue(RemoteBzrDirFormat
123
 
                        in BzrDirFormat._control_server_formats)
 
124
        self.assertTrue(bzrdir.RemoteBzrProber
 
125
                        in controldir.ControlDirFormat._server_probers)
124
126
        self.assertIsInstance(fmt, remote.RemoteBzrDirFormat)
125
127
 
126
128
    def test_open_detected_smart_format(self):
132
134
        b = BzrDir.open_from_transport(self.transport).open_branch()
133
135
        self.assertStartsWith(str(b), 'RemoteBranch(')
134
136
 
 
137
    def test_remote_bzrdir_repr(self):
 
138
        b = BzrDir.open_from_transport(self.transport)
 
139
        self.assertStartsWith(str(b), 'RemoteBzrDir(')
 
140
 
135
141
    def test_remote_branch_format_supports_stacking(self):
136
142
        t = self.transport
137
143
        self.make_branch('unstackable', format='pack-0.92')
277
283
        self.expecting_body = True
278
284
        return result[1], FakeProtocol(result[2], self)
279
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
 
280
292
    def call_with_body_bytes_expecting_body(self, method, args, body):
281
293
        self._check_call(method, args)
282
294
        self._calls.append(('call_with_body_bytes_expecting_body', method,
332
344
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
333
345
        return reference_bzrdir_format.repository_format
334
346
 
335
 
    def disable_verb(self, verb):
336
 
        """Disable a verb for one test."""
337
 
        request_handlers = smart.request.request_handlers
338
 
        orig_method = request_handlers.get(verb)
339
 
        request_handlers.remove(verb)
340
 
        def restoreVerb():
341
 
            request_handlers.register(verb, orig_method)
342
 
        self.addCleanup(restoreVerb)
343
 
 
344
347
    def assertFinished(self, fake_client):
345
348
        """Assert that all of a FakeClient's expected calls have occurred."""
346
349
        fake_client.finished_test()
355
358
        a given client_base and transport_base.
356
359
        """
357
360
        client_medium = medium.SmartClientMedium(client_base)
358
 
        transport = get_transport(transport_base)
359
 
        result = client_medium.remote_path_from_transport(transport)
 
361
        t = transport.get_transport(transport_base)
 
362
        result = client_medium.remote_path_from_transport(t)
360
363
        self.assertEqual(expected, result)
361
364
 
362
365
    def test_remote_path_from_transport(self):
373
376
        a given transport_base and relpath of that transport.  (Note that
374
377
        HttpTransportBase is a subclass of SmartClientMedium)
375
378
        """
376
 
        base_transport = get_transport(transport_base)
 
379
        base_transport = transport.get_transport(transport_base)
377
380
        client_medium = base_transport.get_smart_medium()
378
381
        cloned_transport = base_transport.clone(relpath)
379
382
        result = client_medium.remote_path_from_transport(cloned_transport)
414
417
        # Calling _remember_remote_is_before again with a lower value works.
415
418
        client_medium._remember_remote_is_before((1, 5))
416
419
        self.assertTrue(client_medium._is_remote_before((1, 5)))
417
 
        # You cannot call _remember_remote_is_before with a larger value.
418
 
        self.assertRaises(
419
 
            AssertionError, client_medium._remember_remote_is_before, (1, 9))
 
420
        # If you call _remember_remote_is_before with a higher value it logs a
 
421
        # warning, and continues to remember the lower value.
 
422
        self.assertNotContainsRe(self.get_log(), '_remember_remote_is_before')
 
423
        client_medium._remember_remote_is_before((1, 9))
 
424
        self.assertContainsRe(self.get_log(), '_remember_remote_is_before')
 
425
        self.assertTrue(client_medium._is_remote_before((1, 5)))
420
426
 
421
427
 
422
428
class TestBzrDirCloningMetaDir(TestRemote):
441
447
            'BzrDir.cloning_metadir', ('quack/', 'False'),
442
448
            'error', ('BranchReference',)),
443
449
        client.add_expected_call(
444
 
            'BzrDir.open_branchV2', ('quack/',),
 
450
            'BzrDir.open_branchV3', ('quack/',),
445
451
            'success', ('ref', self.get_url('referenced'))),
446
452
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
447
453
            _client=client)
474
480
        self.assertFinished(client)
475
481
 
476
482
 
 
483
class TestBzrDirOpen(TestRemote):
 
484
 
 
485
    def make_fake_client_and_transport(self, path='quack'):
 
486
        transport = MemoryTransport()
 
487
        transport.mkdir(path)
 
488
        transport = transport.clone(path)
 
489
        client = FakeClient(transport.base)
 
490
        return client, transport
 
491
 
 
492
    def test_absent(self):
 
493
        client, transport = self.make_fake_client_and_transport()
 
494
        client.add_expected_call(
 
495
            'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
 
496
        self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
 
497
                remote.RemoteBzrDirFormat(), _client=client, _force_probe=True)
 
498
        self.assertFinished(client)
 
499
 
 
500
    def test_present_without_workingtree(self):
 
501
        client, transport = self.make_fake_client_and_transport()
 
502
        client.add_expected_call(
 
503
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
 
504
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
505
            _client=client, _force_probe=True)
 
506
        self.assertIsInstance(bd, RemoteBzrDir)
 
507
        self.assertFalse(bd.has_workingtree())
 
508
        self.assertRaises(errors.NoWorkingTree, bd.open_workingtree)
 
509
        self.assertFinished(client)
 
510
 
 
511
    def test_present_with_workingtree(self):
 
512
        client, transport = self.make_fake_client_and_transport()
 
513
        client.add_expected_call(
 
514
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
 
515
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
516
            _client=client, _force_probe=True)
 
517
        self.assertIsInstance(bd, RemoteBzrDir)
 
518
        self.assertTrue(bd.has_workingtree())
 
519
        self.assertRaises(errors.NotLocalUrl, bd.open_workingtree)
 
520
        self.assertFinished(client)
 
521
 
 
522
    def test_backwards_compat(self):
 
523
        client, transport = self.make_fake_client_and_transport()
 
524
        client.add_expected_call(
 
525
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
 
526
        client.add_expected_call(
 
527
            'BzrDir.open', ('quack/',), 'success', ('yes',))
 
528
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
529
            _client=client, _force_probe=True)
 
530
        self.assertIsInstance(bd, RemoteBzrDir)
 
531
        self.assertFinished(client)
 
532
 
 
533
    def test_backwards_compat_hpss_v2(self):
 
534
        client, transport = self.make_fake_client_and_transport()
 
535
        # Monkey-patch fake client to simulate real-world behaviour with v2
 
536
        # server: upon first RPC call detect the protocol version, and because
 
537
        # the version is 2 also do _remember_remote_is_before((1, 6)) before
 
538
        # continuing with the RPC.
 
539
        orig_check_call = client._check_call
 
540
        def check_call(method, args):
 
541
            client._medium._protocol_version = 2
 
542
            client._medium._remember_remote_is_before((1, 6))
 
543
            client._check_call = orig_check_call
 
544
            client._check_call(method, args)
 
545
        client._check_call = check_call
 
546
        client.add_expected_call(
 
547
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
 
548
        client.add_expected_call(
 
549
            'BzrDir.open', ('quack/',), 'success', ('yes',))
 
550
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
551
            _client=client, _force_probe=True)
 
552
        self.assertIsInstance(bd, RemoteBzrDir)
 
553
        self.assertFinished(client)
 
554
 
 
555
 
477
556
class TestBzrDirOpenBranch(TestRemote):
478
557
 
479
558
    def test_backwards_compat(self):
481
560
        self.make_branch('.')
482
561
        a_dir = BzrDir.open(self.get_url('.'))
483
562
        self.reset_smart_call_log()
484
 
        verb = 'BzrDir.open_branchV2'
 
563
        verb = 'BzrDir.open_branchV3'
485
564
        self.disable_verb(verb)
486
565
        format = a_dir.open_branch()
487
566
        call_count = len([call for call in self.hpss_calls if
497
576
        transport = transport.clone('quack')
498
577
        client = FakeClient(transport.base)
499
578
        client.add_expected_call(
500
 
            'BzrDir.open_branchV2', ('quack/',),
 
579
            'BzrDir.open_branchV3', ('quack/',),
501
580
            'success', ('branch', branch_network_name))
502
581
        client.add_expected_call(
503
582
            'BzrDir.find_repositoryV3', ('quack/',),
522
601
            _client=client)
523
602
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
524
603
        self.assertEqual(
525
 
            [('call', 'BzrDir.open_branchV2', ('quack/',))],
 
604
            [('call', 'BzrDir.open_branchV3', ('quack/',))],
526
605
            client._calls)
527
606
 
528
607
    def test__get_tree_branch(self):
529
608
        # _get_tree_branch is a form of open_branch, but it should only ask for
530
609
        # branch opening, not any other network requests.
531
610
        calls = []
532
 
        def open_branch():
 
611
        def open_branch(name=None):
533
612
            calls.append("Called")
534
613
            return "a-branch"
535
614
        transport = MemoryTransport()
552
631
        network_name = reference_format.network_name()
553
632
        branch_network_name = self.get_branch_format().network_name()
554
633
        client.add_expected_call(
555
 
            'BzrDir.open_branchV2', ('~hello/',),
 
634
            'BzrDir.open_branchV3', ('~hello/',),
556
635
            'success', ('branch', branch_network_name))
557
636
        client.add_expected_call(
558
637
            'BzrDir.find_repositoryV3', ('~hello/',),
606
685
        old.
607
686
        """
608
687
        self.assertRaises(errors.NotBranchError,
609
 
            RemoteBzrDirFormat.probe_transport, OldServerTransport())
 
688
            RemoteBzrProber.probe_transport, OldServerTransport())
610
689
 
611
690
 
612
691
class TestBzrDirCreateBranch(TestRemote):
667
746
        network_name = reference_format.network_name()
668
747
        client.add_expected_call(
669
748
            'BzrDir.create_repository', ('quack/',
670
 
                'Bazaar pack repository format 1 (needs bzr 0.92)\n', 'False'),
671
 
            'success', ('ok', 'no', 'no', 'no', network_name))
 
749
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
 
750
                'False'),
 
751
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
672
752
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
673
753
            _client=client)
674
754
        repo = a_bzrdir.create_repository()
676
756
        self.assertIsInstance(repo, remote.RemoteRepository)
677
757
        # its format should have the settings from the response
678
758
        format = repo._format
679
 
        self.assertFalse(format.rich_root_data)
680
 
        self.assertFalse(format.supports_tree_reference)
681
 
        self.assertFalse(format.supports_external_lookups)
 
759
        self.assertTrue(format.rich_root_data)
 
760
        self.assertTrue(format.supports_tree_reference)
 
761
        self.assertTrue(format.supports_external_lookups)
682
762
        self.assertEqual(network_name, format.network_name())
683
763
 
684
764
 
688
768
        # fallback all the way to the first version.
689
769
        reference_format = self.get_repo_format()
690
770
        network_name = reference_format.network_name()
691
 
        client = FakeClient('bzr://example.com/')
 
771
        server_url = 'bzr://example.com/'
 
772
        self.permit_url(server_url)
 
773
        client = FakeClient(server_url)
692
774
        client.add_unknown_method_response('BzrDir.find_repositoryV3')
693
775
        client.add_unknown_method_response('BzrDir.find_repositoryV2')
694
776
        client.add_success_response('ok', '', 'no', 'no')
700
782
            reference_format.get_format_string(), 'ok')
701
783
        # PackRepository wants to do a stat
702
784
        client.add_success_response('stat', '0', '65535')
703
 
        remote_transport = RemoteTransport('bzr://example.com/quack/', medium=False,
 
785
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
704
786
            _client=client)
705
787
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
706
788
            _client=client)
720
802
        # fallback to find_repositoryV2
721
803
        reference_format = self.get_repo_format()
722
804
        network_name = reference_format.network_name()
723
 
        client = FakeClient('bzr://example.com/')
 
805
        server_url = 'bzr://example.com/'
 
806
        self.permit_url(server_url)
 
807
        client = FakeClient(server_url)
724
808
        client.add_unknown_method_response('BzrDir.find_repositoryV3')
725
809
        client.add_success_response('ok', '', 'no', 'no', 'no')
726
810
        # A real repository instance will be created to determine the network
731
815
            reference_format.get_format_string(), 'ok')
732
816
        # PackRepository wants to do a stat
733
817
        client.add_success_response('stat', '0', '65535')
734
 
        remote_transport = RemoteTransport('bzr://example.com/quack/', medium=False,
 
818
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
735
819
            _client=client)
736
820
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
737
821
            _client=client)
856
940
 
857
941
class RemoteBranchTestCase(RemoteBzrDirTestCase):
858
942
 
 
943
    def lock_remote_branch(self, branch):
 
944
        """Trick a RemoteBranch into thinking it is locked."""
 
945
        branch._lock_mode = 'w'
 
946
        branch._lock_count = 2
 
947
        branch._lock_token = 'branch token'
 
948
        branch._repo_lock_token = 'repo token'
 
949
        branch.repository._lock_mode = 'w'
 
950
        branch.repository._lock_count = 2
 
951
        branch.repository._lock_token = 'repo token'
 
952
 
859
953
    def make_remote_branch(self, transport, client):
860
954
        """Make a RemoteBranch using 'client' as its _SmartClient.
861
955
 
1000
1094
        self.assertEqual({}, result)
1001
1095
 
1002
1096
 
 
1097
class TestBranchSetTagsBytes(RemoteBranchTestCase):
 
1098
 
 
1099
    def test_trivial(self):
 
1100
        transport = MemoryTransport()
 
1101
        client = FakeClient(transport.base)
 
1102
        client.add_expected_call(
 
1103
            'Branch.get_stacked_on_url', ('quack/',),
 
1104
            'error', ('NotStacked',))
 
1105
        client.add_expected_call(
 
1106
            'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
 
1107
            'success', ('',))
 
1108
        transport.mkdir('quack')
 
1109
        transport = transport.clone('quack')
 
1110
        branch = self.make_remote_branch(transport, client)
 
1111
        self.lock_remote_branch(branch)
 
1112
        branch._set_tags_bytes('tags bytes')
 
1113
        self.assertFinished(client)
 
1114
        self.assertEqual('tags bytes', client._calls[-1][-1])
 
1115
 
 
1116
    def test_backwards_compatible(self):
 
1117
        transport = MemoryTransport()
 
1118
        client = FakeClient(transport.base)
 
1119
        client.add_expected_call(
 
1120
            'Branch.get_stacked_on_url', ('quack/',),
 
1121
            'error', ('NotStacked',))
 
1122
        client.add_expected_call(
 
1123
            'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
 
1124
            'unknown', ('Branch.set_tags_bytes',))
 
1125
        transport.mkdir('quack')
 
1126
        transport = transport.clone('quack')
 
1127
        branch = self.make_remote_branch(transport, client)
 
1128
        self.lock_remote_branch(branch)
 
1129
        class StubRealBranch(object):
 
1130
            def __init__(self):
 
1131
                self.calls = []
 
1132
            def _set_tags_bytes(self, bytes):
 
1133
                self.calls.append(('set_tags_bytes', bytes))
 
1134
        real_branch = StubRealBranch()
 
1135
        branch._real_branch = real_branch
 
1136
        branch._set_tags_bytes('tags bytes')
 
1137
        # Call a second time, to exercise the 'remote version already inferred'
 
1138
        # code path.
 
1139
        branch._set_tags_bytes('tags bytes')
 
1140
        self.assertFinished(client)
 
1141
        self.assertEqual(
 
1142
            [('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
 
1143
 
 
1144
 
1003
1145
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
1004
1146
 
1005
1147
    def test_empty_branch(self):
1077
1219
        client = FakeClient(self.get_url())
1078
1220
        branch_network_name = self.get_branch_format().network_name()
1079
1221
        client.add_expected_call(
1080
 
            'BzrDir.open_branchV2', ('stacked/',),
 
1222
            'BzrDir.open_branchV3', ('stacked/',),
1081
1223
            'success', ('branch', branch_network_name))
1082
1224
        client.add_expected_call(
1083
1225
            'BzrDir.find_repositoryV3', ('stacked/',),
1105
1247
            len(branch.repository._real_repository._fallback_repositories))
1106
1248
 
1107
1249
    def test_get_stacked_on_real_branch(self):
1108
 
        base_branch = self.make_branch('base', format='1.6')
1109
 
        stacked_branch = self.make_branch('stacked', format='1.6')
 
1250
        base_branch = self.make_branch('base')
 
1251
        stacked_branch = self.make_branch('stacked')
1110
1252
        stacked_branch.set_stacked_on_url('../base')
1111
1253
        reference_format = self.get_repo_format()
1112
1254
        network_name = reference_format.network_name()
1113
1255
        client = FakeClient(self.get_url())
1114
1256
        branch_network_name = self.get_branch_format().network_name()
1115
1257
        client.add_expected_call(
1116
 
            'BzrDir.open_branchV2', ('stacked/',),
 
1258
            'BzrDir.open_branchV3', ('stacked/',),
1117
1259
            'success', ('branch', branch_network_name))
1118
1260
        client.add_expected_call(
1119
1261
            'BzrDir.find_repositoryV3', ('stacked/',),
1120
 
            'success', ('ok', '', 'no', 'no', 'yes', network_name))
 
1262
            'success', ('ok', '', 'yes', 'no', 'yes', network_name))
1121
1263
        # called twice, once from constructor and then again by us
1122
1264
        client.add_expected_call(
1123
1265
            'Branch.get_stacked_on_url', ('stacked/',),
1347
1489
            errors.NoSuchRevision, branch.set_last_revision_info, 123, 'revid')
1348
1490
        branch.unlock()
1349
1491
 
1350
 
    def lock_remote_branch(self, branch):
1351
 
        """Trick a RemoteBranch into thinking it is locked."""
1352
 
        branch._lock_mode = 'w'
1353
 
        branch._lock_count = 2
1354
 
        branch._lock_token = 'branch token'
1355
 
        branch._repo_lock_token = 'repo token'
1356
 
        branch.repository._lock_mode = 'w'
1357
 
        branch.repository._lock_count = 2
1358
 
        branch.repository._lock_token = 'repo token'
1359
 
 
1360
1492
    def test_backwards_compatibility(self):
1361
1493
        """If the server does not support the Branch.set_last_revision_info
1362
1494
        verb (which is new in 1.4), then the client falls back to VFS methods.
1485
1617
    def test_get_multi_line_branch_conf(self):
1486
1618
        # Make sure that multiple-line branch.conf files are supported
1487
1619
        #
1488
 
        # https://bugs.edge.launchpad.net/bzr/+bug/354075
 
1620
        # https://bugs.launchpad.net/bzr/+bug/354075
1489
1621
        client = FakeClient()
1490
1622
        client.add_expected_call(
1491
1623
            'Branch.get_stacked_on_url', ('memory:///',),
1519
1651
        branch.unlock()
1520
1652
        self.assertFinished(client)
1521
1653
 
 
1654
    def test_set_option_with_dict(self):
 
1655
        client = FakeClient()
 
1656
        client.add_expected_call(
 
1657
            'Branch.get_stacked_on_url', ('memory:///',),
 
1658
            'error', ('NotStacked',),)
 
1659
        client.add_expected_call(
 
1660
            'Branch.lock_write', ('memory:///', '', ''),
 
1661
            'success', ('ok', 'branch token', 'repo token'))
 
1662
        encoded_dict_value = 'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
 
1663
        client.add_expected_call(
 
1664
            'Branch.set_config_option_dict', ('memory:///', 'branch token',
 
1665
            'repo token', encoded_dict_value, 'foo', ''),
 
1666
            'success', ())
 
1667
        client.add_expected_call(
 
1668
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
 
1669
            'success', ('ok',))
 
1670
        transport = MemoryTransport()
 
1671
        branch = self.make_remote_branch(transport, client)
 
1672
        branch.lock_write()
 
1673
        config = branch._get_config()
 
1674
        config.set_option(
 
1675
            {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'},
 
1676
            'foo')
 
1677
        branch.unlock()
 
1678
        self.assertFinished(client)
 
1679
 
1522
1680
    def test_backwards_compat_set_option(self):
1523
1681
        self.setup_smart_server_with_call_log()
1524
1682
        branch = self.make_branch('.')
1531
1689
        self.assertLength(10, self.hpss_calls)
1532
1690
        self.assertEqual('value', branch._get_config().get_option('name'))
1533
1691
 
 
1692
    def test_backwards_compat_set_option_with_dict(self):
 
1693
        self.setup_smart_server_with_call_log()
 
1694
        branch = self.make_branch('.')
 
1695
        verb = 'Branch.set_config_option_dict'
 
1696
        self.disable_verb(verb)
 
1697
        branch.lock_write()
 
1698
        self.addCleanup(branch.unlock)
 
1699
        self.reset_smart_call_log()
 
1700
        config = branch._get_config()
 
1701
        value_dict = {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
 
1702
        config.set_option(value_dict, 'name')
 
1703
        self.assertLength(10, self.hpss_calls)
 
1704
        self.assertEqual(value_dict, branch._get_config().get_option('name'))
 
1705
 
1534
1706
 
1535
1707
class TestBranchLockWrite(RemoteBranchTestCase):
1536
1708
 
1678
1850
        return repo, client
1679
1851
 
1680
1852
 
 
1853
def remoted_description(format):
 
1854
    return 'Remote: ' + format.get_format_description()
 
1855
 
 
1856
 
 
1857
class TestBranchFormat(tests.TestCase):
 
1858
 
 
1859
    def test_get_format_description(self):
 
1860
        remote_format = RemoteBranchFormat()
 
1861
        real_format = branch.BranchFormat.get_default_format()
 
1862
        remote_format._network_name = real_format.network_name()
 
1863
        self.assertEqual(remoted_description(real_format),
 
1864
            remote_format.get_format_description())
 
1865
 
 
1866
 
1681
1867
class TestRepositoryFormat(TestRemoteRepository):
1682
1868
 
1683
1869
    def test_fast_delta(self):
1690
1876
        false_format._network_name = false_name
1691
1877
        self.assertEqual(False, false_format.fast_deltas)
1692
1878
 
 
1879
    def test_get_format_description(self):
 
1880
        remote_repo_format = RemoteRepositoryFormat()
 
1881
        real_format = repository.RepositoryFormat.get_default_format()
 
1882
        remote_repo_format._network_name = real_format.network_name()
 
1883
        self.assertEqual(remoted_description(real_format),
 
1884
            remote_repo_format.get_format_description())
 
1885
 
1693
1886
 
1694
1887
class TestRepositoryGatherStats(TestRemoteRepository):
1695
1888
 
1880
2073
        self.assertLength(1, self.hpss_calls)
1881
2074
 
1882
2075
    def disableExtraResults(self):
1883
 
        old_flag = SmartServerRepositoryGetParentMap.no_extra_results
1884
 
        SmartServerRepositoryGetParentMap.no_extra_results = True
1885
 
        def reset_values():
1886
 
            SmartServerRepositoryGetParentMap.no_extra_results = old_flag
1887
 
        self.addCleanup(reset_values)
 
2076
        self.overrideAttr(SmartServerRepositoryGetParentMap,
 
2077
                          'no_extra_results', True)
1888
2078
 
1889
2079
    def test_null_cached_missing_and_stop_key(self):
1890
2080
        self.setup_smart_server_with_call_log()
1949
2139
 
1950
2140
    def test_allows_new_revisions(self):
1951
2141
        """get_parent_map's results can be updated by commit."""
1952
 
        smart_server = server.SmartTCPServer_for_testing()
1953
 
        smart_server.setUp()
1954
 
        self.addCleanup(smart_server.tearDown)
 
2142
        smart_server = test_server.SmartTCPServer_for_testing()
 
2143
        self.start_server(smart_server)
1955
2144
        self.make_branch('branch')
1956
2145
        branch = Branch.open(smart_server.get_url() + '/branch')
1957
2146
        tree = branch.create_checkout('tree', lightweight=True)
2066
2255
        """
2067
2256
        # Make a repo with a fallback repo, both using a FakeClient.
2068
2257
        format = remote.response_tuple_to_repo_format(
2069
 
            ('yes', 'no', 'yes', 'fake-network-name'))
 
2258
            ('yes', 'no', 'yes', self.get_repo_format().network_name()))
2070
2259
        repo, client = self.setup_fake_client_and_repository('quack')
2071
2260
        repo._format = format
2072
2261
        fallback_repo, ignored = self.setup_fake_client_and_repository(
2073
2262
            'fallback')
2074
2263
        fallback_repo._client = client
 
2264
        fallback_repo._format = format
2075
2265
        repo.add_fallback_repository(fallback_repo)
2076
2266
        # First the client should ask the primary repo
2077
2267
        client.add_expected_call(
2098
2288
            repo.get_rev_id_for_revno, 5, (42, 'rev-foo'))
2099
2289
        self.assertFinished(client)
2100
2290
 
 
2291
    def test_branch_fallback_locking(self):
 
2292
        """RemoteBranch.get_rev_id takes a read lock, and tries to call the
 
2293
        get_rev_id_for_revno verb.  If the verb is unknown the VFS fallback
 
2294
        will be invoked, which will fail if the repo is unlocked.
 
2295
        """
 
2296
        self.setup_smart_server_with_call_log()
 
2297
        tree = self.make_branch_and_memory_tree('.')
 
2298
        tree.lock_write()
 
2299
        tree.add('')
 
2300
        rev1 = tree.commit('First')
 
2301
        rev2 = tree.commit('Second')
 
2302
        tree.unlock()
 
2303
        branch = tree.branch
 
2304
        self.assertFalse(branch.is_locked())
 
2305
        self.reset_smart_call_log()
 
2306
        verb = 'Repository.get_rev_id_for_revno'
 
2307
        self.disable_verb(verb)
 
2308
        self.assertEqual(rev1, branch.get_rev_id(1))
 
2309
        self.assertLength(1, [call for call in self.hpss_calls if
 
2310
                              call.call.method == verb])
 
2311
 
2101
2312
 
2102
2313
class TestRepositoryIsShared(TestRemoteRepository):
2103
2314
 
2130
2341
        transport_path = 'quack'
2131
2342
        repo, client = self.setup_fake_client_and_repository(transport_path)
2132
2343
        client.add_success_response('ok', 'a token')
2133
 
        result = repo.lock_write()
 
2344
        token = repo.lock_write().repository_token
2134
2345
        self.assertEqual(
2135
2346
            [('call', 'Repository.lock_write', ('quack/', ''))],
2136
2347
            client._calls)
2137
 
        self.assertEqual('a token', result)
 
2348
        self.assertEqual('a token', token)
2138
2349
 
2139
2350
    def test_lock_write_already_locked(self):
2140
2351
        transport_path = 'quack'
2219
2430
        self.assertEqual([], client._calls)
2220
2431
 
2221
2432
 
2222
 
class TestRepositoryInsertStream(TestRemoteRepository):
2223
 
 
2224
 
    def test_unlocked_repo(self):
2225
 
        transport_path = 'quack'
2226
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2227
 
        client.add_expected_call(
2228
 
            'Repository.insert_stream', ('quack/', ''),
2229
 
            'success', ('ok',))
2230
 
        client.add_expected_call(
2231
 
            'Repository.insert_stream', ('quack/', ''),
2232
 
            'success', ('ok',))
2233
 
        sink = repo._get_sink()
2234
 
        fmt = repository.RepositoryFormat.get_default_format()
2235
 
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2236
 
        self.assertEqual([], resume_tokens)
2237
 
        self.assertEqual(set(), missing_keys)
2238
 
        self.assertFinished(client)
2239
 
 
2240
 
    def test_locked_repo_with_no_lock_token(self):
2241
 
        transport_path = 'quack'
2242
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2243
 
        client.add_expected_call(
2244
 
            'Repository.lock_write', ('quack/', ''),
2245
 
            'success', ('ok', ''))
2246
 
        client.add_expected_call(
2247
 
            'Repository.insert_stream', ('quack/', ''),
2248
 
            'success', ('ok',))
2249
 
        client.add_expected_call(
2250
 
            'Repository.insert_stream', ('quack/', ''),
2251
 
            'success', ('ok',))
2252
 
        repo.lock_write()
2253
 
        sink = repo._get_sink()
2254
 
        fmt = repository.RepositoryFormat.get_default_format()
2255
 
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2256
 
        self.assertEqual([], resume_tokens)
2257
 
        self.assertEqual(set(), missing_keys)
2258
 
        self.assertFinished(client)
2259
 
 
2260
 
    def test_locked_repo_with_lock_token(self):
2261
 
        transport_path = 'quack'
2262
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2263
 
        client.add_expected_call(
2264
 
            'Repository.lock_write', ('quack/', ''),
2265
 
            'success', ('ok', 'a token'))
2266
 
        client.add_expected_call(
2267
 
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
2268
 
            'success', ('ok',))
2269
 
        client.add_expected_call(
2270
 
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
2271
 
            'success', ('ok',))
2272
 
        repo.lock_write()
2273
 
        sink = repo._get_sink()
2274
 
        fmt = repository.RepositoryFormat.get_default_format()
2275
 
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2276
 
        self.assertEqual([], resume_tokens)
2277
 
        self.assertEqual(set(), missing_keys)
2278
 
        self.assertFinished(client)
 
2433
class TestRepositoryInsertStreamBase(TestRemoteRepository):
 
2434
    """Base class for Repository.insert_stream and .insert_stream_1.19
 
2435
    tests.
 
2436
    """
 
2437
    
 
2438
    def checkInsertEmptyStream(self, repo, client):
 
2439
        """Insert an empty stream, checking the result.
 
2440
 
 
2441
        This checks that there are no resume_tokens or missing_keys, and that
 
2442
        the client is finished.
 
2443
        """
 
2444
        sink = repo._get_sink()
 
2445
        fmt = repository.RepositoryFormat.get_default_format()
 
2446
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
 
2447
        self.assertEqual([], resume_tokens)
 
2448
        self.assertEqual(set(), missing_keys)
 
2449
        self.assertFinished(client)
 
2450
 
 
2451
 
 
2452
class TestRepositoryInsertStream(TestRepositoryInsertStreamBase):
 
2453
    """Tests for using Repository.insert_stream verb when the _1.19 variant is
 
2454
    not available.
 
2455
 
 
2456
    This test case is very similar to TestRepositoryInsertStream_1_19.
 
2457
    """
 
2458
 
 
2459
    def setUp(self):
 
2460
        TestRemoteRepository.setUp(self)
 
2461
        self.disable_verb('Repository.insert_stream_1.19')
 
2462
 
 
2463
    def test_unlocked_repo(self):
 
2464
        transport_path = 'quack'
 
2465
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2466
        client.add_expected_call(
 
2467
            'Repository.insert_stream_1.19', ('quack/', ''),
 
2468
            'unknown', ('Repository.insert_stream_1.19',))
 
2469
        client.add_expected_call(
 
2470
            'Repository.insert_stream', ('quack/', ''),
 
2471
            'success', ('ok',))
 
2472
        client.add_expected_call(
 
2473
            'Repository.insert_stream', ('quack/', ''),
 
2474
            'success', ('ok',))
 
2475
        self.checkInsertEmptyStream(repo, client)
 
2476
 
 
2477
    def test_locked_repo_with_no_lock_token(self):
 
2478
        transport_path = 'quack'
 
2479
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2480
        client.add_expected_call(
 
2481
            'Repository.lock_write', ('quack/', ''),
 
2482
            'success', ('ok', ''))
 
2483
        client.add_expected_call(
 
2484
            'Repository.insert_stream_1.19', ('quack/', ''),
 
2485
            'unknown', ('Repository.insert_stream_1.19',))
 
2486
        client.add_expected_call(
 
2487
            'Repository.insert_stream', ('quack/', ''),
 
2488
            'success', ('ok',))
 
2489
        client.add_expected_call(
 
2490
            'Repository.insert_stream', ('quack/', ''),
 
2491
            'success', ('ok',))
 
2492
        repo.lock_write()
 
2493
        self.checkInsertEmptyStream(repo, client)
 
2494
 
 
2495
    def test_locked_repo_with_lock_token(self):
 
2496
        transport_path = 'quack'
 
2497
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2498
        client.add_expected_call(
 
2499
            'Repository.lock_write', ('quack/', ''),
 
2500
            'success', ('ok', 'a token'))
 
2501
        client.add_expected_call(
 
2502
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
 
2503
            'unknown', ('Repository.insert_stream_1.19',))
 
2504
        client.add_expected_call(
 
2505
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
 
2506
            'success', ('ok',))
 
2507
        client.add_expected_call(
 
2508
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
 
2509
            'success', ('ok',))
 
2510
        repo.lock_write()
 
2511
        self.checkInsertEmptyStream(repo, client)
 
2512
 
 
2513
    def test_stream_with_inventory_deltas(self):
 
2514
        """'inventory-deltas' substreams cannot be sent to the
 
2515
        Repository.insert_stream verb, because not all servers that implement
 
2516
        that verb will accept them.  So when one is encountered the RemoteSink
 
2517
        immediately stops using that verb and falls back to VFS insert_stream.
 
2518
        """
 
2519
        transport_path = 'quack'
 
2520
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2521
        client.add_expected_call(
 
2522
            'Repository.insert_stream_1.19', ('quack/', ''),
 
2523
            'unknown', ('Repository.insert_stream_1.19',))
 
2524
        client.add_expected_call(
 
2525
            'Repository.insert_stream', ('quack/', ''),
 
2526
            'success', ('ok',))
 
2527
        client.add_expected_call(
 
2528
            'Repository.insert_stream', ('quack/', ''),
 
2529
            'success', ('ok',))
 
2530
        # Create a fake real repository for insert_stream to fall back on, so
 
2531
        # that we can directly see the records the RemoteSink passes to the
 
2532
        # real sink.
 
2533
        class FakeRealSink:
 
2534
            def __init__(self):
 
2535
                self.records = []
 
2536
            def insert_stream(self, stream, src_format, resume_tokens):
 
2537
                for substream_kind, substream in stream:
 
2538
                    self.records.append(
 
2539
                        (substream_kind, [record.key for record in substream]))
 
2540
                return ['fake tokens'], ['fake missing keys']
 
2541
        fake_real_sink = FakeRealSink()
 
2542
        class FakeRealRepository:
 
2543
            def _get_sink(self):
 
2544
                return fake_real_sink
 
2545
            def is_in_write_group(self):
 
2546
                return False
 
2547
            def refresh_data(self):
 
2548
                return True
 
2549
        repo._real_repository = FakeRealRepository()
 
2550
        sink = repo._get_sink()
 
2551
        fmt = repository.RepositoryFormat.get_default_format()
 
2552
        stream = self.make_stream_with_inv_deltas(fmt)
 
2553
        resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
 
2554
        # Every record from the first inventory delta should have been sent to
 
2555
        # the VFS sink.
 
2556
        expected_records = [
 
2557
            ('inventory-deltas', [('rev2',), ('rev3',)]),
 
2558
            ('texts', [('some-rev', 'some-file')])]
 
2559
        self.assertEqual(expected_records, fake_real_sink.records)
 
2560
        # The return values from the real sink's insert_stream are propagated
 
2561
        # back to the original caller.
 
2562
        self.assertEqual(['fake tokens'], resume_tokens)
 
2563
        self.assertEqual(['fake missing keys'], missing_keys)
 
2564
        self.assertFinished(client)
 
2565
 
 
2566
    def make_stream_with_inv_deltas(self, fmt):
 
2567
        """Make a simple stream with an inventory delta followed by more
 
2568
        records and more substreams to test that all records and substreams
 
2569
        from that point on are used.
 
2570
 
 
2571
        This sends, in order:
 
2572
           * inventories substream: rev1, rev2, rev3.  rev2 and rev3 are
 
2573
             inventory-deltas.
 
2574
           * texts substream: (some-rev, some-file)
 
2575
        """
 
2576
        # Define a stream using generators so that it isn't rewindable.
 
2577
        inv = inventory.Inventory(revision_id='rev1')
 
2578
        inv.root.revision = 'rev1'
 
2579
        def stream_with_inv_delta():
 
2580
            yield ('inventories', inventories_substream())
 
2581
            yield ('inventory-deltas', inventory_delta_substream())
 
2582
            yield ('texts', [
 
2583
                versionedfile.FulltextContentFactory(
 
2584
                    ('some-rev', 'some-file'), (), None, 'content')])
 
2585
        def inventories_substream():
 
2586
            # An empty inventory fulltext.  This will be streamed normally.
 
2587
            text = fmt._serializer.write_inventory_to_string(inv)
 
2588
            yield versionedfile.FulltextContentFactory(
 
2589
                ('rev1',), (), None, text)
 
2590
        def inventory_delta_substream():
 
2591
            # An inventory delta.  This can't be streamed via this verb, so it
 
2592
            # will trigger a fallback to VFS insert_stream.
 
2593
            entry = inv.make_entry(
 
2594
                'directory', 'newdir', inv.root.file_id, 'newdir-id')
 
2595
            entry.revision = 'ghost'
 
2596
            delta = [(None, 'newdir', 'newdir-id', entry)]
 
2597
            serializer = inventory_delta.InventoryDeltaSerializer(
 
2598
                versioned_root=True, tree_references=False)
 
2599
            lines = serializer.delta_to_lines('rev1', 'rev2', delta)
 
2600
            yield versionedfile.ChunkedContentFactory(
 
2601
                ('rev2',), (('rev1',)), None, lines)
 
2602
            # Another delta.
 
2603
            lines = serializer.delta_to_lines('rev1', 'rev3', delta)
 
2604
            yield versionedfile.ChunkedContentFactory(
 
2605
                ('rev3',), (('rev1',)), None, lines)
 
2606
        return stream_with_inv_delta()
 
2607
 
 
2608
 
 
2609
class TestRepositoryInsertStream_1_19(TestRepositoryInsertStreamBase):
 
2610
 
 
2611
    def test_unlocked_repo(self):
 
2612
        transport_path = 'quack'
 
2613
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2614
        client.add_expected_call(
 
2615
            'Repository.insert_stream_1.19', ('quack/', ''),
 
2616
            'success', ('ok',))
 
2617
        client.add_expected_call(
 
2618
            'Repository.insert_stream_1.19', ('quack/', ''),
 
2619
            'success', ('ok',))
 
2620
        self.checkInsertEmptyStream(repo, client)
 
2621
 
 
2622
    def test_locked_repo_with_no_lock_token(self):
 
2623
        transport_path = 'quack'
 
2624
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2625
        client.add_expected_call(
 
2626
            'Repository.lock_write', ('quack/', ''),
 
2627
            'success', ('ok', ''))
 
2628
        client.add_expected_call(
 
2629
            'Repository.insert_stream_1.19', ('quack/', ''),
 
2630
            'success', ('ok',))
 
2631
        client.add_expected_call(
 
2632
            'Repository.insert_stream_1.19', ('quack/', ''),
 
2633
            'success', ('ok',))
 
2634
        repo.lock_write()
 
2635
        self.checkInsertEmptyStream(repo, client)
 
2636
 
 
2637
    def test_locked_repo_with_lock_token(self):
 
2638
        transport_path = 'quack'
 
2639
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2640
        client.add_expected_call(
 
2641
            'Repository.lock_write', ('quack/', ''),
 
2642
            'success', ('ok', 'a token'))
 
2643
        client.add_expected_call(
 
2644
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
 
2645
            'success', ('ok',))
 
2646
        client.add_expected_call(
 
2647
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
 
2648
            'success', ('ok',))
 
2649
        repo.lock_write()
 
2650
        self.checkInsertEmptyStream(repo, client)
2279
2651
 
2280
2652
 
2281
2653
class TestRepositoryTarball(TestRemoteRepository):
2317
2689
    """RemoteRepository.copy_content_into optimizations"""
2318
2690
 
2319
2691
    def test_copy_content_remote_to_local(self):
2320
 
        self.transport_server = server.SmartTCPServer_for_testing
 
2692
        self.transport_server = test_server.SmartTCPServer_for_testing
2321
2693
        src_repo = self.make_repository('repo1')
2322
2694
        src_repo = repository.Repository.open(self.get_url('repo1'))
2323
2695
        # At the moment the tarball-based copy_content_into can't write back
2471
2843
        expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
2472
2844
        self.assertEqual(expected_error, translated_error)
2473
2845
 
 
2846
    def test_nobranch_one_arg(self):
 
2847
        bzrdir = self.make_bzrdir('')
 
2848
        translated_error = self.translateTuple(
 
2849
            ('nobranch', 'extra detail'), bzrdir=bzrdir)
 
2850
        expected_error = errors.NotBranchError(
 
2851
            path=bzrdir.root_transport.base,
 
2852
            detail='extra detail')
 
2853
        self.assertEqual(expected_error, translated_error)
 
2854
 
2474
2855
    def test_LockContention(self):
2475
2856
        translated_error = self.translateTuple(('LockContention',))
2476
2857
        expected_error = errors.LockContention('(remote lock)')
2516
2897
        expected_error = errors.ReadError(path)
2517
2898
        self.assertEqual(expected_error, translated_error)
2518
2899
 
 
2900
    def test_IncompatibleRepositories(self):
 
2901
        translated_error = self.translateTuple(('IncompatibleRepositories',
 
2902
            "repo1", "repo2", "details here"))
 
2903
        expected_error = errors.IncompatibleRepositories("repo1", "repo2",
 
2904
            "details here")
 
2905
        self.assertEqual(expected_error, translated_error)
 
2906
 
2519
2907
    def test_PermissionDenied_no_args(self):
2520
2908
        path = 'a path'
2521
2909
        translated_error = self.translateTuple(('PermissionDenied',), path=path)
2582
2970
        # In addition to re-raising ErrorFromSmartServer, some debug info has
2583
2971
        # been muttered to the log file for developer to look at.
2584
2972
        self.assertContainsRe(
2585
 
            self._get_log(keep_log_file=True),
 
2973
            self.get_log(),
2586
2974
            "Missing key 'branch' in context")
2587
2975
 
2588
2976
    def test_path_missing(self):
2596
2984
        self.assertEqual(server_error, translated_error)
2597
2985
        # In addition to re-raising ErrorFromSmartServer, some debug info has
2598
2986
        # been muttered to the log file for developer to look at.
2599
 
        self.assertContainsRe(
2600
 
            self._get_log(keep_log_file=True), "Missing key 'path' in context")
 
2987
        self.assertContainsRe(self.get_log(), "Missing key 'path' in context")
2601
2988
 
2602
2989
 
2603
2990
class TestStacking(tests.TestCaseWithTransport):
2621
3008
        stacked_branch = self.make_branch('stacked', format='1.9')
2622
3009
        stacked_branch.set_stacked_on_url('../base')
2623
3010
        # start a server looking at this
2624
 
        smart_server = server.SmartTCPServer_for_testing()
2625
 
        smart_server.setUp()
2626
 
        self.addCleanup(smart_server.tearDown)
 
3011
        smart_server = test_server.SmartTCPServer_for_testing()
 
3012
        self.start_server(smart_server)
2627
3013
        remote_bzrdir = BzrDir.open(smart_server.get_url() + '/stacked')
2628
3014
        # can get its branch and repository
2629
3015
        remote_branch = remote_bzrdir.open_branch()
2651
3037
        tree1.commit('rev1', rev_id='rev1')
2652
3038
        tree2 = tree1.branch.bzrdir.sprout('tree2', stacked=True
2653
3039
            ).open_workingtree()
2654
 
        tree2.commit('local changes make me feel good.')
 
3040
        local_tree = tree2.branch.create_checkout('local')
 
3041
        local_tree.commit('local changes make me feel good.')
2655
3042
        branch2 = Branch.open(self.get_url('tree2'))
2656
3043
        branch2.lock_read()
2657
3044
        self.addCleanup(branch2.unlock)
2727
3114
            _, stacked = self.prepare_stacked_remote_branch()
2728
3115
            tree = stacked.bzrdir.sprout('tree3', stacked=True
2729
3116
                ).open_workingtree()
2730
 
            tree.commit('more local changes are better')
 
3117
            local_tree = tree.branch.create_checkout('local-tree3')
 
3118
            local_tree.commit('more local changes are better')
2731
3119
            branch = Branch.open(self.get_url('tree3'))
2732
3120
            branch.lock_read()
 
3121
            self.addCleanup(branch.unlock)
2733
3122
            return None, branch
2734
3123
        rev_ord, expected_revs = self.get_ordered_revs('1.9', 'unordered',
2735
3124
            branch_factory=make_stacked_stacked)
2744
3133
        # stacked upon sources in topological order.
2745
3134
        rev_ord, expected_revs = self.get_ordered_revs('knit', 'topological')
2746
3135
        self.assertEqual(expected_revs, rev_ord)
2747
 
        # Getting topological sort requires VFS calls still
2748
 
        self.assertLength(12, self.hpss_calls)
 
3136
        # Getting topological sort requires VFS calls still - one of which is
 
3137
        # pushing up from the bound branch.
 
3138
        self.assertLength(13, self.hpss_calls)
2749
3139
 
2750
3140
    def test_stacked_get_stream_groupcompress(self):
2751
3141
        # Repository._get_source.get_stream() from a stacked repository with
2780
3170
        super(TestRemoteBranchEffort, self).setUp()
2781
3171
        # Create a smart server that publishes whatever the backing VFS server
2782
3172
        # does.
2783
 
        self.smart_server = server.SmartTCPServer_for_testing()
2784
 
        self.smart_server.setUp(self.get_server())
2785
 
        self.addCleanup(self.smart_server.tearDown)
 
3173
        self.smart_server = test_server.SmartTCPServer_for_testing()
 
3174
        self.start_server(self.smart_server, self.get_server())
2786
3175
        # Log all HPSS calls into self.hpss_calls.
2787
3176
        _SmartClient.hooks.install_named_hook(
2788
3177
            'call', self.capture_hpss_call, None)