55
55
from bzrlib.repofmt import groupcompress_repo, pack_repo
56
56
from bzrlib.revision import NULL_REVISION
57
from bzrlib.smart import server, medium
57
from bzrlib.smart import medium
58
58
from bzrlib.smart.client import _SmartClient
59
59
from bzrlib.smart.repository import SmartServerRepositoryGetParentMap
60
60
from bzrlib.tests import (
61
61
condition_isinstance,
62
62
split_suite_by_condition,
66
from bzrlib.transport import get_transport, http
66
from bzrlib.transport import get_transport
67
67
from bzrlib.transport.memory import MemoryTransport
68
68
from bzrlib.transport.remote import (
76
76
standard_tests, condition_isinstance(BasicRemoteObjectTests))
77
77
smart_server_version_scenarios = [
79
{'transport_server': server.SmartTCPServer_for_testing_v2_only}),
79
{'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
81
{'transport_server': server.SmartTCPServer_for_testing})]
81
{'transport_server': test_server.SmartTCPServer_for_testing})]
82
82
return multiply_tests(to_adapt, smart_server_version_scenarios, result)
280
284
self.expecting_body = True
281
285
return result[1], FakeProtocol(result[2], self)
287
def call_with_body_bytes(self, method, args, body):
288
self._check_call(method, args)
289
self._calls.append(('call_with_body_bytes', method, args, body))
290
result = self._get_next_response()
291
return result[1], FakeProtocol(result[2], self)
283
293
def call_with_body_bytes_expecting_body(self, method, args, body):
284
294
self._check_call(method, args)
285
295
self._calls.append(('call_with_body_bytes_expecting_body', method,
435
445
'BzrDir.cloning_metadir', ('quack/', 'False'),
436
446
'error', ('BranchReference',)),
437
447
client.add_expected_call(
438
'BzrDir.open_branchV2', ('quack/',),
448
'BzrDir.open_branchV3', ('quack/',),
439
449
'success', ('ref', self.get_url('referenced'))),
440
450
a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
468
478
self.assertFinished(client)
481
class TestBzrDirOpen(TestRemote):
483
def make_fake_client_and_transport(self, path='quack'):
484
transport = MemoryTransport()
485
transport.mkdir(path)
486
transport = transport.clone(path)
487
client = FakeClient(transport.base)
488
return client, transport
490
def test_absent(self):
491
client, transport = self.make_fake_client_and_transport()
492
client.add_expected_call(
493
'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
494
self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
495
remote.RemoteBzrDirFormat(), _client=client, _force_probe=True)
496
self.assertFinished(client)
498
def test_present_without_workingtree(self):
499
client, transport = self.make_fake_client_and_transport()
500
client.add_expected_call(
501
'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
502
bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
503
_client=client, _force_probe=True)
504
self.assertIsInstance(bd, RemoteBzrDir)
505
self.assertFalse(bd.has_workingtree())
506
self.assertRaises(errors.NoWorkingTree, bd.open_workingtree)
507
self.assertFinished(client)
509
def test_present_with_workingtree(self):
510
client, transport = self.make_fake_client_and_transport()
511
client.add_expected_call(
512
'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
513
bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
514
_client=client, _force_probe=True)
515
self.assertIsInstance(bd, RemoteBzrDir)
516
self.assertTrue(bd.has_workingtree())
517
self.assertRaises(errors.NotLocalUrl, bd.open_workingtree)
518
self.assertFinished(client)
520
def test_backwards_compat(self):
521
client, transport = self.make_fake_client_and_transport()
522
client.add_expected_call(
523
'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
524
client.add_expected_call(
525
'BzrDir.open', ('quack/',), 'success', ('yes',))
526
bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
527
_client=client, _force_probe=True)
528
self.assertIsInstance(bd, RemoteBzrDir)
529
self.assertFinished(client)
471
532
class TestBzrDirOpenBranch(TestRemote):
473
534
def test_backwards_compat(self):
491
552
transport = transport.clone('quack')
492
553
client = FakeClient(transport.base)
493
554
client.add_expected_call(
494
'BzrDir.open_branchV2', ('quack/',),
555
'BzrDir.open_branchV3', ('quack/',),
495
556
'success', ('branch', branch_network_name))
496
557
client.add_expected_call(
497
558
'BzrDir.find_repositoryV3', ('quack/',),
546
607
network_name = reference_format.network_name()
547
608
branch_network_name = self.get_branch_format().network_name()
548
609
client.add_expected_call(
549
'BzrDir.open_branchV2', ('~hello/',),
610
'BzrDir.open_branchV3', ('~hello/',),
550
611
'success', ('branch', branch_network_name))
551
612
client.add_expected_call(
552
613
'BzrDir.find_repositoryV3', ('~hello/',),
661
722
network_name = reference_format.network_name()
662
723
client.add_expected_call(
663
724
'BzrDir.create_repository', ('quack/',
664
'Bazaar pack repository format 1 (needs bzr 0.92)\n', 'False'),
665
'success', ('ok', 'no', 'no', 'no', network_name))
725
'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
727
'success', ('ok', 'yes', 'yes', 'yes', network_name))
666
728
a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
668
730
repo = a_bzrdir.create_repository()
670
732
self.assertIsInstance(repo, remote.RemoteRepository)
671
733
# its format should have the settings from the response
672
734
format = repo._format
673
self.assertFalse(format.rich_root_data)
674
self.assertFalse(format.supports_tree_reference)
675
self.assertFalse(format.supports_external_lookups)
735
self.assertTrue(format.rich_root_data)
736
self.assertTrue(format.supports_tree_reference)
737
self.assertTrue(format.supports_external_lookups)
676
738
self.assertEqual(network_name, format.network_name())
682
744
# fallback all the way to the first version.
683
745
reference_format = self.get_repo_format()
684
746
network_name = reference_format.network_name()
685
client = FakeClient('bzr://example.com/')
747
server_url = 'bzr://example.com/'
748
self.permit_url(server_url)
749
client = FakeClient(server_url)
686
750
client.add_unknown_method_response('BzrDir.find_repositoryV3')
687
751
client.add_unknown_method_response('BzrDir.find_repositoryV2')
688
752
client.add_success_response('ok', '', 'no', 'no')
694
758
reference_format.get_format_string(), 'ok')
695
759
# PackRepository wants to do a stat
696
760
client.add_success_response('stat', '0', '65535')
697
remote_transport = RemoteTransport('bzr://example.com/quack/', medium=False,
761
remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
699
763
bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
714
778
# fallback to find_repositoryV2
715
779
reference_format = self.get_repo_format()
716
780
network_name = reference_format.network_name()
717
client = FakeClient('bzr://example.com/')
781
server_url = 'bzr://example.com/'
782
self.permit_url(server_url)
783
client = FakeClient(server_url)
718
784
client.add_unknown_method_response('BzrDir.find_repositoryV3')
719
785
client.add_success_response('ok', '', 'no', 'no', 'no')
720
786
# A real repository instance will be created to determine the network
725
791
reference_format.get_format_string(), 'ok')
726
792
# PackRepository wants to do a stat
727
793
client.add_success_response('stat', '0', '65535')
728
remote_transport = RemoteTransport('bzr://example.com/quack/', medium=False,
794
remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
730
796
bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
851
917
class RemoteBranchTestCase(RemoteBzrDirTestCase):
919
def lock_remote_branch(self, branch):
920
"""Trick a RemoteBranch into thinking it is locked."""
921
branch._lock_mode = 'w'
922
branch._lock_count = 2
923
branch._lock_token = 'branch token'
924
branch._repo_lock_token = 'repo token'
925
branch.repository._lock_mode = 'w'
926
branch.repository._lock_count = 2
927
branch.repository._lock_token = 'repo token'
853
929
def make_remote_branch(self, transport, client):
854
930
"""Make a RemoteBranch using 'client' as its _SmartClient.
994
1070
self.assertEqual({}, result)
1073
class TestBranchSetTagsBytes(RemoteBranchTestCase):
1075
def test_trivial(self):
1076
transport = MemoryTransport()
1077
client = FakeClient(transport.base)
1078
client.add_expected_call(
1079
'Branch.get_stacked_on_url', ('quack/',),
1080
'error', ('NotStacked',))
1081
client.add_expected_call(
1082
'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1084
transport.mkdir('quack')
1085
transport = transport.clone('quack')
1086
branch = self.make_remote_branch(transport, client)
1087
self.lock_remote_branch(branch)
1088
branch._set_tags_bytes('tags bytes')
1089
self.assertFinished(client)
1090
self.assertEqual('tags bytes', client._calls[-1][-1])
1092
def test_backwards_compatible(self):
1093
transport = MemoryTransport()
1094
client = FakeClient(transport.base)
1095
client.add_expected_call(
1096
'Branch.get_stacked_on_url', ('quack/',),
1097
'error', ('NotStacked',))
1098
client.add_expected_call(
1099
'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1100
'unknown', ('Branch.set_tags_bytes',))
1101
transport.mkdir('quack')
1102
transport = transport.clone('quack')
1103
branch = self.make_remote_branch(transport, client)
1104
self.lock_remote_branch(branch)
1105
class StubRealBranch(object):
1108
def _set_tags_bytes(self, bytes):
1109
self.calls.append(('set_tags_bytes', bytes))
1110
real_branch = StubRealBranch()
1111
branch._real_branch = real_branch
1112
branch._set_tags_bytes('tags bytes')
1113
# Call a second time, to exercise the 'remote version already inferred'
1115
branch._set_tags_bytes('tags bytes')
1116
self.assertFinished(client)
1118
[('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
997
1121
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
999
1123
def test_empty_branch(self):
1071
1195
client = FakeClient(self.get_url())
1072
1196
branch_network_name = self.get_branch_format().network_name()
1073
1197
client.add_expected_call(
1074
'BzrDir.open_branchV2', ('stacked/',),
1198
'BzrDir.open_branchV3', ('stacked/',),
1075
1199
'success', ('branch', branch_network_name))
1076
1200
client.add_expected_call(
1077
1201
'BzrDir.find_repositoryV3', ('stacked/',),
1107
1231
client = FakeClient(self.get_url())
1108
1232
branch_network_name = self.get_branch_format().network_name()
1109
1233
client.add_expected_call(
1110
'BzrDir.open_branchV2', ('stacked/',),
1234
'BzrDir.open_branchV3', ('stacked/',),
1111
1235
'success', ('branch', branch_network_name))
1112
1236
client.add_expected_call(
1113
1237
'BzrDir.find_repositoryV3', ('stacked/',),
1341
1465
errors.NoSuchRevision, branch.set_last_revision_info, 123, 'revid')
1342
1466
branch.unlock()
1344
def lock_remote_branch(self, branch):
1345
"""Trick a RemoteBranch into thinking it is locked."""
1346
branch._lock_mode = 'w'
1347
branch._lock_count = 2
1348
branch._lock_token = 'branch token'
1349
branch._repo_lock_token = 'repo token'
1350
branch.repository._lock_mode = 'w'
1351
branch.repository._lock_count = 2
1352
branch.repository._lock_token = 'repo token'
1354
1468
def test_backwards_compatibility(self):
1355
1469
"""If the server does not support the Branch.set_last_revision_info
1356
1470
verb (which is new in 1.4), then the client falls back to VFS methods.
1672
1786
return repo, client
1789
def remoted_description(format):
1790
return 'Remote: ' + format.get_format_description()
1793
class TestBranchFormat(tests.TestCase):
1795
def test_get_format_description(self):
1796
remote_format = RemoteBranchFormat()
1797
real_format = branch.BranchFormat.get_default_format()
1798
remote_format._network_name = real_format.network_name()
1799
self.assertEqual(remoted_description(real_format),
1800
remote_format.get_format_description())
1675
1803
class TestRepositoryFormat(TestRemoteRepository):
1677
1805
def test_fast_delta(self):
1684
1812
false_format._network_name = false_name
1685
1813
self.assertEqual(False, false_format.fast_deltas)
1815
def test_get_format_description(self):
1816
remote_repo_format = RemoteRepositoryFormat()
1817
real_format = repository.RepositoryFormat.get_default_format()
1818
remote_repo_format._network_name = real_format.network_name()
1819
self.assertEqual(remoted_description(real_format),
1820
remote_repo_format.get_format_description())
1688
1823
class TestRepositoryGatherStats(TestRemoteRepository):
1874
2009
self.assertLength(1, self.hpss_calls)
1876
2011
def disableExtraResults(self):
1877
old_flag = SmartServerRepositoryGetParentMap.no_extra_results
1878
SmartServerRepositoryGetParentMap.no_extra_results = True
1880
SmartServerRepositoryGetParentMap.no_extra_results = old_flag
1881
self.addCleanup(reset_values)
2012
self.overrideAttr(SmartServerRepositoryGetParentMap,
2013
'no_extra_results', True)
1883
2015
def test_null_cached_missing_and_stop_key(self):
1884
2016
self.setup_smart_server_with_call_log()
2092
2223
repo.get_rev_id_for_revno, 5, (42, 'rev-foo'))
2093
2224
self.assertFinished(client)
2226
def test_branch_fallback_locking(self):
2227
"""RemoteBranch.get_rev_id takes a read lock, and tries to call the
2228
get_rev_id_for_revno verb. If the verb is unknown the VFS fallback
2229
will be invoked, which will fail if the repo is unlocked.
2231
self.setup_smart_server_with_call_log()
2232
tree = self.make_branch_and_memory_tree('.')
2234
rev1 = tree.commit('First')
2235
rev2 = tree.commit('Second')
2237
branch = tree.branch
2238
self.assertFalse(branch.is_locked())
2239
self.reset_smart_call_log()
2240
verb = 'Repository.get_rev_id_for_revno'
2241
self.disable_verb(verb)
2242
self.assertEqual(rev1, branch.get_rev_id(1))
2243
self.assertLength(1, [call for call in self.hpss_calls if
2244
call.call.method == verb])
2096
2247
class TestRepositoryIsShared(TestRemoteRepository):
2621
2777
expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
2622
2778
self.assertEqual(expected_error, translated_error)
2780
def test_nobranch_one_arg(self):
2781
bzrdir = self.make_bzrdir('')
2782
translated_error = self.translateTuple(
2783
('nobranch', 'extra detail'), bzrdir=bzrdir)
2784
expected_error = errors.NotBranchError(
2785
path=bzrdir.root_transport.base,
2786
detail='extra detail')
2787
self.assertEqual(expected_error, translated_error)
2624
2789
def test_LockContention(self):
2625
2790
translated_error = self.translateTuple(('LockContention',))
2626
2791
expected_error = errors.LockContention('(remote lock)')
2666
2831
expected_error = errors.ReadError(path)
2667
2832
self.assertEqual(expected_error, translated_error)
2834
def test_IncompatibleRepositories(self):
2835
translated_error = self.translateTuple(('IncompatibleRepositories',
2836
"repo1", "repo2", "details here"))
2837
expected_error = errors.IncompatibleRepositories("repo1", "repo2",
2839
self.assertEqual(expected_error, translated_error)
2669
2841
def test_PermissionDenied_no_args(self):
2670
2842
path = 'a path'
2671
2843
translated_error = self.translateTuple(('PermissionDenied',), path=path)
2771
2942
stacked_branch = self.make_branch('stacked', format='1.9')
2772
2943
stacked_branch.set_stacked_on_url('../base')
2773
2944
# start a server looking at this
2774
smart_server = server.SmartTCPServer_for_testing()
2775
smart_server.setUp()
2776
self.addCleanup(smart_server.tearDown)
2945
smart_server = test_server.SmartTCPServer_for_testing()
2946
self.start_server(smart_server)
2777
2947
remote_bzrdir = BzrDir.open(smart_server.get_url() + '/stacked')
2778
2948
# can get its branch and repository
2779
2949
remote_branch = remote_bzrdir.open_branch()
2933
3104
super(TestRemoteBranchEffort, self).setUp()
2934
3105
# Create a smart server that publishes whatever the backing VFS server
2936
self.smart_server = server.SmartTCPServer_for_testing()
2937
self.smart_server.setUp(self.get_server())
2938
self.addCleanup(self.smart_server.tearDown)
3107
self.smart_server = test_server.SmartTCPServer_for_testing()
3108
self.start_server(self.smart_server, self.get_server())
2939
3109
# Log all HPSS calls into self.hpss_calls.
2940
3110
_SmartClient.hooks.install_named_hook(
2941
3111
'call', self.capture_hpss_call, None)