~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_branch.py

  • Committer: Robert Collins
  • Date: 2009-03-31 00:12:10 UTC
  • mto: This revision was merged to the branch mainline in revision 4219.
  • Revision ID: robertc@robertcollins.net-20090331001210-fufeq2heozx9jne0
Fix Tree.get_symlink_target to decode from the disk encoding to get a unicode encoded string.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
16
16
 
17
17
"""Tests for the Branch facility that are not interface  tests.
18
18
 
19
 
For interface tests see tests/per_branch/*.py.
 
19
For interface tests see tests/branch_implementations/*.py.
20
20
 
21
21
For concrete class tests see this file, and for meta-branch tests
22
22
also see this file.
23
23
"""
24
24
 
25
 
from cStringIO import StringIO
 
25
from StringIO import StringIO
26
26
 
27
27
from bzrlib import (
28
28
    branch as _mod_branch,
29
29
    bzrdir,
30
30
    config,
31
31
    errors,
32
 
    symbol_versioning,
33
 
    tests,
34
32
    trace,
35
 
    transport,
36
33
    urlutils,
37
34
    )
38
 
 
39
 
 
40
 
class TestDefaultFormat(tests.TestCase):
 
35
from bzrlib.branch import (
 
36
    Branch,
 
37
    BranchHooks,
 
38
    BranchFormat,
 
39
    BranchReferenceFormat,
 
40
    BzrBranch5,
 
41
    BzrBranchFormat5,
 
42
    BzrBranchFormat6,
 
43
    PullResult,
 
44
    _run_with_write_locked_target,
 
45
    )
 
46
from bzrlib.bzrdir import (BzrDirMetaFormat1, BzrDirMeta1,
 
47
                           BzrDir, BzrDirFormat)
 
48
from bzrlib.errors import (NotBranchError,
 
49
                           UnknownFormatError,
 
50
                           UnknownHook,
 
51
                           UnsupportedFormatError,
 
52
                           )
 
53
 
 
54
from bzrlib.tests import TestCase, TestCaseWithTransport
 
55
from bzrlib.transport import get_transport
 
56
 
 
57
 
 
58
class TestDefaultFormat(TestCase):
41
59
 
42
60
    def test_default_format(self):
43
61
        # update this if you change the default branch format
44
 
        self.assertIsInstance(_mod_branch.BranchFormat.get_default_format(),
45
 
                _mod_branch.BzrBranchFormat7)
 
62
        self.assertIsInstance(BranchFormat.get_default_format(),
 
63
                BzrBranchFormat6)
46
64
 
47
65
    def test_default_format_is_same_as_bzrdir_default(self):
48
66
        # XXX: it might be nice if there was only one place the default was
49
67
        # set, but at the moment that's not true -- mbp 20070814 --
50
68
        # https://bugs.launchpad.net/bzr/+bug/132376
51
 
        self.assertEqual(
52
 
            _mod_branch.BranchFormat.get_default_format(),
53
 
            bzrdir.BzrDirFormat.get_default_format().get_branch_format())
 
69
        self.assertEqual(BranchFormat.get_default_format(),
 
70
                BzrDirFormat.get_default_format().get_branch_format())
54
71
 
55
72
    def test_get_set_default_format(self):
56
73
        # set the format and then set it back again
57
 
        old_format = _mod_branch.BranchFormat.get_default_format()
58
 
        _mod_branch.BranchFormat.set_default_format(SampleBranchFormat())
 
74
        old_format = BranchFormat.get_default_format()
 
75
        BranchFormat.set_default_format(SampleBranchFormat())
59
76
        try:
60
77
            # the default branch format is used by the meta dir format
61
78
            # which is not the default bzrdir format at this point
62
 
            dir = bzrdir.BzrDirMetaFormat1().initialize('memory:///')
 
79
            dir = BzrDirMetaFormat1().initialize('memory:///')
63
80
            result = dir.create_branch()
64
81
            self.assertEqual(result, 'A branch')
65
82
        finally:
66
 
            _mod_branch.BranchFormat.set_default_format(old_format)
67
 
        self.assertEqual(old_format,
68
 
                         _mod_branch.BranchFormat.get_default_format())
69
 
 
70
 
 
71
 
class TestBranchFormat5(tests.TestCaseWithTransport):
 
83
            BranchFormat.set_default_format(old_format)
 
84
        self.assertEqual(old_format, BranchFormat.get_default_format())
 
85
 
 
86
 
 
87
class TestBranchFormat5(TestCaseWithTransport):
72
88
    """Tests specific to branch format 5"""
73
89
 
74
90
    def test_branch_format_5_uses_lockdir(self):
75
91
        url = self.get_url()
76
 
        bdir = bzrdir.BzrDirMetaFormat1().initialize(url)
77
 
        bdir.create_repository()
78
 
        branch = bdir.create_branch()
 
92
        bzrdir = BzrDirMetaFormat1().initialize(url)
 
93
        bzrdir.create_repository()
 
94
        branch = bzrdir.create_branch()
79
95
        t = self.get_transport()
80
96
        self.log("branch instance is %r" % branch)
81
 
        self.assert_(isinstance(branch, _mod_branch.BzrBranch5))
 
97
        self.assert_(isinstance(branch, BzrBranch5))
82
98
        self.assertIsDirectory('.', t)
83
99
        self.assertIsDirectory('.bzr/branch', t)
84
100
        self.assertIsDirectory('.bzr/branch/lock', t)
85
101
        branch.lock_write()
86
 
        self.addCleanup(branch.unlock)
87
 
        self.assertIsDirectory('.bzr/branch/lock/held', t)
 
102
        try:
 
103
            self.assertIsDirectory('.bzr/branch/lock/held', t)
 
104
        finally:
 
105
            branch.unlock()
88
106
 
89
107
    def test_set_push_location(self):
90
 
        conf = config.LocationConfig.from_string('# comment\n', '.', save=True)
 
108
        from bzrlib.config import (locations_config_filename,
 
109
                                   ensure_config_dir_exists)
 
110
        ensure_config_dir_exists()
 
111
        fn = locations_config_filename()
 
112
        # write correct newlines to locations.conf
 
113
        # by default ConfigObj uses native line-endings for new files
 
114
        # but uses already existing line-endings if file is not empty
 
115
        f = open(fn, 'wb')
 
116
        try:
 
117
            f.write('# comment\n')
 
118
        finally:
 
119
            f.close()
91
120
 
92
121
        branch = self.make_branch('.', format='knit')
93
122
        branch.set_push_location('foo')
96
125
                             "[%s]\n"
97
126
                             "push_location = foo\n"
98
127
                             "push_location:policy = norecurse\n" % local_path,
99
 
                             config.locations_config_filename())
 
128
                             fn)
100
129
 
101
130
    # TODO RBC 20051029 test getting a push location from a branch in a
102
131
    # recursive section - that is, it appends the branch name.
103
132
 
104
133
 
105
 
class SampleBranchFormat(_mod_branch.BranchFormat):
 
134
class SampleBranchFormat(BranchFormat):
106
135
    """A sample format
107
136
 
108
137
    this format is initializable, unsupported to aid in testing the
113
142
        """See BzrBranchFormat.get_format_string()."""
114
143
        return "Sample branch format."
115
144
 
116
 
    def initialize(self, a_bzrdir, name=None):
 
145
    def initialize(self, a_bzrdir):
117
146
        """Format 4 branches cannot be created."""
118
 
        t = a_bzrdir.get_branch_transport(self, name=name)
 
147
        t = a_bzrdir.get_branch_transport(self)
119
148
        t.put_bytes('format', self.get_format_string())
120
149
        return 'A branch'
121
150
 
122
151
    def is_supported(self):
123
152
        return False
124
153
 
125
 
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
 
154
    def open(self, transport, _found=False, ignore_fallbacks=False):
126
155
        return "opened branch."
127
156
 
128
157
 
129
 
# Demonstrating how lazy loading is often implemented:
130
 
# A constant string is created.
131
 
SampleSupportedBranchFormatString = "Sample supported branch format."
132
 
 
133
 
# And the format class can then reference the constant to avoid skew.
134
 
class SampleSupportedBranchFormat(_mod_branch.BranchFormat):
135
 
    """A sample supported format."""
136
 
 
137
 
    def get_format_string(self):
138
 
        """See BzrBranchFormat.get_format_string()."""
139
 
        return SampleSupportedBranchFormatString
140
 
 
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())
144
 
        return 'A branch'
145
 
 
146
 
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
147
 
        return "opened supported branch."
148
 
 
149
 
 
150
 
class TestBzrBranchFormat(tests.TestCaseWithTransport):
 
158
class TestBzrBranchFormat(TestCaseWithTransport):
151
159
    """Tests for the BzrBranchFormat facility."""
152
160
 
153
161
    def test_find_format(self):
159
167
            dir = format._matchingbzrdir.initialize(url)
160
168
            dir.create_repository()
161
169
            format.initialize(dir)
162
 
            found_format = _mod_branch.BranchFormat.find_format(dir)
 
170
            found_format = BranchFormat.find_format(dir)
163
171
            self.failUnless(isinstance(found_format, format.__class__))
164
 
        check_format(_mod_branch.BzrBranchFormat5(), "bar")
165
 
 
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.")
 
172
        check_format(BzrBranchFormat5(), "bar")
176
173
 
177
174
    def test_find_format_not_branch(self):
178
175
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
179
 
        self.assertRaises(errors.NotBranchError,
180
 
                          _mod_branch.BranchFormat.find_format,
 
176
        self.assertRaises(NotBranchError,
 
177
                          BranchFormat.find_format,
181
178
                          dir)
182
179
 
183
180
    def test_find_format_unknown_format(self):
184
181
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
185
182
        SampleBranchFormat().initialize(dir)
186
 
        self.assertRaises(errors.UnknownFormatError,
187
 
                          _mod_branch.BranchFormat.find_format,
 
183
        self.assertRaises(UnknownFormatError,
 
184
                          BranchFormat.find_format,
188
185
                          dir)
189
186
 
190
187
    def test_register_unregister_format(self):
194
191
        # make a branch
195
192
        format.initialize(dir)
196
193
        # register a format for it.
197
 
        _mod_branch.BranchFormat.register_format(format)
 
194
        BranchFormat.register_format(format)
198
195
        # which branch.Open will refuse (not supported)
199
 
        self.assertRaises(errors.UnsupportedFormatError,
200
 
                          _mod_branch.Branch.open, self.get_url())
 
196
        self.assertRaises(UnsupportedFormatError, Branch.open, self.get_url())
201
197
        self.make_branch_and_tree('foo')
202
198
        # but open_downlevel will work
203
 
        self.assertEqual(
204
 
            format.open(dir),
205
 
            bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
 
199
        self.assertEqual(format.open(dir), bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
206
200
        # unregister the format
207
 
        _mod_branch.BranchFormat.unregister_format(format)
 
201
        BranchFormat.unregister_format(format)
208
202
        self.make_branch_and_tree('bar')
209
203
 
210
204
 
211
 
#Used by TestMetaDirBranchFormatFactory 
212
 
FakeLazyFormat = None
213
 
 
214
 
 
215
 
class TestMetaDirBranchFormatFactory(tests.TestCase):
216
 
 
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())
221
 
 
222
 
    def test_call_loads(self):
223
 
        # __call__ is used by the network_format_registry interface to get a
224
 
        # Format.
225
 
        global FakeLazyFormat
226
 
        del FakeLazyFormat
227
 
        factory = _mod_branch.MetaDirBranchFormatFactory(None,
228
 
            "bzrlib.tests.test_branch", "FakeLazyFormat")
229
 
        self.assertRaises(AttributeError, factory)
230
 
 
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())
237
 
 
238
 
 
239
205
class TestBranch67(object):
240
206
    """Common tests for both branch 6 and 7 which are mostly the same."""
241
207
 
249
215
        raise NotImplementedError(self.get_class)
250
216
 
251
217
    def test_creation(self):
252
 
        format = bzrdir.BzrDirMetaFormat1()
 
218
        format = BzrDirMetaFormat1()
253
219
        format.set_branch_format(_mod_branch.BzrBranchFormat6())
254
220
        branch = self.make_branch('a', format=format)
255
221
        self.assertIsInstance(branch, self.get_class())
262
228
        branch = self.make_branch('a', format=self.get_format_name())
263
229
        self.failUnlessExists('a/.bzr/branch/last-revision')
264
230
        self.failIfExists('a/.bzr/branch/revision-history')
265
 
        self.failIfExists('a/.bzr/branch/references')
266
231
 
267
232
    def test_config(self):
268
233
        """Ensure that all configuration data is stored in the branch"""
342
307
                         'locations.conf')
343
308
 
344
309
 
345
 
class TestBranch6(TestBranch67, tests.TestCaseWithTransport):
 
310
class TestBranch6(TestBranch67, TestCaseWithTransport):
346
311
 
347
312
    def get_class(self):
348
313
        return _mod_branch.BzrBranch6
363
328
        self.assertRaises(errors.UnstackableBranchFormat, branch.get_stacked_on_url)
364
329
 
365
330
 
366
 
class TestBranch7(TestBranch67, tests.TestCaseWithTransport):
 
331
class TestBranch7(TestBranch67, TestCaseWithTransport):
367
332
 
368
333
    def get_class(self):
369
334
        return _mod_branch.BzrBranch7
370
335
 
371
336
    def get_format_name(self):
372
 
        return "1.9"
 
337
        return "development"
373
338
 
374
339
    def get_format_name_subtree(self):
375
340
        return "development-subtree"
413
378
        self.assertTrue(branch.repository.has_revision(revid))
414
379
 
415
380
 
416
 
class BzrBranch8(tests.TestCaseWithTransport):
417
 
 
418
 
    def make_branch(self, location, format=None):
419
 
        if format is 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)
424
 
 
425
 
    def create_branch_with_reference(self):
426
 
        branch = self.make_branch('branch')
427
 
        branch._set_all_reference_info({'file-id': ('path', 'location')})
428
 
        return branch
429
 
 
430
 
    @staticmethod
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
437
 
 
438
 
    def test_reference_info_caching_read_locked(self):
439
 
        gets = []
440
 
        branch = self.create_branch_with_reference()
441
 
        branch.lock_read()
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))
447
 
 
448
 
    def test_reference_info_caching_read_unlocked(self):
449
 
        gets = []
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))
455
 
 
456
 
    def test_reference_info_caching_write_locked(self):
457
 
        gets = []
458
 
        branch = self.make_branch('branch')
459
 
        branch.lock_write()
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)
467
 
 
468
 
    def test_reference_info_caches_cleared(self):
469
 
        branch = self.make_branch('branch')
470
 
        branch.lock_write()
471
 
        branch.set_reference_info('file-id', 'path2', 'location2')
472
 
        branch.unlock()
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'))
477
 
 
478
 
class TestBranchReference(tests.TestCaseWithTransport):
 
381
class TestBranchReference(TestCaseWithTransport):
479
382
    """Tests for the branch reference facility."""
480
383
 
481
384
    def test_create_open_reference(self):
482
385
        bzrdirformat = bzrdir.BzrDirMetaFormat1()
483
 
        t = transport.get_transport(self.get_url('.'))
 
386
        t = get_transport(self.get_url('.'))
484
387
        t.mkdir('repo')
485
388
        dir = bzrdirformat.initialize(self.get_url('repo'))
486
389
        dir.create_repository()
487
390
        target_branch = dir.create_branch()
488
391
        t.mkdir('branch')
489
392
        branch_dir = bzrdirformat.initialize(self.get_url('branch'))
490
 
        made_branch = _mod_branch.BranchReferenceFormat().initialize(
491
 
            branch_dir, target_branch=target_branch)
 
393
        made_branch = BranchReferenceFormat().initialize(branch_dir, target_branch)
492
394
        self.assertEqual(made_branch.base, target_branch.base)
493
395
        opened_branch = branch_dir.open_branch()
494
396
        self.assertEqual(opened_branch.base, target_branch.base)
505
407
            _mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
506
408
 
507
409
 
508
 
class TestHooks(tests.TestCaseWithTransport):
 
410
class TestHooks(TestCase):
509
411
 
510
412
    def test_constructor(self):
511
413
        """Check that creating a BranchHooks instance has the right defaults."""
512
 
        hooks = _mod_branch.BranchHooks()
 
414
        hooks = BranchHooks()
513
415
        self.assertTrue("set_rh" in hooks, "set_rh not in %s" % hooks)
514
416
        self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
515
417
        self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
516
418
        self.assertTrue("pre_commit" in hooks, "pre_commit not in %s" % hooks)
517
419
        self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
518
 
        self.assertTrue("post_uncommit" in hooks,
519
 
                        "post_uncommit not in %s" % hooks)
 
420
        self.assertTrue("post_uncommit" in hooks, "post_uncommit not in %s" % hooks)
520
421
        self.assertTrue("post_change_branch_tip" in hooks,
521
422
                        "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)
526
423
 
527
424
    def test_installed_hooks_are_BranchHooks(self):
528
425
        """The installed hooks object should be a BranchHooks."""
529
426
        # the installed hooks are saved in self._preserved_hooks.
530
427
        self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch][1],
531
 
                              _mod_branch.BranchHooks)
532
 
 
533
 
    def test_post_branch_init_hook(self):
534
 
        calls = []
535
 
        _mod_branch.Branch.hooks.install_named_hook('post_branch_init',
536
 
            calls.append, None)
537
 
        self.assertLength(0, calls)
538
 
        branch = self.make_branch('a')
539
 
        self.assertLength(1, calls)
540
 
        params = calls[0]
541
 
        self.assertIsInstance(params, _mod_branch.BranchInitHookParams)
542
 
        self.assertTrue(hasattr(params, 'bzrdir'))
543
 
        self.assertTrue(hasattr(params, 'branch'))
544
 
 
545
 
    def test_post_branch_init_hook_repr(self):
546
 
        param_reprs = []
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 ')
553
 
 
554
 
    def test_post_switch_hook(self):
555
 
        from bzrlib import switch
556
 
        calls = []
557
 
        _mod_branch.Branch.hooks.install_named_hook('post_switch',
558
 
            calls.append, None)
559
 
        tree = self.make_branch_and_tree('branch-1')
560
 
        self.build_tree(['branch-1/file-1'])
561
 
        tree.add('file-1')
562
 
        tree.commit('rev1')
563
 
        to_branch = tree.bzrdir.sprout('branch-2').open_branch()
564
 
        self.build_tree(['branch-1/file-2'])
565
 
        tree.add('file-2')
566
 
        tree.remove('file-1')
567
 
        tree.commit('rev2')
568
 
        checkout = tree.branch.create_checkout('checkout')
569
 
        self.assertLength(0, calls)
570
 
        switch.switch(checkout.bzrdir, to_branch)
571
 
        self.assertLength(1, calls)
572
 
        params = calls[0]
573
 
        self.assertIsInstance(params, _mod_branch.SwitchHookParams)
574
 
        self.assertTrue(hasattr(params, 'to_branch'))
575
 
        self.assertTrue(hasattr(params, 'revision_id'))
576
 
 
577
 
 
578
 
class TestBranchOptions(tests.TestCaseWithTransport):
579
 
 
580
 
    def setUp(self):
581
 
        super(TestBranchOptions, self).setUp()
582
 
        self.branch = self.make_branch('.')
583
 
        self.config = self.branch.get_config()
584
 
 
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())
591
 
 
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')
602
 
 
603
 
    def test_invalid_append_revisions_only(self):
604
 
        """Ensure warning is noted on invalid settings"""
605
 
        self.warnings = []
606
 
        def warning(*args):
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)
611
 
        self.assertEqual(
612
 
            'Value "not-a-bool" is not a boolean for "append_revisions_only"',
613
 
            self.warnings[0])
614
 
 
615
 
 
616
 
class TestPullResult(tests.TestCase):
 
428
            BranchHooks)
 
429
 
 
430
 
 
431
class TestPullResult(TestCase):
617
432
 
618
433
    def test_pull_result_to_int(self):
619
434
        # to support old code, the pull result can be used as an int
620
 
        r = _mod_branch.PullResult()
 
435
        r = PullResult()
621
436
        r.old_revno = 10
622
437
        r.new_revno = 20
623
438
        # this usage of results is not recommended for new code (because it
624
439
        # doesn't describe very well what happened), but for api stability
625
440
        # it's still supported
626
 
        self.assertEqual(self.applyDeprecated(
627
 
            symbol_versioning.deprecated_in((2, 3, 0)),
628
 
            r.__int__),
629
 
            10)
630
 
 
631
 
    def test_report_changed(self):
632
 
        r = _mod_branch.PullResult()
633
 
        r.old_revid = "old-revid"
634
 
        r.old_revno = 10
635
 
        r.new_revid = "new-revid"
636
 
        r.new_revno = 20
637
 
        f = StringIO()
638
 
        r.report(f)
639
 
        self.assertEqual("Now on revision 20.\n", f.getvalue())
640
 
 
641
 
    def test_report_unchanged(self):
642
 
        r = _mod_branch.PullResult()
643
 
        r.old_revid = "same-revid"
644
 
        r.new_revid = "same-revid"
645
 
        f = StringIO()
646
 
        r.report(f)
647
 
        self.assertEqual("No revisions to pull.\n", f.getvalue())
 
441
        a = "%d revisions pulled" % r
 
442
        self.assertEqual(a, "10 revisions pulled")
 
443
 
648
444
 
649
445
 
650
446
class _StubLockable(object):
671
467
    """Helper for TestRunWithWriteLockedTarget."""
672
468
 
673
469
 
674
 
class TestRunWithWriteLockedTarget(tests.TestCase):
 
470
class TestRunWithWriteLockedTarget(TestCase):
675
471
    """Tests for _run_with_write_locked_target."""
676
472
 
677
473
    def setUp(self):
678
 
        tests.TestCase.setUp(self)
 
474
        TestCase.setUp(self)
679
475
        self._calls = []
680
476
 
681
477
    def func_that_returns_ok(self):
688
484
 
689
485
    def test_success_unlocks(self):
690
486
        lockable = _StubLockable(self._calls)
691
 
        result = _mod_branch._run_with_write_locked_target(
 
487
        result = _run_with_write_locked_target(
692
488
            lockable, self.func_that_returns_ok)
693
489
        self.assertEqual('ok', result)
694
490
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
696
492
    def test_exception_unlocks_and_propagates(self):
697
493
        lockable = _StubLockable(self._calls)
698
494
        self.assertRaises(_ErrorFromCallable,
699
 
                          _mod_branch._run_with_write_locked_target,
700
 
                          lockable, self.func_that_raises)
 
495
            _run_with_write_locked_target, lockable, self.func_that_raises)
701
496
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
702
497
 
703
498
    def test_callable_succeeds_but_error_during_unlock(self):
704
499
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
705
500
        self.assertRaises(_ErrorFromUnlock,
706
 
                          _mod_branch._run_with_write_locked_target,
707
 
                          lockable, self.func_that_returns_ok)
 
501
            _run_with_write_locked_target, lockable, self.func_that_returns_ok)
708
502
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
709
503
 
710
504
    def test_error_during_unlock_does_not_mask_original_error(self):
711
505
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
712
506
        self.assertRaises(_ErrorFromCallable,
713
 
                          _mod_branch._run_with_write_locked_target,
714
 
                          lockable, self.func_that_raises)
 
507
            _run_with_write_locked_target, lockable, self.func_that_raises)
715
508
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
716
509
 
717
510