28
from cStringIO import StringIO
29
31
from bzrlib import (
30
branch as _mod_branch,
38
from bzrlib.smart import (
39
branch as smart_branch,
41
repository as smart_repo,
42
packrepository as smart_packrepo,
47
from bzrlib.tests import test_server
48
from bzrlib.transport import (
40
from bzrlib.branch import Branch, BranchReferenceFormat
41
import bzrlib.smart.branch
42
import bzrlib.smart.bzrdir, bzrlib.smart.bzrdir as smart_dir
43
import bzrlib.smart.packrepository
44
import bzrlib.smart.repository
45
from bzrlib.smart.request import (
46
FailedSmartServerResponse,
49
SuccessfulSmartServerResponse,
51
from bzrlib.tests import (
54
from bzrlib.transport import chroot, get_transport
54
57
def load_tests(standard_tests, module, loader):
55
58
"""Multiply tests version and protocol consistency."""
56
59
# FindRepository tests.
60
bzrdir_mod = bzrlib.smart.bzrdir
58
62
("find_repository", {
59
"_request_class": smart_dir.SmartServerRequestFindRepositoryV1}),
63
"_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV1}),
60
64
("find_repositoryV2", {
61
"_request_class": smart_dir.SmartServerRequestFindRepositoryV2}),
65
"_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV2}),
62
66
("find_repositoryV3", {
63
"_request_class": smart_dir.SmartServerRequestFindRepositoryV3}),
67
"_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV3}),
65
to_adapt, result = tests.split_suite_by_re(standard_tests,
69
to_adapt, result = split_suite_by_re(standard_tests,
66
70
"TestSmartServerRequestFindRepository")
67
v2_only, v1_and_2 = tests.split_suite_by_re(to_adapt,
71
v2_only, v1_and_2 = split_suite_by_re(to_adapt,
69
73
tests.multiply_tests(v1_and_2, scenarios, result)
70
74
# The first scenario is only applicable to v1 protocols, it is deleted
99
103
# the default or a parameterized class, but rather use the
100
104
# TestCaseWithTransport infrastructure to set up a smart server and
102
self.overrideAttr(self, "transport_server", self.make_transport_server)
106
self.transport_server = self.make_transport_server
104
108
def make_transport_server(self):
105
return test_server.SmartTCPServer_for_testing('-' + self.id())
109
return smart.server.SmartTCPServer_for_testing('-' + self.id())
107
111
def get_smart_medium(self):
108
112
"""Get a smart medium to use in tests."""
109
113
return self.get_transport().get_smart_medium()
112
class TestByteStreamToStream(tests.TestCase):
114
def test_repeated_substreams_same_kind_are_one_stream(self):
115
# Make a stream - an iterable of bytestrings.
116
stream = [('text', [versionedfile.FulltextContentFactory(('k1',), None,
117
None, 'foo')]),('text', [
118
versionedfile.FulltextContentFactory(('k2',), None, None, 'bar')])]
119
fmt = bzrdir.format_registry.get('pack-0.92')().repository_format
120
bytes = smart_repo._stream_to_byte_stream(stream, fmt)
122
# Iterate the resulting iterable; checking that we get only one stream
124
fmt, stream = smart_repo._byte_stream_to_stream(bytes)
125
for kind, substream in stream:
126
streams.append((kind, list(substream)))
127
self.assertLength(1, streams)
128
self.assertLength(2, streams[0][1])
131
116
class TestSmartServerResponse(tests.TestCase):
133
118
def test__eq__(self):
134
self.assertEqual(smart_req.SmartServerResponse(('ok', )),
135
smart_req.SmartServerResponse(('ok', )))
136
self.assertEqual(smart_req.SmartServerResponse(('ok', ), 'body'),
137
smart_req.SmartServerResponse(('ok', ), 'body'))
138
self.assertNotEqual(smart_req.SmartServerResponse(('ok', )),
139
smart_req.SmartServerResponse(('notok', )))
140
self.assertNotEqual(smart_req.SmartServerResponse(('ok', ), 'body'),
141
smart_req.SmartServerResponse(('ok', )))
119
self.assertEqual(SmartServerResponse(('ok', )),
120
SmartServerResponse(('ok', )))
121
self.assertEqual(SmartServerResponse(('ok', ), 'body'),
122
SmartServerResponse(('ok', ), 'body'))
123
self.assertNotEqual(SmartServerResponse(('ok', )),
124
SmartServerResponse(('notok', )))
125
self.assertNotEqual(SmartServerResponse(('ok', ), 'body'),
126
SmartServerResponse(('ok', )))
142
127
self.assertNotEqual(None,
143
smart_req.SmartServerResponse(('ok', )))
128
SmartServerResponse(('ok', )))
145
130
def test__str__(self):
146
131
"""SmartServerResponses can be stringified."""
147
132
self.assertEqual(
148
133
"<SuccessfulSmartServerResponse args=('args',) body='body'>",
149
str(smart_req.SuccessfulSmartServerResponse(('args',), 'body')))
134
str(SuccessfulSmartServerResponse(('args',), 'body')))
150
135
self.assertEqual(
151
136
"<FailedSmartServerResponse args=('args',) body='body'>",
152
str(smart_req.FailedSmartServerResponse(('args',), 'body')))
137
str(FailedSmartServerResponse(('args',), 'body')))
155
140
class TestSmartServerRequest(tests.TestCaseWithMemoryTransport):
157
142
def test_translate_client_path(self):
158
143
transport = self.get_transport()
159
request = smart_req.SmartServerRequest(transport, 'foo/')
144
request = SmartServerRequest(transport, 'foo/')
160
145
self.assertEqual('./', request.translate_client_path('foo/'))
161
146
self.assertRaises(
162
147
errors.InvalidURLJoin, request.translate_client_path, 'foo/..')
423
388
"""Initializing an extant directory should fail like the bzrdir api."""
424
389
backing = self.get_transport()
425
390
name = self.make_bzrdir('reference')._format.network_name()
426
request = smart_dir.SmartServerRequestBzrDirInitializeEx(backing)
391
request = smart.bzrdir.SmartServerRequestBzrDirInitializeEx(backing)
427
392
self.make_bzrdir('subdir')
428
393
self.assertRaises(errors.FileExists, request.execute, name, 'subdir',
429
394
'False', 'False', 'False', '', '', '', '', 'False')
432
class TestSmartServerRequestOpenBzrDir(tests.TestCaseWithMemoryTransport):
434
def test_no_directory(self):
435
backing = self.get_transport()
436
request = smart_dir.SmartServerRequestOpenBzrDir(backing)
437
self.assertEqual(smart_req.SmartServerResponse(('no', )),
438
request.execute('does-not-exist'))
440
def test_empty_directory(self):
441
backing = self.get_transport()
442
backing.mkdir('empty')
443
request = smart_dir.SmartServerRequestOpenBzrDir(backing)
444
self.assertEqual(smart_req.SmartServerResponse(('no', )),
445
request.execute('empty'))
447
def test_outside_root_client_path(self):
448
backing = self.get_transport()
449
request = smart_dir.SmartServerRequestOpenBzrDir(backing,
450
root_client_path='root')
451
self.assertEqual(smart_req.SmartServerResponse(('no', )),
452
request.execute('not-root'))
455
class TestSmartServerRequestOpenBzrDir_2_1(tests.TestCaseWithMemoryTransport):
457
def test_no_directory(self):
458
backing = self.get_transport()
459
request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing)
460
self.assertEqual(smart_req.SmartServerResponse(('no', )),
461
request.execute('does-not-exist'))
463
def test_empty_directory(self):
464
backing = self.get_transport()
465
backing.mkdir('empty')
466
request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing)
467
self.assertEqual(smart_req.SmartServerResponse(('no', )),
468
request.execute('empty'))
470
def test_present_without_workingtree(self):
471
backing = self.get_transport()
472
request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing)
473
self.make_bzrdir('.')
474
self.assertEqual(smart_req.SmartServerResponse(('yes', 'no')),
477
def test_outside_root_client_path(self):
478
backing = self.get_transport()
479
request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing,
480
root_client_path='root')
481
self.assertEqual(smart_req.SmartServerResponse(('no',)),
482
request.execute('not-root'))
485
class TestSmartServerRequestOpenBzrDir_2_1_disk(TestCaseWithChrootedTransport):
487
def test_present_with_workingtree(self):
488
self.vfs_transport_factory = test_server.LocalURLServer
489
backing = self.get_transport()
490
request = smart_dir.SmartServerRequestOpenBzrDir_2_1(backing)
491
bd = self.make_bzrdir('.')
492
bd.create_repository()
494
bd.create_workingtree()
495
self.assertEqual(smart_req.SmartServerResponse(('yes', 'yes')),
499
397
class TestSmartServerRequestOpenBranch(TestCaseWithChrootedTransport):
501
399
def test_no_branch(self):
502
400
"""When there is no branch, ('nobranch', ) is returned."""
503
401
backing = self.get_transport()
504
request = smart_dir.SmartServerRequestOpenBranch(backing)
402
request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
505
403
self.make_bzrdir('.')
506
self.assertEqual(smart_req.SmartServerResponse(('nobranch', )),
404
self.assertEqual(SmartServerResponse(('nobranch', )),
507
405
request.execute(''))
509
407
def test_branch(self):
510
408
"""When there is a branch, 'ok' is returned."""
511
409
backing = self.get_transport()
512
request = smart_dir.SmartServerRequestOpenBranch(backing)
410
request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
513
411
self.make_branch('.')
514
self.assertEqual(smart_req.SmartServerResponse(('ok', '')),
412
self.assertEqual(SmartServerResponse(('ok', '')),
515
413
request.execute(''))
517
415
def test_branch_reference(self):
518
416
"""When there is a branch reference, the reference URL is returned."""
519
self.vfs_transport_factory = test_server.LocalURLServer
520
417
backing = self.get_transport()
521
request = smart_dir.SmartServerRequestOpenBranch(backing)
418
request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
522
419
branch = self.make_branch('branch')
523
420
checkout = branch.create_checkout('reference',lightweight=True)
524
reference_url = _mod_branch.BranchReferenceFormat().get_reference(
421
reference_url = BranchReferenceFormat().get_reference(checkout.bzrdir)
526
422
self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
527
self.assertEqual(smart_req.SmartServerResponse(('ok', reference_url)),
423
self.assertEqual(SmartServerResponse(('ok', reference_url)),
528
424
request.execute('reference'))
530
def test_notification_on_branch_from_repository(self):
531
"""When there is a repository, the error should return details."""
532
backing = self.get_transport()
533
request = smart_dir.SmartServerRequestOpenBranch(backing)
534
repo = self.make_repository('.')
535
self.assertEqual(smart_req.SmartServerResponse(('nobranch',)),
539
427
class TestSmartServerRequestOpenBranchV2(TestCaseWithChrootedTransport):
542
430
"""When there is no branch, ('nobranch', ) is returned."""
543
431
backing = self.get_transport()
544
432
self.make_bzrdir('.')
545
request = smart_dir.SmartServerRequestOpenBranchV2(backing)
546
self.assertEqual(smart_req.SmartServerResponse(('nobranch', )),
549
def test_branch(self):
550
"""When there is a branch, 'ok' is returned."""
551
backing = self.get_transport()
552
expected = self.make_branch('.')._format.network_name()
553
request = smart_dir.SmartServerRequestOpenBranchV2(backing)
554
self.assertEqual(smart_req.SuccessfulSmartServerResponse(
555
('branch', expected)),
558
def test_branch_reference(self):
559
"""When there is a branch reference, the reference URL is returned."""
560
self.vfs_transport_factory = test_server.LocalURLServer
561
backing = self.get_transport()
562
request = smart_dir.SmartServerRequestOpenBranchV2(backing)
563
branch = self.make_branch('branch')
564
checkout = branch.create_checkout('reference',lightweight=True)
565
reference_url = _mod_branch.BranchReferenceFormat().get_reference(
567
self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
568
self.assertEqual(smart_req.SuccessfulSmartServerResponse(
569
('ref', reference_url)),
570
request.execute('reference'))
572
def test_stacked_branch(self):
573
"""Opening a stacked branch does not open the stacked-on branch."""
574
trunk = self.make_branch('trunk')
575
feature = self.make_branch('feature')
576
feature.set_stacked_on_url(trunk.base)
578
_mod_branch.Branch.hooks.install_named_hook(
579
'open', opened_branches.append, None)
580
backing = self.get_transport()
581
request = smart_dir.SmartServerRequestOpenBranchV2(backing)
584
response = request.execute('feature')
586
request.teardown_jail()
587
expected_format = feature._format.network_name()
588
self.assertEqual(smart_req.SuccessfulSmartServerResponse(
589
('branch', expected_format)),
591
self.assertLength(1, opened_branches)
593
def test_notification_on_branch_from_repository(self):
594
"""When there is a repository, the error should return details."""
595
backing = self.get_transport()
596
request = smart_dir.SmartServerRequestOpenBranchV2(backing)
597
repo = self.make_repository('.')
598
self.assertEqual(smart_req.SmartServerResponse(('nobranch',)),
602
class TestSmartServerRequestOpenBranchV3(TestCaseWithChrootedTransport):
604
def test_no_branch(self):
605
"""When there is no branch, ('nobranch', ) is returned."""
606
backing = self.get_transport()
607
self.make_bzrdir('.')
608
request = smart_dir.SmartServerRequestOpenBranchV3(backing)
609
self.assertEqual(smart_req.SmartServerResponse(('nobranch',)),
612
def test_branch(self):
613
"""When there is a branch, 'ok' is returned."""
614
backing = self.get_transport()
615
expected = self.make_branch('.')._format.network_name()
616
request = smart_dir.SmartServerRequestOpenBranchV3(backing)
617
self.assertEqual(smart_req.SuccessfulSmartServerResponse(
618
('branch', expected)),
621
def test_branch_reference(self):
622
"""When there is a branch reference, the reference URL is returned."""
623
self.vfs_transport_factory = test_server.LocalURLServer
624
backing = self.get_transport()
625
request = smart_dir.SmartServerRequestOpenBranchV3(backing)
626
branch = self.make_branch('branch')
627
checkout = branch.create_checkout('reference',lightweight=True)
628
reference_url = _mod_branch.BranchReferenceFormat().get_reference(
630
self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
631
self.assertEqual(smart_req.SuccessfulSmartServerResponse(
632
('ref', reference_url)),
633
request.execute('reference'))
635
def test_stacked_branch(self):
636
"""Opening a stacked branch does not open the stacked-on branch."""
637
trunk = self.make_branch('trunk')
638
feature = self.make_branch('feature')
639
feature.set_stacked_on_url(trunk.base)
641
_mod_branch.Branch.hooks.install_named_hook(
642
'open', opened_branches.append, None)
643
backing = self.get_transport()
644
request = smart_dir.SmartServerRequestOpenBranchV3(backing)
647
response = request.execute('feature')
649
request.teardown_jail()
650
expected_format = feature._format.network_name()
651
self.assertEqual(smart_req.SuccessfulSmartServerResponse(
652
('branch', expected_format)),
654
self.assertLength(1, opened_branches)
656
def test_notification_on_branch_from_repository(self):
657
"""When there is a repository, the error should return details."""
658
backing = self.get_transport()
659
request = smart_dir.SmartServerRequestOpenBranchV3(backing)
660
repo = self.make_repository('.')
661
self.assertEqual(smart_req.SmartServerResponse(
662
('nobranch', 'location is a repository')),
433
request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
434
self.assertEqual(SmartServerResponse(('nobranch', )),
437
def test_branch(self):
438
"""When there is a branch, 'ok' is returned."""
439
backing = self.get_transport()
440
expected = self.make_branch('.')._format.network_name()
441
request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
442
self.assertEqual(SuccessfulSmartServerResponse(('branch', expected)),
445
def test_branch_reference(self):
446
"""When there is a branch reference, the reference URL is returned."""
447
backing = self.get_transport()
448
request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
449
branch = self.make_branch('branch')
450
checkout = branch.create_checkout('reference',lightweight=True)
451
reference_url = BranchReferenceFormat().get_reference(checkout.bzrdir)
452
self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
453
self.assertEqual(SuccessfulSmartServerResponse(('ref', reference_url)),
454
request.execute('reference'))
456
def test_stacked_branch(self):
457
"""Opening a stacked branch does not open the stacked-on branch."""
458
trunk = self.make_branch('trunk')
459
feature = self.make_branch('feature')
460
feature.set_stacked_on_url(trunk.base)
462
Branch.hooks.install_named_hook('open', opened_branches.append, None)
463
backing = self.get_transport()
464
request = smart.bzrdir.SmartServerRequestOpenBranchV2(backing)
467
response = request.execute('feature')
469
request.teardown_jail()
470
expected_format = feature._format.network_name()
472
SuccessfulSmartServerResponse(('branch', expected_format)),
474
self.assertLength(1, opened_branches)
666
477
class TestSmartServerRequestRevisionHistory(tests.TestCaseWithMemoryTransport):
774
583
def test_value_name(self):
775
584
branch = self.make_branch('.')
776
request = smart_branch.SmartServerBranchRequestSetConfigOption(
585
request = smart.branch.SmartServerBranchRequestSetConfigOption(
777
586
branch.bzrdir.root_transport)
778
587
branch_token, repo_token = self.get_lock_tokens(branch)
779
588
config = branch._get_config()
780
589
result = request.execute('', branch_token, repo_token, 'bar', 'foo',
782
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
591
self.assertEqual(SuccessfulSmartServerResponse(()), result)
783
592
self.assertEqual('bar', config.get_option('foo'))
787
596
def test_value_name_section(self):
788
597
branch = self.make_branch('.')
789
request = smart_branch.SmartServerBranchRequestSetConfigOption(
598
request = smart.branch.SmartServerBranchRequestSetConfigOption(
790
599
branch.bzrdir.root_transport)
791
600
branch_token, repo_token = self.get_lock_tokens(branch)
792
601
config = branch._get_config()
793
602
result = request.execute('', branch_token, repo_token, 'bar', 'foo',
795
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
604
self.assertEqual(SuccessfulSmartServerResponse(()), result)
796
605
self.assertEqual('bar', config.get_option('foo', 'gam'))
801
class TestSmartServerBranchRequestSetConfigOptionDict(TestLockedBranch):
804
TestLockedBranch.setUp(self)
805
# A dict with non-ascii keys and values to exercise unicode
807
self.encoded_value_dict = (
808
'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde')
810
'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
812
def test_value_name(self):
813
branch = self.make_branch('.')
814
request = smart_branch.SmartServerBranchRequestSetConfigOptionDict(
815
branch.bzrdir.root_transport)
816
branch_token, repo_token = self.get_lock_tokens(branch)
817
config = branch._get_config()
818
result = request.execute('', branch_token, repo_token,
819
self.encoded_value_dict, 'foo', '')
820
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
821
self.assertEqual(self.value_dict, config.get_option('foo'))
825
def test_value_name_section(self):
826
branch = self.make_branch('.')
827
request = smart_branch.SmartServerBranchRequestSetConfigOptionDict(
828
branch.bzrdir.root_transport)
829
branch_token, repo_token = self.get_lock_tokens(branch)
830
config = branch._get_config()
831
result = request.execute('', branch_token, repo_token,
832
self.encoded_value_dict, 'foo', 'gam')
833
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
834
self.assertEqual(self.value_dict, config.get_option('foo', 'gam'))
839
610
class TestSmartServerBranchRequestSetTagsBytes(TestLockedBranch):
840
611
# Only called when the branch format and tags match [yay factory
841
612
# methods] so only need to test straight forward cases.
1093
863
def test_get_parent_none(self):
1094
864
base_branch = self.make_branch('base')
1095
request = smart_branch.SmartServerBranchGetParent(self.get_transport())
865
request = smart.branch.SmartServerBranchGetParent(self.get_transport())
1096
866
response = request.execute('base')
1097
867
self.assertEquals(
1098
smart_req.SuccessfulSmartServerResponse(('',)), response)
868
SuccessfulSmartServerResponse(('',)), response)
1100
870
def test_get_parent_something(self):
1101
871
base_branch = self.make_branch('base')
1102
872
base_branch.set_parent(self.get_url('foo'))
1103
request = smart_branch.SmartServerBranchGetParent(self.get_transport())
873
request = smart.branch.SmartServerBranchGetParent(self.get_transport())
1104
874
response = request.execute('base')
1105
875
self.assertEquals(
1106
smart_req.SuccessfulSmartServerResponse(("../foo",)),
876
SuccessfulSmartServerResponse(("../foo",)),
1110
class TestSmartServerBranchRequestSetParent(TestLockedBranch):
880
class TestSmartServerBranchRequestSetParent(tests.TestCaseWithMemoryTransport):
1112
882
def test_set_parent_none(self):
1113
883
branch = self.make_branch('base', format="1.9")
1114
884
branch.lock_write()
1115
885
branch._set_parent_location('foo')
1117
request = smart_branch.SmartServerBranchRequestSetParentLocation(
887
request = smart.branch.SmartServerBranchRequestSetParentLocation(
1118
888
self.get_transport())
1119
branch_token, repo_token = self.get_lock_tokens(branch)
889
branch_token = branch.lock_write()
890
repo_token = branch.repository.lock_write()
1121
892
response = request.execute('base', branch_token, repo_token, '')
894
branch.repository.unlock()
1124
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
896
self.assertEqual(SuccessfulSmartServerResponse(()), response)
1125
897
self.assertEqual(None, branch.get_parent())
1127
899
def test_set_parent_something(self):
1128
900
branch = self.make_branch('base', format="1.9")
1129
request = smart_branch.SmartServerBranchRequestSetParentLocation(
901
request = smart.branch.SmartServerBranchRequestSetParentLocation(
1130
902
self.get_transport())
1131
branch_token, repo_token = self.get_lock_tokens(branch)
903
branch_token = branch.lock_write()
904
repo_token = branch.repository.lock_write()
1133
906
response = request.execute('base', branch_token, repo_token,
909
branch.repository.unlock()
1137
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
911
self.assertEqual(SuccessfulSmartServerResponse(()), response)
1138
912
self.assertEqual('http://bar/', branch.get_parent())
1141
class TestSmartServerBranchRequestGetTagsBytes(
1142
tests.TestCaseWithMemoryTransport):
915
class TestSmartServerBranchRequestGetTagsBytes(tests.TestCaseWithMemoryTransport):
1143
916
# Only called when the branch format and tags match [yay factory
1144
917
# methods] so only need to test straight forward cases.
1146
919
def test_get_bytes(self):
1147
920
base_branch = self.make_branch('base')
1148
request = smart_branch.SmartServerBranchGetTagsBytes(
921
request = smart.branch.SmartServerBranchGetTagsBytes(
1149
922
self.get_transport())
1150
923
response = request.execute('base')
1151
924
self.assertEquals(
1152
smart_req.SuccessfulSmartServerResponse(('',)), response)
925
SuccessfulSmartServerResponse(('',)), response)
1155
928
class TestSmartServerBranchRequestGetStackedOnURL(tests.TestCaseWithMemoryTransport):
1159
932
stacked_branch = self.make_branch('stacked', format='1.6')
1160
933
# typically should be relative
1161
934
stacked_branch.set_stacked_on_url('../base')
1162
request = smart_branch.SmartServerBranchRequestGetStackedOnURL(
935
request = smart.branch.SmartServerBranchRequestGetStackedOnURL(
1163
936
self.get_transport())
1164
937
response = request.execute('stacked')
1165
938
self.assertEquals(
1166
smart_req.SmartServerResponse(('ok', '../base')),
939
SmartServerResponse(('ok', '../base')),
1170
class TestSmartServerBranchRequestLockWrite(TestLockedBranch):
943
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithMemoryTransport):
1172
945
def setUp(self):
1173
946
tests.TestCaseWithMemoryTransport.setUp(self)
1175
948
def test_lock_write_on_unlocked_branch(self):
1176
949
backing = self.get_transport()
1177
request = smart_branch.SmartServerBranchRequestLockWrite(backing)
950
request = smart.branch.SmartServerBranchRequestLockWrite(backing)
1178
951
branch = self.make_branch('.', format='knit')
1179
952
repository = branch.repository
1180
953
response = request.execute('')
1181
954
branch_nonce = branch.control_files._lock.peek().get('nonce')
1182
955
repository_nonce = repository.control_files._lock.peek().get('nonce')
1183
self.assertEqual(smart_req.SmartServerResponse(
1184
('ok', branch_nonce, repository_nonce)),
957
SmartServerResponse(('ok', branch_nonce, repository_nonce)),
1186
959
# The branch (and associated repository) is now locked. Verify that
1187
960
# with a new branch object.
1188
961
new_branch = repository.bzrdir.open_branch()
1189
962
self.assertRaises(errors.LockContention, new_branch.lock_write)
1191
request = smart_branch.SmartServerBranchRequestUnlock(backing)
964
request = smart.branch.SmartServerBranchRequestUnlock(backing)
1192
965
response = request.execute('', branch_nonce, repository_nonce)
1194
967
def test_lock_write_on_locked_branch(self):
1195
968
backing = self.get_transport()
1196
request = smart_branch.SmartServerBranchRequestLockWrite(backing)
969
request = smart.branch.SmartServerBranchRequestLockWrite(backing)
1197
970
branch = self.make_branch('.')
1198
branch_token = branch.lock_write().branch_token
971
branch_token = branch.lock_write()
1199
972
branch.leave_lock_in_place()
1201
974
response = request.execute('')
1202
975
self.assertEqual(
1203
smart_req.SmartServerResponse(('LockContention',)), response)
976
SmartServerResponse(('LockContention',)), response)
1205
978
branch.lock_write(branch_token)
1206
979
branch.dont_leave_lock_in_place()
1304
1082
def test_unlock_on_unlocked_branch_unlocked_repo(self):
1305
1083
backing = self.get_transport()
1306
request = smart_branch.SmartServerBranchRequestUnlock(backing)
1084
request = smart.branch.SmartServerBranchRequestUnlock(backing)
1307
1085
branch = self.make_branch('.', format='knit')
1308
1086
response = request.execute(
1309
1087
'', 'branch token', 'repo token')
1310
1088
self.assertEqual(
1311
smart_req.SmartServerResponse(('TokenMismatch',)), response)
1089
SmartServerResponse(('TokenMismatch',)), response)
1313
1091
def test_unlock_on_unlocked_branch_locked_repo(self):
1314
1092
backing = self.get_transport()
1315
request = smart_branch.SmartServerBranchRequestUnlock(backing)
1093
request = smart.branch.SmartServerBranchRequestUnlock(backing)
1316
1094
branch = self.make_branch('.', format='knit')
1317
1095
# Lock the repository.
1318
repo_token = branch.repository.lock_write().repository_token
1096
repo_token = branch.repository.lock_write()
1319
1097
branch.repository.leave_lock_in_place()
1320
1098
branch.repository.unlock()
1321
1099
# Issue branch lock_write request on the unlocked branch (with locked
1323
response = request.execute('', 'branch token', repo_token)
1101
response = request.execute(
1102
'', 'branch token', repo_token)
1324
1103
self.assertEqual(
1325
smart_req.SmartServerResponse(('TokenMismatch',)), response)
1104
SmartServerResponse(('TokenMismatch',)), response)
1327
1106
branch.repository.lock_write(repo_token)
1328
1107
branch.repository.dont_leave_lock_in_place()
1350
1129
def test_trivial_bzipped(self):
1351
1130
# This tests that the wire encoding is actually bzipped
1352
1131
backing = self.get_transport()
1353
request = smart_repo.SmartServerRepositoryGetParentMap(backing)
1132
request = smart.repository.SmartServerRepositoryGetParentMap(backing)
1354
1133
tree = self.make_branch_and_memory_tree('.')
1356
1135
self.assertEqual(None,
1357
1136
request.execute('', 'missing-id'))
1358
1137
# Note that it returns a body that is bzipped.
1359
1138
self.assertEqual(
1360
smart_req.SuccessfulSmartServerResponse(('ok', ), bz2.compress('')),
1139
SuccessfulSmartServerResponse(('ok', ), bz2.compress('')),
1361
1140
request.do_body('\n\n0\n'))
1363
1142
def test_trivial_include_missing(self):
1364
1143
backing = self.get_transport()
1365
request = smart_repo.SmartServerRepositoryGetParentMap(backing)
1144
request = smart.repository.SmartServerRepositoryGetParentMap(backing)
1366
1145
tree = self.make_branch_and_memory_tree('.')
1368
1147
self.assertEqual(None,
1369
1148
request.execute('', 'missing-id', 'include-missing:'))
1370
1149
self.assertEqual(
1371
smart_req.SuccessfulSmartServerResponse(('ok', ),
1150
SuccessfulSmartServerResponse(('ok', ),
1372
1151
bz2.compress('missing:missing-id')),
1373
1152
request.do_body('\n\n0\n'))
1376
class TestSmartServerRepositoryGetRevisionGraph(
1377
tests.TestCaseWithMemoryTransport):
1155
class TestSmartServerRepositoryGetRevisionGraph(tests.TestCaseWithMemoryTransport):
1379
1157
def test_none_argument(self):
1380
1158
backing = self.get_transport()
1381
request = smart_repo.SmartServerRepositoryGetRevisionGraph(backing)
1159
request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
1382
1160
tree = self.make_branch_and_memory_tree('.')
1383
1161
tree.lock_write()
1511
1285
stream_bytes = ''.join(response.body_stream)
1512
1286
self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
1514
def test_search_everything(self):
1515
"""A search of 'everything' returns a stream."""
1516
backing = self.get_transport()
1517
request = smart_repo.SmartServerRepositoryGetStream_1_19(backing)
1518
repo, r1, r2 = self.make_two_commit_repo()
1519
serialised_fetch_spec = 'everything'
1520
request.execute('', repo._format.network_name())
1521
response = request.do_body(serialised_fetch_spec)
1522
self.assertEqual(('ok',), response.args)
1523
stream_bytes = ''.join(response.body_stream)
1524
self.assertStartsWith(stream_bytes, 'Bazaar pack format 1')
1527
1289
class TestSmartServerRequestHasRevision(tests.TestCaseWithMemoryTransport):
1529
1291
def test_missing_revision(self):
1530
1292
"""For a missing revision, ('no', ) is returned."""
1531
1293
backing = self.get_transport()
1532
request = smart_repo.SmartServerRequestHasRevision(backing)
1294
request = smart.repository.SmartServerRequestHasRevision(backing)
1533
1295
self.make_repository('.')
1534
self.assertEqual(smart_req.SmartServerResponse(('no', )),
1296
self.assertEqual(SmartServerResponse(('no', )),
1535
1297
request.execute('', 'revid'))
1537
1299
def test_present_revision(self):
1538
1300
"""For a present revision, ('yes', ) is returned."""
1539
1301
backing = self.get_transport()
1540
request = smart_repo.SmartServerRequestHasRevision(backing)
1302
request = smart.repository.SmartServerRequestHasRevision(backing)
1541
1303
tree = self.make_branch_and_memory_tree('.')
1542
1304
tree.lock_write()
1632
1394
def test_lock_write_on_unlocked_repo(self):
1633
1395
backing = self.get_transport()
1634
request = smart_repo.SmartServerRepositoryLockWrite(backing)
1396
request = smart.repository.SmartServerRepositoryLockWrite(backing)
1635
1397
repository = self.make_repository('.', format='knit')
1636
1398
response = request.execute('')
1637
1399
nonce = repository.control_files._lock.peek().get('nonce')
1638
self.assertEqual(smart_req.SmartServerResponse(('ok', nonce)), response)
1400
self.assertEqual(SmartServerResponse(('ok', nonce)), response)
1639
1401
# The repository is now locked. Verify that with a new repository
1641
1403
new_repo = repository.bzrdir.open_repository()
1642
1404
self.assertRaises(errors.LockContention, new_repo.lock_write)
1644
request = smart_repo.SmartServerRepositoryUnlock(backing)
1406
request = smart.repository.SmartServerRepositoryUnlock(backing)
1645
1407
response = request.execute('', nonce)
1647
1409
def test_lock_write_on_locked_repo(self):
1648
1410
backing = self.get_transport()
1649
request = smart_repo.SmartServerRepositoryLockWrite(backing)
1411
request = smart.repository.SmartServerRepositoryLockWrite(backing)
1650
1412
repository = self.make_repository('.', format='knit')
1651
repo_token = repository.lock_write().repository_token
1413
repo_token = repository.lock_write()
1652
1414
repository.leave_lock_in_place()
1653
1415
repository.unlock()
1654
1416
response = request.execute('')
1655
1417
self.assertEqual(
1656
smart_req.SmartServerResponse(('LockContention',)), response)
1418
SmartServerResponse(('LockContention',)), response)
1658
1420
repository.lock_write(repo_token)
1659
1421
repository.dont_leave_lock_in_place()
1680
1442
def test_insert_stream_empty(self):
1681
1443
backing = self.get_transport()
1682
request = smart_repo.SmartServerRepositoryInsertStream(backing)
1444
request = smart.repository.SmartServerRepositoryInsertStream(backing)
1683
1445
repository = self.make_repository('.')
1684
1446
response = request.execute('', '')
1685
1447
self.assertEqual(None, response)
1686
1448
response = request.do_chunk(self.make_empty_byte_stream(repository))
1687
1449
self.assertEqual(None, response)
1688
1450
response = request.do_end()
1689
self.assertEqual(smart_req.SmartServerResponse(('ok', )), response)
1451
self.assertEqual(SmartServerResponse(('ok', )), response)
1692
1454
class TestSmartServerRepositoryInsertStreamLocked(TestInsertStreamBase):
1694
1456
def test_insert_stream_empty(self):
1695
1457
backing = self.get_transport()
1696
request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1458
request = smart.repository.SmartServerRepositoryInsertStreamLocked(
1698
1460
repository = self.make_repository('.', format='knit')
1699
lock_token = repository.lock_write().repository_token
1461
lock_token = repository.lock_write()
1700
1462
response = request.execute('', '', lock_token)
1701
1463
self.assertEqual(None, response)
1702
1464
response = request.do_chunk(self.make_empty_byte_stream(repository))
1703
1465
self.assertEqual(None, response)
1704
1466
response = request.do_end()
1705
self.assertEqual(smart_req.SmartServerResponse(('ok', )), response)
1467
self.assertEqual(SmartServerResponse(('ok', )), response)
1706
1468
repository.unlock()
1708
1470
def test_insert_stream_with_wrong_lock_token(self):
1709
1471
backing = self.get_transport()
1710
request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1472
request = smart.repository.SmartServerRepositoryInsertStreamLocked(
1712
1474
repository = self.make_repository('.', format='knit')
1713
lock_token = repository.lock_write().repository_token
1475
lock_token = repository.lock_write()
1714
1476
self.assertRaises(
1715
1477
errors.TokenMismatch, request.execute, '', '', 'wrong-token')
1716
1478
repository.unlock()
1740
1502
def test_unlock_on_unlocked_repo(self):
1741
1503
backing = self.get_transport()
1742
request = smart_repo.SmartServerRepositoryUnlock(backing)
1504
request = smart.repository.SmartServerRepositoryUnlock(backing)
1743
1505
repository = self.make_repository('.', format='knit')
1744
1506
response = request.execute('', 'some token')
1745
1507
self.assertEqual(
1746
smart_req.SmartServerResponse(('TokenMismatch',)), response)
1508
SmartServerResponse(('TokenMismatch',)), response)
1749
1511
class TestSmartServerIsReadonly(tests.TestCaseWithMemoryTransport):
1751
1513
def test_is_readonly_no(self):
1752
1514
backing = self.get_transport()
1753
request = smart_req.SmartServerIsReadonly(backing)
1515
request = smart.request.SmartServerIsReadonly(backing)
1754
1516
response = request.execute()
1755
1517
self.assertEqual(
1756
smart_req.SmartServerResponse(('no',)), response)
1518
SmartServerResponse(('no',)), response)
1758
1520
def test_is_readonly_yes(self):
1759
1521
backing = self.get_readonly_transport()
1760
request = smart_req.SmartServerIsReadonly(backing)
1522
request = smart.request.SmartServerIsReadonly(backing)
1761
1523
response = request.execute()
1762
1524
self.assertEqual(
1763
smart_req.SmartServerResponse(('yes',)), response)
1766
class TestSmartServerRepositorySetMakeWorkingTrees(
1767
tests.TestCaseWithMemoryTransport):
1525
SmartServerResponse(('yes',)), response)
1528
class TestSmartServerRepositorySetMakeWorkingTrees(tests.TestCaseWithMemoryTransport):
1769
1530
def test_set_false(self):
1770
1531
backing = self.get_transport()
1771
1532
repo = self.make_repository('.', shared=True)
1772
1533
repo.set_make_working_trees(True)
1773
request_class = smart_repo.SmartServerRepositorySetMakeWorkingTrees
1534
request_class = smart.repository.SmartServerRepositorySetMakeWorkingTrees
1774
1535
request = request_class(backing)
1775
self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
1536
self.assertEqual(SuccessfulSmartServerResponse(('ok',)),
1776
1537
request.execute('', 'False'))
1777
1538
repo = repo.bzrdir.open_repository()
1778
1539
self.assertFalse(repo.make_working_trees())
1860
1608
"""All registered request_handlers can be found."""
1861
1609
# If there's a typo in a register_lazy call, this loop will fail with
1862
1610
# an AttributeError.
1863
for key, item in smart_req.request_handlers.iteritems():
1611
for key, item in smart.request.request_handlers.iteritems():
1866
1614
def assertHandlerEqual(self, verb, handler):
1867
self.assertEqual(smart_req.request_handlers.get(verb), handler)
1615
self.assertEqual(smart.request.request_handlers.get(verb), handler)
1869
1617
def test_registered_methods(self):
1870
1618
"""Test that known methods are registered to the correct object."""
1871
1619
self.assertHandlerEqual('Branch.get_config_file',
1872
smart_branch.SmartServerBranchGetConfigFile)
1620
smart.branch.SmartServerBranchGetConfigFile)
1873
1621
self.assertHandlerEqual('Branch.get_parent',
1874
smart_branch.SmartServerBranchGetParent)
1622
smart.branch.SmartServerBranchGetParent)
1875
1623
self.assertHandlerEqual('Branch.get_tags_bytes',
1876
smart_branch.SmartServerBranchGetTagsBytes)
1624
smart.branch.SmartServerBranchGetTagsBytes)
1877
1625
self.assertHandlerEqual('Branch.lock_write',
1878
smart_branch.SmartServerBranchRequestLockWrite)
1626
smart.branch.SmartServerBranchRequestLockWrite)
1879
1627
self.assertHandlerEqual('Branch.last_revision_info',
1880
smart_branch.SmartServerBranchRequestLastRevisionInfo)
1628
smart.branch.SmartServerBranchRequestLastRevisionInfo)
1881
1629
self.assertHandlerEqual('Branch.revision_history',
1882
smart_branch.SmartServerRequestRevisionHistory)
1630
smart.branch.SmartServerRequestRevisionHistory)
1883
1631
self.assertHandlerEqual('Branch.set_config_option',
1884
smart_branch.SmartServerBranchRequestSetConfigOption)
1632
smart.branch.SmartServerBranchRequestSetConfigOption)
1885
1633
self.assertHandlerEqual('Branch.set_last_revision',
1886
smart_branch.SmartServerBranchRequestSetLastRevision)
1634
smart.branch.SmartServerBranchRequestSetLastRevision)
1887
1635
self.assertHandlerEqual('Branch.set_last_revision_info',
1888
smart_branch.SmartServerBranchRequestSetLastRevisionInfo)
1636
smart.branch.SmartServerBranchRequestSetLastRevisionInfo)
1889
1637
self.assertHandlerEqual('Branch.set_last_revision_ex',
1890
smart_branch.SmartServerBranchRequestSetLastRevisionEx)
1638
smart.branch.SmartServerBranchRequestSetLastRevisionEx)
1891
1639
self.assertHandlerEqual('Branch.set_parent_location',
1892
smart_branch.SmartServerBranchRequestSetParentLocation)
1640
smart.branch.SmartServerBranchRequestSetParentLocation)
1893
1641
self.assertHandlerEqual('Branch.unlock',
1894
smart_branch.SmartServerBranchRequestUnlock)
1642
smart.branch.SmartServerBranchRequestUnlock)
1895
1643
self.assertHandlerEqual('BzrDir.find_repository',
1896
smart_dir.SmartServerRequestFindRepositoryV1)
1644
smart.bzrdir.SmartServerRequestFindRepositoryV1)
1897
1645
self.assertHandlerEqual('BzrDir.find_repositoryV2',
1898
smart_dir.SmartServerRequestFindRepositoryV2)
1646
smart.bzrdir.SmartServerRequestFindRepositoryV2)
1899
1647
self.assertHandlerEqual('BzrDirFormat.initialize',
1900
smart_dir.SmartServerRequestInitializeBzrDir)
1648
smart.bzrdir.SmartServerRequestInitializeBzrDir)
1901
1649
self.assertHandlerEqual('BzrDirFormat.initialize_ex_1.16',
1902
smart_dir.SmartServerRequestBzrDirInitializeEx)
1650
smart.bzrdir.SmartServerRequestBzrDirInitializeEx)
1903
1651
self.assertHandlerEqual('BzrDir.cloning_metadir',
1904
smart_dir.SmartServerBzrDirRequestCloningMetaDir)
1652
smart.bzrdir.SmartServerBzrDirRequestCloningMetaDir)
1905
1653
self.assertHandlerEqual('BzrDir.get_config_file',
1906
smart_dir.SmartServerBzrDirRequestConfigFile)
1654
smart.bzrdir.SmartServerBzrDirRequestConfigFile)
1907
1655
self.assertHandlerEqual('BzrDir.open_branch',
1908
smart_dir.SmartServerRequestOpenBranch)
1656
smart.bzrdir.SmartServerRequestOpenBranch)
1909
1657
self.assertHandlerEqual('BzrDir.open_branchV2',
1910
smart_dir.SmartServerRequestOpenBranchV2)
1911
self.assertHandlerEqual('BzrDir.open_branchV3',
1912
smart_dir.SmartServerRequestOpenBranchV3)
1658
smart.bzrdir.SmartServerRequestOpenBranchV2)
1913
1659
self.assertHandlerEqual('PackRepository.autopack',
1914
smart_packrepo.SmartServerPackRepositoryAutopack)
1660
smart.packrepository.SmartServerPackRepositoryAutopack)
1915
1661
self.assertHandlerEqual('Repository.gather_stats',
1916
smart_repo.SmartServerRepositoryGatherStats)
1662
smart.repository.SmartServerRepositoryGatherStats)
1917
1663
self.assertHandlerEqual('Repository.get_parent_map',
1918
smart_repo.SmartServerRepositoryGetParentMap)
1664
smart.repository.SmartServerRepositoryGetParentMap)
1919
1665
self.assertHandlerEqual('Repository.get_rev_id_for_revno',
1920
smart_repo.SmartServerRepositoryGetRevIdForRevno)
1666
smart.repository.SmartServerRepositoryGetRevIdForRevno)
1921
1667
self.assertHandlerEqual('Repository.get_revision_graph',
1922
smart_repo.SmartServerRepositoryGetRevisionGraph)
1668
smart.repository.SmartServerRepositoryGetRevisionGraph)
1923
1669
self.assertHandlerEqual('Repository.get_stream',
1924
smart_repo.SmartServerRepositoryGetStream)
1925
self.assertHandlerEqual('Repository.get_stream_1.19',
1926
smart_repo.SmartServerRepositoryGetStream_1_19)
1670
smart.repository.SmartServerRepositoryGetStream)
1927
1671
self.assertHandlerEqual('Repository.has_revision',
1928
smart_repo.SmartServerRequestHasRevision)
1672
smart.repository.SmartServerRequestHasRevision)
1929
1673
self.assertHandlerEqual('Repository.insert_stream',
1930
smart_repo.SmartServerRepositoryInsertStream)
1674
smart.repository.SmartServerRepositoryInsertStream)
1931
1675
self.assertHandlerEqual('Repository.insert_stream_locked',
1932
smart_repo.SmartServerRepositoryInsertStreamLocked)
1676
smart.repository.SmartServerRepositoryInsertStreamLocked)
1933
1677
self.assertHandlerEqual('Repository.is_shared',
1934
smart_repo.SmartServerRepositoryIsShared)
1678
smart.repository.SmartServerRepositoryIsShared)
1935
1679
self.assertHandlerEqual('Repository.lock_write',
1936
smart_repo.SmartServerRepositoryLockWrite)
1680
smart.repository.SmartServerRepositoryLockWrite)
1937
1681
self.assertHandlerEqual('Repository.tarball',
1938
smart_repo.SmartServerRepositoryTarball)
1682
smart.repository.SmartServerRepositoryTarball)
1939
1683
self.assertHandlerEqual('Repository.unlock',
1940
smart_repo.SmartServerRepositoryUnlock)
1684
smart.repository.SmartServerRepositoryUnlock)
1941
1685
self.assertHandlerEqual('Transport.is_readonly',
1942
smart_req.SmartServerIsReadonly)
1945
class SmartTCPServerHookTests(tests.TestCaseWithMemoryTransport):
1946
"""Tests for SmartTCPServer hooks."""
1949
super(SmartTCPServerHookTests, self).setUp()
1950
self.server = server.SmartTCPServer(self.get_transport())
1952
def test_run_server_started_hooks(self):
1953
"""Test the server started hooks get fired properly."""
1955
server.SmartTCPServer.hooks.install_named_hook('server_started',
1956
lambda backing_urls, url: started_calls.append((backing_urls, url)),
1958
started_ex_calls = []
1959
server.SmartTCPServer.hooks.install_named_hook('server_started_ex',
1960
lambda backing_urls, url: started_ex_calls.append((backing_urls, url)),
1962
self.server._sockname = ('example.com', 42)
1963
self.server.run_server_started_hooks()
1964
self.assertEquals(started_calls,
1965
[([self.get_transport().base], 'bzr://example.com:42/')])
1966
self.assertEquals(started_ex_calls,
1967
[([self.get_transport().base], self.server)])
1969
def test_run_server_started_hooks_ipv6(self):
1970
"""Test that socknames can contain 4-tuples."""
1971
self.server._sockname = ('::', 42, 0, 0)
1973
server.SmartTCPServer.hooks.install_named_hook('server_started',
1974
lambda backing_urls, url: started_calls.append((backing_urls, url)),
1976
self.server.run_server_started_hooks()
1977
self.assertEquals(started_calls,
1978
[([self.get_transport().base], 'bzr://:::42/')])
1980
def test_run_server_stopped_hooks(self):
1981
"""Test the server stopped hooks."""
1982
self.server._sockname = ('example.com', 42)
1984
server.SmartTCPServer.hooks.install_named_hook('server_stopped',
1985
lambda backing_urls, url: stopped_calls.append((backing_urls, url)),
1987
self.server.run_server_stopped_hooks()
1988
self.assertEquals(stopped_calls,
1989
[([self.get_transport().base], 'bzr://example.com:42/')])
1686
smart.request.SmartServerIsReadonly)