130
130
class FakeClient(_SmartClient):
131
131
"""Lookalike for _SmartClient allowing testing."""
133
def __init__(self, responses):
134
# We don't call the super init because there is no medium.
133
def __init__(self, responses, fake_medium_base='fake base'):
135
134
"""Create a FakeClient.
137
:param respones: A list of response-tuple, body-data pairs to be sent
136
:param responses: A list of response-tuple, body-data pairs to be sent
140
139
self.responses = responses
142
141
self.expecting_body = False
142
_SmartClient.__init__(self, FakeMedium(fake_medium_base))
144
144
def call(self, method, *args):
145
145
self._calls.append(('call', method, args))
152
152
return result[0], FakeProtocol(result[1], self)
155
class FakeMedium(object):
157
def __init__(self, base):
155
161
class TestBzrDirOpenBranch(tests.TestCase):
157
163
def test_branch_present(self):
158
client = FakeClient([(('ok', ''), ), (('ok', '', 'no', 'no'), )])
159
164
transport = MemoryTransport()
160
165
transport.mkdir('quack')
161
166
transport = transport.clone('quack')
167
client = FakeClient([(('ok', ''), ), (('ok', '', 'no', 'no'), )],
162
169
bzrdir = RemoteBzrDir(transport, _client=client)
163
170
result = bzrdir.open_branch()
164
171
self.assertEqual(
165
[('call', 'BzrDir.open_branch', ('///quack/',)),
166
('call', 'BzrDir.find_repository', ('///quack/',))],
172
[('call', 'BzrDir.open_branch', ('quack/',)),
173
('call', 'BzrDir.find_repository', ('quack/',))],
168
175
self.assertIsInstance(result, RemoteBranch)
169
176
self.assertEqual(bzrdir, result.bzrdir)
171
178
def test_branch_missing(self):
172
client = FakeClient([(('nobranch',), )])
173
179
transport = MemoryTransport()
174
180
transport.mkdir('quack')
175
181
transport = transport.clone('quack')
182
client = FakeClient([(('nobranch',), )], transport.base)
176
183
bzrdir = RemoteBzrDir(transport, _client=client)
177
184
self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
178
185
self.assertEqual(
179
[('call', 'BzrDir.open_branch', ('///quack/',))],
186
[('call', 'BzrDir.open_branch', ('quack/',))],
182
189
def check_open_repository(self, rich_root, subtrees):
190
transport = MemoryTransport()
191
transport.mkdir('quack')
192
transport = transport.clone('quack')
184
194
rich_response = 'yes'
188
198
subtree_response = 'yes'
190
200
subtree_response = 'no'
191
client = FakeClient([(('ok', '', rich_response, subtree_response), ),])
192
transport = MemoryTransport()
193
transport.mkdir('quack')
194
transport = transport.clone('quack')
201
client = FakeClient([(('ok', '', rich_response, subtree_response), ),],
195
203
bzrdir = RemoteBzrDir(transport, _client=client)
196
204
result = bzrdir.open_repository()
197
205
self.assertEqual(
198
[('call', 'BzrDir.find_repository', ('///quack/',))],
206
[('call', 'BzrDir.find_repository', ('quack/',))],
200
208
self.assertIsInstance(result, RemoteRepository)
201
209
self.assertEqual(bzrdir, result.bzrdir)
246
254
def test_empty_branch(self):
247
255
# in an empty branch we decode the response properly
248
client = FakeClient([(('ok', '0', 'null:'), )])
249
256
transport = MemoryTransport()
257
client = FakeClient([(('ok', '0', 'null:'), )], transport.base)
250
258
transport.mkdir('quack')
251
259
transport = transport.clone('quack')
252
260
# we do not want bzrdir to make any remote calls
255
263
result = branch.last_revision_info()
257
265
self.assertEqual(
258
[('call', 'Branch.last_revision_info', ('///quack/',))],
266
[('call', 'Branch.last_revision_info', ('quack/',))],
260
268
self.assertEqual((0, NULL_REVISION), result)
262
270
def test_non_empty_branch(self):
263
271
# in a non-empty branch we also decode the response properly
264
272
revid = u'\xc8'.encode('utf8')
265
client = FakeClient([(('ok', '2', revid), )])
266
273
transport = MemoryTransport()
274
client = FakeClient([(('ok', '2', revid), )], transport.base)
267
275
transport.mkdir('kwaak')
268
276
transport = transport.clone('kwaak')
269
277
# we do not want bzrdir to make any remote calls
272
280
result = branch.last_revision_info()
274
282
self.assertEqual(
275
[('call', 'Branch.last_revision_info', ('///kwaak/',))],
283
[('call', 'Branch.last_revision_info', ('kwaak/',))],
277
285
self.assertEqual((2, revid), result)
282
290
def test_set_empty(self):
283
291
# set_revision_history([]) is translated to calling
284
292
# Branch.set_last_revision(path, '') on the wire.
293
transport = MemoryTransport()
294
transport.mkdir('branch')
295
transport = transport.clone('branch')
285
297
client = FakeClient([
287
299
(('ok', 'branch token', 'repo token'), ),
288
300
# set_last_revision
292
transport = MemoryTransport()
293
transport.mkdir('branch')
294
transport = transport.clone('branch')
296
305
bzrdir = RemoteBzrDir(transport, _client=False)
297
306
branch = RemoteBranch(bzrdir, None, _client=client)
298
307
# This is a hack to work around the problem that RemoteBranch currently
303
312
result = branch.set_revision_history([])
304
313
self.assertEqual(
305
314
[('call', 'Branch.set_last_revision',
306
('///branch/', 'branch token', 'repo token', 'null:'))],
315
('branch/', 'branch token', 'repo token', 'null:'))],
309
318
self.assertEqual(None, result)
311
320
def test_set_nonempty(self):
312
321
# set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
313
322
# Branch.set_last_revision(path, rev-idN) on the wire.
323
transport = MemoryTransport()
324
transport.mkdir('branch')
325
transport = transport.clone('branch')
314
327
client = FakeClient([
316
329
(('ok', 'branch token', 'repo token'), ),
317
330
# set_last_revision
321
transport = MemoryTransport()
322
transport.mkdir('branch')
323
transport = transport.clone('branch')
325
335
bzrdir = RemoteBzrDir(transport, _client=False)
326
336
branch = RemoteBranch(bzrdir, None, _client=client)
327
337
# This is a hack to work around the problem that RemoteBranch currently
334
344
result = branch.set_revision_history(['rev-id1', 'rev-id2'])
335
345
self.assertEqual(
336
346
[('call', 'Branch.set_last_revision',
337
('///branch/', 'branch token', 'repo token', 'rev-id2'))],
347
('branch/', 'branch token', 'repo token', 'rev-id2'))],
340
350
self.assertEqual(None, result)
375
385
def test_get_branch_conf(self):
376
386
# in an empty branch we decode the response properly
377
client = FakeClient([(('ok', ), 'config file body')])
387
client = FakeClient([(('ok', ), 'config file body')], self.get_url())
378
388
# we need to make a real branch because the remote_branch.control_files
379
389
# will trigger _ensure_real.
380
390
branch = self.make_branch('quack')
384
394
branch = RemoteBranch(bzrdir, None, _client=client)
385
395
result = branch.control_files.get('branch.conf')
386
396
self.assertEqual(
387
[('call_expecting_body', 'Branch.get_config_file', ('///quack/',))],
397
[('call_expecting_body', 'Branch.get_config_file', ('quack/',))],
389
399
self.assertEqual('config file body', result.read())
392
402
class TestBranchLockWrite(tests.TestCase):
394
404
def test_lock_write_unlockable(self):
395
client = FakeClient([(('UnlockableTransport', ), '')])
396
405
transport = MemoryTransport()
406
client = FakeClient([(('UnlockableTransport', ), '')], transport.base)
397
407
transport.mkdir('quack')
398
408
transport = transport.clone('quack')
399
409
# we do not want bzrdir to make any remote calls
401
411
branch = RemoteBranch(bzrdir, None, _client=client)
402
412
self.assertRaises(errors.UnlockableTransport, branch.lock_write)
403
413
self.assertEqual(
404
[('call', 'Branch.lock_write', ('///quack/', '', ''))],
414
[('call', 'Branch.lock_write', ('quack/', '', ''))],
474
484
:param transport_path: Path below the root of the MemoryTransport
475
485
where the repository will be created.
477
client = FakeClient(responses)
478
487
transport = MemoryTransport()
479
488
transport.mkdir(transport_path)
489
client = FakeClient(responses, transport.base)
480
490
transport = transport.clone(transport_path)
481
491
# we do not want bzrdir to make any remote calls
482
492
bzrdir = RemoteBzrDir(transport, _client=False)
513
523
result = repo.gather_stats(revid)
514
524
self.assertEqual(
515
525
[('call_expecting_body', 'Repository.gather_stats',
516
('///quick/', revid, 'no'))],
526
('quick/', revid, 'no'))],
518
528
self.assertEqual({'revisions': 2, 'size': 18,
519
529
'firstrev': (123456.300, 3600),
535
545
result = repo.gather_stats(revid, True)
536
546
self.assertEqual(
537
547
[('call_expecting_body', 'Repository.gather_stats',
538
('///buick/', revid, 'yes'))],
548
('buick/', revid, 'yes'))],
540
550
self.assertEqual({'revisions': 2, 'size': 18,
541
551
'committers': 128,
620
630
responses, transport_path)
621
631
result = repo.is_shared()
622
632
self.assertEqual(
623
[('call', 'Repository.is_shared', ('///quack/',))],
633
[('call', 'Repository.is_shared', ('quack/',))],
625
635
self.assertEqual(True, result)
632
642
responses, transport_path)
633
643
result = repo.is_shared()
634
644
self.assertEqual(
635
[('call', 'Repository.is_shared', ('///qwack/',))],
645
[('call', 'Repository.is_shared', ('qwack/',))],
637
647
self.assertEqual(False, result)
646
656
responses, transport_path)
647
657
result = repo.lock_write()
648
658
self.assertEqual(
649
[('call', 'Repository.lock_write', ('///quack/', ''))],
659
[('call', 'Repository.lock_write', ('quack/', ''))],
651
661
self.assertEqual('a token', result)
657
667
responses, transport_path)
658
668
self.assertRaises(errors.LockContention, repo.lock_write)
659
669
self.assertEqual(
660
[('call', 'Repository.lock_write', ('///quack/', ''))],
670
[('call', 'Repository.lock_write', ('quack/', ''))],
663
673
def test_lock_write_unlockable(self):
667
677
responses, transport_path)
668
678
self.assertRaises(errors.UnlockableTransport, repo.lock_write)
669
679
self.assertEqual(
670
[('call', 'Repository.lock_write', ('///quack/', ''))],
680
[('call', 'Repository.lock_write', ('quack/', ''))],
682
692
repo.lock_write()
684
694
self.assertEqual(
685
[('call', 'Repository.lock_write', ('///quack/', '')),
686
('call', 'Repository.unlock', ('///quack/', 'a token'))],
695
[('call', 'Repository.lock_write', ('quack/', '')),
696
('call', 'Repository.unlock', ('quack/', 'a token'))],
689
699
def test_unlock_wrong_token(self):
737
747
expected_responses = [(('ok',), self.tarball_content),
739
749
expected_calls = [('call_expecting_body', 'Repository.tarball',
740
('///repo/', 'bz2',),),
742
752
remote_repo, client = self.setup_fake_client_and_repository(
743
753
expected_responses, transport_path)