72
73
tests.TestCaseWithTransport.tearDown(self)
74
75
def test_create_remote_bzrdir(self):
75
b = remote.RemoteBzrDir(self.transport)
76
b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
76
77
self.assertIsInstance(b, BzrDir)
78
79
def test_open_remote_branch(self):
79
80
# open a standalone branch in the working directory
80
b = remote.RemoteBzrDir(self.transport)
81
b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
81
82
branch = b.open_branch()
82
83
self.assertIsInstance(branch, Branch)
113
114
self.assertStartsWith(str(b), 'RemoteBranch(')
116
class FakeRemoteTransport(object):
117
"""This class provides the minimum support for use in place of a RemoteTransport.
119
It doesn't actually transmit requests, but rather expects them to be
120
handled by a FakeClient which holds canned responses. It does not allow
121
any vfs access, therefore is not suitable for testing any operation that
122
will fallback to vfs access. Backing the test by an instance of this
123
class guarantees that it's - done using non-vfs operations.
126
_default_url = 'fakeremotetransport://host/path/'
128
def __init__(self, url=None):
130
url = self._default_url
134
return "%r(%r)" % (self.__class__.__name__,
137
def clone(self, relpath):
138
return FakeRemoteTransport(urlutils.join(self.base, relpath))
140
def get(self, relpath):
141
# only get is specifically stubbed out, because it's usually the first
142
# thing we do. anything else will fail with an AttributeError.
143
raise AssertionError("%r doesn't support file access to %r"
148
117
class FakeProtocol(object):
149
118
"""Lookalike SmartClientRequestProtocolOne allowing body reading tests."""
178
147
self.expecting_body = False
179
148
# if non-None, this is the list of expected calls, with only the
180
149
# method name and arguments included. the body might be hard to
181
# compute so is not included
150
# compute so is not included. If a call is None, that call can
182
152
self._expected_calls = None
183
153
_SmartClient.__init__(self, FakeMedium(self._calls, fake_medium_base))
195
165
def add_success_response_with_body(self, body, *args):
196
166
self.responses.append(('success', args, body))
167
if self._expected_calls is not None:
168
self._expected_calls.append(None)
198
170
def add_error_response(self, *args):
199
171
self.responses.append(('error', args))
286
260
self.assertTrue(result)
263
class TestRemote(tests.TestCaseWithMemoryTransport):
265
def disable_verb(self, verb):
266
"""Disable a verb for one test."""
267
request_handlers = smart.request.request_handlers
268
orig_method = request_handlers.get(verb)
269
request_handlers.remove(verb)
271
request_handlers.register(verb, orig_method)
272
self.addCleanup(restoreVerb)
289
275
class Test_ClientMedium_remote_path_from_transport(tests.TestCase):
290
276
"""Tests for the behaviour of client_medium.remote_path_from_transport."""
375
361
client.add_expected_call(
376
362
'Branch.get_stacked_on_url', ('quack/',),
377
363
'error', ('NotStacked',))
378
bzrdir = RemoteBzrDir(transport, _client=client)
364
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
379
366
result = bzrdir.open_branch()
380
367
self.assertIsInstance(result, RemoteBranch)
381
368
self.assertEqual(bzrdir, result.bzrdir)
387
374
transport = transport.clone('quack')
388
375
client = FakeClient(transport.base)
389
376
client.add_error_response('nobranch')
390
bzrdir = RemoteBzrDir(transport, _client=client)
377
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
391
379
self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
392
380
self.assertEqual(
393
381
[('call', 'BzrDir.open_branch', ('quack/',))],
403
391
transport = MemoryTransport()
404
392
# no requests on the network - catches other api calls being made.
405
393
client = FakeClient(transport.base)
406
bzrdir = RemoteBzrDir(transport, _client=client)
394
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
407
396
# patch the open_branch call to record that it was called.
408
397
bzrdir.open_branch = open_branch
409
398
self.assertEqual((None, "a-branch"), bzrdir._get_tree_branch())
424
413
client.add_expected_call(
425
414
'Branch.get_stacked_on_url', ('~hello/',),
426
415
'error', ('NotStacked',))
427
bzrdir = RemoteBzrDir(transport, _client=client)
416
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
428
418
result = bzrdir.open_branch()
429
419
client.finished_test()
443
433
client = FakeClient(transport.base)
444
434
client.add_success_response(
445
435
'ok', '', rich_response, subtree_response, external_lookup)
446
bzrdir = RemoteBzrDir(transport, _client=client)
436
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
447
438
result = bzrdir.open_repository()
448
439
self.assertEqual(
449
440
[('call', 'BzrDir.find_repositoryV2', ('quack/',))],
468
459
RemoteBzrDirFormat.probe_transport, OldServerTransport())
462
class TestBzrDirCreateRepository(TestRemote):
464
def test_backwards_compat(self):
465
self.setup_smart_server_with_call_log()
466
bzrdir = self.make_bzrdir('.')
467
self.reset_smart_call_log()
468
self.disable_verb('BzrDir.create_repository')
469
repo = bzrdir.create_repository()
470
create_repo_call_count = len([call for call in self.hpss_calls if
471
call[0].method == 'BzrDir.create_repository'])
472
self.assertEqual(1, create_repo_call_count)
474
def test_current_server(self):
475
transport = self.get_transport('.')
476
transport = transport.clone('quack')
477
self.make_bzrdir('quack')
478
client = FakeClient(transport.base)
479
reference_bzrdir_format = bzrdir.format_registry.get('default')()
480
reference_format = reference_bzrdir_format.repository_format
481
network_name = reference_format.network_name()
482
client.add_expected_call(
483
'BzrDir.create_repository', ('quack/',
484
'Bazaar pack repository format 1 (needs bzr 0.92)\n', 'False'),
485
'success', ('ok', 'no', 'no', 'no', network_name))
486
a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
488
repo = a_bzrdir.create_repository()
489
# We should have got a remote repository
490
self.assertIsInstance(repo, remote.RemoteRepository)
491
# its format should have the settings from the response
492
format = repo._format
493
self.assertFalse(format.rich_root_data)
494
self.assertFalse(format.supports_tree_reference)
495
self.assertFalse(format.supports_external_lookups)
496
self.assertEqual(network_name, format.network_name())
471
499
class TestBzrDirOpenRepository(tests.TestCase):
473
501
def test_backwards_compat_1_2(self):
475
503
transport.mkdir('quack')
476
504
transport = transport.clone('quack')
477
505
client = FakeClient(transport.base)
478
client.add_unknown_method_response('RemoteRepository.find_repositoryV2')
506
client.add_unknown_method_response('BzrDir.find_repositoryV2')
479
507
client.add_success_response('ok', '', 'no', 'no')
480
bzrdir = RemoteBzrDir(transport, _client=client)
508
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
481
510
repo = bzrdir.open_repository()
482
511
self.assertEqual(
483
512
[('call', 'BzrDir.find_repositoryV2', ('quack/',)),
524
553
# we do not want bzrdir to make any remote calls, so use False as its
525
554
# _client. If it tries to make a remote call, this will fail
527
bzrdir = RemoteBzrDir(transport, _client=False)
556
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
528
558
repo = RemoteRepository(bzrdir, None, _client=client)
529
559
return RemoteBranch(bzrdir, repo, _client=client)
570
600
"""Test Branch._get_stacked_on_url rpc"""
572
602
def test_get_stacked_on_invalid_url(self):
573
raise tests.KnownFailure('opening a branch requires the server to open the fallback repository')
574
transport = FakeRemoteTransport('fakeremotetransport:///')
603
# test that asking for a stacked on url the server can't access works.
604
# This isn't perfect, but then as we're in the same process there
605
# really isn't anything we can do to be 100% sure that the server
606
# doesn't just open in - this test probably needs to be rewritten using
607
# a spawn()ed server.
608
stacked_branch = self.make_branch('stacked', format='1.9')
609
memory_branch = self.make_branch('base', format='1.9')
610
vfs_url = self.get_vfs_only_url('base')
611
stacked_branch.set_stacked_on_url(vfs_url)
612
transport = stacked_branch.bzrdir.root_transport
575
613
client = FakeClient(transport.base)
576
614
client.add_expected_call(
577
'Branch.get_stacked_on_url', ('.',),
578
'success', ('ok', 'file:///stacked/on'))
579
bzrdir = RemoteBzrDir(transport, _client=client)
580
branch = RemoteBranch(bzrdir, None, _client=client)
615
'Branch.get_stacked_on_url', ('stacked/',),
616
'success', ('ok', vfs_url))
617
# XXX: Multiple calls are bad, this second call documents what is
619
client.add_expected_call(
620
'Branch.get_stacked_on_url', ('stacked/',),
621
'success', ('ok', vfs_url))
622
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
624
branch = RemoteBranch(bzrdir, RemoteRepository(bzrdir, None),
581
626
result = branch.get_stacked_on_url()
583
'file:///stacked/on', result)
627
self.assertEqual(vfs_url, result)
585
629
def test_backwards_compatible(self):
586
630
# like with bzr1.6 with no Branch.get_stacked_on_url rpc
603
647
'unknown', ('Branch.get_stacked_on_url',))
604
648
# this will also do vfs access, but that goes direct to the transport
605
649
# and isn't seen by the FakeClient.
606
bzrdir = RemoteBzrDir(self.get_transport('stacked'), _client=client)
650
bzrdir = RemoteBzrDir(self.get_transport('stacked'),
651
remote.RemoteBzrDirFormat(), _client=client)
607
652
branch = bzrdir.open_branch()
608
653
result = branch.get_stacked_on_url()
609
654
self.assertEqual('../base', result)
632
677
client.add_expected_call(
633
678
'Branch.get_stacked_on_url', ('stacked/',),
634
679
'success', ('ok', '../base'))
635
bzrdir = RemoteBzrDir(self.get_transport('stacked'), _client=client)
680
bzrdir = RemoteBzrDir(self.get_transport('stacked'),
681
remote.RemoteBzrDirFormat(), _client=client)
636
682
branch = bzrdir.open_branch()
637
683
result = branch.get_stacked_on_url()
638
684
self.assertEqual('../base', result)
661
707
'Branch.lock_write', ('branch/', '', ''),
662
708
'success', ('ok', 'branch token', 'repo token'))
663
709
client.add_expected_call(
710
'Branch.last_revision_info',
712
'success', ('ok', '0', 'null:'))
713
client.add_expected_call(
664
714
'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'null:',),
665
715
'success', ('ok',))
666
716
client.add_expected_call(
691
741
'Branch.lock_write', ('branch/', '', ''),
692
742
'success', ('ok', 'branch token', 'repo token'))
693
743
client.add_expected_call(
744
'Branch.last_revision_info',
746
'success', ('ok', '0', 'null:'))
748
encoded_body = bz2.compress('\n'.join(lines))
749
client.add_success_response_with_body(encoded_body, 'ok')
750
client.add_expected_call(
694
751
'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id2',),
695
752
'success', ('ok',))
696
753
client.add_expected_call(
720
777
'Branch.lock_write', ('branch/', '', ''),
721
778
'success', ('ok', 'branch token', 'repo token'))
722
779
client.add_expected_call(
780
'Branch.last_revision_info',
782
'success', ('ok', '0', 'null:'))
783
# get_graph calls to construct the revision history, for the set_rh
786
encoded_body = bz2.compress('\n'.join(lines))
787
client.add_success_response_with_body(encoded_body, 'ok')
788
client.add_expected_call(
723
789
'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id',),
724
790
'error', ('NoSuchRevision', 'rev-id'))
725
791
client.add_expected_call(
750
816
'Branch.lock_write', ('branch/', '', ''),
751
817
'success', ('ok', 'branch token', 'repo token'))
752
818
client.add_expected_call(
819
'Branch.last_revision_info',
821
'success', ('ok', '0', 'null:'))
823
encoded_body = bz2.compress('\n'.join(lines))
824
client.add_success_response_with_body(encoded_body, 'ok')
825
client.add_expected_call(
753
826
'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id',),
754
827
'error', ('TipChangeRejected', rejection_msg_utf8))
755
828
client.add_expected_call(
784
857
client.add_error_response('NotStacked')
786
859
client.add_success_response('ok', 'branch token', 'repo token')
860
# query the current revision
861
client.add_success_response('ok', '0', 'null:')
787
862
# set_last_revision
788
863
client.add_success_response('ok')
795
870
client._calls = []
796
871
result = branch.set_last_revision_info(1234, 'a-revision-id')
797
872
self.assertEqual(
798
[('call', 'Branch.set_last_revision_info',
873
[('call', 'Branch.last_revision_info', ('branch/',)),
874
('call', 'Branch.set_last_revision_info',
799
875
('branch/', 'branch token', 'repo token',
800
876
'1234', 'a-revision-id'))],
855
931
'Branch.get_stacked_on_url', ('branch/',),
856
932
'error', ('NotStacked',))
857
933
client.add_expected_call(
934
'Branch.last_revision_info',
936
'success', ('ok', '0', 'null:'))
937
client.add_expected_call(
858
938
'Branch.set_last_revision_info',
859
939
('branch/', 'branch token', 'repo token', '1234', 'a-revision-id',),
860
940
'unknown', 'Branch.set_last_revision_info')
1072
1152
client = FakeClient(transport.base)
1073
1153
transport = transport.clone(transport_path)
1074
1154
# we do not want bzrdir to make any remote calls
1075
bzrdir = RemoteBzrDir(transport, _client=False)
1155
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1076
1157
repo = RemoteRepository(bzrdir, None, _client=client)
1077
1158
return repo, client
1476
class TestRepositorySetMakeWorkingTrees(TestRemoteRepository):
1478
def test_backwards_compat(self):
1479
self.setup_smart_server_with_call_log()
1480
repo = self.make_repository('.')
1481
self.reset_smart_call_log()
1482
verb = 'Repository.set_make_working_trees'
1483
self.disable_verb(verb)
1484
repo.set_make_working_trees(True)
1485
call_count = len([call for call in self.hpss_calls if
1486
call[0].method == verb])
1487
self.assertEqual(1, call_count)
1489
def test_current(self):
1490
transport_path = 'quack'
1491
repo, client = self.setup_fake_client_and_repository(transport_path)
1492
client.add_expected_call(
1493
'Repository.set_make_working_trees', ('quack/', 'True'),
1495
client.add_expected_call(
1496
'Repository.set_make_working_trees', ('quack/', 'False'),
1498
repo.set_make_working_trees(True)
1499
repo.set_make_working_trees(False)
1395
1502
class TestRepositoryUnlock(TestRemoteRepository):
1397
1504
def test_unlock(self):