28
from cStringIO import StringIO
31
29
from bzrlib import (
30
branch as _mod_branch,
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
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 (
57
54
def load_tests(standard_tests, module, loader):
58
55
"""Multiply tests version and protocol consistency."""
59
56
# FindRepository tests.
60
bzrdir_mod = bzrlib.smart.bzrdir
62
58
("find_repository", {
63
"_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV1}),
59
"_request_class": smart_dir.SmartServerRequestFindRepositoryV1}),
64
60
("find_repositoryV2", {
65
"_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV2}),
61
"_request_class": smart_dir.SmartServerRequestFindRepositoryV2}),
66
62
("find_repositoryV3", {
67
"_request_class":bzrdir_mod.SmartServerRequestFindRepositoryV3}),
63
"_request_class": smart_dir.SmartServerRequestFindRepositoryV3}),
69
to_adapt, result = split_suite_by_re(standard_tests,
65
to_adapt, result = tests.split_suite_by_re(standard_tests,
70
66
"TestSmartServerRequestFindRepository")
71
v2_only, v1_and_2 = split_suite_by_re(to_adapt,
67
v2_only, v1_and_2 = tests.split_suite_by_re(to_adapt,
73
69
tests.multiply_tests(v1_and_2, scenarios, result)
74
70
# The first scenario is only applicable to v1 protocols, it is deleted
106
102
self.transport_server = self.make_transport_server
108
104
def make_transport_server(self):
109
return smart.server.SmartTCPServer_for_testing('-' + self.id())
105
return test_server.SmartTCPServer_for_testing('-' + self.id())
111
107
def get_smart_medium(self):
112
108
"""Get a smart medium to use in tests."""
113
109
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])
116
131
class TestSmartServerResponse(tests.TestCase):
118
133
def test__eq__(self):
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', )))
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', )))
127
142
self.assertNotEqual(None,
128
SmartServerResponse(('ok', )))
143
smart_req.SmartServerResponse(('ok', )))
130
145
def test__str__(self):
131
146
"""SmartServerResponses can be stringified."""
132
147
self.assertEqual(
133
148
"<SuccessfulSmartServerResponse args=('args',) body='body'>",
134
str(SuccessfulSmartServerResponse(('args',), 'body')))
149
str(smart_req.SuccessfulSmartServerResponse(('args',), 'body')))
135
150
self.assertEqual(
136
151
"<FailedSmartServerResponse args=('args',) body='body'>",
137
str(FailedSmartServerResponse(('args',), 'body')))
152
str(smart_req.FailedSmartServerResponse(('args',), 'body')))
140
155
class TestSmartServerRequest(tests.TestCaseWithMemoryTransport):
142
157
def test_translate_client_path(self):
143
158
transport = self.get_transport()
144
request = SmartServerRequest(transport, 'foo/')
159
request = smart_req.SmartServerRequest(transport, 'foo/')
145
160
self.assertEqual('./', request.translate_client_path('foo/'))
146
161
self.assertRaises(
147
162
errors.InvalidURLJoin, request.translate_client_path, 'foo/..')
388
423
"""Initializing an extant directory should fail like the bzrdir api."""
389
424
backing = self.get_transport()
390
425
name = self.make_bzrdir('reference')._format.network_name()
391
request = smart.bzrdir.SmartServerRequestBzrDirInitializeEx(backing)
426
request = smart_dir.SmartServerRequestBzrDirInitializeEx(backing)
392
427
self.make_bzrdir('subdir')
393
428
self.assertRaises(errors.FileExists, request.execute, name, 'subdir',
394
429
'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')),
397
499
class TestSmartServerRequestOpenBranch(TestCaseWithChrootedTransport):
399
501
def test_no_branch(self):
400
502
"""When there is no branch, ('nobranch', ) is returned."""
401
503
backing = self.get_transport()
402
request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
504
request = smart_dir.SmartServerRequestOpenBranch(backing)
403
505
self.make_bzrdir('.')
404
self.assertEqual(SmartServerResponse(('nobranch', )),
506
self.assertEqual(smart_req.SmartServerResponse(('nobranch', )),
405
507
request.execute(''))
407
509
def test_branch(self):
408
510
"""When there is a branch, 'ok' is returned."""
409
511
backing = self.get_transport()
410
request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
512
request = smart_dir.SmartServerRequestOpenBranch(backing)
411
513
self.make_branch('.')
412
self.assertEqual(SmartServerResponse(('ok', '')),
514
self.assertEqual(smart_req.SmartServerResponse(('ok', '')),
413
515
request.execute(''))
415
517
def test_branch_reference(self):
416
518
"""When there is a branch reference, the reference URL is returned."""
519
self.vfs_transport_factory = test_server.LocalURLServer
417
520
backing = self.get_transport()
418
request = smart.bzrdir.SmartServerRequestOpenBranch(backing)
521
request = smart_dir.SmartServerRequestOpenBranch(backing)
419
522
branch = self.make_branch('branch')
420
523
checkout = branch.create_checkout('reference',lightweight=True)
421
reference_url = BranchReferenceFormat().get_reference(checkout.bzrdir)
524
reference_url = _mod_branch.BranchReferenceFormat().get_reference(
422
526
self.assertFileEqual(reference_url, 'reference/.bzr/branch/location')
423
self.assertEqual(SmartServerResponse(('ok', reference_url)),
527
self.assertEqual(smart_req.SmartServerResponse(('ok', reference_url)),
424
528
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',)),
427
539
class TestSmartServerRequestOpenBranchV2(TestCaseWithChrootedTransport):
430
542
"""When there is no branch, ('nobranch', ) is returned."""
431
543
backing = self.get_transport()
432
544
self.make_bzrdir('.')
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)
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')),
477
666
class TestSmartServerRequestRevisionHistory(tests.TestCaseWithMemoryTransport):
583
774
def test_value_name(self):
584
775
branch = self.make_branch('.')
585
request = smart.branch.SmartServerBranchRequestSetConfigOption(
776
request = smart_branch.SmartServerBranchRequestSetConfigOption(
586
777
branch.bzrdir.root_transport)
587
778
branch_token, repo_token = self.get_lock_tokens(branch)
588
779
config = branch._get_config()
589
780
result = request.execute('', branch_token, repo_token, 'bar', 'foo',
591
self.assertEqual(SuccessfulSmartServerResponse(()), result)
782
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
592
783
self.assertEqual('bar', config.get_option('foo'))
596
787
def test_value_name_section(self):
597
788
branch = self.make_branch('.')
598
request = smart.branch.SmartServerBranchRequestSetConfigOption(
789
request = smart_branch.SmartServerBranchRequestSetConfigOption(
599
790
branch.bzrdir.root_transport)
600
791
branch_token, repo_token = self.get_lock_tokens(branch)
601
792
config = branch._get_config()
602
793
result = request.execute('', branch_token, repo_token, 'bar', 'foo',
604
self.assertEqual(SuccessfulSmartServerResponse(()), result)
795
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), result)
605
796
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'))
610
839
class TestSmartServerBranchRequestSetTagsBytes(TestLockedBranch):
611
840
# Only called when the branch format and tags match [yay factory
612
841
# methods] so only need to test straight forward cases.
863
1093
def test_get_parent_none(self):
864
1094
base_branch = self.make_branch('base')
865
request = smart.branch.SmartServerBranchGetParent(self.get_transport())
1095
request = smart_branch.SmartServerBranchGetParent(self.get_transport())
866
1096
response = request.execute('base')
867
1097
self.assertEquals(
868
SuccessfulSmartServerResponse(('',)), response)
1098
smart_req.SuccessfulSmartServerResponse(('',)), response)
870
1100
def test_get_parent_something(self):
871
1101
base_branch = self.make_branch('base')
872
1102
base_branch.set_parent(self.get_url('foo'))
873
request = smart.branch.SmartServerBranchGetParent(self.get_transport())
1103
request = smart_branch.SmartServerBranchGetParent(self.get_transport())
874
1104
response = request.execute('base')
875
1105
self.assertEquals(
876
SuccessfulSmartServerResponse(("../foo",)),
1106
smart_req.SuccessfulSmartServerResponse(("../foo",)),
880
class TestSmartServerBranchRequestSetParent(tests.TestCaseWithMemoryTransport):
1110
class TestSmartServerBranchRequestSetParent(TestLockedBranch):
882
1112
def test_set_parent_none(self):
883
1113
branch = self.make_branch('base', format="1.9")
884
1114
branch.lock_write()
885
1115
branch._set_parent_location('foo')
887
request = smart.branch.SmartServerBranchRequestSetParentLocation(
1117
request = smart_branch.SmartServerBranchRequestSetParentLocation(
888
1118
self.get_transport())
889
branch_token = branch.lock_write()
890
repo_token = branch.repository.lock_write()
1119
branch_token, repo_token = self.get_lock_tokens(branch)
892
1121
response = request.execute('base', branch_token, repo_token, '')
894
branch.repository.unlock()
896
self.assertEqual(SuccessfulSmartServerResponse(()), response)
1124
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
897
1125
self.assertEqual(None, branch.get_parent())
899
1127
def test_set_parent_something(self):
900
1128
branch = self.make_branch('base', format="1.9")
901
request = smart.branch.SmartServerBranchRequestSetParentLocation(
1129
request = smart_branch.SmartServerBranchRequestSetParentLocation(
902
1130
self.get_transport())
903
branch_token = branch.lock_write()
904
repo_token = branch.repository.lock_write()
1131
branch_token, repo_token = self.get_lock_tokens(branch)
906
1133
response = request.execute('base', branch_token, repo_token,
909
branch.repository.unlock()
911
self.assertEqual(SuccessfulSmartServerResponse(()), response)
1137
self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
912
1138
self.assertEqual('http://bar/', branch.get_parent())
915
class TestSmartServerBranchRequestGetTagsBytes(tests.TestCaseWithMemoryTransport):
1141
class TestSmartServerBranchRequestGetTagsBytes(
1142
tests.TestCaseWithMemoryTransport):
916
1143
# Only called when the branch format and tags match [yay factory
917
1144
# methods] so only need to test straight forward cases.
919
1146
def test_get_bytes(self):
920
1147
base_branch = self.make_branch('base')
921
request = smart.branch.SmartServerBranchGetTagsBytes(
1148
request = smart_branch.SmartServerBranchGetTagsBytes(
922
1149
self.get_transport())
923
1150
response = request.execute('base')
924
1151
self.assertEquals(
925
SuccessfulSmartServerResponse(('',)), response)
1152
smart_req.SuccessfulSmartServerResponse(('',)), response)
928
1155
class TestSmartServerBranchRequestGetStackedOnURL(tests.TestCaseWithMemoryTransport):
932
1159
stacked_branch = self.make_branch('stacked', format='1.6')
933
1160
# typically should be relative
934
1161
stacked_branch.set_stacked_on_url('../base')
935
request = smart.branch.SmartServerBranchRequestGetStackedOnURL(
1162
request = smart_branch.SmartServerBranchRequestGetStackedOnURL(
936
1163
self.get_transport())
937
1164
response = request.execute('stacked')
938
1165
self.assertEquals(
939
SmartServerResponse(('ok', '../base')),
1166
smart_req.SmartServerResponse(('ok', '../base')),
943
class TestSmartServerBranchRequestLockWrite(tests.TestCaseWithMemoryTransport):
1170
class TestSmartServerBranchRequestLockWrite(TestLockedBranch):
945
1172
def setUp(self):
946
1173
tests.TestCaseWithMemoryTransport.setUp(self)
948
1175
def test_lock_write_on_unlocked_branch(self):
949
1176
backing = self.get_transport()
950
request = smart.branch.SmartServerBranchRequestLockWrite(backing)
1177
request = smart_branch.SmartServerBranchRequestLockWrite(backing)
951
1178
branch = self.make_branch('.', format='knit')
952
1179
repository = branch.repository
953
1180
response = request.execute('')
954
1181
branch_nonce = branch.control_files._lock.peek().get('nonce')
955
1182
repository_nonce = repository.control_files._lock.peek().get('nonce')
957
SmartServerResponse(('ok', branch_nonce, repository_nonce)),
1183
self.assertEqual(smart_req.SmartServerResponse(
1184
('ok', branch_nonce, repository_nonce)),
959
1186
# The branch (and associated repository) is now locked. Verify that
960
1187
# with a new branch object.
961
1188
new_branch = repository.bzrdir.open_branch()
962
1189
self.assertRaises(errors.LockContention, new_branch.lock_write)
964
request = smart.branch.SmartServerBranchRequestUnlock(backing)
1191
request = smart_branch.SmartServerBranchRequestUnlock(backing)
965
1192
response = request.execute('', branch_nonce, repository_nonce)
967
1194
def test_lock_write_on_locked_branch(self):
968
1195
backing = self.get_transport()
969
request = smart.branch.SmartServerBranchRequestLockWrite(backing)
1196
request = smart_branch.SmartServerBranchRequestLockWrite(backing)
970
1197
branch = self.make_branch('.')
971
branch_token = branch.lock_write()
1198
branch_token = branch.lock_write().branch_token
972
1199
branch.leave_lock_in_place()
974
1201
response = request.execute('')
975
1202
self.assertEqual(
976
SmartServerResponse(('LockContention',)), response)
1203
smart_req.SmartServerResponse(('LockContention',)), response)
978
1205
branch.lock_write(branch_token)
979
1206
branch.dont_leave_lock_in_place()
1082
1304
def test_unlock_on_unlocked_branch_unlocked_repo(self):
1083
1305
backing = self.get_transport()
1084
request = smart.branch.SmartServerBranchRequestUnlock(backing)
1306
request = smart_branch.SmartServerBranchRequestUnlock(backing)
1085
1307
branch = self.make_branch('.', format='knit')
1086
1308
response = request.execute(
1087
1309
'', 'branch token', 'repo token')
1088
1310
self.assertEqual(
1089
SmartServerResponse(('TokenMismatch',)), response)
1311
smart_req.SmartServerResponse(('TokenMismatch',)), response)
1091
1313
def test_unlock_on_unlocked_branch_locked_repo(self):
1092
1314
backing = self.get_transport()
1093
request = smart.branch.SmartServerBranchRequestUnlock(backing)
1315
request = smart_branch.SmartServerBranchRequestUnlock(backing)
1094
1316
branch = self.make_branch('.', format='knit')
1095
1317
# Lock the repository.
1096
repo_token = branch.repository.lock_write()
1318
repo_token = branch.repository.lock_write().repository_token
1097
1319
branch.repository.leave_lock_in_place()
1098
1320
branch.repository.unlock()
1099
1321
# Issue branch lock_write request on the unlocked branch (with locked
1101
response = request.execute(
1102
'', 'branch token', repo_token)
1323
response = request.execute('', 'branch token', repo_token)
1103
1324
self.assertEqual(
1104
SmartServerResponse(('TokenMismatch',)), response)
1325
smart_req.SmartServerResponse(('TokenMismatch',)), response)
1106
1327
branch.repository.lock_write(repo_token)
1107
1328
branch.repository.dont_leave_lock_in_place()
1129
1350
def test_trivial_bzipped(self):
1130
1351
# This tests that the wire encoding is actually bzipped
1131
1352
backing = self.get_transport()
1132
request = smart.repository.SmartServerRepositoryGetParentMap(backing)
1353
request = smart_repo.SmartServerRepositoryGetParentMap(backing)
1133
1354
tree = self.make_branch_and_memory_tree('.')
1135
1356
self.assertEqual(None,
1136
1357
request.execute('', 'missing-id'))
1137
1358
# Note that it returns a body that is bzipped.
1138
1359
self.assertEqual(
1139
SuccessfulSmartServerResponse(('ok', ), bz2.compress('')),
1360
smart_req.SuccessfulSmartServerResponse(('ok', ), bz2.compress('')),
1140
1361
request.do_body('\n\n0\n'))
1142
1363
def test_trivial_include_missing(self):
1143
1364
backing = self.get_transport()
1144
request = smart.repository.SmartServerRepositoryGetParentMap(backing)
1365
request = smart_repo.SmartServerRepositoryGetParentMap(backing)
1145
1366
tree = self.make_branch_and_memory_tree('.')
1147
1368
self.assertEqual(None,
1148
1369
request.execute('', 'missing-id', 'include-missing:'))
1149
1370
self.assertEqual(
1150
SuccessfulSmartServerResponse(('ok', ),
1371
smart_req.SuccessfulSmartServerResponse(('ok', ),
1151
1372
bz2.compress('missing:missing-id')),
1152
1373
request.do_body('\n\n0\n'))
1155
class TestSmartServerRepositoryGetRevisionGraph(tests.TestCaseWithMemoryTransport):
1376
class TestSmartServerRepositoryGetRevisionGraph(
1377
tests.TestCaseWithMemoryTransport):
1157
1379
def test_none_argument(self):
1158
1380
backing = self.get_transport()
1159
request = smart.repository.SmartServerRepositoryGetRevisionGraph(backing)
1381
request = smart_repo.SmartServerRepositoryGetRevisionGraph(backing)
1160
1382
tree = self.make_branch_and_memory_tree('.')
1161
1383
tree.lock_write()
1285
1511
stream_bytes = ''.join(response.body_stream)
1286
1512
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')
1289
1527
class TestSmartServerRequestHasRevision(tests.TestCaseWithMemoryTransport):
1291
1529
def test_missing_revision(self):
1292
1530
"""For a missing revision, ('no', ) is returned."""
1293
1531
backing = self.get_transport()
1294
request = smart.repository.SmartServerRequestHasRevision(backing)
1532
request = smart_repo.SmartServerRequestHasRevision(backing)
1295
1533
self.make_repository('.')
1296
self.assertEqual(SmartServerResponse(('no', )),
1534
self.assertEqual(smart_req.SmartServerResponse(('no', )),
1297
1535
request.execute('', 'revid'))
1299
1537
def test_present_revision(self):
1300
1538
"""For a present revision, ('yes', ) is returned."""
1301
1539
backing = self.get_transport()
1302
request = smart.repository.SmartServerRequestHasRevision(backing)
1540
request = smart_repo.SmartServerRequestHasRevision(backing)
1303
1541
tree = self.make_branch_and_memory_tree('.')
1304
1542
tree.lock_write()
1394
1632
def test_lock_write_on_unlocked_repo(self):
1395
1633
backing = self.get_transport()
1396
request = smart.repository.SmartServerRepositoryLockWrite(backing)
1634
request = smart_repo.SmartServerRepositoryLockWrite(backing)
1397
1635
repository = self.make_repository('.', format='knit')
1398
1636
response = request.execute('')
1399
1637
nonce = repository.control_files._lock.peek().get('nonce')
1400
self.assertEqual(SmartServerResponse(('ok', nonce)), response)
1638
self.assertEqual(smart_req.SmartServerResponse(('ok', nonce)), response)
1401
1639
# The repository is now locked. Verify that with a new repository
1403
1641
new_repo = repository.bzrdir.open_repository()
1404
1642
self.assertRaises(errors.LockContention, new_repo.lock_write)
1406
request = smart.repository.SmartServerRepositoryUnlock(backing)
1644
request = smart_repo.SmartServerRepositoryUnlock(backing)
1407
1645
response = request.execute('', nonce)
1409
1647
def test_lock_write_on_locked_repo(self):
1410
1648
backing = self.get_transport()
1411
request = smart.repository.SmartServerRepositoryLockWrite(backing)
1649
request = smart_repo.SmartServerRepositoryLockWrite(backing)
1412
1650
repository = self.make_repository('.', format='knit')
1413
repo_token = repository.lock_write()
1651
repo_token = repository.lock_write().repository_token
1414
1652
repository.leave_lock_in_place()
1415
1653
repository.unlock()
1416
1654
response = request.execute('')
1417
1655
self.assertEqual(
1418
SmartServerResponse(('LockContention',)), response)
1656
smart_req.SmartServerResponse(('LockContention',)), response)
1420
1658
repository.lock_write(repo_token)
1421
1659
repository.dont_leave_lock_in_place()
1442
1680
def test_insert_stream_empty(self):
1443
1681
backing = self.get_transport()
1444
request = smart.repository.SmartServerRepositoryInsertStream(backing)
1682
request = smart_repo.SmartServerRepositoryInsertStream(backing)
1445
1683
repository = self.make_repository('.')
1446
1684
response = request.execute('', '')
1447
1685
self.assertEqual(None, response)
1448
1686
response = request.do_chunk(self.make_empty_byte_stream(repository))
1449
1687
self.assertEqual(None, response)
1450
1688
response = request.do_end()
1451
self.assertEqual(SmartServerResponse(('ok', )), response)
1689
self.assertEqual(smart_req.SmartServerResponse(('ok', )), response)
1454
1692
class TestSmartServerRepositoryInsertStreamLocked(TestInsertStreamBase):
1456
1694
def test_insert_stream_empty(self):
1457
1695
backing = self.get_transport()
1458
request = smart.repository.SmartServerRepositoryInsertStreamLocked(
1696
request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1460
1698
repository = self.make_repository('.', format='knit')
1461
lock_token = repository.lock_write()
1699
lock_token = repository.lock_write().repository_token
1462
1700
response = request.execute('', '', lock_token)
1463
1701
self.assertEqual(None, response)
1464
1702
response = request.do_chunk(self.make_empty_byte_stream(repository))
1465
1703
self.assertEqual(None, response)
1466
1704
response = request.do_end()
1467
self.assertEqual(SmartServerResponse(('ok', )), response)
1705
self.assertEqual(smart_req.SmartServerResponse(('ok', )), response)
1468
1706
repository.unlock()
1470
1708
def test_insert_stream_with_wrong_lock_token(self):
1471
1709
backing = self.get_transport()
1472
request = smart.repository.SmartServerRepositoryInsertStreamLocked(
1710
request = smart_repo.SmartServerRepositoryInsertStreamLocked(
1474
1712
repository = self.make_repository('.', format='knit')
1475
lock_token = repository.lock_write()
1713
lock_token = repository.lock_write().repository_token
1476
1714
self.assertRaises(
1477
1715
errors.TokenMismatch, request.execute, '', '', 'wrong-token')
1478
1716
repository.unlock()
1502
1740
def test_unlock_on_unlocked_repo(self):
1503
1741
backing = self.get_transport()
1504
request = smart.repository.SmartServerRepositoryUnlock(backing)
1742
request = smart_repo.SmartServerRepositoryUnlock(backing)
1505
1743
repository = self.make_repository('.', format='knit')
1506
1744
response = request.execute('', 'some token')
1507
1745
self.assertEqual(
1508
SmartServerResponse(('TokenMismatch',)), response)
1746
smart_req.SmartServerResponse(('TokenMismatch',)), response)
1511
1749
class TestSmartServerIsReadonly(tests.TestCaseWithMemoryTransport):
1513
1751
def test_is_readonly_no(self):
1514
1752
backing = self.get_transport()
1515
request = smart.request.SmartServerIsReadonly(backing)
1753
request = smart_req.SmartServerIsReadonly(backing)
1516
1754
response = request.execute()
1517
1755
self.assertEqual(
1518
SmartServerResponse(('no',)), response)
1756
smart_req.SmartServerResponse(('no',)), response)
1520
1758
def test_is_readonly_yes(self):
1521
1759
backing = self.get_readonly_transport()
1522
request = smart.request.SmartServerIsReadonly(backing)
1760
request = smart_req.SmartServerIsReadonly(backing)
1523
1761
response = request.execute()
1524
1762
self.assertEqual(
1525
SmartServerResponse(('yes',)), response)
1528
class TestSmartServerRepositorySetMakeWorkingTrees(tests.TestCaseWithMemoryTransport):
1763
smart_req.SmartServerResponse(('yes',)), response)
1766
class TestSmartServerRepositorySetMakeWorkingTrees(
1767
tests.TestCaseWithMemoryTransport):
1530
1769
def test_set_false(self):
1531
1770
backing = self.get_transport()
1532
1771
repo = self.make_repository('.', shared=True)
1533
1772
repo.set_make_working_trees(True)
1534
request_class = smart.repository.SmartServerRepositorySetMakeWorkingTrees
1773
request_class = smart_repo.SmartServerRepositorySetMakeWorkingTrees
1535
1774
request = request_class(backing)
1536
self.assertEqual(SuccessfulSmartServerResponse(('ok',)),
1775
self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
1537
1776
request.execute('', 'False'))
1538
1777
repo = repo.bzrdir.open_repository()
1539
1778
self.assertFalse(repo.make_working_trees())
1608
1860
"""All registered request_handlers can be found."""
1609
1861
# If there's a typo in a register_lazy call, this loop will fail with
1610
1862
# an AttributeError.
1611
for key, item in smart.request.request_handlers.iteritems():
1863
for key, item in smart_req.request_handlers.iteritems():
1614
1866
def assertHandlerEqual(self, verb, handler):
1615
self.assertEqual(smart.request.request_handlers.get(verb), handler)
1867
self.assertEqual(smart_req.request_handlers.get(verb), handler)
1617
1869
def test_registered_methods(self):
1618
1870
"""Test that known methods are registered to the correct object."""
1619
1871
self.assertHandlerEqual('Branch.get_config_file',
1620
smart.branch.SmartServerBranchGetConfigFile)
1872
smart_branch.SmartServerBranchGetConfigFile)
1621
1873
self.assertHandlerEqual('Branch.get_parent',
1622
smart.branch.SmartServerBranchGetParent)
1874
smart_branch.SmartServerBranchGetParent)
1623
1875
self.assertHandlerEqual('Branch.get_tags_bytes',
1624
smart.branch.SmartServerBranchGetTagsBytes)
1876
smart_branch.SmartServerBranchGetTagsBytes)
1625
1877
self.assertHandlerEqual('Branch.lock_write',
1626
smart.branch.SmartServerBranchRequestLockWrite)
1878
smart_branch.SmartServerBranchRequestLockWrite)
1627
1879
self.assertHandlerEqual('Branch.last_revision_info',
1628
smart.branch.SmartServerBranchRequestLastRevisionInfo)
1880
smart_branch.SmartServerBranchRequestLastRevisionInfo)
1629
1881
self.assertHandlerEqual('Branch.revision_history',
1630
smart.branch.SmartServerRequestRevisionHistory)
1882
smart_branch.SmartServerRequestRevisionHistory)
1631
1883
self.assertHandlerEqual('Branch.set_config_option',
1632
smart.branch.SmartServerBranchRequestSetConfigOption)
1884
smart_branch.SmartServerBranchRequestSetConfigOption)
1633
1885
self.assertHandlerEqual('Branch.set_last_revision',
1634
smart.branch.SmartServerBranchRequestSetLastRevision)
1886
smart_branch.SmartServerBranchRequestSetLastRevision)
1635
1887
self.assertHandlerEqual('Branch.set_last_revision_info',
1636
smart.branch.SmartServerBranchRequestSetLastRevisionInfo)
1888
smart_branch.SmartServerBranchRequestSetLastRevisionInfo)
1637
1889
self.assertHandlerEqual('Branch.set_last_revision_ex',
1638
smart.branch.SmartServerBranchRequestSetLastRevisionEx)
1890
smart_branch.SmartServerBranchRequestSetLastRevisionEx)
1639
1891
self.assertHandlerEqual('Branch.set_parent_location',
1640
smart.branch.SmartServerBranchRequestSetParentLocation)
1892
smart_branch.SmartServerBranchRequestSetParentLocation)
1641
1893
self.assertHandlerEqual('Branch.unlock',
1642
smart.branch.SmartServerBranchRequestUnlock)
1894
smart_branch.SmartServerBranchRequestUnlock)
1643
1895
self.assertHandlerEqual('BzrDir.find_repository',
1644
smart.bzrdir.SmartServerRequestFindRepositoryV1)
1896
smart_dir.SmartServerRequestFindRepositoryV1)
1645
1897
self.assertHandlerEqual('BzrDir.find_repositoryV2',
1646
smart.bzrdir.SmartServerRequestFindRepositoryV2)
1898
smart_dir.SmartServerRequestFindRepositoryV2)
1647
1899
self.assertHandlerEqual('BzrDirFormat.initialize',
1648
smart.bzrdir.SmartServerRequestInitializeBzrDir)
1900
smart_dir.SmartServerRequestInitializeBzrDir)
1649
1901
self.assertHandlerEqual('BzrDirFormat.initialize_ex_1.16',
1650
smart.bzrdir.SmartServerRequestBzrDirInitializeEx)
1902
smart_dir.SmartServerRequestBzrDirInitializeEx)
1651
1903
self.assertHandlerEqual('BzrDir.cloning_metadir',
1652
smart.bzrdir.SmartServerBzrDirRequestCloningMetaDir)
1904
smart_dir.SmartServerBzrDirRequestCloningMetaDir)
1653
1905
self.assertHandlerEqual('BzrDir.get_config_file',
1654
smart.bzrdir.SmartServerBzrDirRequestConfigFile)
1906
smart_dir.SmartServerBzrDirRequestConfigFile)
1655
1907
self.assertHandlerEqual('BzrDir.open_branch',
1656
smart.bzrdir.SmartServerRequestOpenBranch)
1908
smart_dir.SmartServerRequestOpenBranch)
1657
1909
self.assertHandlerEqual('BzrDir.open_branchV2',
1658
smart.bzrdir.SmartServerRequestOpenBranchV2)
1910
smart_dir.SmartServerRequestOpenBranchV2)
1911
self.assertHandlerEqual('BzrDir.open_branchV3',
1912
smart_dir.SmartServerRequestOpenBranchV3)
1659
1913
self.assertHandlerEqual('PackRepository.autopack',
1660
smart.packrepository.SmartServerPackRepositoryAutopack)
1914
smart_packrepo.SmartServerPackRepositoryAutopack)
1661
1915
self.assertHandlerEqual('Repository.gather_stats',
1662
smart.repository.SmartServerRepositoryGatherStats)
1916
smart_repo.SmartServerRepositoryGatherStats)
1663
1917
self.assertHandlerEqual('Repository.get_parent_map',
1664
smart.repository.SmartServerRepositoryGetParentMap)
1918
smart_repo.SmartServerRepositoryGetParentMap)
1665
1919
self.assertHandlerEqual('Repository.get_rev_id_for_revno',
1666
smart.repository.SmartServerRepositoryGetRevIdForRevno)
1920
smart_repo.SmartServerRepositoryGetRevIdForRevno)
1667
1921
self.assertHandlerEqual('Repository.get_revision_graph',
1668
smart.repository.SmartServerRepositoryGetRevisionGraph)
1922
smart_repo.SmartServerRepositoryGetRevisionGraph)
1669
1923
self.assertHandlerEqual('Repository.get_stream',
1670
smart.repository.SmartServerRepositoryGetStream)
1924
smart_repo.SmartServerRepositoryGetStream)
1925
self.assertHandlerEqual('Repository.get_stream_1.19',
1926
smart_repo.SmartServerRepositoryGetStream_1_19)
1671
1927
self.assertHandlerEqual('Repository.has_revision',
1672
smart.repository.SmartServerRequestHasRevision)
1928
smart_repo.SmartServerRequestHasRevision)
1673
1929
self.assertHandlerEqual('Repository.insert_stream',
1674
smart.repository.SmartServerRepositoryInsertStream)
1930
smart_repo.SmartServerRepositoryInsertStream)
1675
1931
self.assertHandlerEqual('Repository.insert_stream_locked',
1676
smart.repository.SmartServerRepositoryInsertStreamLocked)
1932
smart_repo.SmartServerRepositoryInsertStreamLocked)
1677
1933
self.assertHandlerEqual('Repository.is_shared',
1678
smart.repository.SmartServerRepositoryIsShared)
1934
smart_repo.SmartServerRepositoryIsShared)
1679
1935
self.assertHandlerEqual('Repository.lock_write',
1680
smart.repository.SmartServerRepositoryLockWrite)
1936
smart_repo.SmartServerRepositoryLockWrite)
1681
1937
self.assertHandlerEqual('Repository.tarball',
1682
smart.repository.SmartServerRepositoryTarball)
1938
smart_repo.SmartServerRepositoryTarball)
1683
1939
self.assertHandlerEqual('Repository.unlock',
1684
smart.repository.SmartServerRepositoryUnlock)
1940
smart_repo.SmartServerRepositoryUnlock)
1685
1941
self.assertHandlerEqual('Transport.is_readonly',
1686
smart.request.SmartServerIsReadonly)
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/')])