55
55
from bzrlib.repofmt import groupcompress_repo, pack_repo
56
56
from bzrlib.revision import NULL_REVISION
57
from bzrlib.smart import medium
57
from bzrlib.smart import server, 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
66
from bzrlib.transport import get_transport, http
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': test_server.SmartTCPServer_for_testing_v2_only}),
79
{'transport_server': server.SmartTCPServer_for_testing_v2_only}),
81
{'transport_server': test_server.SmartTCPServer_for_testing})]
81
{'transport_server': server.SmartTCPServer_for_testing})]
82
82
return multiply_tests(to_adapt, smart_server_version_scenarios, result)
284
280
self.expecting_body = True
285
281
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)
293
283
def call_with_body_bytes_expecting_body(self, method, args, body):
294
284
self._check_call(method, args)
295
285
self._calls.append(('call_with_body_bytes_expecting_body', method,
445
435
'BzrDir.cloning_metadir', ('quack/', 'False'),
446
436
'error', ('BranchReference',)),
447
437
client.add_expected_call(
448
'BzrDir.open_branchV3', ('quack/',),
438
'BzrDir.open_branchV2', ('quack/',),
449
439
'success', ('ref', self.get_url('referenced'))),
450
440
a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
478
468
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)
532
471
class TestBzrDirOpenBranch(TestRemote):
534
473
def test_backwards_compat(self):
552
491
transport = transport.clone('quack')
553
492
client = FakeClient(transport.base)
554
493
client.add_expected_call(
555
'BzrDir.open_branchV3', ('quack/',),
494
'BzrDir.open_branchV2', ('quack/',),
556
495
'success', ('branch', branch_network_name))
557
496
client.add_expected_call(
558
497
'BzrDir.find_repositoryV3', ('quack/',),
607
546
network_name = reference_format.network_name()
608
547
branch_network_name = self.get_branch_format().network_name()
609
548
client.add_expected_call(
610
'BzrDir.open_branchV3', ('~hello/',),
549
'BzrDir.open_branchV2', ('~hello/',),
611
550
'success', ('branch', branch_network_name))
612
551
client.add_expected_call(
613
552
'BzrDir.find_repositoryV3', ('~hello/',),
744
683
# fallback all the way to the first version.
745
684
reference_format = self.get_repo_format()
746
685
network_name = reference_format.network_name()
747
server_url = 'bzr://example.com/'
748
self.permit_url(server_url)
749
client = FakeClient(server_url)
686
client = FakeClient('bzr://example.com/')
750
687
client.add_unknown_method_response('BzrDir.find_repositoryV3')
751
688
client.add_unknown_method_response('BzrDir.find_repositoryV2')
752
689
client.add_success_response('ok', '', 'no', 'no')
758
695
reference_format.get_format_string(), 'ok')
759
696
# PackRepository wants to do a stat
760
697
client.add_success_response('stat', '0', '65535')
761
remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
698
remote_transport = RemoteTransport('bzr://example.com/quack/', medium=False,
763
700
bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
778
715
# fallback to find_repositoryV2
779
716
reference_format = self.get_repo_format()
780
717
network_name = reference_format.network_name()
781
server_url = 'bzr://example.com/'
782
self.permit_url(server_url)
783
client = FakeClient(server_url)
718
client = FakeClient('bzr://example.com/')
784
719
client.add_unknown_method_response('BzrDir.find_repositoryV3')
785
720
client.add_success_response('ok', '', 'no', 'no', 'no')
786
721
# A real repository instance will be created to determine the network
791
726
reference_format.get_format_string(), 'ok')
792
727
# PackRepository wants to do a stat
793
728
client.add_success_response('stat', '0', '65535')
794
remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
729
remote_transport = RemoteTransport('bzr://example.com/quack/', medium=False,
796
731
bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
917
852
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'
929
854
def make_remote_branch(self, transport, client):
930
855
"""Make a RemoteBranch using 'client' as its _SmartClient.
1070
995
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)
1121
998
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
1123
1000
def test_empty_branch(self):
1195
1072
client = FakeClient(self.get_url())
1196
1073
branch_network_name = self.get_branch_format().network_name()
1197
1074
client.add_expected_call(
1198
'BzrDir.open_branchV3', ('stacked/',),
1075
'BzrDir.open_branchV2', ('stacked/',),
1199
1076
'success', ('branch', branch_network_name))
1200
1077
client.add_expected_call(
1201
1078
'BzrDir.find_repositoryV3', ('stacked/',),
1231
1108
client = FakeClient(self.get_url())
1232
1109
branch_network_name = self.get_branch_format().network_name()
1233
1110
client.add_expected_call(
1234
'BzrDir.open_branchV3', ('stacked/',),
1111
'BzrDir.open_branchV2', ('stacked/',),
1235
1112
'success', ('branch', branch_network_name))
1236
1113
client.add_expected_call(
1237
1114
'BzrDir.find_repositoryV3', ('stacked/',),
1465
1342
errors.NoSuchRevision, branch.set_last_revision_info, 123, 'revid')
1466
1343
branch.unlock()
1345
def lock_remote_branch(self, branch):
1346
"""Trick a RemoteBranch into thinking it is locked."""
1347
branch._lock_mode = 'w'
1348
branch._lock_count = 2
1349
branch._lock_token = 'branch token'
1350
branch._repo_lock_token = 'repo token'
1351
branch.repository._lock_mode = 'w'
1352
branch.repository._lock_count = 2
1353
branch.repository._lock_token = 'repo token'
1468
1355
def test_backwards_compatibility(self):
1469
1356
"""If the server does not support the Branch.set_last_revision_info
1470
1357
verb (which is new in 1.4), then the client falls back to VFS methods.
1786
1673
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())
1803
1676
class TestRepositoryFormat(TestRemoteRepository):
1805
1678
def test_fast_delta(self):
1812
1685
false_format._network_name = false_name
1813
1686
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())
1823
1689
class TestRepositoryGatherStats(TestRemoteRepository):
2009
1875
self.assertLength(1, self.hpss_calls)
2011
1877
def disableExtraResults(self):
2012
self.overrideAttr(SmartServerRepositoryGetParentMap,
2013
'no_extra_results', True)
1878
old_flag = SmartServerRepositoryGetParentMap.no_extra_results
1879
SmartServerRepositoryGetParentMap.no_extra_results = True
1881
SmartServerRepositoryGetParentMap.no_extra_results = old_flag
1882
self.addCleanup(reset_values)
2015
1884
def test_null_cached_missing_and_stop_key(self):
2016
1885
self.setup_smart_server_with_call_log()
2223
2093
repo.get_rev_id_for_revno, 5, (42, 'rev-foo'))
2224
2094
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])
2247
2097
class TestRepositoryIsShared(TestRemoteRepository):
2777
2623
expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
2778
2624
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)
2789
2626
def test_LockContention(self):
2790
2627
translated_error = self.translateTuple(('LockContention',))
2791
2628
expected_error = errors.LockContention('(remote lock)')
2942
2780
stacked_branch = self.make_branch('stacked', format='1.9')
2943
2781
stacked_branch.set_stacked_on_url('../base')
2944
2782
# start a server looking at this
2945
smart_server = test_server.SmartTCPServer_for_testing()
2946
self.start_server(smart_server)
2783
smart_server = server.SmartTCPServer_for_testing()
2784
smart_server.setUp()
2785
self.addCleanup(smart_server.tearDown)
2947
2786
remote_bzrdir = BzrDir.open(smart_server.get_url() + '/stacked')
2948
2787
# can get its branch and repository
2949
2788
remote_branch = remote_bzrdir.open_branch()
3104
2942
super(TestRemoteBranchEffort, self).setUp()
3105
2943
# Create a smart server that publishes whatever the backing VFS server
3107
self.smart_server = test_server.SmartTCPServer_for_testing()
3108
self.start_server(self.smart_server, self.get_server())
2945
self.smart_server = server.SmartTCPServer_for_testing()
2946
self.smart_server.setUp(self.get_server())
2947
self.addCleanup(self.smart_server.tearDown)
3109
2948
# Log all HPSS calls into self.hpss_calls.
3110
2949
_SmartClient.hooks.install_named_hook(
3111
2950
'call', self.capture_hpss_call, None)