106
109
self.transport_server = self.make_transport_server
108
111
def make_transport_server(self):
109
return test_server.SmartTCPServer_for_testing('-' + self.id())
112
return smart.server.SmartTCPServer_for_testing('-' + self.id())
111
114
def get_smart_medium(self):
112
115
"""Get a smart medium to use in tests."""
113
116
return self.get_transport().get_smart_medium()
116
class TestByteStreamToStream(tests.TestCase):
118
def test_repeated_substreams_same_kind_are_one_stream(self):
119
# Make a stream - an iterable of bytestrings.
120
stream = [('text', [versionedfile.FulltextContentFactory(('k1',), None,
121
None, 'foo')]),('text', [
122
versionedfile.FulltextContentFactory(('k2',), None, None, 'bar')])]
123
fmt = bzrdir.format_registry.get('pack-0.92')().repository_format
124
bytes = smart_repo._stream_to_byte_stream(stream, fmt)
126
# Iterate the resulting iterable; checking that we get only one stream
128
fmt, stream = smart_repo._byte_stream_to_stream(bytes)
129
for kind, substream in stream:
130
streams.append((kind, list(substream)))
131
self.assertLength(1, streams)
132
self.assertLength(2, streams[0][1])
135
119
class TestSmartServerResponse(tests.TestCase):
137
121
def test__eq__(self):
138
self.assertEqual(smart_req.SmartServerResponse(('ok', )),
139
smart_req.SmartServerResponse(('ok', )))
140
self.assertEqual(smart_req.SmartServerResponse(('ok', ), 'body'),
141
smart_req.SmartServerResponse(('ok', ), 'body'))
142
self.assertNotEqual(smart_req.SmartServerResponse(('ok', )),
143
smart_req.SmartServerResponse(('notok', )))
144
self.assertNotEqual(smart_req.SmartServerResponse(('ok', ), 'body'),
145
smart_req.SmartServerResponse(('ok', )))
122
self.assertEqual(SmartServerResponse(('ok', )),
123
SmartServerResponse(('ok', )))
124
self.assertEqual(SmartServerResponse(('ok', ), 'body'),
125
SmartServerResponse(('ok', ), 'body'))
126
self.assertNotEqual(SmartServerResponse(('ok', )),
127
SmartServerResponse(('notok', )))
128
self.assertNotEqual(SmartServerResponse(('ok', ), 'body'),
129
SmartServerResponse(('ok', )))
146
130
self.assertNotEqual(None,
147
smart_req.SmartServerResponse(('ok', )))
131
SmartServerResponse(('ok', )))
149
133
def test__str__(self):
150
134
"""SmartServerResponses can be stringified."""
151
135
self.assertEqual(
152
136
"<SuccessfulSmartServerResponse args=('args',) body='body'>",
153
str(smart_req.SuccessfulSmartServerResponse(('args',), 'body')))
137
str(SuccessfulSmartServerResponse(('args',), 'body')))
154
138
self.assertEqual(
155
139
"<FailedSmartServerResponse args=('args',) body='body'>",
156
str(smart_req.FailedSmartServerResponse(('args',), 'body')))
140
str(FailedSmartServerResponse(('args',), 'body')))
159
143
class TestSmartServerRequest(tests.TestCaseWithMemoryTransport):
161
145
def test_translate_client_path(self):
162
146
transport = self.get_transport()
163
request = smart_req.SmartServerRequest(transport, 'foo/')
147
request = SmartServerRequest(transport, 'foo/')
164
148
self.assertEqual('./', request.translate_client_path('foo/'))
165
149
self.assertRaises(
166
150
errors.InvalidURLJoin, request.translate_client_path, 'foo/..')
169
153
self.assertRaises(
170
154
errors.PathNotChild, request.translate_client_path, 'bar/')
171
155
self.assertEqual('./baz', request.translate_client_path('foo/baz'))
172
e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'.encode('utf-8')
173
self.assertEqual('./' + urlutils.escape(e_acute),
174
request.translate_client_path('foo/' + e_acute))
176
def test_translate_client_path_vfs(self):
177
"""VfsRequests receive escaped paths rather than raw UTF-8."""
178
transport = self.get_transport()
179
request = vfs.VfsRequest(transport, 'foo/')
180
e_acute = u'\N{LATIN SMALL LETTER E WITH ACUTE}'.encode('utf-8')
181
escaped = urlutils.escape('foo/' + e_acute)
182
self.assertEqual('./' + urlutils.escape(e_acute),
183
request.translate_client_path(escaped))
185
157
def test_transport_from_client_path(self):
186
158
transport = self.get_transport()
187
request = smart_req.SmartServerRequest(transport, 'foo/')
159
request = SmartServerRequest(transport, 'foo/')
188
160
self.assertEqual(
190
162
request.transport_from_client_path('foo/').base)
193
class TestSmartServerBzrDirRequestCloningMetaDir(
194
tests.TestCaseWithMemoryTransport):
195
"""Tests for BzrDir.cloning_metadir."""
197
def test_cloning_metadir(self):
198
"""When there is a bzrdir present, the call succeeds."""
199
backing = self.get_transport()
200
dir = self.make_bzrdir('.')
201
local_result = dir.cloning_metadir()
202
request_class = smart_dir.SmartServerBzrDirRequestCloningMetaDir
203
request = request_class(backing)
204
expected = smart_req.SuccessfulSmartServerResponse(
205
(local_result.network_name(),
206
local_result.repository_format.network_name(),
207
('branch', local_result.get_branch_format().network_name())))
208
self.assertEqual(expected, request.execute('', 'False'))
210
def test_cloning_metadir_reference(self):
211
"""The request fails when bzrdir contains a branch reference."""
212
backing = self.get_transport()
213
referenced_branch = self.make_branch('referenced')
214
dir = self.make_bzrdir('.')
215
local_result = dir.cloning_metadir()
216
reference = _mod_branch.BranchReferenceFormat().initialize(
217
dir, target_branch=referenced_branch)
218
reference_url = _mod_branch.BranchReferenceFormat().get_reference(dir)
219
# The server shouldn't try to follow the branch reference, so it's fine
220
# if the referenced branch isn't reachable.
221
backing.rename('referenced', 'moved')
222
request_class = smart_dir.SmartServerBzrDirRequestCloningMetaDir
223
request = request_class(backing)
224
expected = smart_req.FailedSmartServerResponse(('BranchReference',))
225
self.assertEqual(expected, request.execute('', 'False'))
228
165
class TestSmartServerRequestCreateRepository(tests.TestCaseWithMemoryTransport):
229
166
"""Tests for BzrDir.create_repository."""
378
283
def test_missing_dir(self):
379
284
"""Initializing a missing directory should fail like the bzrdir api."""
380
285
backing = self.get_transport()
381
request = smart_dir.SmartServerRequestInitializeBzrDir(backing)
286
request = smart.bzrdir.SmartServerRequestInitializeBzrDir(backing)
382
287
self.assertRaises(errors.NoSuchFile,
383
288
request.execute, 'subdir')
385
290
def test_initialized_dir(self):
386
291
"""Initializing an extant bzrdir should fail like the bzrdir api."""
387
292
backing = self.get_transport()
388
request = smart_dir.SmartServerRequestInitializeBzrDir(backing)
293
request = smart.bzrdir.SmartServerRequestInitializeBzrDir(backing)
389
294
self.make_bzrdir('subdir')
390
295
self.assertRaises(errors.FileExists,
391
296
request.execute, 'subdir')
394
class TestSmartServerRequestBzrDirInitializeEx(
395
tests.TestCaseWithMemoryTransport):
396
"""Basic tests for BzrDir.initialize_ex_1.16 in the smart server.
398
The main unit tests in test_bzrdir exercise the API comprehensively.
401
def test_empty_dir(self):
402
"""Initializing an empty dir should succeed and do it."""
403
backing = self.get_transport()
404
name = self.make_bzrdir('reference')._format.network_name()
405
request = smart_dir.SmartServerRequestBzrDirInitializeEx(backing)
407
smart_req.SmartServerResponse(('', '', '', '', '', '', name,
408
'False', '', '', '')),
409
request.execute(name, '', 'True', 'False', 'False', '', '', '', '',
411
made_dir = bzrdir.BzrDir.open_from_transport(backing)
412
# no branch, tree or repository is expected with the current
414
self.assertRaises(errors.NoWorkingTree, made_dir.open_workingtree)
415
self.assertRaises(errors.NotBranchError, made_dir.open_branch)
416
self.assertRaises(errors.NoRepositoryPresent, made_dir.open_repository)
418
def test_missing_dir(self):
419
"""Initializing a missing directory should fail like the bzrdir api."""
420
backing = self.get_transport()
421
name = self.make_bzrdir('reference')._format.network_name()
422
request = smart_dir.SmartServerRequestBzrDirInitializeEx(backing)
423
self.assertRaises(errors.NoSuchFile, request.execute, name,
424
'subdir/dir', 'False', 'False', 'False', '', '', '', '', 'False')
426
def test_initialized_dir(self):
427
"""Initializing an extant directory should fail like the bzrdir api."""
428
backing = self.get_transport()
429
name = self.make_bzrdir('reference')._format.network_name()
430
request = smart_dir.SmartServerRequestBzrDirInitializeEx(backing)
431
self.make_bzrdir('subdir')
432
self.assertRaises(errors.FileExists, request.execute, name, 'subdir',
433
'False', 'False', 'False', '', '', '', '', 'False')
436
class TestSmartServerRequestOpenBzrDir(tests.TestCaseWithMemoryTransport):
438
def test_no_directory(self):
439
backing = self.get_transport()
440
request = smart_dir.SmartServerRequestOpenBzrDir(backing)
441
self.assertEqual(smart_req.SmartServerResponse(('no', )),
442
request.execute('does-not-exist'))
444
def test_empty_directory(self):
445
backing = self.get_transport()
446
backing.mkdir('empty')
447
request = smart_dir.SmartServerRequestOpenBzrDir(backing)
448
self.assertEqual(smart_req.SmartServerResponse(('no', )),
449
request.execute('empty'))
451
def test_outside_root_client_path(self):
452
backing = self.get_transport()
453
request = smart_dir.SmartServerRequestOpenBzrDir(backing,
454
root_client_path='root')
455
self.assertEqual(smart_req.SmartServerResponse(('no', )),
456
request.execute('not-root'))
459
class TestSmartServerRequestOpenBzrDir_2_1(tests.TestCaseWithMemoryTransport):
461
def test_no_directory(self):
462
backing = self.get_transport()
463
request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing)
464
self.assertEqual(smart_req.SmartServerResponse(('no', )),
465
request.execute('does-not-exist'))
467
def test_empty_directory(self):
468
backing = self.get_transport()
469
backing.mkdir('empty')
470
request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing)
471
self.assertEqual(smart_req.SmartServerResponse(('no', )),
472
request.execute('empty'))
474
def test_present_without_workingtree(self):
475
backing = self.get_transport()
476
request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing)
477
self.make_bzrdir('.')
478
self.assertEqual(smart_req.SmartServerResponse(('yes', 'no')),
481
def test_outside_root_client_path(self):
482
backing = self.get_transport()
483
request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing,
484
root_client_path='root')
485
self.assertEqual(smart_req.SmartServerResponse(('no',)),
486
request.execute('not-root'))
489
class TestSmartServerRequestOpenBzrDir_2_1_disk(TestCaseWithChrootedTransport):
491
def test_present_with_workingtree(self):
492
self.vfs_transport_factory = test_server.LocalURLServer
493
backing = self.get_transport()
494
request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing)
495
bd = self.make_bzrdir('.')
496
bd.create_repository()
498
bd.create_workingtree()
499
self.assertEqual(smart_req.SmartServerResponse(('yes', 'yes')),
503
299
class TestSmartServerRequestOpenBranch(TestCaseWithChrootedTransport):
505
301
def test_no_branch(self):
506
302
"""When there is no branch, ('nobranch', ) is returned."""
507
303
backing = self.get_transport()
508
request = smart_dir.SmartServerRequestOpenBranch(backing)
304
request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
509
305
self.make_bzrdir('.')
510
self.assertEqual(smart_req.SmartServerResponse(('nobranch', )),
306
self.assertEqual(SmartServerResponse(('nobranch', )),
511
307
request.execute(''))
513
309
def test_branch(self):
514
310
"""When there is a branch, 'ok' is returned."""
515
311
backing = self.get_transport()
516
request = smart_dir.SmartServerRequestOpenBranch(backing)
312
request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
517
313
self.make_branch('.')
518
self.assertEqual(smart_req.SmartServerResponse(('ok', '')),
314
self.assertEqual(SmartServerResponse(('ok', '')),
519
315
request.execute(''))
521
317
def test_branch_reference(self):
522
318
"""When there is a branch reference, the reference URL is returned."""
523
self.vfs_transport_factory = test_server.LocalURLServer
524
319
backing = self.get_transport()
525
request = smart_dir.SmartServerRequestOpenBranch(backing)
320
request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
526
321
branch = self.make_branch('branch')
527
322
checkout = branch.create_checkout('reference',lightweight=True)
528
reference_url = _mod_branch.BranchReferenceFormat().get_reference(
323
reference_url = BranchReferenceFormat().get_reference(checkout.bzrdir)
530
324
self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
531
self.assertEqual(smart_req.SmartServerResponse(('ok', reference_url)),
325
self.assertEqual(SmartServerResponse(('ok', reference_url)),
532
326
request.execute('reference'))
534
def test_notification_on_branch_from_repository(self):
535
"""When there is a repository, the error should return details."""
536
backing = self.get_transport()
537
request = smart_dir.SmartServerRequestOpenBranch(backing)
538
repo = self.make_repository('.')
539
self.assertEqual(smart_req.SmartServerResponse(('nobranch',)),
543
class TestSmartServerRequestOpenBranchV2(TestCaseWithChrootedTransport):
545
def test_no_branch(self):
546
"""When there is no branch, ('nobranch', ) is returned."""
547
backing = self.get_transport()
548
self.make_bzrdir('.')
549
request = smart_dir.SmartServerRequestOpenBranchV2(backing)
550
self.assertEqual(smart_req.SmartServerResponse(('nobranch', )),
553
def test_branch(self):
554
"""When there is a branch, 'ok' is returned."""
555
backing = self.get_transport()
556
expected = self.make_branch('.')._format.network_name()
557
request = smart_dir.SmartServerRequestOpenBranchV2(backing)
558
self.assertEqual(smart_req.SuccessfulSmartServerResponse(
559
('branch', expected)),
562
def test_branch_reference(self):
563
"""When there is a branch reference, the reference URL is returned."""
564
self.vfs_transport_factory = test_server.LocalURLServer
565
backing = self.get_transport()
566
request = smart_dir.SmartServerRequestOpenBranchV2(backing)
567
branch = self.make_branch('branch')
568
checkout = branch.create_checkout('reference',lightweight=True)
569
reference_url = _mod_branch.BranchReferenceFormat().get_reference(
571
self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
572
self.assertEqual(smart_req.SuccessfulSmartServerResponse(
573
('ref', reference_url)),
574
request.execute('reference'))
576
def test_stacked_branch(self):
577
"""Opening a stacked branch does not open the stacked-on branch."""
578
trunk = self.make_branch('trunk')
579
feature = self.make_branch('feature')
580
feature.set_stacked_on_url(trunk.base)
582
_mod_branch.Branch.hooks.install_named_hook(
583
'open', opened_branches.append, None)
584
backing = self.get_transport()
585
request = smart_dir.SmartServerRequestOpenBranchV2(backing)
588
response = request.execute('feature')
590
request.teardown_jail()
591
expected_format = feature._format.network_name()
592
self.assertEqual(smart_req.SuccessfulSmartServerResponse(
593
('branch', expected_format)),
595
self.assertLength(1, opened_branches)
597
def test_notification_on_branch_from_repository(self):
598
"""When there is a repository, the error should return details."""
599
backing = self.get_transport()
600
request = smart_dir.SmartServerRequestOpenBranchV2(backing)
601
repo = self.make_repository('.')
602
self.assertEqual(smart_req.SmartServerResponse(('nobranch',)),
606
class TestSmartServerRequestOpenBranchV3(TestCaseWithChrootedTransport):
608
def test_no_branch(self):
609
"""When there is no branch, ('nobranch', ) is returned."""
610
backing = self.get_transport()
611
self.make_bzrdir('.')
612
request = smart_dir.SmartServerRequestOpenBranchV3(backing)
613
self.assertEqual(smart_req.SmartServerResponse(('nobranch',)),
616
def test_branch(self):
617
"""When there is a branch, 'ok' is returned."""
618
backing = self.get_transport()
619
expected = self.make_branch('.')._format.network_name()
620
request = smart_dir.SmartServerRequestOpenBranchV3(backing)
621
self.assertEqual(smart_req.SuccessfulSmartServerResponse(
622
('branch', expected)),
625
def test_branch_reference(self):
626
"""When there is a branch reference, the reference URL is returned."""
627
self.vfs_transport_factory = test_server.LocalURLServer
628
backing = self.get_transport()
629
request = smart_dir.SmartServerRequestOpenBranchV3(backing)
630
branch = self.make_branch('branch')
631
checkout = branch.create_checkout('reference',lightweight=True)
632
reference_url = _mod_branch.BranchReferenceFormat().get_reference(
634
self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
635
self.assertEqual(smart_req.SuccessfulSmartServerResponse(
636
('ref', reference_url)),
637
request.execute('reference'))
639
def test_stacked_branch(self):
640
"""Opening a stacked branch does not open the stacked-on branch."""
641
trunk = self.make_branch('trunk')
642
feature = self.make_branch('feature')
643
feature.set_stacked_on_url(trunk.base)
645
_mod_branch.Branch.hooks.install_named_hook(
646
'open', opened_branches.append, None)
647
backing = self.get_transport()
648
request = smart_dir.SmartServerRequestOpenBranchV3(backing)
651
response = request.execute('feature')
653
request.teardown_jail()
654
expected_format = feature._format.network_name()
655
self.assertEqual(smart_req.SuccessfulSmartServerResponse(
656
('branch', expected_format)),
658
self.assertLength(1, opened_branches)
660
def test_notification_on_branch_from_repository(self):
661
"""When there is a repository, the error should return details."""
662
backing = self.get_transport()
663
request = smart_dir.SmartServerRequestOpenBranchV3(backing)
664
repo = self.make_repository('.')
665
self.assertEqual(smart_req.SmartServerResponse(
666
('nobranch', 'location is a repository')),
670
329
class TestSmartServerRequestRevisionHistory(tests.TestCaseWithMemoryTransport):
672
331
def test_empty(self):
673
332
"""For an empty branch, the body is empty."""
674
333
backing = self.get_transport()
675
request = smart_branch.SmartServerRequestRevisionHistory(backing)
334
request = smart.branch.SmartServerRequestRevisionHistory(backing)
676
335
self.make_branch('.')
677
self.assertEqual(smart_req.SmartServerResponse(('ok', ), ''),
336
self.assertEqual(SmartServerResponse(('ok', ), ''),
678
337
request.execute(''))
680
339
def test_not_empty(self):
681
340
"""For a non-empty branch, the body is empty."""
682
341
backing = self.get_transport()
683
request = smart_branch.SmartServerRequestRevisionHistory(backing)
342
request = smart.branch.SmartServerRequestRevisionHistory(backing)
684
343
tree = self.make_branch_and_memory_tree('.')
685
344
tree.lock_write()
757
414
# branch.control_files.get('branch.conf') for now - in the future it may
758
415
# perform more complex processing.
759
416
backing = self.get_transport()
760
request = smart_branch.SmartServerBranchGetConfigFile(backing)
417
request = smart.branch.SmartServerBranchGetConfigFile(backing)
761
418
branch = self.make_branch('.')
762
419
branch._transport.put_bytes('branch.conf', 'foo bar baz')
763
self.assertEqual(smart_req.SmartServerResponse(('ok', ), 'foo bar baz'),
420
self.assertEqual(SmartServerResponse(('ok', ), 'foo bar baz'),
764
421
request.execute(''))
767
class TestLockedBranch(tests.TestCaseWithMemoryTransport):
769
def get_lock_tokens(self, branch):
770
branch_token = branch.lock_write()
771
repo_token = branch.repository.lock_write()
772
branch.repository.unlock()
773
return branch_token, repo_token
776
class TestSmartServerBranchRequestSetConfigOption(TestLockedBranch):
778
def test_value_name(self):
779
branch = self.make_branch('.')
780
request = smart_branch.SmartServerBranchRequestSetConfigOption(
781
branch.bzrdir.root_transport)
782
branch_token, repo_token = self.get_lock_tokens(branch)
783
config = branch._get_config()
784
result = request.execute('', branch_token, repo_token, 'bar', 'foo',
786
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
787
self.assertEqual('bar', config.get_option('foo'))
791
def test_value_name_section(self):
792
branch = self.make_branch('.')
793
request = smart_branch.SmartServerBranchRequestSetConfigOption(
794
branch.bzrdir.root_transport)
795
branch_token, repo_token = self.get_lock_tokens(branch)
796
config = branch._get_config()
797
result = request.execute('', branch_token, repo_token, 'bar', 'foo',
799
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
800
self.assertEqual('bar', config.get_option('foo', 'gam'))
805
class TestSmartServerBranchRequestSetTagsBytes(TestLockedBranch):
806
# Only called when the branch format and tags match [yay factory
807
# methods] so only need to test straight forward cases.
809
def test_set_bytes(self):
810
base_branch = self.make_branch('base')
811
tag_bytes = base_branch._get_tags_bytes()
812
# get_lock_tokens takes out a lock.
813
branch_token, repo_token = self.get_lock_tokens(base_branch)
814
request = smart_branch.SmartServerBranchSetTagsBytes(
815
self.get_transport())
816
response = request.execute('base', branch_token, repo_token)
817
self.assertEqual(None, response)
818
response = request.do_chunk(tag_bytes)
819
self.assertEqual(None, response)
820
response = request.do_end()
822
smart_req.SuccessfulSmartServerResponse(()), response)
825
def test_lock_failed(self):
826
base_branch = self.make_branch('base')
827
base_branch.lock_write()
828
tag_bytes = base_branch._get_tags_bytes()
829
request = smart_branch.SmartServerBranchSetTagsBytes(
830
self.get_transport())
831
self.assertRaises(errors.TokenMismatch, request.execute,
832
'base', 'wrong token', 'wrong token')
833
# The request handler will keep processing the message parts, so even
834
# if the request fails immediately do_chunk and do_end are still
836
request.do_chunk(tag_bytes)
842
class SetLastRevisionTestBase(TestLockedBranch):
424
class SetLastRevisionTestBase(tests.TestCaseWithMemoryTransport):
843
425
"""Base test case for verbs that implement set_last_revision."""
1047
632
response = self.request.execute(
1048
633
'', branch_token, repo_token, 'child-1', 1, 0)
1049
634
self.assertEqual(
1050
smart_req.SuccessfulSmartServerResponse(('ok', 2, 'child-1')),
635
SuccessfulSmartServerResponse(('ok', 2, 'child-1')),
1052
637
self.unlock_branch()
1053
638
# The branch tip was changed.
1054
639
self.assertEqual('child-1', self.tree.branch.last_revision())
1057
class TestSmartServerBranchRequestGetParent(tests.TestCaseWithMemoryTransport):
1059
def test_get_parent_none(self):
1060
base_branch = self.make_branch('base')
1061
request = smart_branch.SmartServerBranchGetParent(self.get_transport())
1062
response = request.execute('base')
1064
smart_req.SuccessfulSmartServerResponse(('',)), response)
1066
def test_get_parent_something(self):
1067
base_branch = self.make_branch('base')
1068
base_branch.set_parent(self.get_url('foo'))
1069
request = smart_branch.SmartServerBranchGetParent(self.get_transport())
1070
response = request.execute('base')
1072
smart_req.SuccessfulSmartServerResponse(("../foo",)),
1076
class TestSmartServerBranchRequestSetParent(tests.TestCaseWithMemoryTransport):
1078
def test_set_parent_none(self):
1079
branch = self.make_branch('base', format="1.9")
1081
branch._set_parent_location('foo')
1083
request = smart_branch.SmartServerBranchRequestSetParentLocation(
1084
self.get_transport())
1085
branch_token = branch.lock_write()
1086
repo_token = branch.repository.lock_write()
1088
response = request.execute('base', branch_token, repo_token, '')
1090
branch.repository.unlock()
1092
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
1093
self.assertEqual(None, branch.get_parent())
1095
def test_set_parent_something(self):
1096
branch = self.make_branch('base', format="1.9")
1097
request = smart_branch.SmartServerBranchRequestSetParentLocation(
1098
self.get_transport())
1099
branch_token = branch.lock_write()
1100
repo_token = branch.repository.lock_write()
1102
response = request.execute('base', branch_token, repo_token,
1105
branch.repository.unlock()
1107
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
1108
self.assertEqual('http://bar/', branch.get_parent())
1111
class TestSmartServerBranchRequestGetTagsBytes(
1112
tests.TestCaseWithMemoryTransport):
1113
# Only called when the branch format and tags match [yay factory
1114
# methods] so only need to test straight forward cases.
1116
def test_get_bytes(self):
1117
base_branch = self.make_branch('base')
1118
request = smart_branch.SmartServerBranchGetTagsBytes(
1119
self.get_transport())
1120
response = request.execute('base')
1122
smart_req.SuccessfulSmartServerResponse(('',)), response)
1125
642
class TestSmartServerBranchRequestGetStackedOnURL(tests.TestCaseWithMemoryTransport):
1127
644
def test_get_stacked_on_url(self):
1398
871
# Note that it still returns body (of zero bytes).
1399
self.assertEqual(smart_req.SmartServerResponse(
1400
('nosuchrevision', 'missingrevision', ), ''),
1401
request.execute('', 'missingrevision'))
1404
class TestSmartServerRepositoryGetRevIdForRevno(
1405
tests.TestCaseWithMemoryTransport):
1407
def test_revno_found(self):
1408
backing = self.get_transport()
1409
request = smart_repo.SmartServerRepositoryGetRevIdForRevno(backing)
1410
tree = self.make_branch_and_memory_tree('.')
1413
rev1_id_utf8 = u'\xc8'.encode('utf-8')
1414
rev2_id_utf8 = u'\xc9'.encode('utf-8')
1415
tree.commit('1st commit', rev_id=rev1_id_utf8)
1416
tree.commit('2nd commit', rev_id=rev2_id_utf8)
1419
self.assertEqual(smart_req.SmartServerResponse(('ok', rev1_id_utf8)),
1420
request.execute('', 1, (2, rev2_id_utf8)))
1422
def test_known_revid_missing(self):
1423
backing = self.get_transport()
1424
request = smart_repo.SmartServerRepositoryGetRevIdForRevno(backing)
1425
repo = self.make_repository('.')
1427
smart_req.FailedSmartServerResponse(('nosuchrevision', 'ghost')),
1428
request.execute('', 1, (2, 'ghost')))
1430
def test_history_incomplete(self):
1431
backing = self.get_transport()
1432
request = smart_repo.SmartServerRepositoryGetRevIdForRevno(backing)
1433
parent = self.make_branch_and_memory_tree('parent', format='1.9')
1435
parent.add([''], ['TREE_ROOT'])
1436
r1 = parent.commit(message='first commit')
1437
r2 = parent.commit(message='second commit')
1439
local = self.make_branch_and_memory_tree('local', format='1.9')
1440
local.branch.pull(parent.branch)
1441
local.set_parent_ids([r2])
1442
r3 = local.commit(message='local commit')
1443
local.branch.create_clone_on_transport(
1444
self.get_transport('stacked'), stacked_on=self.get_url('parent'))
1446
smart_req.SmartServerResponse(('history-incomplete', 2, r2)),
1447
request.execute('stacked', 1, (3, r3)))
1450
class TestSmartServerRepositoryGetStream(tests.TestCaseWithMemoryTransport):
1452
def make_two_commit_repo(self):
1453
tree = self.make_branch_and_memory_tree('.')
1456
r1 = tree.commit('1st commit')
1457
r2 = tree.commit('2nd commit', rev_id=u'\xc8'.encode('utf-8'))
1459
repo = tree.branch.repository
1462
def test_ancestry_of(self):
1463
"""The search argument may be a 'ancestry-of' some heads'."""
1464
backing = self.get_transport()
1465
request = smart_repo.SmartServerRepositoryGetStream(backing)
1466
repo, r1, r2 = self.make_two_commit_repo()
1467
fetch_spec = ['ancestry-of', r2]
1468
lines = '\n'.join(fetch_spec)
1469
request.execute('', repo._format.network_name())
1470
response = request.do_body(lines)
1471
self.assertEqual(('ok',), response.args)
1472
stream_bytes = ''.join(response.body_stream)
1473
self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
1475
def test_search(self):
1476
"""The search argument may be a 'search' of some explicit keys."""
1477
backing = self.get_transport()
1478
request = smart_repo.SmartServerRepositoryGetStream(backing)
1479
repo, r1, r2 = self.make_two_commit_repo()
1480
fetch_spec = ['search', '%s %s' % (r1, r2), 'null:', '2']
1481
lines = '\n'.join(fetch_spec)
1482
request.execute('', repo._format.network_name())
1483
response = request.do_body(lines)
1484
self.assertEqual(('ok',), response.args)
1485
stream_bytes = ''.join(response.body_stream)
1486
self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
873
SmartServerResponse(('nosuchrevision', 'missingrevision', ), ''),
874
request.execute('', 'missingrevision'))
1489
877
class TestSmartServerRequestHasRevision(tests.TestCaseWithMemoryTransport):
1575
963
def test_is_shared(self):
1576
964
"""For a shared repository, ('yes', ) is returned."""
1577
965
backing = self.get_transport()
1578
request = smart_repo.SmartServerRepositoryIsShared(backing)
966
request = smart.repository.SmartServerRepositoryIsShared(backing)
1579
967
self.make_repository('.', shared=True)
1580
self.assertEqual(smart_req.SmartServerResponse(('yes', )),
968
self.assertEqual(SmartServerResponse(('yes', )),
1581
969
request.execute('', ))
1583
971
def test_is_not_shared(self):
1584
972
"""For a shared repository, ('no', ) is returned."""
1585
973
backing = self.get_transport()
1586
request = smart_repo.SmartServerRepositoryIsShared(backing)
974
request = smart.repository.SmartServerRepositoryIsShared(backing)
1587
975
self.make_repository('.', shared=False)
1588
self.assertEqual(smart_req.SmartServerResponse(('no', )),
976
self.assertEqual(SmartServerResponse(('no', )),
1589
977
request.execute('', ))
1592
980
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
983
tests.TestCaseWithMemoryTransport.setUp(self)
1594
985
def test_lock_write_on_unlocked_repo(self):
1595
986
backing = self.get_transport()
1596
request = smart_repo.SmartServerRepositoryLockWrite(backing)
987
request = smart.repository.SmartServerRepositoryLockWrite(backing)
1597
988
repository = self.make_repository('.', format='knit')
1598
989
response = request.execute('')
1599
990
nonce = repository.control_files._lock.peek().get('nonce')
1600
self.assertEqual(smart_req.SmartServerResponse(('ok', nonce)), response)
991
self.assertEqual(SmartServerResponse(('ok', nonce)), response)
1601
992
# The repository is now locked. Verify that with a new repository
1603
994
new_repo = repository.bzrdir.open_repository()
1604
995
self.assertRaises(errors.LockContention, new_repo.lock_write)
1606
request = smart_repo.SmartServerRepositoryUnlock(backing)
1607
response = request.execute('', nonce)
1609
997
def test_lock_write_on_locked_repo(self):
1610
998
backing = self.get_transport()
1611
request = smart_repo.SmartServerRepositoryLockWrite(backing)
999
request = smart.repository.SmartServerRepositoryLockWrite(backing)
1612
1000
repository = self.make_repository('.', format='knit')
1613
repo_token = repository.lock_write()
1001
repository.lock_write()
1614
1002
repository.leave_lock_in_place()
1615
1003
repository.unlock()
1616
1004
response = request.execute('')
1617
1005
self.assertEqual(
1618
smart_req.SmartServerResponse(('LockContention',)), response)
1620
repository.lock_write(repo_token)
1621
repository.dont_leave_lock_in_place()
1006
SmartServerResponse(('LockContention',)), response)
1624
1008
def test_lock_write_on_readonly_transport(self):
1625
1009
backing = self.get_readonly_transport()
1626
request = smart_repo.SmartServerRepositoryLockWrite(backing)
1010
request = smart.repository.SmartServerRepositoryLockWrite(backing)
1627
1011
repository = self.make_repository('.', format='knit')
1628
1012
response = request.execute('')
1629
1013
self.assertFalse(response.is_successful())
1630
1014
self.assertEqual('LockFailed', response.args[0])
1633
class TestInsertStreamBase(tests.TestCaseWithMemoryTransport):
1635
def make_empty_byte_stream(self, repo):
1636
byte_stream = smart_repo._stream_to_byte_stream([], repo._format)
1637
return ''.join(byte_stream)
1640
class TestSmartServerRepositoryInsertStream(TestInsertStreamBase):
1642
def test_insert_stream_empty(self):
1643
backing = self.get_transport()
1644
request = smart_repo.SmartServerRepositoryInsertStream(backing)
1645
repository = self.make_repository('.')
1646
response = request.execute('', '')
1647
self.assertEqual(None, response)
1648
response = request.do_chunk(self.make_empty_byte_stream(repository))
1649
self.assertEqual(None, response)
1650
response = request.do_end()
1651
self.assertEqual(smart_req.SmartServerResponse(('ok', )), response)
1654
class TestSmartServerRepositoryInsertStreamLocked(TestInsertStreamBase):
1656
def test_insert_stream_empty(self):
1657
backing = self.get_transport()
1658
request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1660
repository = self.make_repository('.', format='knit')
1661
lock_token = repository.lock_write()
1662
response = request.execute('', '', lock_token)
1663
self.assertEqual(None, response)
1664
response = request.do_chunk(self.make_empty_byte_stream(repository))
1665
self.assertEqual(None, response)
1666
response = request.do_end()
1667
self.assertEqual(smart_req.SmartServerResponse(('ok', )), response)
1670
def test_insert_stream_with_wrong_lock_token(self):
1671
backing = self.get_transport()
1672
request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1674
repository = self.make_repository('.', format='knit')
1675
lock_token = repository.lock_write()
1677
errors.TokenMismatch, request.execute, '', '', 'wrong-token')
1681
1017
class TestSmartServerRepositoryUnlock(tests.TestCaseWithMemoryTransport):
1683
1019
def setUp(self):
1822
1140
"""All registered request_handlers can be found."""
1823
1141
# If there's a typo in a register_lazy call, this loop will fail with
1824
1142
# an AttributeError.
1825
for key, item in smart_req.request_handlers.iteritems():
1143
for key, item in smart.request.request_handlers.iteritems():
1828
def assertHandlerEqual(self, verb, handler):
1829
self.assertEqual(smart_req.request_handlers.get(verb), handler)
1831
1146
def test_registered_methods(self):
1832
1147
"""Test that known methods are registered to the correct object."""
1833
self.assertHandlerEqual('Branch.get_config_file',
1834
smart_branch.SmartServerBranchGetConfigFile)
1835
self.assertHandlerEqual('Branch.get_parent',
1836
smart_branch.SmartServerBranchGetParent)
1837
self.assertHandlerEqual('Branch.get_tags_bytes',
1838
smart_branch.SmartServerBranchGetTagsBytes)
1839
self.assertHandlerEqual('Branch.lock_write',
1840
smart_branch.SmartServerBranchRequestLockWrite)
1841
self.assertHandlerEqual('Branch.last_revision_info',
1842
smart_branch.SmartServerBranchRequestLastRevisionInfo)
1843
self.assertHandlerEqual('Branch.revision_history',
1844
smart_branch.SmartServerRequestRevisionHistory)
1845
self.assertHandlerEqual('Branch.set_config_option',
1846
smart_branch.SmartServerBranchRequestSetConfigOption)
1847
self.assertHandlerEqual('Branch.set_last_revision',
1848
smart_branch.SmartServerBranchRequestSetLastRevision)
1849
self.assertHandlerEqual('Branch.set_last_revision_info',
1850
smart_branch.SmartServerBranchRequestSetLastRevisionInfo)
1851
self.assertHandlerEqual('Branch.set_last_revision_ex',
1852
smart_branch.SmartServerBranchRequestSetLastRevisionEx)
1853
self.assertHandlerEqual('Branch.set_parent_location',
1854
smart_branch.SmartServerBranchRequestSetParentLocation)
1855
self.assertHandlerEqual('Branch.unlock',
1856
smart_branch.SmartServerBranchRequestUnlock)
1857
self.assertHandlerEqual('BzrDir.find_repository',
1858
smart_dir.SmartServerRequestFindRepositoryV1)
1859
self.assertHandlerEqual('BzrDir.find_repositoryV2',
1860
smart_dir.SmartServerRequestFindRepositoryV2)
1861
self.assertHandlerEqual('BzrDirFormat.initialize',
1862
smart_dir.SmartServerRequestInitializeBzrDir)
1863
self.assertHandlerEqual('BzrDirFormat.initialize_ex_1.16',
1864
smart_dir.SmartServerRequestBzrDirInitializeEx)
1865
self.assertHandlerEqual('BzrDir.cloning_metadir',
1866
smart_dir.SmartServerBzrDirRequestCloningMetaDir)
1867
self.assertHandlerEqual('BzrDir.get_config_file',
1868
smart_dir.SmartServerBzrDirRequestConfigFile)
1869
self.assertHandlerEqual('BzrDir.open_branch',
1870
smart_dir.SmartServerRequestOpenBranch)
1871
self.assertHandlerEqual('BzrDir.open_branchV2',
1872
smart_dir.SmartServerRequestOpenBranchV2)
1873
self.assertHandlerEqual('BzrDir.open_branchV3',
1874
smart_dir.SmartServerRequestOpenBranchV3)
1875
self.assertHandlerEqual('PackRepository.autopack',
1876
smart_packrepo.SmartServerPackRepositoryAutopack)
1877
self.assertHandlerEqual('Repository.gather_stats',
1878
smart_repo.SmartServerRepositoryGatherStats)
1879
self.assertHandlerEqual('Repository.get_parent_map',
1880
smart_repo.SmartServerRepositoryGetParentMap)
1881
self.assertHandlerEqual('Repository.get_rev_id_for_revno',
1882
smart_repo.SmartServerRepositoryGetRevIdForRevno)
1883
self.assertHandlerEqual('Repository.get_revision_graph',
1884
smart_repo.SmartServerRepositoryGetRevisionGraph)
1885
self.assertHandlerEqual('Repository.get_stream',
1886
smart_repo.SmartServerRepositoryGetStream)
1887
self.assertHandlerEqual('Repository.has_revision',
1888
smart_repo.SmartServerRequestHasRevision)
1889
self.assertHandlerEqual('Repository.insert_stream',
1890
smart_repo.SmartServerRepositoryInsertStream)
1891
self.assertHandlerEqual('Repository.insert_stream_locked',
1892
smart_repo.SmartServerRepositoryInsertStreamLocked)
1893
self.assertHandlerEqual('Repository.is_shared',
1894
smart_repo.SmartServerRepositoryIsShared)
1895
self.assertHandlerEqual('Repository.lock_write',
1896
smart_repo.SmartServerRepositoryLockWrite)
1897
self.assertHandlerEqual('Repository.tarball',
1898
smart_repo.SmartServerRepositoryTarball)
1899
self.assertHandlerEqual('Repository.unlock',
1900
smart_repo.SmartServerRepositoryUnlock)
1901
self.assertHandlerEqual('Transport.is_readonly',
1902
smart_req.SmartServerIsReadonly)
1149
smart.request.request_handlers.get('Branch.get_config_file'),
1150
smart.branch.SmartServerBranchGetConfigFile)
1152
smart.request.request_handlers.get('Branch.lock_write'),
1153
smart.branch.SmartServerBranchRequestLockWrite)
1155
smart.request.request_handlers.get('Branch.last_revision_info'),
1156
smart.branch.SmartServerBranchRequestLastRevisionInfo)
1158
smart.request.request_handlers.get('Branch.revision_history'),
1159
smart.branch.SmartServerRequestRevisionHistory)
1161
smart.request.request_handlers.get('Branch.set_last_revision'),
1162
smart.branch.SmartServerBranchRequestSetLastRevision)
1164
smart.request.request_handlers.get('Branch.set_last_revision_info'),
1165
smart.branch.SmartServerBranchRequestSetLastRevisionInfo)
1167
smart.request.request_handlers.get('Branch.unlock'),
1168
smart.branch.SmartServerBranchRequestUnlock)
1170
smart.request.request_handlers.get('BzrDir.find_repository'),
1171
smart.bzrdir.SmartServerRequestFindRepositoryV1)
1173
smart.request.request_handlers.get('BzrDir.find_repositoryV2'),
1174
smart.bzrdir.SmartServerRequestFindRepositoryV2)
1176
smart.request.request_handlers.get('BzrDirFormat.initialize'),
1177
smart.bzrdir.SmartServerRequestInitializeBzrDir)
1179
smart.request.request_handlers.get('BzrDir.open_branch'),
1180
smart.bzrdir.SmartServerRequestOpenBranch)
1182
smart.request.request_handlers.get('PackRepository.autopack'),
1183
smart.packrepository.SmartServerPackRepositoryAutopack)
1185
smart.request.request_handlers.get('Repository.gather_stats'),
1186
smart.repository.SmartServerRepositoryGatherStats)
1188
smart.request.request_handlers.get('Repository.get_parent_map'),
1189
smart.repository.SmartServerRepositoryGetParentMap)
1191
smart.request.request_handlers.get(
1192
'Repository.get_revision_graph'),
1193
smart.repository.SmartServerRepositoryGetRevisionGraph)
1195
smart.request.request_handlers.get('Repository.has_revision'),
1196
smart.repository.SmartServerRequestHasRevision)
1198
smart.request.request_handlers.get('Repository.is_shared'),
1199
smart.repository.SmartServerRepositoryIsShared)
1201
smart.request.request_handlers.get('Repository.lock_write'),
1202
smart.repository.SmartServerRepositoryLockWrite)
1204
smart.request.request_handlers.get('Repository.StreamSource.get_stream'),
1205
smart.repository.SmartServerRepositoryStreamSourceGetStream)
1207
smart.request.request_handlers.get('Repository.tarball'),
1208
smart.repository.SmartServerRepositoryTarball)
1210
smart.request.request_handlers.get('Repository.unlock'),
1211
smart.repository.SmartServerRepositoryUnlock)
1213
smart.request.request_handlers.get('Transport.is_readonly'),
1214
smart.request.SmartServerIsReadonly)