113
115
return self.get_transport().get_smart_medium()
118
class TestByteStreamToStream(tests.TestCase):
120
def test_repeated_substreams_same_kind_are_one_stream(self):
121
# Make a stream - an iterable of bytestrings.
122
stream = [('text', [versionedfile.FulltextContentFactory(('k1',), None,
123
None, 'foo')]),('text', [
124
versionedfile.FulltextContentFactory(('k2',), None, None, 'bar')])]
125
fmt = bzrdir.format_registry.get('pack-0.92')().repository_format
126
bytes = smart.repository._stream_to_byte_stream(stream, fmt)
128
# Iterate the resulting iterable; checking that we get only one stream
130
fmt, stream = smart.repository._byte_stream_to_stream(bytes)
131
for kind, substream in stream:
132
streams.append((kind, list(substream)))
133
self.assertLength(1, streams)
134
self.assertLength(2, streams[0][1])
116
137
class TestSmartServerResponse(tests.TestCase):
118
139
def test__eq__(self):
150
171
self.assertRaises(
151
172
errors.PathNotChild, request.translate_client_path, 'bar/')
152
173
self.assertEqual('./baz', request.translate_client_path('foo/baz'))
174
e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'.encode('utf-8')
175
self.assertEqual('./' + urlutils.escape(e_acute),
176
request.translate_client_path('foo/' + e_acute))
178
def test_translate_client_path_vfs(self):
179
"""VfsRequests receive escaped paths rather than raw UTF-8."""
180
transport = self.get_transport()
181
request = smart.vfs.VfsRequest(transport, 'foo/')
182
e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'.encode('utf-8')
183
escaped = urlutils.escape('foo/' + e_acute)
184
self.assertEqual('./' + urlutils.escape(e_acute),
185
request.translate_client_path(escaped))
154
187
def test_transport_from_client_path(self):
155
188
transport = self.get_transport()
283
if repo._format.supports_external_lookups:
250
287
if (smart.bzrdir.SmartServerRequestFindRepositoryV3 ==
251
288
self._request_class):
252
289
return SuccessfulSmartServerResponse(
253
('ok', '', rich_root, subtrees, 'no',
290
('ok', '', rich_root, subtrees, external,
254
291
repo._format.network_name()))
255
292
elif (smart.bzrdir.SmartServerRequestFindRepositoryV2 ==
256
293
self._request_class):
257
294
# All tests so far are on formats, and for non-external
259
296
return SuccessfulSmartServerResponse(
260
('ok', '', rich_root, subtrees, 'no'))
297
('ok', '', rich_root, subtrees, external))
262
299
return SuccessfulSmartServerResponse(('ok', '', rich_root, subtrees))
350
387
request.execute, 'subdir')
390
class TestSmartServerRequestBzrDirInitializeEx(tests.TestCaseWithMemoryTransport):
391
"""Basic tests for BzrDir.initialize_ex_1.16 in the smart server.
393
The main unit tests in test_bzrdir exercise the API comprehensively.
396
def test_empty_dir(self):
397
"""Initializing an empty dir should succeed and do it."""
398
backing = self.get_transport()
399
name = self.make_bzrdir('reference')._format.network_name()
400
request = smart.bzrdir.SmartServerRequestBzrDirInitializeEx(backing)
401
self.assertEqual(SmartServerResponse(('', '', '', '', '', '', name,
402
'False', '', '', '')),
403
request.execute(name, '', 'True', 'False', 'False', '', '', '', '',
405
made_dir = bzrdir.BzrDir.open_from_transport(backing)
406
# no branch, tree or repository is expected with the current
408
self.assertRaises(errors.NoWorkingTree, made_dir.open_workingtree)
409
self.assertRaises(errors.NotBranchError, made_dir.open_branch)
410
self.assertRaises(errors.NoRepositoryPresent, made_dir.open_repository)
412
def test_missing_dir(self):
413
"""Initializing a missing directory should fail like the bzrdir api."""
414
backing = self.get_transport()
415
name = self.make_bzrdir('reference')._format.network_name()
416
request = smart.bzrdir.SmartServerRequestBzrDirInitializeEx(backing)
417
self.assertRaises(errors.NoSuchFile, request.execute, name,
418
'subdir/dir', 'False', 'False', 'False', '', '', '', '', 'False')
420
def test_initialized_dir(self):
421
"""Initializing an extant directory should fail like the bzrdir api."""
422
backing = self.get_transport()
423
name = self.make_bzrdir('reference')._format.network_name()
424
request = smart.bzrdir.SmartServerRequestBzrDirInitializeEx(backing)
425
self.make_bzrdir('subdir')
426
self.assertRaises(errors.FileExists, request.execute, name, 'subdir',
427
'False', 'False', 'False', '', '', '', '', 'False')
430
class TestSmartServerRequestOpenBzrDir(tests.TestCaseWithMemoryTransport):
432
def test_no_directory(self):
433
backing = self.get_transport()
434
request = smart.bzrdir.SmartServerRequestOpenBzrDir(backing)
435
self.assertEqual(SmartServerResponse(('no', )),
436
request.execute('does-not-exist'))
438
def test_empty_directory(self):
439
backing = self.get_transport()
440
backing.mkdir('empty')
441
request = smart.bzrdir.SmartServerRequestOpenBzrDir(backing)
442
self.assertEqual(SmartServerResponse(('no', )),
443
request.execute('empty'))
445
def test_outside_root_client_path(self):
446
backing = self.get_transport()
447
request = smart.bzrdir.SmartServerRequestOpenBzrDir(backing,
448
root_client_path='root')
449
self.assertEqual(SmartServerResponse(('no', )),
450
request.execute('not-root'))
453
class TestSmartServerRequestOpenBzrDir_2_1(tests.TestCaseWithMemoryTransport):
455
def test_no_directory(self):
456
backing = self.get_transport()
457
request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing)
458
self.assertEqual(SmartServerResponse(('no', )),
459
request.execute('does-not-exist'))
461
def test_empty_directory(self):
462
backing = self.get_transport()
463
backing.mkdir('empty')
464
request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing)
465
self.assertEqual(SmartServerResponse(('no', )),
466
request.execute('empty'))
468
def test_present_without_workingtree(self):
469
backing = self.get_transport()
470
request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing)
471
self.make_bzrdir('.')
472
self.assertEqual(SmartServerResponse(('yes', 'no')),
475
def test_outside_root_client_path(self):
476
backing = self.get_transport()
477
request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing,
478
root_client_path='root')
479
self.assertEqual(SmartServerResponse(('no',)),
480
request.execute('not-root'))
483
class TestSmartServerRequestOpenBzrDir_2_1_disk(TestCaseWithChrootedTransport):
485
def test_present_with_workingtree(self):
486
self.vfs_transport_factory = local.LocalURLServer
487
backing = self.get_transport()
488
request = smart.bzrdir.SmartServerRequestOpenBzrDir_2_1(backing)
489
bd = self.make_bzrdir('.')
490
bd.create_repository()
492
bd.create_workingtree()
493
self.assertEqual(SmartServerResponse(('yes', 'yes')),
353
497
class TestSmartServerRequestOpenBranch(TestCaseWithChrootedTransport):
355
499
def test_no_branch(self):
558
706
self.assertEqual(SuccessfulSmartServerResponse(()), result)
559
707
self.assertEqual('bar', config.get_option('foo', 'gam'))
712
class TestSmartServerBranchRequestSetTagsBytes(TestLockedBranch):
713
# Only called when the branch format and tags match [yay factory
714
# methods] so only need to test straight forward cases.
716
def test_set_bytes(self):
717
base_branch = self.make_branch('base')
718
tag_bytes = base_branch._get_tags_bytes()
719
# get_lock_tokens takes out a lock.
720
branch_token, repo_token = self.get_lock_tokens(base_branch)
721
request = smart.branch.SmartServerBranchSetTagsBytes(
722
self.get_transport())
723
response = request.execute('base', branch_token, repo_token)
724
self.assertEqual(None, response)
725
response = request.do_chunk(tag_bytes)
726
self.assertEqual(None, response)
727
response = request.do_end()
729
SuccessfulSmartServerResponse(()), response)
732
def test_lock_failed(self):
733
base_branch = self.make_branch('base')
734
base_branch.lock_write()
735
tag_bytes = base_branch._get_tags_bytes()
736
request = smart.branch.SmartServerBranchSetTagsBytes(
737
self.get_transport())
738
self.assertRaises(errors.TokenMismatch, request.execute,
739
'base', 'wrong token', 'wrong token')
740
# The request handler will keep processing the message parts, so even
741
# if the request fails immediately do_chunk and do_end are still
743
request.do_chunk(tag_bytes)
562
749
class SetLastRevisionTestBase(TestLockedBranch):
875
1062
# with a new branch object.
876
1063
new_branch = repository.bzrdir.open_branch()
877
1064
self.assertRaises(errors.LockContention, new_branch.lock_write)
1066
request = smart.branch.SmartServerBranchRequestUnlock(backing)
1067
response = request.execute('', branch_nonce, repository_nonce)
879
1069
def test_lock_write_on_locked_branch(self):
880
1070
backing = self.get_transport()
881
1071
request = smart.branch.SmartServerBranchRequestLockWrite(backing)
882
1072
branch = self.make_branch('.')
1073
branch_token = branch.lock_write()
884
1074
branch.leave_lock_in_place()
886
1076
response = request.execute('')
887
1077
self.assertEqual(
888
1078
SmartServerResponse(('LockContention',)), response)
1080
branch.lock_write(branch_token)
1081
branch.dont_leave_lock_in_place()
890
1084
def test_lock_write_with_tokens_on_locked_branch(self):
891
1085
backing = self.get_transport()
916
1117
branch_token+'xxx', repo_token)
917
1118
self.assertEqual(
918
1119
SmartServerResponse(('TokenMismatch',)), response)
1121
branch.repository.lock_write(repo_token)
1122
branch.repository.dont_leave_lock_in_place()
1123
branch.repository.unlock()
1124
branch.lock_write(branch_token)
1125
branch.dont_leave_lock_in_place()
920
1128
def test_lock_write_on_locked_repo(self):
921
1129
backing = self.get_transport()
922
1130
request = smart.branch.SmartServerBranchRequestLockWrite(backing)
923
1131
branch = self.make_branch('.', format='knit')
924
branch.repository.lock_write()
925
branch.repository.leave_lock_in_place()
926
branch.repository.unlock()
1132
repo = branch.repository
1133
repo_token = repo.lock_write()
1134
repo.leave_lock_in_place()
927
1136
response = request.execute('')
928
1137
self.assertEqual(
929
1138
SmartServerResponse(('LockContention',)), response)
1140
repo.lock_write(repo_token)
1141
repo.dont_leave_lock_in_place()
931
1144
def test_lock_write_on_readonly_transport(self):
932
1145
backing = self.get_readonly_transport()
1087
1304
request.execute('', 'missingrevision'))
1307
class TestSmartServerRepositoryGetRevIdForRevno(tests.TestCaseWithMemoryTransport):
1309
def test_revno_found(self):
1310
backing = self.get_transport()
1311
request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
1312
tree = self.make_branch_and_memory_tree('.')
1315
rev1_id_utf8 = u'\xc8'.encode('utf-8')
1316
rev2_id_utf8 = u'\xc9'.encode('utf-8')
1317
tree.commit('1st commit', rev_id=rev1_id_utf8)
1318
tree.commit('2nd commit', rev_id=rev2_id_utf8)
1321
self.assertEqual(SmartServerResponse(('ok', rev1_id_utf8)),
1322
request.execute('', 1, (2, rev2_id_utf8)))
1324
def test_known_revid_missing(self):
1325
backing = self.get_transport()
1326
request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
1327
repo = self.make_repository('.')
1329
FailedSmartServerResponse(('nosuchrevision', 'ghost')),
1330
request.execute('', 1, (2, 'ghost')))
1332
def test_history_incomplete(self):
1333
backing = self.get_transport()
1334
request = smart.repository.SmartServerRepositoryGetRevIdForRevno(backing)
1335
parent = self.make_branch_and_memory_tree('parent', format='1.9')
1337
parent.add([''], ['TREE_ROOT'])
1338
r1 = parent.commit(message='first commit')
1339
r2 = parent.commit(message='second commit')
1341
local = self.make_branch_and_memory_tree('local', format='1.9')
1342
local.branch.pull(parent.branch)
1343
local.set_parent_ids([r2])
1344
r3 = local.commit(message='local commit')
1345
local.branch.create_clone_on_transport(
1346
self.get_transport('stacked'), stacked_on=self.get_url('parent'))
1348
SmartServerResponse(('history-incomplete', 2, r2)),
1349
request.execute('stacked', 1, (3, r3)))
1090
1352
class TestSmartServerRepositoryGetStream(tests.TestCaseWithMemoryTransport):
1092
1354
def make_two_commit_repo(self):
1243
1505
new_repo = repository.bzrdir.open_repository()
1244
1506
self.assertRaises(errors.LockContention, new_repo.lock_write)
1508
request = smart.repository.SmartServerRepositoryUnlock(backing)
1509
response = request.execute('', nonce)
1246
1511
def test_lock_write_on_locked_repo(self):
1247
1512
backing = self.get_transport()
1248
1513
request = smart.repository.SmartServerRepositoryLockWrite(backing)
1249
1514
repository = self.make_repository('.', format='knit')
1250
repository.lock_write()
1515
repo_token = repository.lock_write()
1251
1516
repository.leave_lock_in_place()
1252
1517
repository.unlock()
1253
1518
response = request.execute('')
1254
1519
self.assertEqual(
1255
1520
SmartServerResponse(('LockContention',)), response)
1522
repository.lock_write(repo_token)
1523
repository.dont_leave_lock_in_place()
1257
1526
def test_lock_write_on_readonly_transport(self):
1258
1527
backing = self.get_readonly_transport()