13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
"""Tests for the BzrDir facility and any format specific tests.
19
For interface contract tests, see tests/per_bzr_dir.
19
For interface contract tests, see tests/bzr_dir_implementations.
24
from StringIO import StringIO
26
28
from bzrlib import (
35
revision as _mod_revision,
38
transport as _mod_transport,
44
39
import bzrlib.branch
45
from bzrlib.branchfmt.fullhistory import BzrBranchFormat5
46
from bzrlib.errors import (
48
NoColocatedBranchSupport,
50
UnsupportedFormatError,
40
from bzrlib.errors import (NotBranchError,
42
UnsupportedFormatError,
52
44
from bzrlib.tests import (
54
46
TestCaseWithMemoryTransport,
55
47
TestCaseWithTransport,
58
from bzrlib.tests import(
51
from bzrlib.tests.http_server import HttpServer
52
from bzrlib.tests.http_utils import (
53
TestCaseWithTwoWebservers,
54
HTTPServerRedirecting,
62
56
from bzrlib.tests.test_http import TestWithTransport_pycurl
63
from bzrlib.transport import (
57
from bzrlib.transport import get_transport
67
58
from bzrlib.transport.http._urllib import HttpTransport_urllib
68
from bzrlib.transport.nosmart import NoSmartTransportDecorator
69
from bzrlib.transport.readonly import ReadonlyTransportDecorator
70
from bzrlib.repofmt import knitrepo, knitpack_repo
59
from bzrlib.transport.memory import MemoryServer
60
from bzrlib.repofmt import knitrepo, weaverepo
73
63
class TestDefaultFormat(TestCase):
75
65
def test_get_set_default_format(self):
76
66
old_format = bzrdir.BzrDirFormat.get_default_format()
77
# default is BzrDirMetaFormat1
78
self.assertIsInstance(old_format, bzrdir.BzrDirMetaFormat1)
79
controldir.ControlDirFormat._set_default_format(SampleBzrDirFormat())
67
# default is BzrDirFormat6
68
self.failUnless(isinstance(old_format, bzrdir.BzrDirMetaFormat1))
69
bzrdir.BzrDirFormat._set_default_format(SampleBzrDirFormat())
80
70
# creating a bzr dir should now create an instrumented dir.
82
72
result = bzrdir.BzrDir.create('memory:///')
83
self.assertIsInstance(result, SampleBzrDir)
73
self.failUnless(isinstance(result, SampleBzrDir))
85
controldir.ControlDirFormat._set_default_format(old_format)
75
bzrdir.BzrDirFormat._set_default_format(old_format)
86
76
self.assertEqual(old_format, bzrdir.BzrDirFormat.get_default_format())
89
class DeprecatedBzrDirFormat(bzrdir.BzrDirFormat):
90
"""A deprecated bzr dir format."""
93
79
class TestFormatRegistry(TestCase):
95
81
def make_format_registry(self):
96
my_format_registry = controldir.ControlDirFormatRegistry()
97
my_format_registry.register('deprecated', DeprecatedBzrDirFormat,
98
'Some format. Slower and unawesome and deprecated.',
100
my_format_registry.register_lazy('lazy', 'bzrlib.tests.test_bzrdir',
101
'DeprecatedBzrDirFormat', 'Format registered lazily',
103
bzrdir.register_metadir(my_format_registry, 'knit',
82
my_format_registry = bzrdir.BzrDirFormatRegistry()
83
my_format_registry.register('weave', bzrdir.BzrDirFormat6,
84
'Pre-0.8 format. Slower and does not support checkouts or shared'
85
' repositories', deprecated=True)
86
my_format_registry.register_lazy('lazy', 'bzrlib.bzrdir',
87
'BzrDirFormat6', 'Format registered lazily', deprecated=True)
88
my_format_registry.register_metadir('knit',
104
89
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
105
90
'Format using knits',
107
92
my_format_registry.set_default('knit')
108
bzrdir.register_metadir(my_format_registry,
93
my_format_registry.register_metadir(
110
95
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
111
96
'Experimental successor to knit. Use at your own risk.',
112
97
branch_format='bzrlib.branch.BzrBranchFormat6',
113
98
experimental=True)
114
bzrdir.register_metadir(my_format_registry,
99
my_format_registry.register_metadir(
116
101
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
117
102
'Experimental successor to knit. Use at your own risk.',
118
103
branch_format='bzrlib.branch.BzrBranchFormat6', hidden=True)
119
my_format_registry.register('hiddendeprecated', DeprecatedBzrDirFormat,
120
'Old format. Slower and does not support things. ', hidden=True)
121
my_format_registry.register_lazy('hiddenlazy', 'bzrlib.tests.test_bzrdir',
122
'DeprecatedBzrDirFormat', 'Format registered lazily',
123
deprecated=True, hidden=True)
104
my_format_registry.register('hiddenweave', bzrdir.BzrDirFormat6,
105
'Pre-0.8 format. Slower and does not support checkouts or shared'
106
' repositories', hidden=True)
107
my_format_registry.register_lazy('hiddenlazy', 'bzrlib.bzrdir',
108
'BzrDirFormat6', 'Format registered lazily', deprecated=True,
124
110
return my_format_registry
126
112
def test_format_registry(self):
127
113
my_format_registry = self.make_format_registry()
128
114
my_bzrdir = my_format_registry.make_bzrdir('lazy')
129
self.assertIsInstance(my_bzrdir, DeprecatedBzrDirFormat)
130
my_bzrdir = my_format_registry.make_bzrdir('deprecated')
131
self.assertIsInstance(my_bzrdir, DeprecatedBzrDirFormat)
115
self.assertIsInstance(my_bzrdir, bzrdir.BzrDirFormat6)
116
my_bzrdir = my_format_registry.make_bzrdir('weave')
117
self.assertIsInstance(my_bzrdir, bzrdir.BzrDirFormat6)
132
118
my_bzrdir = my_format_registry.make_bzrdir('default')
133
self.assertIsInstance(my_bzrdir.repository_format,
119
self.assertIsInstance(my_bzrdir.repository_format,
134
120
knitrepo.RepositoryFormatKnit1)
135
121
my_bzrdir = my_format_registry.make_bzrdir('knit')
136
self.assertIsInstance(my_bzrdir.repository_format,
122
self.assertIsInstance(my_bzrdir.repository_format,
137
123
knitrepo.RepositoryFormatKnit1)
138
124
my_bzrdir = my_format_registry.make_bzrdir('branch6')
139
125
self.assertIsInstance(my_bzrdir.get_branch_format(),
143
129
my_format_registry = self.make_format_registry()
144
130
self.assertEqual('Format registered lazily',
145
131
my_format_registry.get_help('lazy'))
146
self.assertEqual('Format using knits',
132
self.assertEqual('Format using knits',
147
133
my_format_registry.get_help('knit'))
148
self.assertEqual('Format using knits',
134
self.assertEqual('Format using knits',
149
135
my_format_registry.get_help('default'))
150
self.assertEqual('Some format. Slower and unawesome and deprecated.',
151
my_format_registry.get_help('deprecated'))
136
self.assertEqual('Pre-0.8 format. Slower and does not support'
137
' checkouts or shared repositories',
138
my_format_registry.get_help('weave'))
153
140
def test_help_topic(self):
154
141
topics = help_topics.HelpTopicRegistry()
155
registry = self.make_format_registry()
156
topics.register('current-formats', registry.help_topic,
158
topics.register('other-formats', registry.help_topic,
160
new = topics.get_detail('current-formats')
161
rest = topics.get_detail('other-formats')
142
topics.register('formats', self.make_format_registry().help_topic,
144
topic = topics.get_detail('formats')
145
new, rest = topic.split('Experimental formats')
162
146
experimental, deprecated = rest.split('Deprecated formats')
163
self.assertContainsRe(new, 'formats-help')
164
self.assertContainsRe(new,
147
self.assertContainsRe(new, 'These formats can be used')
148
self.assertContainsRe(new,
165
149
':knit:\n \(native\) \(default\) Format using knits\n')
166
self.assertContainsRe(experimental,
150
self.assertContainsRe(experimental,
167
151
':branch6:\n \(native\) Experimental successor to knit')
168
self.assertContainsRe(deprecated,
152
self.assertContainsRe(deprecated,
169
153
':lazy:\n \(native\) Format registered lazily\n')
170
154
self.assertNotContainsRe(new, 'hidden')
172
156
def test_set_default_repository(self):
173
default_factory = controldir.format_registry.get('default')
174
old_default = [k for k, v in controldir.format_registry.iteritems()
157
default_factory = bzrdir.format_registry.get('default')
158
old_default = [k for k, v in bzrdir.format_registry.iteritems()
175
159
if v == default_factory and k != 'default'][0]
176
controldir.format_registry.set_default_repository('dirstate-with-subtree')
160
bzrdir.format_registry.set_default_repository('dirstate-with-subtree')
178
self.assertIs(controldir.format_registry.get('dirstate-with-subtree'),
179
controldir.format_registry.get('default'))
162
self.assertIs(bzrdir.format_registry.get('dirstate-with-subtree'),
163
bzrdir.format_registry.get('default'))
181
repository.format_registry.get_default().__class__,
165
repository.RepositoryFormat.get_default_format().__class__,
182
166
knitrepo.RepositoryFormatKnit3)
184
controldir.format_registry.set_default_repository(old_default)
168
bzrdir.format_registry.set_default_repository(old_default)
186
170
def test_aliases(self):
187
a_registry = controldir.ControlDirFormatRegistry()
188
a_registry.register('deprecated', DeprecatedBzrDirFormat,
189
'Old format. Slower and does not support stuff',
191
a_registry.register('deprecatedalias', DeprecatedBzrDirFormat,
192
'Old format. Slower and does not support stuff',
193
deprecated=True, alias=True)
194
self.assertEqual(frozenset(['deprecatedalias']), a_registry.aliases())
171
a_registry = bzrdir.BzrDirFormatRegistry()
172
a_registry.register('weave', bzrdir.BzrDirFormat6,
173
'Pre-0.8 format. Slower and does not support checkouts or shared'
174
' repositories', deprecated=True)
175
a_registry.register('weavealias', bzrdir.BzrDirFormat6,
176
'Pre-0.8 format. Slower and does not support checkouts or shared'
177
' repositories', deprecated=True, alias=True)
178
self.assertEqual(frozenset(['weavealias']), a_registry.aliases())
197
181
class SampleBranch(bzrlib.branch.Branch):
198
182
"""A dummy branch for guess what, dummy use."""
278
235
def test_find_format(self):
279
236
# is the right format object found for a branch?
280
237
# create a branch with a few known format objects.
281
bzrdir.BzrProber.formats.register(BzrDirFormatTest1.get_format_string(),
283
self.addCleanup(bzrdir.BzrProber.formats.remove,
284
BzrDirFormatTest1.get_format_string())
285
bzrdir.BzrProber.formats.register(BzrDirFormatTest2.get_format_string(),
287
self.addCleanup(bzrdir.BzrProber.formats.remove,
288
BzrDirFormatTest2.get_format_string())
289
t = self.get_transport()
238
# this is not quite the same as
239
t = get_transport(self.get_url())
290
240
self.build_tree(["foo/", "bar/"], transport=t)
291
241
def check_format(format, url):
292
242
format.initialize(url)
293
t = _mod_transport.get_transport_from_path(url)
243
t = get_transport(url)
294
244
found_format = bzrdir.BzrDirFormat.find_format(t)
295
self.assertIsInstance(found_format, format.__class__)
296
check_format(BzrDirFormatTest1(), "foo")
297
check_format(BzrDirFormatTest2(), "bar")
245
self.failUnless(isinstance(found_format, format.__class__))
246
check_format(bzrdir.BzrDirFormat5(), "foo")
247
check_format(bzrdir.BzrDirFormat6(), "bar")
299
249
def test_find_format_nothing_there(self):
300
250
self.assertRaises(NotBranchError,
301
251
bzrdir.BzrDirFormat.find_format,
302
_mod_transport.get_transport_from_path('.'))
304
254
def test_find_format_unknown_format(self):
305
t = self.get_transport()
255
t = get_transport(self.get_url())
307
257
t.put_bytes('.bzr/branch-format', '')
308
258
self.assertRaises(UnknownFormatError,
309
259
bzrdir.BzrDirFormat.find_format,
310
_mod_transport.get_transport_from_path('.'))
312
262
def test_register_unregister_format(self):
313
263
format = SampleBzrDirFormat()
357
307
def test_create_standalone_working_tree(self):
358
308
format = SampleBzrDirFormat()
359
# note this is deliberately readonly, as this failure should
309
# note this is deliberately readonly, as this failure should
360
310
# occur before any writes.
361
311
self.assertRaises(errors.NotLocalUrl,
362
312
bzrdir.BzrDir.create_standalone_workingtree,
363
313
self.get_readonly_url(), format=format)
364
tree = bzrdir.BzrDir.create_standalone_workingtree('.',
314
tree = bzrdir.BzrDir.create_standalone_workingtree('.',
366
316
self.assertEqual('A tree', tree)
368
318
def test_create_standalone_working_tree_under_shared_repo(self):
369
319
# create standalone working tree always makes a repo.
370
format = controldir.format_registry.make_bzrdir('knit')
320
format = bzrdir.format_registry.make_bzrdir('knit')
371
321
self.make_repository('.', shared=True, format=format)
372
# note this is deliberately readonly, as this failure should
322
# note this is deliberately readonly, as this failure should
373
323
# occur before any writes.
374
324
self.assertRaises(errors.NotLocalUrl,
375
325
bzrdir.BzrDir.create_standalone_workingtree,
376
326
self.get_readonly_url('child'), format=format)
377
tree = bzrdir.BzrDir.create_standalone_workingtree('child',
327
tree = bzrdir.BzrDir.create_standalone_workingtree('child',
379
329
tree.bzrdir.open_repository()
381
331
def test_create_branch_convenience(self):
382
332
# outside a repo the default convenience output is a repo+branch_tree
383
format = controldir.format_registry.make_bzrdir('knit')
333
format = bzrdir.format_registry.make_bzrdir('knit')
384
334
branch = bzrdir.BzrDir.create_branch_convenience('.', format=format)
385
335
branch.bzrdir.open_workingtree()
386
336
branch.bzrdir.open_repository()
388
338
def test_create_branch_convenience_possible_transports(self):
389
339
"""Check that the optional 'possible_transports' is recognized"""
390
format = controldir.format_registry.make_bzrdir('knit')
340
format = bzrdir.format_registry.make_bzrdir('knit')
391
341
t = self.get_transport()
392
342
branch = bzrdir.BzrDir.create_branch_convenience(
393
343
'.', format=format, possible_transports=[t])
504
455
self.assertEqual(child_branch.base,
505
456
new_child.open_branch().get_stacked_on_url())
507
def test_default_stacking_with_stackable_branch_unstackable_repo(self):
508
# Make stackable source branch with an unstackable repo format.
509
source_bzrdir = self.make_bzrdir('source')
510
knitpack_repo.RepositoryFormatKnitPack1().initialize(source_bzrdir)
511
source_branch = bzrlib.branch.BzrBranchFormat7().initialize(
513
# Make a directory with a default stacking policy
514
parent_bzrdir = self.make_bzrdir('parent')
515
stacked_on = self.make_branch('parent/stacked-on', format='pack-0.92')
516
parent_bzrdir.get_config().set_default_stack_on(stacked_on.base)
517
# Clone source into directory
518
target = source_bzrdir.clone(self.get_url('parent/target'))
520
def test_format_initialize_on_transport_ex_stacked_on(self):
521
# trunk is a stackable format. Note that its in the same server area
522
# which is what launchpad does, but not sufficient to exercise the
524
trunk = self.make_branch('trunk', format='1.9')
525
t = self.get_transport('stacked')
526
old_fmt = controldir.format_registry.make_bzrdir('pack-0.92')
527
repo_name = old_fmt.repository_format.network_name()
528
# Should end up with a 1.9 format (stackable)
529
repo, control, require_stacking, repo_policy = \
530
old_fmt.initialize_on_transport_ex(t,
531
repo_format_name=repo_name, stacked_on='../trunk',
534
# Repositories are open write-locked
535
self.assertTrue(repo.is_write_locked())
536
self.addCleanup(repo.unlock)
538
repo = control.open_repository()
539
self.assertIsInstance(control, bzrdir.BzrDir)
540
opened = bzrdir.BzrDir.open(t.base)
541
if not isinstance(old_fmt, remote.RemoteBzrDirFormat):
542
self.assertEqual(control._format.network_name(),
543
old_fmt.network_name())
544
self.assertEqual(control._format.network_name(),
545
opened._format.network_name())
546
self.assertEqual(control.__class__, opened.__class__)
547
self.assertLength(1, repo._fallback_repositories)
549
458
def test_sprout_obeys_stacking_policy(self):
550
459
child_branch, new_child_transport = self.prepare_default_stacking()
551
460
new_child = child_branch.bzrdir.sprout(new_child_transport.base)
598
507
self.assertTrue(repo.supports_rich_root())
600
509
def test_add_fallback_repo_handles_absolute_urls(self):
601
stack_on = self.make_branch('stack_on', format='1.6')
602
repo = self.make_repository('repo', format='1.6')
510
stack_on = self.make_branch('stack_on', format='development1')
511
repo = self.make_repository('repo', format='development1')
603
512
policy = bzrdir.UseExistingRepository(repo, stack_on.base)
604
513
policy._add_fallback(repo)
606
515
def test_add_fallback_repo_handles_relative_urls(self):
607
stack_on = self.make_branch('stack_on', format='1.6')
608
repo = self.make_repository('repo', format='1.6')
516
stack_on = self.make_branch('stack_on', format='development1')
517
repo = self.make_repository('repo', format='development1')
609
518
policy = bzrdir.UseExistingRepository(repo, '.', stack_on.base)
610
519
policy._add_fallback(repo)
612
521
def test_configure_relative_branch_stacking_url(self):
613
stack_on = self.make_branch('stack_on', format='1.6')
614
stacked = self.make_branch('stack_on/stacked', format='1.6')
522
stack_on = self.make_branch('stack_on', format='development1')
523
stacked = self.make_branch('stack_on/stacked', format='development1')
615
524
policy = bzrdir.UseExistingRepository(stacked.repository,
616
525
'.', stack_on.base)
617
526
policy.configure_branch(stacked)
618
527
self.assertEqual('..', stacked.get_stacked_on_url())
620
529
def test_relative_branch_stacking_to_absolute(self):
621
stack_on = self.make_branch('stack_on', format='1.6')
622
stacked = self.make_branch('stack_on/stacked', format='1.6')
530
stack_on = self.make_branch('stack_on', format='development1')
531
stacked = self.make_branch('stack_on/stacked', format='development1')
623
532
policy = bzrdir.UseExistingRepository(stacked.repository,
624
533
'.', self.get_readonly_url('stack_on'))
625
534
policy.configure_branch(stacked)
806
710
# transport pointing at bzrdir should give a bzrdir with root transport
807
711
# set to the given transport
808
712
control = bzrdir.BzrDir.create(self.get_url())
809
t = self.get_transport()
810
opened_bzrdir = bzrdir.BzrDir.open_from_transport(t)
811
self.assertEqual(t.base, opened_bzrdir.root_transport.base)
713
transport = get_transport(self.get_url())
714
opened_bzrdir = bzrdir.BzrDir.open_from_transport(transport)
715
self.assertEqual(transport.base, opened_bzrdir.root_transport.base)
812
716
self.assertIsInstance(opened_bzrdir, bzrdir.BzrDir)
814
718
def test_open_from_transport_no_bzrdir(self):
815
t = self.get_transport()
816
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport, t)
719
transport = get_transport(self.get_url())
720
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
818
723
def test_open_from_transport_bzrdir_in_parent(self):
819
724
control = bzrdir.BzrDir.create(self.get_url())
820
t = self.get_transport()
822
t = t.clone('subdir')
823
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport, t)
725
transport = get_transport(self.get_url())
726
transport.mkdir('subdir')
727
transport = transport.clone('subdir')
728
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
825
731
def test_sprout_recursive(self):
826
tree = self.make_branch_and_tree('tree1',
827
format='development-subtree')
732
tree = self.make_branch_and_tree('tree1', format='dirstate-with-subtree')
828
733
sub_tree = self.make_branch_and_tree('tree1/subtree',
829
format='development-subtree')
830
sub_tree.set_root_id('subtree-root')
734
format='dirstate-with-subtree')
831
735
tree.add_reference(sub_tree)
832
736
self.build_tree(['tree1/subtree/file'])
833
737
sub_tree.add('file')
834
738
tree.commit('Initial commit')
835
tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
837
self.addCleanup(tree2.unlock)
838
self.assertPathExists('tree2/subtree/file')
839
self.assertEqual('tree-reference', tree2.kind('subtree-root'))
739
tree.bzrdir.sprout('tree2')
740
self.failUnlessExists('tree2/subtree/file')
841
742
def test_cloning_metadir(self):
842
743
"""Ensure that cloning metadir is suitable"""
845
746
branch = self.make_branch('branch', format='knit')
846
747
format = branch.bzrdir.cloning_metadir()
847
748
self.assertIsInstance(format.workingtree_format,
848
workingtree_4.WorkingTreeFormat6)
749
workingtree.WorkingTreeFormat3)
850
751
def test_sprout_recursive_treeless(self):
851
752
tree = self.make_branch_and_tree('tree1',
852
format='development-subtree')
753
format='dirstate-with-subtree')
853
754
sub_tree = self.make_branch_and_tree('tree1/subtree',
854
format='development-subtree')
755
format='dirstate-with-subtree')
855
756
tree.add_reference(sub_tree)
856
757
self.build_tree(['tree1/subtree/file'])
857
758
sub_tree.add('file')
858
759
tree.commit('Initial commit')
859
# The following line force the orhaning to reveal bug #634470
860
tree.branch.get_config_stack().set(
861
'bzr.transform.orphan_policy', 'move')
862
760
tree.bzrdir.destroy_workingtree()
863
# FIXME: subtree/.bzr is left here which allows the test to pass (or
864
# fail :-( ) -- vila 20100909
865
761
repo = self.make_repository('repo', shared=True,
866
format='development-subtree')
762
format='dirstate-with-subtree')
867
763
repo.set_make_working_trees(False)
868
# FIXME: we just deleted the workingtree and now we want to use it ????
869
# At a minimum, we should use tree.branch below (but this fails too
870
# currently) or stop calling this test 'treeless'. Specifically, I've
871
# turn the line below into an assertRaises when 'subtree/.bzr' is
872
# orphaned and sprout tries to access the branch there (which is left
873
# by bzrdir.BzrDirMeta1.destroy_workingtree when it ignores the
874
# [DeletingParent('Not deleting', u'subtree', None)] conflict). See bug
875
# #634470. -- vila 20100909
876
self.assertRaises(errors.NotBranchError,
877
tree.bzrdir.sprout, 'repo/tree2')
878
# self.assertPathExists('repo/tree2/subtree')
879
# self.assertPathDoesNotExist('repo/tree2/subtree/file')
764
tree.bzrdir.sprout('repo/tree2')
765
self.failUnlessExists('repo/tree2/subtree')
766
self.failIfExists('repo/tree2/subtree/file')
881
768
def make_foo_bar_baz(self):
882
769
foo = bzrdir.BzrDir.create_branch_convenience('foo').bzrdir
887
774
def test_find_bzrdirs(self):
888
775
foo, bar, baz = self.make_foo_bar_baz()
889
t = self.get_transport()
890
self.assertEqualBzrdirs([baz, foo, bar], bzrdir.BzrDir.find_bzrdirs(t))
892
def make_fake_permission_denied_transport(self, transport, paths):
893
"""Create a transport that raises PermissionDenied for some paths."""
896
raise errors.PermissionDenied(path)
898
path_filter_server = pathfilter.PathFilteringServer(transport, filter)
899
path_filter_server.start_server()
900
self.addCleanup(path_filter_server.stop_server)
901
path_filter_transport = pathfilter.PathFilteringTransport(
902
path_filter_server, '.')
903
return (path_filter_server, path_filter_transport)
905
def assertBranchUrlsEndWith(self, expect_url_suffix, actual_bzrdirs):
906
"""Check that each branch url ends with the given suffix."""
907
for actual_bzrdir in actual_bzrdirs:
908
self.assertEndsWith(actual_bzrdir.user_url, expect_url_suffix)
910
def test_find_bzrdirs_permission_denied(self):
911
foo, bar, baz = self.make_foo_bar_baz()
912
t = self.get_transport()
913
path_filter_server, path_filter_transport = \
914
self.make_fake_permission_denied_transport(t, ['foo'])
916
self.assertBranchUrlsEndWith('/baz/',
917
bzrdir.BzrDir.find_bzrdirs(path_filter_transport))
919
smart_transport = self.make_smart_server('.',
920
backing_server=path_filter_server)
921
self.assertBranchUrlsEndWith('/baz/',
922
bzrdir.BzrDir.find_bzrdirs(smart_transport))
776
transport = get_transport(self.get_url())
777
self.assertEqualBzrdirs([baz, foo, bar],
778
bzrdir.BzrDir.find_bzrdirs(transport))
924
780
def test_find_bzrdirs_list_current(self):
925
781
def list_current(transport):
926
782
return [s for s in transport.list_dir('') if s != 'baz']
928
784
foo, bar, baz = self.make_foo_bar_baz()
929
t = self.get_transport()
930
self.assertEqualBzrdirs(
932
bzrdir.BzrDir.find_bzrdirs(t, list_current=list_current))
785
transport = get_transport(self.get_url())
786
self.assertEqualBzrdirs([foo, bar],
787
bzrdir.BzrDir.find_bzrdirs(transport,
788
list_current=list_current))
934
791
def test_find_bzrdirs_evaluate(self):
935
792
def evaluate(bzrdir):
937
794
repo = bzrdir.open_repository()
938
except errors.NoRepositoryPresent:
795
except NoRepositoryPresent:
939
796
return True, bzrdir.root_transport.base
941
798
return False, bzrdir.root_transport.base
943
800
foo, bar, baz = self.make_foo_bar_baz()
944
t = self.get_transport()
801
transport = get_transport(self.get_url())
945
802
self.assertEqual([baz.root_transport.base, foo.root_transport.base],
946
list(bzrdir.BzrDir.find_bzrdirs(t, evaluate=evaluate)))
803
list(bzrdir.BzrDir.find_bzrdirs(transport,
948
806
def assertEqualBzrdirs(self, first, second):
949
807
first = list(first)
1015
857
Metadirs should compare equal iff they have the same repo, branch and
1018
mydir = controldir.format_registry.make_bzrdir('knit')
860
mydir = bzrdir.format_registry.make_bzrdir('knit')
1019
861
self.assertEqual(mydir, mydir)
1020
862
self.assertFalse(mydir != mydir)
1021
otherdir = controldir.format_registry.make_bzrdir('knit')
863
otherdir = bzrdir.format_registry.make_bzrdir('knit')
1022
864
self.assertEqual(otherdir, mydir)
1023
865
self.assertFalse(otherdir != mydir)
1024
otherdir2 = controldir.format_registry.make_bzrdir('development-subtree')
866
otherdir2 = bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
1025
867
self.assertNotEqual(otherdir2, mydir)
1026
868
self.assertFalse(otherdir2 == mydir)
1028
def test_with_features(self):
1029
tree = self.make_branch_and_tree('tree', format='2a')
1030
tree.bzrdir.update_feature_flags({"bar": "required"})
1031
self.assertRaises(errors.MissingFeature, bzrdir.BzrDir.open, 'tree')
1032
bzrdir.BzrDirMetaFormat1.register_feature('bar')
1033
self.addCleanup(bzrdir.BzrDirMetaFormat1.unregister_feature, 'bar')
1034
dir = bzrdir.BzrDir.open('tree')
1035
self.assertEqual("required", dir._format.features.get("bar"))
1036
tree.bzrdir.update_feature_flags({"bar": None, "nonexistant": None})
1037
dir = bzrdir.BzrDir.open('tree')
1038
self.assertEqual({}, dir._format.features)
1040
870
def test_needs_conversion_different_working_tree(self):
1041
871
# meta1dirs need an conversion if any element is not the default.
1042
new_format = controldir.format_registry.make_bzrdir('dirstate')
1043
tree = self.make_branch_and_tree('tree', format='knit')
1044
self.assertTrue(tree.bzrdir.needs_format_conversion(
1047
def test_initialize_on_format_uses_smart_transport(self):
1048
self.setup_smart_server_with_call_log()
1049
new_format = controldir.format_registry.make_bzrdir('dirstate')
1050
transport = self.get_transport('target')
1051
transport.ensure_base()
1052
self.reset_smart_call_log()
1053
instance = new_format.initialize_on_transport(transport)
1054
self.assertIsInstance(instance, remote.RemoteBzrDir)
1055
rpc_count = len(self.hpss_calls)
1056
# This figure represent the amount of work to perform this use case. It
1057
# is entirely ok to reduce this number if a test fails due to rpc_count
1058
# being too low. If rpc_count increases, more network roundtrips have
1059
# become necessary for this use case. Please do not adjust this number
1060
# upwards without agreement from bzr's network support maintainers.
1061
self.assertEqual(2, rpc_count)
872
old_format = bzrdir.BzrDirFormat.get_default_format()
874
new_default = bzrdir.format_registry.make_bzrdir('dirstate')
875
bzrdir.BzrDirFormat._set_default_format(new_default)
877
tree = self.make_branch_and_tree('tree', format='knit')
878
self.assertTrue(tree.bzrdir.needs_format_conversion())
880
bzrdir.BzrDirFormat._set_default_format(old_format)
883
class TestFormat5(TestCaseWithTransport):
884
"""Tests specific to the version 5 bzrdir format."""
886
def test_same_lockfiles_between_tree_repo_branch(self):
887
# this checks that only a single lockfiles instance is created
888
# for format 5 objects
889
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
890
def check_dir_components_use_same_lock(dir):
891
ctrl_1 = dir.open_repository().control_files
892
ctrl_2 = dir.open_branch().control_files
893
ctrl_3 = dir.open_workingtree()._control_files
894
self.assertTrue(ctrl_1 is ctrl_2)
895
self.assertTrue(ctrl_2 is ctrl_3)
896
check_dir_components_use_same_lock(dir)
897
# and if we open it normally.
898
dir = bzrdir.BzrDir.open(self.get_url())
899
check_dir_components_use_same_lock(dir)
901
def test_can_convert(self):
902
# format 5 dirs are convertable
903
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
904
self.assertTrue(dir.can_convert_format())
906
def test_needs_conversion(self):
907
# format 5 dirs need a conversion if they are not the default.
908
# and they start of not the default.
909
old_format = bzrdir.BzrDirFormat.get_default_format()
910
bzrdir.BzrDirFormat._set_default_format(bzrdir.BzrDirFormat5())
912
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
913
self.assertFalse(dir.needs_format_conversion())
915
bzrdir.BzrDirFormat._set_default_format(old_format)
916
self.assertTrue(dir.needs_format_conversion())
919
class TestFormat6(TestCaseWithTransport):
920
"""Tests specific to the version 6 bzrdir format."""
922
def test_same_lockfiles_between_tree_repo_branch(self):
923
# this checks that only a single lockfiles instance is created
924
# for format 6 objects
925
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
926
def check_dir_components_use_same_lock(dir):
927
ctrl_1 = dir.open_repository().control_files
928
ctrl_2 = dir.open_branch().control_files
929
ctrl_3 = dir.open_workingtree()._control_files
930
self.assertTrue(ctrl_1 is ctrl_2)
931
self.assertTrue(ctrl_2 is ctrl_3)
932
check_dir_components_use_same_lock(dir)
933
# and if we open it normally.
934
dir = bzrdir.BzrDir.open(self.get_url())
935
check_dir_components_use_same_lock(dir)
937
def test_can_convert(self):
938
# format 6 dirs are convertable
939
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
940
self.assertTrue(dir.can_convert_format())
942
def test_needs_conversion(self):
943
# format 6 dirs need an conversion if they are not the default.
944
old_format = bzrdir.BzrDirFormat.get_default_format()
945
bzrdir.BzrDirFormat._set_default_format(bzrdir.BzrDirMetaFormat1())
947
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
948
self.assertTrue(dir.needs_format_conversion())
950
bzrdir.BzrDirFormat._set_default_format(old_format)
953
class NotBzrDir(bzrlib.bzrdir.BzrDir):
954
"""A non .bzr based control directory."""
956
def __init__(self, transport, format):
957
self._format = format
958
self.root_transport = transport
959
self.transport = transport.clone('.not')
962
class NotBzrDirFormat(bzrlib.bzrdir.BzrDirFormat):
963
"""A test class representing any non-.bzr based disk format."""
965
def initialize_on_transport(self, transport):
966
"""Initialize a new .not dir in the base directory of a Transport."""
967
transport.mkdir('.not')
968
return self.open(transport)
970
def open(self, transport):
971
"""Open this directory."""
972
return NotBzrDir(transport, self)
975
def _known_formats(self):
976
return set([NotBzrDirFormat()])
979
def probe_transport(self, transport):
980
"""Our format is present if the transport ends in '.not/'."""
981
if transport.has('.not'):
982
return NotBzrDirFormat()
985
class TestNotBzrDir(TestCaseWithTransport):
986
"""Tests for using the bzrdir api with a non .bzr based disk format.
988
If/when one of these is in the core, we can let the implementation tests
992
def test_create_and_find_format(self):
993
# create a .notbzr dir
994
format = NotBzrDirFormat()
995
dir = format.initialize(self.get_url())
996
self.assertIsInstance(dir, NotBzrDir)
998
bzrlib.bzrdir.BzrDirFormat.register_control_format(format)
1000
found = bzrlib.bzrdir.BzrDirFormat.find_format(
1001
get_transport(self.get_url()))
1002
self.assertIsInstance(found, NotBzrDirFormat)
1004
bzrlib.bzrdir.BzrDirFormat.unregister_control_format(format)
1006
def test_included_in_known_formats(self):
1007
bzrlib.bzrdir.BzrDirFormat.register_control_format(NotBzrDirFormat)
1009
formats = bzrlib.bzrdir.BzrDirFormat.known_formats()
1010
for format in formats:
1011
if isinstance(format, NotBzrDirFormat):
1013
self.fail("No NotBzrDirFormat in %s" % formats)
1015
bzrlib.bzrdir.BzrDirFormat.unregister_control_format(NotBzrDirFormat)
1064
1018
class NonLocalTests(TestCaseWithTransport):
1107
1061
my_bzrdir = bzrdir.BzrDir.open(self.get_url('branch-knit2'))
1108
1062
checkout_format = my_bzrdir.checkout_metadir()
1109
1063
self.assertIsInstance(checkout_format.workingtree_format,
1110
workingtree_4.WorkingTreeFormat4)
1113
class TestHTTPRedirections(object):
1114
"""Test redirection between two http servers.
1064
workingtree.WorkingTreeFormat3)
1067
class TestHTTPRedirectionLoop(object):
1068
"""Test redirection loop between two http servers.
1116
1070
This MUST be used by daughter classes that also inherit from
1117
1071
TestCaseWithTwoWebservers.
1119
1073
We can't inherit directly from TestCaseWithTwoWebservers or the
1120
1074
test framework will try to create an instance which cannot
1121
run, its implementation being incomplete.
1075
run, its implementation being incomplete.
1078
# Should be defined by daughter classes to ensure redirection
1079
# still use the same transport implementation (not currently
1080
# enforced as it's a bit tricky to get right (see the FIXME
1081
# in BzrDir.open_from_transport for the unique use case so
1124
1085
def create_transport_readonly_server(self):
1125
# We don't set the http protocol version, relying on the default
1126
return http_utils.HTTPServerRedirecting()
1086
return HTTPServerRedirecting()
1128
1088
def create_transport_secondary_server(self):
1129
# We don't set the http protocol version, relying on the default
1130
return http_utils.HTTPServerRedirecting()
1089
return HTTPServerRedirecting()
1132
1091
def setUp(self):
1133
super(TestHTTPRedirections, self).setUp()
1092
# Both servers redirect to each server creating a loop
1093
super(TestHTTPRedirectionLoop, self).setUp()
1134
1094
# The redirections will point to the new server
1135
1095
self.new_server = self.get_readonly_server()
1136
1096
# The requests to the old server will be redirected
1137
1097
self.old_server = self.get_secondary_server()
1138
1098
# Configure the redirections
1139
1099
self.old_server.redirect_to(self.new_server.host, self.new_server.port)
1100
self.new_server.redirect_to(self.old_server.host, self.old_server.port)
1102
def _qualified_url(self, host, port):
1103
return 'http+%s://%s:%s' % (self._qualifier, host, port)
1141
1105
def test_loop(self):
1142
# Both servers redirect to each other creating a loop
1143
self.new_server.redirect_to(self.old_server.host, self.old_server.port)
1144
1106
# Starting from either server should loop
1145
old_url = self._qualified_url(self.old_server.host,
1107
old_url = self._qualified_url(self.old_server.host,
1146
1108
self.old_server.port)
1147
1109
oldt = self._transport(old_url)
1148
1110
self.assertRaises(errors.NotBranchError,
1149
1111
bzrdir.BzrDir.open_from_transport, oldt)
1150
new_url = self._qualified_url(self.new_server.host,
1112
new_url = self._qualified_url(self.new_server.host,
1151
1113
self.new_server.port)
1152
1114
newt = self._transport(new_url)
1153
1115
self.assertRaises(errors.NotBranchError,
1154
1116
bzrdir.BzrDir.open_from_transport, newt)
1156
def test_qualifier_preserved(self):
1157
wt = self.make_branch_and_tree('branch')
1158
old_url = self._qualified_url(self.old_server.host,
1159
self.old_server.port)
1160
start = self._transport(old_url).clone('branch')
1161
bdir = bzrdir.BzrDir.open_from_transport(start)
1162
# Redirection should preserve the qualifier, hence the transport class
1164
self.assertIsInstance(bdir.root_transport, type(start))
1167
class TestHTTPRedirections_urllib(TestHTTPRedirections,
1168
http_utils.TestCaseWithTwoWebservers):
1119
class TestHTTPRedirections_urllib(TestHTTPRedirectionLoop,
1120
TestCaseWithTwoWebservers):
1169
1121
"""Tests redirections for urllib implementation"""
1123
_qualifier = 'urllib'
1171
1124
_transport = HttpTransport_urllib
1173
def _qualified_url(self, host, port):
1174
result = 'http+urllib://%s:%s' % (host, port)
1175
self.permit_url(result)
1180
1128
class TestHTTPRedirections_pycurl(TestWithTransport_pycurl,
1181
TestHTTPRedirections,
1182
http_utils.TestCaseWithTwoWebservers):
1129
TestHTTPRedirectionLoop,
1130
TestCaseWithTwoWebservers):
1183
1131
"""Tests redirections for pycurl implementation"""
1185
def _qualified_url(self, host, port):
1186
result = 'http+pycurl://%s:%s' % (host, port)
1187
self.permit_url(result)
1191
class TestHTTPRedirections_nosmart(TestHTTPRedirections,
1192
http_utils.TestCaseWithTwoWebservers):
1193
"""Tests redirections for the nosmart decorator"""
1195
_transport = NoSmartTransportDecorator
1197
def _qualified_url(self, host, port):
1198
result = 'nosmart+http://%s:%s' % (host, port)
1199
self.permit_url(result)
1203
class TestHTTPRedirections_readonly(TestHTTPRedirections,
1204
http_utils.TestCaseWithTwoWebservers):
1205
"""Tests redirections for readonly decoratror"""
1207
_transport = ReadonlyTransportDecorator
1209
def _qualified_url(self, host, port):
1210
result = 'readonly+http://%s:%s' % (host, port)
1211
self.permit_url(result)
1133
_qualifier = 'pycurl'
1215
1136
class TestDotBzrHidden(TestCaseWithTransport):
1251
1172
class _TestBzrDir(bzrdir.BzrDirMeta1):
1252
1173
"""Test BzrDir implementation for TestBzrDirSprout.
1254
1175
When created a _TestBzrDir already has repository and a branch. The branch
1255
1176
is a test double as well.
1258
1179
def __init__(self, *args, **kwargs):
1259
1180
super(_TestBzrDir, self).__init__(*args, **kwargs)
1260
self.test_branch = _TestBranch(self.transport)
1181
self.test_branch = _TestBranch()
1261
1182
self.test_branch.repository = self.create_repository()
1263
def open_branch(self, unsupported=False, possible_transports=None):
1184
def open_branch(self, unsupported=False):
1264
1185
return self.test_branch
1266
1187
def cloning_metadir(self, require_stacking=False):
1267
1188
return _TestBzrDirFormat()
1270
class _TestBranchFormat(bzrlib.branch.BranchFormat):
1271
"""Test Branch format for TestBzrDirSprout."""
1274
1191
class _TestBranch(bzrlib.branch.Branch):
1275
1192
"""Test Branch implementation for TestBzrDirSprout."""
1277
def __init__(self, transport, *args, **kwargs):
1278
self._format = _TestBranchFormat()
1279
self._transport = transport
1280
self.base = transport.base
1194
def __init__(self, *args, **kwargs):
1281
1195
super(_TestBranch, self).__init__(*args, **kwargs)
1282
1196
self.calls = []
1283
1197
self._parent = None
1285
1199
def sprout(self, *args, **kwargs):
1286
1200
self.calls.append('sprout')
1287
return _TestBranch(self._transport)
1201
return _TestBranch()
1289
1203
def copy_content_into(self, destination, revision_id=None):
1290
1204
self.calls.append('copy_content_into')
1292
def last_revision(self):
1293
return _mod_revision.NULL_REVISION
1295
1206
def get_parent(self):
1296
1207
return self._parent
1298
def _get_config(self):
1299
return config.TransportConfig(self._transport, 'branch.conf')
1301
def _get_config_store(self):
1302
return config.BranchStore(self)
1304
1209
def set_parent(self, parent):
1305
1210
self._parent = parent
1307
def lock_read(self):
1308
return lock.LogicalLockResult(self.unlock)
1314
1213
class TestBzrDirSprout(TestCaseWithMemoryTransport):
1346
1245
parent = grandparent_tree.bzrdir.sprout('parent').open_branch()
1347
1246
branch_tree = parent.bzrdir.sprout('branch').open_branch()
1348
1247
self.assertContainsRe(branch_tree.get_parent(), '/parent/$')
1351
class TestBzrDirHooks(TestCaseWithMemoryTransport):
1353
def test_pre_open_called(self):
1355
bzrdir.BzrDir.hooks.install_named_hook('pre_open', calls.append, None)
1356
transport = self.get_transport('foo')
1357
url = transport.base
1358
self.assertRaises(errors.NotBranchError, bzrdir.BzrDir.open, url)
1359
self.assertEqual([transport.base], [t.base for t in calls])
1361
def test_pre_open_actual_exceptions_raised(self):
1363
def fail_once(transport):
1366
raise errors.BzrError("fail")
1367
bzrdir.BzrDir.hooks.install_named_hook('pre_open', fail_once, None)
1368
transport = self.get_transport('foo')
1369
url = transport.base
1370
err = self.assertRaises(errors.BzrError, bzrdir.BzrDir.open, url)
1371
self.assertEqual('fail', err._preformatted_string)
1373
def test_post_repo_init(self):
1374
from bzrlib.controldir import RepoInitHookParams
1376
bzrdir.BzrDir.hooks.install_named_hook('post_repo_init',
1378
self.make_repository('foo')
1379
self.assertLength(1, calls)
1381
self.assertIsInstance(params, RepoInitHookParams)
1382
self.assertTrue(hasattr(params, 'bzrdir'))
1383
self.assertTrue(hasattr(params, 'repository'))
1385
def test_post_repo_init_hook_repr(self):
1387
bzrdir.BzrDir.hooks.install_named_hook('post_repo_init',
1388
lambda params: param_reprs.append(repr(params)), None)
1389
self.make_repository('foo')
1390
self.assertLength(1, param_reprs)
1391
param_repr = param_reprs[0]
1392
self.assertStartsWith(param_repr, '<RepoInitHookParams for ')
1395
class TestGenerateBackupName(TestCaseWithMemoryTransport):
1396
# FIXME: This may need to be unified with test_osutils.TestBackupNames or
1397
# moved to per_bzrdir or per_transport for better coverage ?
1401
super(TestGenerateBackupName, self).setUp()
1402
self._transport = self.get_transport()
1403
bzrdir.BzrDir.create(self.get_url(),
1404
possible_transports=[self._transport])
1405
self._bzrdir = bzrdir.BzrDir.open_from_transport(self._transport)
1408
self.assertEqual("a.~1~", self._bzrdir._available_backup_name("a"))
1410
def test_exiting(self):
1411
self._transport.put_bytes("a.~1~", "some content")
1412
self.assertEqual("a.~2~", self._bzrdir._available_backup_name("a"))
1415
class TestMeta1DirColoFormat(TestCaseWithTransport):
1416
"""Tests specific to the meta1 dir with colocated branches format."""
1418
def test_supports_colo(self):
1419
format = bzrdir.BzrDirMetaFormat1Colo()
1420
self.assertTrue(format.colocated_branches)
1422
def test_upgrade_from_2a(self):
1423
tree = self.make_branch_and_tree('.', format='2a')
1424
format = bzrdir.BzrDirMetaFormat1Colo()
1425
self.assertTrue(tree.bzrdir.needs_format_conversion(format))
1426
converter = tree.bzrdir._format.get_converter(format)
1427
result = converter.convert(tree.bzrdir, None)
1428
self.assertIsInstance(result._format, bzrdir.BzrDirMetaFormat1Colo)
1429
self.assertFalse(result.needs_format_conversion(format))
1431
def test_downgrade_to_2a(self):
1432
tree = self.make_branch_and_tree('.', format='development-colo')
1433
format = bzrdir.BzrDirMetaFormat1()
1434
self.assertTrue(tree.bzrdir.needs_format_conversion(format))
1435
converter = tree.bzrdir._format.get_converter(format)
1436
result = converter.convert(tree.bzrdir, None)
1437
self.assertIsInstance(result._format, bzrdir.BzrDirMetaFormat1)
1438
self.assertFalse(result.needs_format_conversion(format))
1440
def test_downgrade_to_2a_too_many_branches(self):
1441
tree = self.make_branch_and_tree('.', format='development-colo')
1442
tree.bzrdir.create_branch(name="another-colocated-branch")
1443
converter = tree.bzrdir._format.get_converter(
1444
bzrdir.BzrDirMetaFormat1())
1445
result = converter.convert(tree.bzrdir, bzrdir.BzrDirMetaFormat1())
1446
self.assertIsInstance(result._format, bzrdir.BzrDirMetaFormat1)
1448
def test_nested(self):
1449
tree = self.make_branch_and_tree('.', format='development-colo')
1450
tree.bzrdir.create_branch(name='foo')
1451
tree.bzrdir.create_branch(name='fool/bla')
1453
errors.ParentBranchExists, tree.bzrdir.create_branch,
1456
def test_parent(self):
1457
tree = self.make_branch_and_tree('.', format='development-colo')
1458
tree.bzrdir.create_branch(name='fool/bla')
1459
tree.bzrdir.create_branch(name='foo/bar')
1461
errors.AlreadyBranchError, tree.bzrdir.create_branch,
1465
class SampleBzrFormat(bzrdir.BzrFormat):
1468
def get_format_string(cls):
1469
return "First line\n"
1472
class TestBzrFormat(TestCase):
1473
"""Tests for BzrFormat."""
1475
def test_as_string(self):
1476
format = SampleBzrFormat()
1477
format.features = {"foo": "required"}
1478
self.assertEqual(format.as_string(),
1481
format.features["another"] = "optional"
1482
self.assertEqual(format.as_string(),
1485
"optional another\n")
1487
def test_network_name(self):
1488
# The network string should include the feature info
1489
format = SampleBzrFormat()
1490
format.features = {"foo": "required"}
1492
"First line\nrequired foo\n",
1493
format.network_name())
1495
def test_from_string_no_features(self):
1497
format = SampleBzrFormat.from_string(
1499
self.assertEqual({}, format.features)
1501
def test_from_string_with_feature(self):
1503
format = SampleBzrFormat.from_string(
1504
"First line\nrequired foo\n")
1505
self.assertEqual("required", format.features.get("foo"))
1507
def test_from_string_format_string_mismatch(self):
1508
# The first line has to match the format string
1509
self.assertRaises(AssertionError, SampleBzrFormat.from_string,
1510
"Second line\nrequired foo\n")
1512
def test_from_string_missing_space(self):
1513
# At least one space is required in the feature lines
1514
self.assertRaises(errors.ParseFormatError, SampleBzrFormat.from_string,
1515
"First line\nfoo\n")
1517
def test_from_string_with_spaces(self):
1518
# Feature with spaces (in case we add stuff like this in the future)
1519
format = SampleBzrFormat.from_string(
1520
"First line\nrequired foo with spaces\n")
1521
self.assertEqual("required", format.features.get("foo with spaces"))
1524
format1 = SampleBzrFormat()
1525
format1.features = {"nested-trees": "optional"}
1526
format2 = SampleBzrFormat()
1527
format2.features = {"nested-trees": "optional"}
1528
self.assertEqual(format1, format1)
1529
self.assertEqual(format1, format2)
1530
format3 = SampleBzrFormat()
1531
self.assertNotEqual(format1, format3)
1533
def test_check_support_status_optional(self):
1534
# Optional, so silently ignore
1535
format = SampleBzrFormat()
1536
format.features = {"nested-trees": "optional"}
1537
format.check_support_status(True)
1538
self.addCleanup(SampleBzrFormat.unregister_feature, "nested-trees")
1539
SampleBzrFormat.register_feature("nested-trees")
1540
format.check_support_status(True)
1542
def test_check_support_status_required(self):
1543
# Optional, so trigger an exception
1544
format = SampleBzrFormat()
1545
format.features = {"nested-trees": "required"}
1546
self.assertRaises(errors.MissingFeature, format.check_support_status,
1548
self.addCleanup(SampleBzrFormat.unregister_feature, "nested-trees")
1549
SampleBzrFormat.register_feature("nested-trees")
1550
format.check_support_status(True)
1552
def test_check_support_status_unknown(self):
1553
# treat unknown necessity as required
1554
format = SampleBzrFormat()
1555
format.features = {"nested-trees": "unknown"}
1556
self.assertRaises(errors.MissingFeature, format.check_support_status,
1558
self.addCleanup(SampleBzrFormat.unregister_feature, "nested-trees")
1559
SampleBzrFormat.register_feature("nested-trees")
1560
format.check_support_status(True)
1562
def test_feature_already_registered(self):
1563
# a feature can only be registered once
1564
self.addCleanup(SampleBzrFormat.unregister_feature, "nested-trees")
1565
SampleBzrFormat.register_feature("nested-trees")
1566
self.assertRaises(errors.FeatureAlreadyRegistered,
1567
SampleBzrFormat.register_feature, "nested-trees")
1569
def test_feature_with_space(self):
1570
# spaces are not allowed in feature names
1571
self.assertRaises(ValueError, SampleBzrFormat.register_feature,