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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
"""Tests for the Branch facility that are not interface tests.
19
For interface tests see tests/branch_implementations/*.py.
19
For interface tests see tests/per_branch/*.py.
21
21
For concrete class tests see this file, and for meta-branch tests
22
22
also see this file.
25
from StringIO import StringIO
25
from cStringIO import StringIO
27
27
from bzrlib import (
28
28
branch as _mod_branch,
35
from bzrlib.branch import (
39
BranchReferenceFormat,
45
from bzrlib.bzrdir import (BzrDirMetaFormat1, BzrDirMeta1,
47
from bzrlib.errors import (NotBranchError,
50
UnsupportedFormatError,
53
from bzrlib.tests import TestCase, TestCaseWithTransport
54
from bzrlib.transport import get_transport
56
class TestDefaultFormat(TestCase):
40
class TestDefaultFormat(tests.TestCase):
58
42
def test_default_format(self):
59
43
# update this if you change the default branch format
60
self.assertIsInstance(BranchFormat.get_default_format(),
44
self.assertIsInstance(_mod_branch.BranchFormat.get_default_format(),
45
_mod_branch.BzrBranchFormat7)
63
47
def test_default_format_is_same_as_bzrdir_default(self):
64
48
# XXX: it might be nice if there was only one place the default was
65
# set, but at the moment that's not true -- mbp 20070814 --
49
# set, but at the moment that's not true -- mbp 20070814 --
66
50
# https://bugs.launchpad.net/bzr/+bug/132376
67
self.assertEqual(BranchFormat.get_default_format(),
68
BzrDirFormat.get_default_format().get_branch_format())
52
_mod_branch.BranchFormat.get_default_format(),
53
bzrdir.BzrDirFormat.get_default_format().get_branch_format())
70
55
def test_get_set_default_format(self):
71
56
# set the format and then set it back again
72
old_format = BranchFormat.get_default_format()
73
BranchFormat.set_default_format(SampleBranchFormat())
57
old_format = _mod_branch.BranchFormat.get_default_format()
58
_mod_branch.BranchFormat.set_default_format(SampleBranchFormat())
75
60
# the default branch format is used by the meta dir format
76
61
# which is not the default bzrdir format at this point
77
dir = BzrDirMetaFormat1().initialize('memory:///')
62
dir = bzrdir.BzrDirMetaFormat1().initialize('memory:///')
78
63
result = dir.create_branch()
79
64
self.assertEqual(result, 'A branch')
81
BranchFormat.set_default_format(old_format)
82
self.assertEqual(old_format, BranchFormat.get_default_format())
85
class TestBranchFormat5(TestCaseWithTransport):
66
_mod_branch.BranchFormat.set_default_format(old_format)
67
self.assertEqual(old_format,
68
_mod_branch.BranchFormat.get_default_format())
71
class TestBranchFormat5(tests.TestCaseWithTransport):
86
72
"""Tests specific to branch format 5"""
88
74
def test_branch_format_5_uses_lockdir(self):
89
75
url = self.get_url()
90
bzrdir = BzrDirMetaFormat1().initialize(url)
91
bzrdir.create_repository()
92
branch = bzrdir.create_branch()
76
bdir = bzrdir.BzrDirMetaFormat1().initialize(url)
77
bdir.create_repository()
78
branch = bdir.create_branch()
93
79
t = self.get_transport()
94
80
self.log("branch instance is %r" % branch)
95
self.assert_(isinstance(branch, BzrBranch5))
81
self.assert_(isinstance(branch, _mod_branch.BzrBranch5))
96
82
self.assertIsDirectory('.', t)
97
83
self.assertIsDirectory('.bzr/branch', t)
98
84
self.assertIsDirectory('.bzr/branch/lock', t)
99
85
branch.lock_write()
101
self.assertIsDirectory('.bzr/branch/lock/held', t)
86
self.addCleanup(branch.unlock)
87
self.assertIsDirectory('.bzr/branch/lock/held', t)
105
89
def test_set_push_location(self):
106
from bzrlib.config import (locations_config_filename,
107
ensure_config_dir_exists)
108
ensure_config_dir_exists()
109
fn = locations_config_filename()
90
conf = config.LocationConfig.from_string('# comment\n', '.', save=True)
110
92
branch = self.make_branch('.', format='knit')
111
93
branch.set_push_location('foo')
112
94
local_path = urlutils.local_path_from_url(branch.base[:-1])
113
self.assertFileEqual("[%s]\n"
95
self.assertFileEqual("# comment\n"
114
97
"push_location = foo\n"
115
"push_location:policy = norecurse" % local_path,
98
"push_location:policy = norecurse\n" % local_path,
99
config.locations_config_filename())
118
101
# TODO RBC 20051029 test getting a push location from a branch in a
119
102
# recursive section - that is, it appends the branch name.
122
class SampleBranchFormat(BranchFormat):
105
class SampleBranchFormat(_mod_branch.BranchFormat):
123
106
"""A sample format
125
this format is initializable, unsupported to aid in testing the
108
this format is initializable, unsupported to aid in testing the
126
109
open and open_downlevel routines.
130
113
"""See BzrBranchFormat.get_format_string()."""
131
114
return "Sample branch format."
133
def initialize(self, a_bzrdir):
116
def initialize(self, a_bzrdir, name=None):
134
117
"""Format 4 branches cannot be created."""
135
t = a_bzrdir.get_branch_transport(self)
118
t = a_bzrdir.get_branch_transport(self, name=name)
136
119
t.put_bytes('format', self.get_format_string())
137
120
return 'A branch'
139
122
def is_supported(self):
142
def open(self, transport, _found=False):
125
def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
143
126
return "opened branch."
146
class TestBzrBranchFormat(TestCaseWithTransport):
129
# Demonstrating how lazy loading is often implemented:
130
# A constant string is created.
131
SampleSupportedBranchFormatString = "Sample supported branch format."
133
# And the format class can then reference the constant to avoid skew.
134
class SampleSupportedBranchFormat(_mod_branch.BranchFormat):
135
"""A sample supported format."""
137
def get_format_string(self):
138
"""See BzrBranchFormat.get_format_string()."""
139
return SampleSupportedBranchFormatString
141
def initialize(self, a_bzrdir, name=None):
142
t = a_bzrdir.get_branch_transport(self, name=name)
143
t.put_bytes('format', self.get_format_string())
146
def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
147
return "opened supported branch."
150
class TestBzrBranchFormat(tests.TestCaseWithTransport):
147
151
"""Tests for the BzrBranchFormat facility."""
149
153
def test_find_format(self):
150
154
# is the right format object found for a branch?
151
155
# create a branch with a few known format objects.
152
# this is not quite the same as
156
# this is not quite the same as
153
157
self.build_tree(["foo/", "bar/"])
154
158
def check_format(format, url):
155
159
dir = format._matchingbzrdir.initialize(url)
156
160
dir.create_repository()
157
161
format.initialize(dir)
158
found_format = BranchFormat.find_format(dir)
162
found_format = _mod_branch.BranchFormat.find_format(dir)
159
163
self.failUnless(isinstance(found_format, format.__class__))
160
check_format(BzrBranchFormat5(), "bar")
164
check_format(_mod_branch.BzrBranchFormat5(), "bar")
166
def test_find_format_factory(self):
167
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
168
SampleSupportedBranchFormat().initialize(dir)
169
factory = _mod_branch.MetaDirBranchFormatFactory(
170
SampleSupportedBranchFormatString,
171
"bzrlib.tests.test_branch", "SampleSupportedBranchFormat")
172
_mod_branch.BranchFormat.register_format(factory)
173
self.addCleanup(_mod_branch.BranchFormat.unregister_format, factory)
174
b = _mod_branch.Branch.open(self.get_url())
175
self.assertEqual(b, "opened supported branch.")
162
177
def test_find_format_not_branch(self):
163
178
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
164
self.assertRaises(NotBranchError,
165
BranchFormat.find_format,
179
self.assertRaises(errors.NotBranchError,
180
_mod_branch.BranchFormat.find_format,
168
183
def test_find_format_unknown_format(self):
169
184
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
170
185
SampleBranchFormat().initialize(dir)
171
self.assertRaises(UnknownFormatError,
172
BranchFormat.find_format,
186
self.assertRaises(errors.UnknownFormatError,
187
_mod_branch.BranchFormat.find_format,
175
190
def test_register_unregister_format(self):
180
195
format.initialize(dir)
181
196
# register a format for it.
182
BranchFormat.register_format(format)
197
_mod_branch.BranchFormat.register_format(format)
183
198
# which branch.Open will refuse (not supported)
184
self.assertRaises(UnsupportedFormatError, Branch.open, self.get_url())
199
self.assertRaises(errors.UnsupportedFormatError,
200
_mod_branch.Branch.open, self.get_url())
185
201
self.make_branch_and_tree('foo')
186
202
# but open_downlevel will work
187
self.assertEqual(format.open(dir), bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
205
bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
188
206
# unregister the format
189
BranchFormat.unregister_format(format)
207
_mod_branch.BranchFormat.unregister_format(format)
190
208
self.make_branch_and_tree('bar')
193
class TestBranch6(TestCaseWithTransport):
211
#Used by TestMetaDirBranchFormatFactory
212
FakeLazyFormat = None
215
class TestMetaDirBranchFormatFactory(tests.TestCase):
217
def test_get_format_string_does_not_load(self):
218
"""Formats have a static format string."""
219
factory = _mod_branch.MetaDirBranchFormatFactory("yo", None, None)
220
self.assertEqual("yo", factory.get_format_string())
222
def test_call_loads(self):
223
# __call__ is used by the network_format_registry interface to get a
225
global FakeLazyFormat
227
factory = _mod_branch.MetaDirBranchFormatFactory(None,
228
"bzrlib.tests.test_branch", "FakeLazyFormat")
229
self.assertRaises(AttributeError, factory)
231
def test_call_returns_call_of_referenced_object(self):
232
global FakeLazyFormat
233
FakeLazyFormat = lambda:'called'
234
factory = _mod_branch.MetaDirBranchFormatFactory(None,
235
"bzrlib.tests.test_branch", "FakeLazyFormat")
236
self.assertEqual('called', factory())
239
class TestBranch67(object):
240
"""Common tests for both branch 6 and 7 which are mostly the same."""
242
def get_format_name(self):
243
raise NotImplementedError(self.get_format_name)
245
def get_format_name_subtree(self):
246
raise NotImplementedError(self.get_format_name)
249
raise NotImplementedError(self.get_class)
195
251
def test_creation(self):
196
format = BzrDirMetaFormat1()
252
format = bzrdir.BzrDirMetaFormat1()
197
253
format.set_branch_format(_mod_branch.BzrBranchFormat6())
198
254
branch = self.make_branch('a', format=format)
199
self.assertIsInstance(branch, _mod_branch.BzrBranch6)
200
branch = self.make_branch('b', format='dirstate-tags')
201
self.assertIsInstance(branch, _mod_branch.BzrBranch6)
255
self.assertIsInstance(branch, self.get_class())
256
branch = self.make_branch('b', format=self.get_format_name())
257
self.assertIsInstance(branch, self.get_class())
202
258
branch = _mod_branch.Branch.open('a')
203
self.assertIsInstance(branch, _mod_branch.BzrBranch6)
259
self.assertIsInstance(branch, self.get_class())
205
261
def test_layout(self):
206
branch = self.make_branch('a', format='dirstate-tags')
262
branch = self.make_branch('a', format=self.get_format_name())
207
263
self.failUnlessExists('a/.bzr/branch/last-revision')
208
264
self.failIfExists('a/.bzr/branch/revision-history')
265
self.failIfExists('a/.bzr/branch/references')
210
267
def test_config(self):
211
268
"""Ensure that all configuration data is stored in the branch"""
212
branch = self.make_branch('a', format='dirstate-tags')
269
branch = self.make_branch('a', format=self.get_format_name())
213
270
branch.set_parent('http://bazaar-vcs.org')
214
271
self.failIfExists('a/.bzr/branch/parent')
215
272
self.assertEqual('http://bazaar-vcs.org', branch.get_parent())
222
279
self.assertEqual('ftp://bazaar-vcs.org', branch.get_bound_location())
224
281
def test_set_revision_history(self):
225
tree = self.make_branch_and_memory_tree('.',
226
format='dirstate-tags')
230
tree.commit('foo', rev_id='foo')
231
tree.commit('bar', rev_id='bar')
232
tree.branch.set_revision_history(['foo', 'bar'])
233
tree.branch.set_revision_history(['foo'])
234
self.assertRaises(errors.NotLefthandHistory,
235
tree.branch.set_revision_history, ['bar'])
282
builder = self.make_branch_builder('.', format=self.get_format_name())
283
builder.build_snapshot('foo', None,
284
[('add', ('', None, 'directory', None))],
286
builder.build_snapshot('bar', None, [], message='bar')
287
branch = builder.get_branch()
289
self.addCleanup(branch.unlock)
290
branch.set_revision_history(['foo', 'bar'])
291
branch.set_revision_history(['foo'])
292
self.assertRaises(errors.NotLefthandHistory,
293
branch.set_revision_history, ['bar'])
239
295
def do_checkout_test(self, lightweight=False):
240
tree = self.make_branch_and_tree('source', format='dirstate-with-subtree')
296
tree = self.make_branch_and_tree('source',
297
format=self.get_format_name_subtree())
241
298
subtree = self.make_branch_and_tree('source/subtree',
242
format='dirstate-with-subtree')
299
format=self.get_format_name_subtree())
243
300
subsubtree = self.make_branch_and_tree('source/subtree/subsubtree',
244
format='dirstate-with-subtree')
301
format=self.get_format_name_subtree())
245
302
self.build_tree(['source/subtree/file',
246
303
'source/subtree/subsubtree/file'])
247
304
subsubtree.add('file')
284
341
self.assertEqual(warnings[0], 'Value "new" is masked by "old" from '
285
342
'locations.conf')
287
class TestBranchReference(TestCaseWithTransport):
345
class TestBranch6(TestBranch67, tests.TestCaseWithTransport):
348
return _mod_branch.BzrBranch6
350
def get_format_name(self):
351
return "dirstate-tags"
353
def get_format_name_subtree(self):
354
return "dirstate-with-subtree"
356
def test_set_stacked_on_url_errors(self):
357
branch = self.make_branch('a', format=self.get_format_name())
358
self.assertRaises(errors.UnstackableBranchFormat,
359
branch.set_stacked_on_url, None)
361
def test_default_stacked_location(self):
362
branch = self.make_branch('a', format=self.get_format_name())
363
self.assertRaises(errors.UnstackableBranchFormat, branch.get_stacked_on_url)
366
class TestBranch7(TestBranch67, tests.TestCaseWithTransport):
369
return _mod_branch.BzrBranch7
371
def get_format_name(self):
374
def get_format_name_subtree(self):
375
return "development-subtree"
377
def test_set_stacked_on_url_unstackable_repo(self):
378
repo = self.make_repository('a', format='dirstate-tags')
379
control = repo.bzrdir
380
branch = _mod_branch.BzrBranchFormat7().initialize(control)
381
target = self.make_branch('b')
382
self.assertRaises(errors.UnstackableRepositoryFormat,
383
branch.set_stacked_on_url, target.base)
385
def test_clone_stacked_on_unstackable_repo(self):
386
repo = self.make_repository('a', format='dirstate-tags')
387
control = repo.bzrdir
388
branch = _mod_branch.BzrBranchFormat7().initialize(control)
389
# Calling clone should not raise UnstackableRepositoryFormat.
390
cloned_bzrdir = control.clone('cloned')
392
def _test_default_stacked_location(self):
393
branch = self.make_branch('a', format=self.get_format_name())
394
self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
396
def test_stack_and_unstack(self):
397
branch = self.make_branch('a', format=self.get_format_name())
398
target = self.make_branch_and_tree('b', format=self.get_format_name())
399
branch.set_stacked_on_url(target.branch.base)
400
self.assertEqual(target.branch.base, branch.get_stacked_on_url())
401
revid = target.commit('foo')
402
self.assertTrue(branch.repository.has_revision(revid))
403
branch.set_stacked_on_url(None)
404
self.assertRaises(errors.NotStacked, branch.get_stacked_on_url)
405
self.assertFalse(branch.repository.has_revision(revid))
407
def test_open_opens_stacked_reference(self):
408
branch = self.make_branch('a', format=self.get_format_name())
409
target = self.make_branch_and_tree('b', format=self.get_format_name())
410
branch.set_stacked_on_url(target.branch.base)
411
branch = branch.bzrdir.open_branch()
412
revid = target.commit('foo')
413
self.assertTrue(branch.repository.has_revision(revid))
416
class BzrBranch8(tests.TestCaseWithTransport):
418
def make_branch(self, location, format=None):
420
format = bzrdir.format_registry.make_bzrdir('1.9')
421
format.set_branch_format(_mod_branch.BzrBranchFormat8())
422
return tests.TestCaseWithTransport.make_branch(
423
self, location, format=format)
425
def create_branch_with_reference(self):
426
branch = self.make_branch('branch')
427
branch._set_all_reference_info({'file-id': ('path', 'location')})
431
def instrument_branch(branch, gets):
432
old_get = branch._transport.get
433
def get(*args, **kwargs):
434
gets.append((args, kwargs))
435
return old_get(*args, **kwargs)
436
branch._transport.get = get
438
def test_reference_info_caching_read_locked(self):
440
branch = self.create_branch_with_reference()
442
self.addCleanup(branch.unlock)
443
self.instrument_branch(branch, gets)
444
branch.get_reference_info('file-id')
445
branch.get_reference_info('file-id')
446
self.assertEqual(1, len(gets))
448
def test_reference_info_caching_read_unlocked(self):
450
branch = self.create_branch_with_reference()
451
self.instrument_branch(branch, gets)
452
branch.get_reference_info('file-id')
453
branch.get_reference_info('file-id')
454
self.assertEqual(2, len(gets))
456
def test_reference_info_caching_write_locked(self):
458
branch = self.make_branch('branch')
460
self.instrument_branch(branch, gets)
461
self.addCleanup(branch.unlock)
462
branch._set_all_reference_info({'file-id': ('path2', 'location2')})
463
path, location = branch.get_reference_info('file-id')
464
self.assertEqual(0, len(gets))
465
self.assertEqual('path2', path)
466
self.assertEqual('location2', location)
468
def test_reference_info_caches_cleared(self):
469
branch = self.make_branch('branch')
471
branch.set_reference_info('file-id', 'path2', 'location2')
473
doppelganger = _mod_branch.Branch.open('branch')
474
doppelganger.set_reference_info('file-id', 'path3', 'location3')
475
self.assertEqual(('path3', 'location3'),
476
branch.get_reference_info('file-id'))
478
class TestBranchReference(tests.TestCaseWithTransport):
288
479
"""Tests for the branch reference facility."""
290
481
def test_create_open_reference(self):
291
482
bzrdirformat = bzrdir.BzrDirMetaFormat1()
292
t = get_transport(self.get_url('.'))
483
t = transport.get_transport(self.get_url('.'))
294
485
dir = bzrdirformat.initialize(self.get_url('repo'))
295
486
dir.create_repository()
296
487
target_branch = dir.create_branch()
297
488
t.mkdir('branch')
298
489
branch_dir = bzrdirformat.initialize(self.get_url('branch'))
299
made_branch = BranchReferenceFormat().initialize(branch_dir, target_branch)
490
made_branch = _mod_branch.BranchReferenceFormat().initialize(
491
branch_dir, target_branch=target_branch)
300
492
self.assertEqual(made_branch.base, target_branch.base)
301
493
opened_branch = branch_dir.open_branch()
302
494
self.assertEqual(opened_branch.base, target_branch.base)
313
505
_mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
316
class TestHooks(TestCase):
508
class TestHooks(tests.TestCaseWithTransport):
318
510
def test_constructor(self):
319
511
"""Check that creating a BranchHooks instance has the right defaults."""
320
hooks = BranchHooks()
512
hooks = _mod_branch.BranchHooks()
321
513
self.assertTrue("set_rh" in hooks, "set_rh not in %s" % hooks)
322
514
self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
323
515
self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
516
self.assertTrue("pre_commit" in hooks, "pre_commit not in %s" % hooks)
324
517
self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
325
self.assertTrue("post_uncommit" in hooks, "post_uncommit not in %s" % hooks)
518
self.assertTrue("post_uncommit" in hooks,
519
"post_uncommit not in %s" % hooks)
520
self.assertTrue("post_change_branch_tip" in hooks,
521
"post_change_branch_tip not in %s" % hooks)
522
self.assertTrue("post_branch_init" in hooks,
523
"post_branch_init not in %s" % hooks)
524
self.assertTrue("post_switch" in hooks,
525
"post_switch not in %s" % hooks)
327
527
def test_installed_hooks_are_BranchHooks(self):
328
528
"""The installed hooks object should be a BranchHooks."""
329
529
# the installed hooks are saved in self._preserved_hooks.
330
self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch], BranchHooks)
333
class TestPullResult(TestCase):
530
self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch][1],
531
_mod_branch.BranchHooks)
533
def test_post_branch_init_hook(self):
535
_mod_branch.Branch.hooks.install_named_hook('post_branch_init',
537
self.assertLength(0, calls)
538
branch = self.make_branch('a')
539
self.assertLength(1, calls)
541
self.assertIsInstance(params, _mod_branch.BranchInitHookParams)
542
self.assertTrue(hasattr(params, 'bzrdir'))
543
self.assertTrue(hasattr(params, 'branch'))
545
def test_post_branch_init_hook_repr(self):
547
_mod_branch.Branch.hooks.install_named_hook('post_branch_init',
548
lambda params: param_reprs.append(repr(params)), None)
549
branch = self.make_branch('a')
550
self.assertLength(1, param_reprs)
551
param_repr = param_reprs[0]
552
self.assertStartsWith(param_repr, '<BranchInitHookParams of ')
554
def test_post_switch_hook(self):
555
from bzrlib import switch
557
_mod_branch.Branch.hooks.install_named_hook('post_switch',
559
tree = self.make_branch_and_tree('branch-1')
560
self.build_tree(['branch-1/file-1'])
563
to_branch = tree.bzrdir.sprout('branch-2').open_branch()
564
self.build_tree(['branch-1/file-2'])
566
tree.remove('file-1')
568
checkout = tree.branch.create_checkout('checkout')
569
self.assertLength(0, calls)
570
switch.switch(checkout.bzrdir, to_branch)
571
self.assertLength(1, calls)
573
self.assertIsInstance(params, _mod_branch.SwitchHookParams)
574
self.assertTrue(hasattr(params, 'to_branch'))
575
self.assertTrue(hasattr(params, 'revision_id'))
578
class TestBranchOptions(tests.TestCaseWithTransport):
581
super(TestBranchOptions, self).setUp()
582
self.branch = self.make_branch('.')
583
self.config = self.branch.get_config()
585
def check_append_revisions_only(self, expected_value, value=None):
586
"""Set append_revisions_only in config and check its interpretation."""
587
if value is not None:
588
self.config.set_user_option('append_revisions_only', value)
589
self.assertEqual(expected_value,
590
self.branch._get_append_revisions_only())
592
def test_valid_append_revisions_only(self):
593
self.assertEquals(None,
594
self.config.get_user_option('append_revisions_only'))
595
self.check_append_revisions_only(None)
596
self.check_append_revisions_only(False, 'False')
597
self.check_append_revisions_only(True, 'True')
598
# The following values will cause compatibility problems on projects
599
# using older bzr versions (<2.2) but are accepted
600
self.check_append_revisions_only(False, 'false')
601
self.check_append_revisions_only(True, 'true')
603
def test_invalid_append_revisions_only(self):
604
"""Ensure warning is noted on invalid settings"""
607
self.warnings.append(args[0] % args[1:])
608
self.overrideAttr(trace, 'warning', warning)
609
self.check_append_revisions_only(None, 'not-a-bool')
610
self.assertLength(1, self.warnings)
612
'Value "not-a-bool" is not a boolean for "append_revisions_only"',
616
class TestPullResult(tests.TestCase):
335
618
def test_pull_result_to_int(self):
336
619
# to support old code, the pull result can be used as an int
620
r = _mod_branch.PullResult()
340
623
# this usage of results is not recommended for new code (because it
341
624
# doesn't describe very well what happened), but for api stability
342
625
# it's still supported
343
a = "%d revisions pulled" % r
344
self.assertEqual(a, "10 revisions pulled")
626
self.assertEqual(self.applyDeprecated(
627
symbol_versioning.deprecated_in((2, 3, 0)),
631
def test_report_changed(self):
632
r = _mod_branch.PullResult()
633
r.old_revid = "old-revid"
635
r.new_revid = "new-revid"
639
self.assertEqual("Now on revision 20.\n", f.getvalue())
641
def test_report_unchanged(self):
642
r = _mod_branch.PullResult()
643
r.old_revid = "same-revid"
644
r.new_revid = "same-revid"
647
self.assertEqual("No revisions to pull.\n", f.getvalue())
650
class _StubLockable(object):
651
"""Helper for TestRunWithWriteLockedTarget."""
653
def __init__(self, calls, unlock_exc=None):
655
self.unlock_exc = unlock_exc
657
def lock_write(self):
658
self.calls.append('lock_write')
661
self.calls.append('unlock')
662
if self.unlock_exc is not None:
663
raise self.unlock_exc
666
class _ErrorFromCallable(Exception):
667
"""Helper for TestRunWithWriteLockedTarget."""
670
class _ErrorFromUnlock(Exception):
671
"""Helper for TestRunWithWriteLockedTarget."""
674
class TestRunWithWriteLockedTarget(tests.TestCase):
675
"""Tests for _run_with_write_locked_target."""
678
tests.TestCase.setUp(self)
681
def func_that_returns_ok(self):
682
self._calls.append('func called')
685
def func_that_raises(self):
686
self._calls.append('func called')
687
raise _ErrorFromCallable()
689
def test_success_unlocks(self):
690
lockable = _StubLockable(self._calls)
691
result = _mod_branch._run_with_write_locked_target(
692
lockable, self.func_that_returns_ok)
693
self.assertEqual('ok', result)
694
self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
696
def test_exception_unlocks_and_propagates(self):
697
lockable = _StubLockable(self._calls)
698
self.assertRaises(_ErrorFromCallable,
699
_mod_branch._run_with_write_locked_target,
700
lockable, self.func_that_raises)
701
self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
703
def test_callable_succeeds_but_error_during_unlock(self):
704
lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
705
self.assertRaises(_ErrorFromUnlock,
706
_mod_branch._run_with_write_locked_target,
707
lockable, self.func_that_returns_ok)
708
self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
710
def test_error_during_unlock_does_not_mask_original_error(self):
711
lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
712
self.assertRaises(_ErrorFromCallable,
713
_mod_branch._run_with_write_locked_target,
714
lockable, self.func_that_raises)
715
self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)