46
46
from bzrlib.smart import server, medium
47
47
from bzrlib.smart.client import _SmartClient
48
48
from bzrlib.symbol_versioning import one_four
49
from bzrlib.transport import get_transport
49
from bzrlib.transport import get_transport, http
50
50
from bzrlib.transport.memory import MemoryTransport
51
from bzrlib.transport.remote import RemoteTransport
51
from bzrlib.transport.remote import RemoteTransport, RemoteTCPTransport
54
54
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
141
141
call, using the second element of the tuple as the verb in the
144
self.responses = responses
146
146
self.expecting_body = False
147
_SmartClient.__init__(self, FakeMedium(self._calls), fake_medium_base)
147
_SmartClient.__init__(self, FakeMedium(self._calls, fake_medium_base))
149
def add_success_response(self, *args):
150
self.responses.append(('success', args, None))
152
def add_success_response_with_body(self, body, *args):
153
self.responses.append(('success', args, body))
155
def add_error_response(self, *args):
156
self.responses.append(('error', args))
158
def add_unknown_method_response(self, verb):
159
self.responses.append(('unknown', verb))
149
161
def _get_next_response(self):
150
162
response_tuple = self.responses.pop(0)
151
if response_tuple[0][0] == 'unknown verb':
152
raise errors.UnknownSmartMethod(response_tuple[0][1])
163
if response_tuple[0] == 'unknown':
164
raise errors.UnknownSmartMethod(response_tuple[1])
165
elif response_tuple[0] == 'error':
166
raise errors.ErrorFromSmartServer(response_tuple[1])
153
167
return response_tuple
155
169
def call(self, method, *args):
156
170
self._calls.append(('call', method, args))
157
return self._get_next_response()[0]
171
return self._get_next_response()[1]
159
173
def call_expecting_body(self, method, *args):
160
174
self._calls.append(('call_expecting_body', method, args))
161
175
result = self._get_next_response()
162
176
self.expecting_body = True
163
return result[0], FakeProtocol(result[1], self)
177
return result[1], FakeProtocol(result[2], self)
165
179
def call_with_body_bytes_expecting_body(self, method, args, body):
166
180
self._calls.append(('call_with_body_bytes_expecting_body', method,
168
182
result = self._get_next_response()
169
183
self.expecting_body = True
170
return result[0], FakeProtocol(result[1], self)
173
class FakeMedium(object):
175
def __init__(self, client_calls):
184
return result[1], FakeProtocol(result[2], self)
187
class FakeMedium(medium.SmartClientMedium):
189
def __init__(self, client_calls, base):
176
190
self._remote_is_at_least_1_2 = True
177
191
self._client_calls = client_calls
179
194
def disconnect(self):
180
195
self._client_calls.append(('disconnect medium',))
183
198
class TestVfsHas(tests.TestCase):
185
200
def test_unicode_path(self):
186
client = FakeClient([(('yes',), )], '/')
201
client = FakeClient('/')
202
client.add_success_response('yes',)
187
203
transport = RemoteTransport('bzr://localhost/', _client=client)
188
204
filename = u'/hell\u00d8'.encode('utf8')
189
205
result = transport.has(filename)
193
209
self.assertTrue(result)
196
class Test_SmartClient_remote_path_from_transport(tests.TestCase):
197
"""Tests for the behaviour of _SmartClient.remote_path_from_transport."""
212
class Test_ClientMedium_remote_path_from_transport(tests.TestCase):
213
"""Tests for the behaviour of client_medium.remote_path_from_transport."""
199
215
def assertRemotePath(self, expected, client_base, transport_base):
200
"""Assert that the result of _SmartClient.remote_path_from_transport
201
is the expected value for a given client_base and transport_base.
216
"""Assert that the result of
217
SmartClientMedium.remote_path_from_transport is the expected value for
218
a given client_base and transport_base.
203
dummy_medium = 'dummy medium'
204
client = _SmartClient(dummy_medium, client_base)
220
client_medium = medium.SmartClientMedium(client_base)
205
221
transport = get_transport(transport_base)
206
result = client.remote_path_from_transport(transport)
222
result = client_medium.remote_path_from_transport(transport)
207
223
self.assertEqual(expected, result)
209
225
def test_remote_path_from_transport(self):
210
"""_SmartClient.remote_path_from_transport calculates a URL for the
211
given transport relative to the root of the client base URL.
226
"""SmartClientMedium.remote_path_from_transport calculates a URL for
227
the given transport relative to the root of the client base URL.
213
229
self.assertRemotePath('xyz/', 'bzr://host/path', 'bzr://host/xyz')
214
230
self.assertRemotePath(
215
231
'path/xyz/', 'bzr://host/path', 'bzr://host/path/xyz')
233
def assertRemotePathHTTP(self, expected, transport_base, relpath):
234
"""Assert that the result of
235
HttpTransportBase.remote_path_from_transport is the expected value for
236
a given transport_base and relpath of that transport. (Note that
237
HttpTransportBase is a subclass of SmartClientMedium)
239
base_transport = get_transport(transport_base)
240
client_medium = base_transport.get_smart_medium()
241
cloned_transport = base_transport.clone(relpath)
242
result = client_medium.remote_path_from_transport(cloned_transport)
243
self.assertEqual(expected, result)
217
245
def test_remote_path_from_transport_http(self):
218
246
"""Remote paths for HTTP transports are calculated differently to other
219
247
transports. They are just relative to the client base, not the root
220
248
directory of the host.
222
250
for scheme in ['http:', 'https:', 'bzr+http:', 'bzr+https:']:
223
self.assertRemotePath(
224
'../xyz/', scheme + '//host/path', scheme + '//host/xyz')
225
self.assertRemotePath(
226
'xyz/', scheme + '//host/path', scheme + '//host/path/xyz')
251
self.assertRemotePathHTTP(
252
'../xyz/', scheme + '//host/path', '../xyz/')
253
self.assertRemotePathHTTP(
254
'xyz/', scheme + '//host/path', 'xyz/')
229
257
class TestBzrDirOpenBranch(tests.TestCase):
232
260
transport = MemoryTransport()
233
261
transport.mkdir('quack')
234
262
transport = transport.clone('quack')
235
client = FakeClient([(('ok', ''), ), (('ok', '', 'no', 'no', 'no'), )],
263
client = FakeClient(transport.base)
264
client.add_success_response('ok', '')
265
client.add_success_response('ok', '', 'no', 'no', 'no')
237
266
bzrdir = RemoteBzrDir(transport, _client=client)
238
267
result = bzrdir.open_branch()
239
268
self.assertEqual(
247
276
transport = MemoryTransport()
248
277
transport.mkdir('quack')
249
278
transport = transport.clone('quack')
250
client = FakeClient([(('nobranch',), )], transport.base)
279
client = FakeClient(transport.base)
280
client.add_error_response('nobranch')
251
281
bzrdir = RemoteBzrDir(transport, _client=client)
252
282
self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
253
283
self.assertEqual(
274
304
def test_url_quoting_of_path(self):
275
305
# Relpaths on the wire should not be URL-escaped. So "~" should be
276
306
# transmitted as "~", not "%7E".
277
transport = RemoteTransport('bzr://localhost/~hello/')
278
client = FakeClient([(('ok', ''), ), (('ok', '', 'no', 'no', 'no'), )],
307
transport = RemoteTCPTransport('bzr://localhost/~hello/')
308
client = FakeClient(transport.base)
309
client.add_success_response('ok', '')
310
client.add_success_response('ok', '', 'no', 'no', 'no')
280
311
bzrdir = RemoteBzrDir(transport, _client=client)
281
312
result = bzrdir.open_branch()
282
313
self.assertEqual(
296
327
subtree_response = 'yes'
298
329
subtree_response = 'no'
300
[(('ok', '', rich_response, subtree_response, external_lookup), ),],
330
client = FakeClient(transport.base)
331
client.add_success_response(
332
'ok', '', rich_response, subtree_response, external_lookup)
302
333
bzrdir = RemoteBzrDir(transport, _client=client)
303
334
result = bzrdir.open_repository()
304
335
self.assertEqual(
330
361
transport = MemoryTransport()
331
362
transport.mkdir('quack')
332
363
transport = transport.clone('quack')
333
client = FakeClient([
334
(('unknown verb', 'RemoteRepository.find_repositoryV2'), ''),
335
(('ok', '', 'no', 'no'), ''),],
364
client = FakeClient(transport.base)
365
client.add_unknown_method_response('RemoteRepository.find_repositoryV2')
366
client.add_success_response('ok', '', 'no', 'no')
337
367
bzrdir = RemoteBzrDir(transport, _client=client)
338
368
repo = bzrdir.open_repository()
339
369
self.assertEqual(
375
405
def test_empty_branch(self):
376
406
# in an empty branch we decode the response properly
377
407
transport = MemoryTransport()
378
client = FakeClient([(('ok', '0', 'null:'), )], transport.base)
408
client = FakeClient(transport.base)
409
client.add_success_response('ok', '0', 'null:')
379
410
transport.mkdir('quack')
380
411
transport = transport.clone('quack')
381
412
# we do not want bzrdir to make any remote calls
392
423
# in a non-empty branch we also decode the response properly
393
424
revid = u'\xc8'.encode('utf8')
394
425
transport = MemoryTransport()
395
client = FakeClient([(('ok', '2', revid), )], transport.base)
426
client = FakeClient(transport.base)
427
client.add_success_response('ok', '2', revid)
396
428
transport.mkdir('kwaak')
397
429
transport = transport.clone('kwaak')
398
430
# we do not want bzrdir to make any remote calls
415
447
transport.mkdir('branch')
416
448
transport = transport.clone('branch')
418
client = FakeClient([
420
(('ok', 'branch token', 'repo token'), ),
450
client = FakeClient(transport.base)
452
client.add_success_response('ok', 'branch token', 'repo token')
454
client.add_success_response('ok')
456
client.add_success_response('ok')
426
457
bzrdir = RemoteBzrDir(transport, _client=False)
427
458
branch = RemoteBranch(bzrdir, None, _client=client)
428
459
# This is a hack to work around the problem that RemoteBranch currently
445
476
transport.mkdir('branch')
446
477
transport = transport.clone('branch')
448
client = FakeClient([
450
(('ok', 'branch token', 'repo token'), ),
479
client = FakeClient(transport.base)
481
client.add_success_response('ok', 'branch token', 'repo token')
483
client.add_success_response('ok')
485
client.add_success_response('ok')
456
486
bzrdir = RemoteBzrDir(transport, _client=False)
457
487
branch = RemoteBranch(bzrdir, None, _client=client)
458
488
# This is a hack to work around the problem that RemoteBranch currently
471
501
self.assertEqual(None, result)
473
503
def test_no_such_revision(self):
474
# A response of 'NoSuchRevision' is translated into an exception.
475
client = FakeClient([
477
(('ok', 'branch token', 'repo token'), ),
479
(('NoSuchRevision', 'rev-id'), ),
482
504
transport = MemoryTransport()
483
505
transport.mkdir('branch')
484
506
transport = transport.clone('branch')
507
# A response of 'NoSuchRevision' is translated into an exception.
508
client = FakeClient(transport.base)
510
client.add_success_response('ok', 'branch token', 'repo token')
512
client.add_error_response('NoSuchRevision', 'rev-id')
514
client.add_success_response('ok')
486
516
bzrdir = RemoteBzrDir(transport, _client=False)
487
517
branch = RemoteBranch(bzrdir, None, _client=client)
502
532
transport = MemoryTransport()
503
533
transport.mkdir('branch')
504
534
transport = transport.clone('branch')
505
client = FakeClient([
507
(('ok', 'branch token', 'repo token'), ),
508
# set_last_revision_info
511
(('ok',), )], transport.base)
535
client = FakeClient(transport.base)
537
client.add_success_response('ok', 'branch token', 'repo token')
539
client.add_success_response('ok')
541
client.add_success_response('ok')
513
543
bzrdir = RemoteBzrDir(transport, _client=False)
514
544
branch = RemoteBranch(bzrdir, None, _client=client)
529
559
def test_no_such_revision(self):
530
560
# A response of 'NoSuchRevision' is translated into an exception.
531
client = FakeClient([
533
(('ok', 'branch token', 'repo token'), ),
534
# set_last_revision_info
535
(('NoSuchRevision', 'revid'), ),
539
561
transport = MemoryTransport()
540
562
transport.mkdir('branch')
541
563
transport = transport.clone('branch')
564
client = FakeClient(transport.base)
566
client.add_success_response('ok', 'branch token', 'repo token')
568
client.add_error_response('NoSuchRevision', 'revid')
570
client.add_success_response('ok')
543
572
bzrdir = RemoteBzrDir(transport, _client=False)
544
573
branch = RemoteBranch(bzrdir, None, _client=client)
575
604
transport = MemoryTransport()
576
605
transport.mkdir('branch')
577
606
transport = transport.clone('branch')
579
[(('unknown verb', 'Branch.set_last_revision_info',), ),],
607
client = FakeClient(transport.base)
608
client.add_unknown_method_response('Branch.set_last_revision_info')
581
609
bzrdir = RemoteBzrDir(transport, _client=False)
582
610
branch = RemoteBranch(bzrdir, None, _client=client)
583
611
class StubRealBranch(object):
601
629
[('set_last_revision_info', 1234, 'a-revision-id')],
602
630
real_branch.calls)
632
def test_unexpected_error(self):
633
# A response of 'NoSuchRevision' is translated into an exception.
634
transport = MemoryTransport()
635
transport.mkdir('branch')
636
transport = transport.clone('branch')
637
client = FakeClient(transport.base)
639
client.add_success_response('ok', 'branch token', 'repo token')
641
client.add_error_response('UnexpectedError')
643
client.add_success_response('ok')
645
bzrdir = RemoteBzrDir(transport, _client=False)
646
branch = RemoteBranch(bzrdir, None, _client=client)
647
# This is a hack to work around the problem that RemoteBranch currently
648
# unnecessarily invokes _ensure_real upon a call to lock_write.
649
branch._ensure_real = lambda: None
650
# Lock the branch, reset the record of remote calls.
654
err = self.assertRaises(
655
errors.ErrorFromSmartServer,
656
branch.set_last_revision_info, 123, 'revid')
657
self.assertEqual(('UnexpectedError',), err.error_tuple)
605
661
class TestBranchControlGetBranchConf(tests.TestCaseWithMemoryTransport):
606
662
"""Getting the branch configuration should use an abstract method not vfs.
609
665
def test_get_branch_conf(self):
610
666
raise tests.KnownFailure('branch.conf is not retrieved by get_config_file')
611
# We should see that branch.get_config() does a single rpc to get the
612
# remote configuration file, abstracting away where that is stored on
613
# the server. However at the moment it always falls back to using the
614
# vfs, and this would need some changes in config.py.
667
## # We should see that branch.get_config() does a single rpc to get the
668
## # remote configuration file, abstracting away where that is stored on
669
## # the server. However at the moment it always falls back to using the
670
## # vfs, and this would need some changes in config.py.
616
# in an empty branch we decode the response properly
617
client = FakeClient([(('ok', ), '# config file body')], self.get_url())
618
# we need to make a real branch because the remote_branch.control_files
619
# will trigger _ensure_real.
620
branch = self.make_branch('quack')
621
transport = branch.bzrdir.root_transport
622
# we do not want bzrdir to make any remote calls
623
bzrdir = RemoteBzrDir(transport, _client=False)
624
branch = RemoteBranch(bzrdir, None, _client=client)
625
config = branch.get_config()
627
[('call_expecting_body', 'Branch.get_config_file', ('quack/',))],
672
## # in an empty branch we decode the response properly
673
## client = FakeClient([(('ok', ), '# config file body')], self.get_url())
674
## # we need to make a real branch because the remote_branch.control_files
675
## # will trigger _ensure_real.
676
## branch = self.make_branch('quack')
677
## transport = branch.bzrdir.root_transport
678
## # we do not want bzrdir to make any remote calls
679
## bzrdir = RemoteBzrDir(transport, _client=False)
680
## branch = RemoteBranch(bzrdir, None, _client=client)
681
## config = branch.get_config()
683
## [('call_expecting_body', 'Branch.get_config_file', ('quack/',))],
631
687
class TestBranchLockWrite(tests.TestCase):
633
689
def test_lock_write_unlockable(self):
634
690
transport = MemoryTransport()
635
client = FakeClient([(('UnlockableTransport', ), '')], transport.base)
691
client = FakeClient(transport.base)
692
client.add_error_response('UnlockableTransport')
636
693
transport.mkdir('quack')
637
694
transport = transport.clone('quack')
638
695
# we do not want bzrdir to make any remote calls
712
772
def test_revid_none(self):
713
773
# ('ok',), body with revisions and size
714
responses = [(('ok', ), 'revisions: 2\nsize: 18\n')]
715
774
transport_path = 'quack'
716
repo, client = self.setup_fake_client_and_repository(
717
responses, transport_path)
775
repo, client = self.setup_fake_client_and_repository(transport_path)
776
client.add_success_response_with_body(
777
'revisions: 2\nsize: 18\n', 'ok')
718
778
result = repo.gather_stats(None)
719
779
self.assertEqual(
720
780
[('call_expecting_body', 'Repository.gather_stats',
725
785
def test_revid_no_committers(self):
726
786
# ('ok',), body without committers
727
responses = [(('ok', ),
728
'firstrev: 123456.300 3600\n'
729
'latestrev: 654231.400 0\n'
787
body = ('firstrev: 123456.300 3600\n'
788
'latestrev: 654231.400 0\n'
732
791
transport_path = 'quick'
733
792
revid = u'\xc8'.encode('utf8')
734
repo, client = self.setup_fake_client_and_repository(
735
responses, transport_path)
793
repo, client = self.setup_fake_client_and_repository(transport_path)
794
client.add_success_response_with_body(body, 'ok')
736
795
result = repo.gather_stats(revid)
737
796
self.assertEqual(
738
797
[('call_expecting_body', 'Repository.gather_stats',
746
805
def test_revid_with_committers(self):
747
806
# ('ok',), body with committers
748
responses = [(('ok', ),
750
'firstrev: 123456.300 3600\n'
751
'latestrev: 654231.400 0\n'
807
body = ('committers: 128\n'
808
'firstrev: 123456.300 3600\n'
809
'latestrev: 654231.400 0\n'
754
812
transport_path = 'buick'
755
813
revid = u'\xc8'.encode('utf8')
756
repo, client = self.setup_fake_client_and_repository(
757
responses, transport_path)
814
repo, client = self.setup_fake_client_and_repository(transport_path)
815
client.add_success_response_with_body(body, 'ok')
758
816
result = repo.gather_stats(revid, True)
759
817
self.assertEqual(
760
818
[('call_expecting_body', 'Repository.gather_stats',
789
845
r2 = u'\u0dab'.encode('utf8')
790
846
lines = [' '.join([r2, r1]), r1]
791
847
encoded_body = bz2.compress('\n'.join(lines))
792
responses = [(('ok', ), encoded_body), (('ok', ), encoded_body)]
794
849
transport_path = 'quack'
795
repo, client = self.setup_fake_client_and_repository(
796
responses, transport_path)
850
repo, client = self.setup_fake_client_and_repository(transport_path)
851
client.add_success_response_with_body(encoded_body, 'ok')
852
client.add_success_response_with_body(encoded_body, 'ok')
798
854
graph = repo.get_graph()
799
855
parents = graph.get_parent_map([r2])
825
881
def test_get_parent_map_reconnects_if_unknown_method(self):
827
(('unknown verb', 'Repository.get_parent_map'), ''),
829
882
transport_path = 'quack'
830
repo, client = self.setup_fake_client_and_repository(
831
responses, transport_path)
883
repo, client = self.setup_fake_client_and_repository(transport_path)
884
client.add_unknown_method_response('Repository,get_parent_map')
885
client.add_success_response_with_body('', 'ok')
832
886
self.assertTrue(client._medium._remote_is_at_least_1_2)
833
887
rev_id = 'revision-id'
834
888
expected_deprecations = [
858
912
This is the test for https://bugs.launchpad.net/bzr/+bug/214894
860
914
rev_id = 'revision-id'
861
responses = [(('ok',), rev_id)]
862
915
transport_path = 'quack'
863
repo, client = self.setup_fake_client_and_repository(
864
responses, transport_path)
916
repo, client = self.setup_fake_client_and_repository(transport_path)
917
client.add_success_response_with_body(rev_id, 'ok')
865
918
client._medium._remote_is_at_least_1_2 = False
866
919
expected_deprecations = [
867
920
'bzrlib.remote.RemoteRepository.get_revision_graph was deprecated '
875
928
self.assertEqual({rev_id: ('null:',)}, parents)
877
930
def test_get_parent_map_unexpected_response(self):
879
(('something unexpected!',), '')]
880
repo, client = self.setup_fake_client_and_repository(responses, 'path')
931
repo, client = self.setup_fake_client_and_repository('path')
932
client.add_success_response('something unexpected!')
881
933
self.assertRaises(
882
934
errors.UnexpectedSmartServerResponse,
883
935
repo.get_parent_map, ['a-revision-id'])
888
940
def test_null_revision(self):
889
941
# a null revision has the predictable result {}, we should have no wire
890
942
# traffic when calling it with this argument
891
responses = [(('notused', ), '')]
892
943
transport_path = 'empty'
893
repo, client = self.setup_fake_client_and_repository(
894
responses, transport_path)
944
repo, client = self.setup_fake_client_and_repository(transport_path)
945
client.add_success_response('notused')
895
946
result = self.applyDeprecated(one_four, repo.get_revision_graph,
897
948
self.assertEqual([], client._calls)
904
955
lines = [' '.join([r2, r1]), r1]
905
956
encoded_body = '\n'.join(lines)
907
responses = [(('ok', ), encoded_body)]
908
958
transport_path = 'sinhala'
909
repo, client = self.setup_fake_client_and_repository(
910
responses, transport_path)
959
repo, client = self.setup_fake_client_and_repository(transport_path)
960
client.add_success_response_with_body(encoded_body, 'ok')
911
961
result = self.applyDeprecated(one_four, repo.get_revision_graph)
912
962
self.assertEqual(
913
963
[('call_expecting_body', 'Repository.get_revision_graph',
924
974
lines = [' '.join([r2, r11, r12]), r11, r12]
925
975
encoded_body = '\n'.join(lines)
927
responses = [(('ok', ), encoded_body)]
928
977
transport_path = 'sinhala'
929
repo, client = self.setup_fake_client_and_repository(
930
responses, transport_path)
978
repo, client = self.setup_fake_client_and_repository(transport_path)
979
client.add_success_response_with_body(encoded_body, 'ok')
931
980
result = self.applyDeprecated(one_four, repo.get_revision_graph, r2)
932
981
self.assertEqual(
933
982
[('call_expecting_body', 'Repository.get_revision_graph',
938
987
def test_no_such_revision(self):
940
responses = [(('nosuchrevision', revid), '')]
941
989
transport_path = 'sinhala'
942
repo, client = self.setup_fake_client_and_repository(
943
responses, transport_path)
990
repo, client = self.setup_fake_client_and_repository(transport_path)
991
client.add_error_response('nosuchrevision', revid)
944
992
# also check that the right revision is reported in the error
945
993
self.assertRaises(errors.NoSuchRevision,
946
994
self.applyDeprecated, one_four, repo.get_revision_graph, revid)
949
997
('sinhala/', revid))],
1000
def test_unexpected_error(self):
1002
transport_path = 'sinhala'
1003
repo, client = self.setup_fake_client_and_repository(transport_path)
1004
client.add_error_response('AnUnexpectedError')
1005
e = self.assertRaises(errors.ErrorFromSmartServer,
1006
self.applyDeprecated, one_four, repo.get_revision_graph, revid)
1007
self.assertEqual(('AnUnexpectedError',), e.error_tuple)
953
1010
class TestRepositoryIsShared(TestRemoteRepository):
955
1012
def test_is_shared(self):
956
1013
# ('yes', ) for Repository.is_shared -> 'True'.
957
responses = [(('yes', ), )]
958
1014
transport_path = 'quack'
959
repo, client = self.setup_fake_client_and_repository(
960
responses, transport_path)
1015
repo, client = self.setup_fake_client_and_repository(transport_path)
1016
client.add_success_response('yes')
961
1017
result = repo.is_shared()
962
1018
self.assertEqual(
963
1019
[('call', 'Repository.is_shared', ('quack/',))],
967
1023
def test_is_not_shared(self):
968
1024
# ('no', ) for Repository.is_shared -> 'False'.
969
responses = [(('no', ), )]
970
1025
transport_path = 'qwack'
971
repo, client = self.setup_fake_client_and_repository(
972
responses, transport_path)
1026
repo, client = self.setup_fake_client_and_repository(transport_path)
1027
client.add_success_response('no')
973
1028
result = repo.is_shared()
974
1029
self.assertEqual(
975
1030
[('call', 'Repository.is_shared', ('qwack/',))],
980
1035
class TestRepositoryLockWrite(TestRemoteRepository):
982
1037
def test_lock_write(self):
983
responses = [(('ok', 'a token'), '')]
984
1038
transport_path = 'quack'
985
repo, client = self.setup_fake_client_and_repository(
986
responses, transport_path)
1039
repo, client = self.setup_fake_client_and_repository(transport_path)
1040
client.add_success_response('ok', 'a token')
987
1041
result = repo.lock_write()
988
1042
self.assertEqual(
989
1043
[('call', 'Repository.lock_write', ('quack/', ''))],
991
1045
self.assertEqual('a token', result)
993
1047
def test_lock_write_already_locked(self):
994
responses = [(('LockContention', ), '')]
995
1048
transport_path = 'quack'
996
repo, client = self.setup_fake_client_and_repository(
997
responses, transport_path)
1049
repo, client = self.setup_fake_client_and_repository(transport_path)
1050
client.add_error_response('LockContention')
998
1051
self.assertRaises(errors.LockContention, repo.lock_write)
999
1052
self.assertEqual(
1000
1053
[('call', 'Repository.lock_write', ('quack/', ''))],
1003
1056
def test_lock_write_unlockable(self):
1004
responses = [(('UnlockableTransport', ), '')]
1005
1057
transport_path = 'quack'
1006
repo, client = self.setup_fake_client_and_repository(
1007
responses, transport_path)
1058
repo, client = self.setup_fake_client_and_repository(transport_path)
1059
client.add_error_response('UnlockableTransport')
1008
1060
self.assertRaises(errors.UnlockableTransport, repo.lock_write)
1009
1061
self.assertEqual(
1010
1062
[('call', 'Repository.lock_write', ('quack/', ''))],
1014
1066
class TestRepositoryUnlock(TestRemoteRepository):
1016
1068
def test_unlock(self):
1017
responses = [(('ok', 'a token'), ''),
1019
1069
transport_path = 'quack'
1020
repo, client = self.setup_fake_client_and_repository(
1021
responses, transport_path)
1070
repo, client = self.setup_fake_client_and_repository(transport_path)
1071
client.add_success_response('ok', 'a token')
1072
client.add_success_response('ok')
1022
1073
repo.lock_write()
1024
1075
self.assertEqual(
1029
1080
def test_unlock_wrong_token(self):
1030
1081
# If somehow the token is wrong, unlock will raise TokenMismatch.
1031
responses = [(('ok', 'a token'), ''),
1032
(('TokenMismatch',), '')]
1033
1082
transport_path = 'quack'
1034
repo, client = self.setup_fake_client_and_repository(
1035
responses, transport_path)
1083
repo, client = self.setup_fake_client_and_repository(transport_path)
1084
client.add_success_response('ok', 'a token')
1085
client.add_error_response('TokenMismatch')
1036
1086
repo.lock_write()
1037
1087
self.assertRaises(errors.TokenMismatch, repo.unlock)
1074
1122
def test_repository_tarball(self):
1075
1123
# Test that Repository.tarball generates the right operations
1076
1124
transport_path = 'repo'
1077
expected_responses = [(('ok',), self.tarball_content),
1079
1125
expected_calls = [('call_expecting_body', 'Repository.tarball',
1080
1126
('repo/', 'bz2',),),
1082
remote_repo, client = self.setup_fake_client_and_repository(
1083
expected_responses, transport_path)
1128
repo, client = self.setup_fake_client_and_repository(transport_path)
1129
client.add_success_response_with_body(self.tarball_content, 'ok')
1084
1130
# Now actually ask for the tarball
1085
tarball_file = remote_repo._get_tarball('bz2')
1131
tarball_file = repo._get_tarball('bz2')
1087
1133
self.assertEqual(expected_calls, client._calls)
1088
1134
self.assertEqual(self.tarball_content, tarball_file.read())