~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_branch.py

  • Committer: Brian de Alwis
  • Date: 2009-09-24 19:51:37 UTC
  • mto: (4715.4.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4727.
  • Revision ID: bsd@acm.org-20090924195137-wubyeqv515mkigi8
Introduce new mailer to support MacOS X's Mail.app

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
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
 
    tests,
33
32
    trace,
34
 
    transport,
35
33
    urlutils,
36
34
    )
37
 
 
38
 
 
39
 
class TestDefaultFormat(tests.TestCase):
 
35
from bzrlib.branch import (
 
36
    Branch,
 
37
    BranchHooks,
 
38
    BranchFormat,
 
39
    BranchReferenceFormat,
 
40
    BzrBranch5,
 
41
    BzrBranchFormat5,
 
42
    BzrBranchFormat6,
 
43
    BzrBranchFormat7,
 
44
    PullResult,
 
45
    _run_with_write_locked_target,
 
46
    )
 
47
from bzrlib.bzrdir import (BzrDirMetaFormat1, BzrDirMeta1,
 
48
                           BzrDir, BzrDirFormat)
 
49
from bzrlib.errors import (NotBranchError,
 
50
                           UnknownFormatError,
 
51
                           UnknownHook,
 
52
                           UnsupportedFormatError,
 
53
                           )
 
54
 
 
55
from bzrlib.tests import TestCase, TestCaseWithTransport
 
56
from bzrlib.transport import get_transport
 
57
 
 
58
 
 
59
class TestDefaultFormat(TestCase):
40
60
 
41
61
    def test_default_format(self):
42
62
        # update this if you change the default branch format
43
 
        self.assertIsInstance(_mod_branch.BranchFormat.get_default_format(),
44
 
                _mod_branch.BzrBranchFormat7)
 
63
        self.assertIsInstance(BranchFormat.get_default_format(),
 
64
                BzrBranchFormat7)
45
65
 
46
66
    def test_default_format_is_same_as_bzrdir_default(self):
47
67
        # XXX: it might be nice if there was only one place the default was
48
68
        # set, but at the moment that's not true -- mbp 20070814 --
49
69
        # https://bugs.launchpad.net/bzr/+bug/132376
50
 
        self.assertEqual(
51
 
            _mod_branch.BranchFormat.get_default_format(),
52
 
            bzrdir.BzrDirFormat.get_default_format().get_branch_format())
 
70
        self.assertEqual(BranchFormat.get_default_format(),
 
71
                BzrDirFormat.get_default_format().get_branch_format())
53
72
 
54
73
    def test_get_set_default_format(self):
55
74
        # set the format and then set it back again
56
 
        old_format = _mod_branch.BranchFormat.get_default_format()
57
 
        _mod_branch.BranchFormat.set_default_format(SampleBranchFormat())
 
75
        old_format = BranchFormat.get_default_format()
 
76
        BranchFormat.set_default_format(SampleBranchFormat())
58
77
        try:
59
78
            # the default branch format is used by the meta dir format
60
79
            # which is not the default bzrdir format at this point
61
 
            dir = bzrdir.BzrDirMetaFormat1().initialize('memory:///')
 
80
            dir = BzrDirMetaFormat1().initialize('memory:///')
62
81
            result = dir.create_branch()
63
82
            self.assertEqual(result, 'A branch')
64
83
        finally:
65
 
            _mod_branch.BranchFormat.set_default_format(old_format)
66
 
        self.assertEqual(old_format,
67
 
                         _mod_branch.BranchFormat.get_default_format())
68
 
 
69
 
 
70
 
class TestBranchFormat5(tests.TestCaseWithTransport):
 
84
            BranchFormat.set_default_format(old_format)
 
85
        self.assertEqual(old_format, BranchFormat.get_default_format())
 
86
 
 
87
 
 
88
class TestBranchFormat5(TestCaseWithTransport):
71
89
    """Tests specific to branch format 5"""
72
90
 
73
91
    def test_branch_format_5_uses_lockdir(self):
74
92
        url = self.get_url()
75
 
        bdir = bzrdir.BzrDirMetaFormat1().initialize(url)
76
 
        bdir.create_repository()
77
 
        branch = bdir.create_branch()
 
93
        bzrdir = BzrDirMetaFormat1().initialize(url)
 
94
        bzrdir.create_repository()
 
95
        branch = bzrdir.create_branch()
78
96
        t = self.get_transport()
79
97
        self.log("branch instance is %r" % branch)
80
 
        self.assert_(isinstance(branch, _mod_branch.BzrBranch5))
 
98
        self.assert_(isinstance(branch, BzrBranch5))
81
99
        self.assertIsDirectory('.', t)
82
100
        self.assertIsDirectory('.bzr/branch', t)
83
101
        self.assertIsDirectory('.bzr/branch/lock', t)
84
102
        branch.lock_write()
85
 
        self.addCleanup(branch.unlock)
86
 
        self.assertIsDirectory('.bzr/branch/lock/held', t)
 
103
        try:
 
104
            self.assertIsDirectory('.bzr/branch/lock/held', t)
 
105
        finally:
 
106
            branch.unlock()
87
107
 
88
108
    def test_set_push_location(self):
89
 
        conf = config.LocationConfig.from_string('# comment\n', '.', save=True)
 
109
        from bzrlib.config import (locations_config_filename,
 
110
                                   ensure_config_dir_exists)
 
111
        ensure_config_dir_exists()
 
112
        fn = locations_config_filename()
 
113
        # write correct newlines to locations.conf
 
114
        # by default ConfigObj uses native line-endings for new files
 
115
        # but uses already existing line-endings if file is not empty
 
116
        f = open(fn, 'wb')
 
117
        try:
 
118
            f.write('# comment\n')
 
119
        finally:
 
120
            f.close()
90
121
 
91
122
        branch = self.make_branch('.', format='knit')
92
123
        branch.set_push_location('foo')
95
126
                             "[%s]\n"
96
127
                             "push_location = foo\n"
97
128
                             "push_location:policy = norecurse\n" % local_path,
98
 
                             config.locations_config_filename())
 
129
                             fn)
99
130
 
100
131
    # TODO RBC 20051029 test getting a push location from a branch in a
101
132
    # recursive section - that is, it appends the branch name.
102
133
 
103
134
 
104
 
class SampleBranchFormat(_mod_branch.BranchFormat):
 
135
class SampleBranchFormat(BranchFormat):
105
136
    """A sample format
106
137
 
107
138
    this format is initializable, unsupported to aid in testing the
112
143
        """See BzrBranchFormat.get_format_string()."""
113
144
        return "Sample branch format."
114
145
 
115
 
    def initialize(self, a_bzrdir, name=None):
 
146
    def initialize(self, a_bzrdir):
116
147
        """Format 4 branches cannot be created."""
117
 
        t = a_bzrdir.get_branch_transport(self, name=name)
 
148
        t = a_bzrdir.get_branch_transport(self)
118
149
        t.put_bytes('format', self.get_format_string())
119
150
        return 'A branch'
120
151
 
121
152
    def is_supported(self):
122
153
        return False
123
154
 
124
 
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
 
155
    def open(self, transport, _found=False, ignore_fallbacks=False):
125
156
        return "opened branch."
126
157
 
127
158
 
128
 
# Demonstrating how lazy loading is often implemented:
129
 
# A constant string is created.
130
 
SampleSupportedBranchFormatString = "Sample supported branch format."
131
 
 
132
 
# And the format class can then reference the constant to avoid skew.
133
 
class SampleSupportedBranchFormat(_mod_branch.BranchFormat):
134
 
    """A sample supported format."""
135
 
 
136
 
    def get_format_string(self):
137
 
        """See BzrBranchFormat.get_format_string()."""
138
 
        return SampleSupportedBranchFormatString
139
 
 
140
 
    def initialize(self, a_bzrdir, name=None):
141
 
        t = a_bzrdir.get_branch_transport(self, name=name)
142
 
        t.put_bytes('format', self.get_format_string())
143
 
        return 'A branch'
144
 
 
145
 
    def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
146
 
        return "opened supported branch."
147
 
 
148
 
 
149
 
class TestBzrBranchFormat(tests.TestCaseWithTransport):
 
159
class TestBzrBranchFormat(TestCaseWithTransport):
150
160
    """Tests for the BzrBranchFormat facility."""
151
161
 
152
162
    def test_find_format(self):
158
168
            dir = format._matchingbzrdir.initialize(url)
159
169
            dir.create_repository()
160
170
            format.initialize(dir)
161
 
            found_format = _mod_branch.BranchFormat.find_format(dir)
 
171
            found_format = BranchFormat.find_format(dir)
162
172
            self.failUnless(isinstance(found_format, format.__class__))
163
 
        check_format(_mod_branch.BzrBranchFormat5(), "bar")
164
 
 
165
 
    def test_find_format_factory(self):
166
 
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
167
 
        SampleSupportedBranchFormat().initialize(dir)
168
 
        factory = _mod_branch.MetaDirBranchFormatFactory(
169
 
            SampleSupportedBranchFormatString,
170
 
            "bzrlib.tests.test_branch", "SampleSupportedBranchFormat")
171
 
        _mod_branch.BranchFormat.register_format(factory)
172
 
        self.addCleanup(_mod_branch.BranchFormat.unregister_format, factory)
173
 
        b = _mod_branch.Branch.open(self.get_url())
174
 
        self.assertEqual(b, "opened supported branch.")
 
173
        check_format(BzrBranchFormat5(), "bar")
175
174
 
176
175
    def test_find_format_not_branch(self):
177
176
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
178
 
        self.assertRaises(errors.NotBranchError,
179
 
                          _mod_branch.BranchFormat.find_format,
 
177
        self.assertRaises(NotBranchError,
 
178
                          BranchFormat.find_format,
180
179
                          dir)
181
180
 
182
181
    def test_find_format_unknown_format(self):
183
182
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
184
183
        SampleBranchFormat().initialize(dir)
185
 
        self.assertRaises(errors.UnknownFormatError,
186
 
                          _mod_branch.BranchFormat.find_format,
 
184
        self.assertRaises(UnknownFormatError,
 
185
                          BranchFormat.find_format,
187
186
                          dir)
188
187
 
189
188
    def test_register_unregister_format(self):
193
192
        # make a branch
194
193
        format.initialize(dir)
195
194
        # register a format for it.
196
 
        _mod_branch.BranchFormat.register_format(format)
 
195
        BranchFormat.register_format(format)
197
196
        # which branch.Open will refuse (not supported)
198
 
        self.assertRaises(errors.UnsupportedFormatError,
199
 
                          _mod_branch.Branch.open, self.get_url())
 
197
        self.assertRaises(UnsupportedFormatError, Branch.open, self.get_url())
200
198
        self.make_branch_and_tree('foo')
201
199
        # but open_downlevel will work
202
 
        self.assertEqual(
203
 
            format.open(dir),
204
 
            bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
 
200
        self.assertEqual(format.open(dir), bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
205
201
        # unregister the format
206
 
        _mod_branch.BranchFormat.unregister_format(format)
 
202
        BranchFormat.unregister_format(format)
207
203
        self.make_branch_and_tree('bar')
208
204
 
209
205
 
210
 
#Used by TestMetaDirBranchFormatFactory 
211
 
FakeLazyFormat = None
212
 
 
213
 
 
214
 
class TestMetaDirBranchFormatFactory(tests.TestCase):
215
 
 
216
 
    def test_get_format_string_does_not_load(self):
217
 
        """Formats have a static format string."""
218
 
        factory = _mod_branch.MetaDirBranchFormatFactory("yo", None, None)
219
 
        self.assertEqual("yo", factory.get_format_string())
220
 
 
221
 
    def test_call_loads(self):
222
 
        # __call__ is used by the network_format_registry interface to get a
223
 
        # Format.
224
 
        global FakeLazyFormat
225
 
        del FakeLazyFormat
226
 
        factory = _mod_branch.MetaDirBranchFormatFactory(None,
227
 
            "bzrlib.tests.test_branch", "FakeLazyFormat")
228
 
        self.assertRaises(AttributeError, factory)
229
 
 
230
 
    def test_call_returns_call_of_referenced_object(self):
231
 
        global FakeLazyFormat
232
 
        FakeLazyFormat = lambda:'called'
233
 
        factory = _mod_branch.MetaDirBranchFormatFactory(None,
234
 
            "bzrlib.tests.test_branch", "FakeLazyFormat")
235
 
        self.assertEqual('called', factory())
236
 
 
237
 
 
238
206
class TestBranch67(object):
239
207
    """Common tests for both branch 6 and 7 which are mostly the same."""
240
208
 
248
216
        raise NotImplementedError(self.get_class)
249
217
 
250
218
    def test_creation(self):
251
 
        format = bzrdir.BzrDirMetaFormat1()
 
219
        format = BzrDirMetaFormat1()
252
220
        format.set_branch_format(_mod_branch.BzrBranchFormat6())
253
221
        branch = self.make_branch('a', format=format)
254
222
        self.assertIsInstance(branch, self.get_class())
341
309
                         'locations.conf')
342
310
 
343
311
 
344
 
class TestBranch6(TestBranch67, tests.TestCaseWithTransport):
 
312
class TestBranch6(TestBranch67, TestCaseWithTransport):
345
313
 
346
314
    def get_class(self):
347
315
        return _mod_branch.BzrBranch6
362
330
        self.assertRaises(errors.UnstackableBranchFormat, branch.get_stacked_on_url)
363
331
 
364
332
 
365
 
class TestBranch7(TestBranch67, tests.TestCaseWithTransport):
 
333
class TestBranch7(TestBranch67, TestCaseWithTransport):
366
334
 
367
335
    def get_class(self):
368
336
        return _mod_branch.BzrBranch7
412
380
        self.assertTrue(branch.repository.has_revision(revid))
413
381
 
414
382
 
415
 
class BzrBranch8(tests.TestCaseWithTransport):
 
383
class BzrBranch8(TestCaseWithTransport):
416
384
 
417
385
    def make_branch(self, location, format=None):
418
386
        if format is None:
419
387
            format = bzrdir.format_registry.make_bzrdir('1.9')
420
388
            format.set_branch_format(_mod_branch.BzrBranchFormat8())
421
 
        return tests.TestCaseWithTransport.make_branch(
422
 
            self, location, format=format)
 
389
        return TestCaseWithTransport.make_branch(self, location, format=format)
423
390
 
424
391
    def create_branch_with_reference(self):
425
392
        branch = self.make_branch('branch')
469
436
        branch.lock_write()
470
437
        branch.set_reference_info('file-id', 'path2', 'location2')
471
438
        branch.unlock()
472
 
        doppelganger = _mod_branch.Branch.open('branch')
 
439
        doppelganger = Branch.open('branch')
473
440
        doppelganger.set_reference_info('file-id', 'path3', 'location3')
474
441
        self.assertEqual(('path3', 'location3'),
475
442
                         branch.get_reference_info('file-id'))
476
443
 
477
 
class TestBranchReference(tests.TestCaseWithTransport):
 
444
class TestBranchReference(TestCaseWithTransport):
478
445
    """Tests for the branch reference facility."""
479
446
 
480
447
    def test_create_open_reference(self):
481
448
        bzrdirformat = bzrdir.BzrDirMetaFormat1()
482
 
        t = transport.get_transport(self.get_url('.'))
 
449
        t = get_transport(self.get_url('.'))
483
450
        t.mkdir('repo')
484
451
        dir = bzrdirformat.initialize(self.get_url('repo'))
485
452
        dir.create_repository()
486
453
        target_branch = dir.create_branch()
487
454
        t.mkdir('branch')
488
455
        branch_dir = bzrdirformat.initialize(self.get_url('branch'))
489
 
        made_branch = _mod_branch.BranchReferenceFormat().initialize(
490
 
            branch_dir, target_branch=target_branch)
 
456
        made_branch = BranchReferenceFormat().initialize(branch_dir, target_branch)
491
457
        self.assertEqual(made_branch.base, target_branch.base)
492
458
        opened_branch = branch_dir.open_branch()
493
459
        self.assertEqual(opened_branch.base, target_branch.base)
504
470
            _mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
505
471
 
506
472
 
507
 
class TestHooks(tests.TestCaseWithTransport):
 
473
class TestHooks(TestCase):
508
474
 
509
475
    def test_constructor(self):
510
476
        """Check that creating a BranchHooks instance has the right defaults."""
511
 
        hooks = _mod_branch.BranchHooks()
 
477
        hooks = BranchHooks()
512
478
        self.assertTrue("set_rh" in hooks, "set_rh not in %s" % hooks)
513
479
        self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
514
480
        self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
515
481
        self.assertTrue("pre_commit" in hooks, "pre_commit not in %s" % hooks)
516
482
        self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
517
 
        self.assertTrue("post_uncommit" in hooks,
518
 
                        "post_uncommit not in %s" % hooks)
 
483
        self.assertTrue("post_uncommit" in hooks, "post_uncommit not in %s" % hooks)
519
484
        self.assertTrue("post_change_branch_tip" in hooks,
520
485
                        "post_change_branch_tip not in %s" % hooks)
521
 
        self.assertTrue("post_branch_init" in hooks,
522
 
                        "post_branch_init not in %s" % hooks)
523
 
        self.assertTrue("post_switch" in hooks,
524
 
                        "post_switch not in %s" % hooks)
525
486
 
526
487
    def test_installed_hooks_are_BranchHooks(self):
527
488
        """The installed hooks object should be a BranchHooks."""
528
489
        # the installed hooks are saved in self._preserved_hooks.
529
490
        self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch][1],
530
 
                              _mod_branch.BranchHooks)
531
 
 
532
 
    def test_post_branch_init_hook(self):
533
 
        calls = []
534
 
        _mod_branch.Branch.hooks.install_named_hook('post_branch_init',
535
 
            calls.append, None)
536
 
        self.assertLength(0, calls)
537
 
        branch = self.make_branch('a')
538
 
        self.assertLength(1, calls)
539
 
        params = calls[0]
540
 
        self.assertIsInstance(params, _mod_branch.BranchInitHookParams)
541
 
        self.assertTrue(hasattr(params, 'bzrdir'))
542
 
        self.assertTrue(hasattr(params, 'branch'))
543
 
 
544
 
    def test_post_branch_init_hook_repr(self):
545
 
        param_reprs = []
546
 
        _mod_branch.Branch.hooks.install_named_hook('post_branch_init',
547
 
            lambda params: param_reprs.append(repr(params)), None)
548
 
        branch = self.make_branch('a')
549
 
        self.assertLength(1, param_reprs)
550
 
        param_repr = param_reprs[0]
551
 
        self.assertStartsWith(param_repr, '<BranchInitHookParams of ')
552
 
 
553
 
    def test_post_switch_hook(self):
554
 
        from bzrlib import switch
555
 
        calls = []
556
 
        _mod_branch.Branch.hooks.install_named_hook('post_switch',
557
 
            calls.append, None)
558
 
        tree = self.make_branch_and_tree('branch-1')
559
 
        self.build_tree(['branch-1/file-1'])
560
 
        tree.add('file-1')
561
 
        tree.commit('rev1')
562
 
        to_branch = tree.bzrdir.sprout('branch-2').open_branch()
563
 
        self.build_tree(['branch-1/file-2'])
564
 
        tree.add('file-2')
565
 
        tree.remove('file-1')
566
 
        tree.commit('rev2')
567
 
        checkout = tree.branch.create_checkout('checkout')
568
 
        self.assertLength(0, calls)
569
 
        switch.switch(checkout.bzrdir, to_branch)
570
 
        self.assertLength(1, calls)
571
 
        params = calls[0]
572
 
        self.assertIsInstance(params, _mod_branch.SwitchHookParams)
573
 
        self.assertTrue(hasattr(params, 'to_branch'))
574
 
        self.assertTrue(hasattr(params, 'revision_id'))
575
 
 
576
 
 
577
 
class TestBranchOptions(tests.TestCaseWithTransport):
578
 
 
579
 
    def setUp(self):
580
 
        super(TestBranchOptions, self).setUp()
581
 
        self.branch = self.make_branch('.')
582
 
        self.config = self.branch.get_config()
583
 
 
584
 
    def check_append_revisions_only(self, expected_value, value=None):
585
 
        """Set append_revisions_only in config and check its interpretation."""
586
 
        if value is not None:
587
 
            self.config.set_user_option('append_revisions_only', value)
588
 
        self.assertEqual(expected_value,
589
 
                         self.branch._get_append_revisions_only())
590
 
 
591
 
    def test_valid_append_revisions_only(self):
592
 
        self.assertEquals(None,
593
 
                          self.config.get_user_option('append_revisions_only'))
594
 
        self.check_append_revisions_only(None)
595
 
        self.check_append_revisions_only(False, 'False')
596
 
        self.check_append_revisions_only(True, 'True')
597
 
        # The following values will cause compatibility problems on projects
598
 
        # using older bzr versions (<2.2) but are accepted
599
 
        self.check_append_revisions_only(False, 'false')
600
 
        self.check_append_revisions_only(True, 'true')
601
 
 
602
 
    def test_invalid_append_revisions_only(self):
603
 
        """Ensure warning is noted on invalid settings"""
604
 
        self.warnings = []
605
 
        def warning(*args):
606
 
            self.warnings.append(args[0] % args[1:])
607
 
        self.overrideAttr(trace, 'warning', warning)
608
 
        self.check_append_revisions_only(None, 'not-a-bool')
609
 
        self.assertLength(1, self.warnings)
610
 
        self.assertEqual(
611
 
            'Value "not-a-bool" is not a boolean for "append_revisions_only"',
612
 
            self.warnings[0])
613
 
 
614
 
 
615
 
class TestPullResult(tests.TestCase):
 
491
            BranchHooks)
 
492
 
 
493
 
 
494
class TestPullResult(TestCase):
616
495
 
617
496
    def test_pull_result_to_int(self):
618
497
        # to support old code, the pull result can be used as an int
619
 
        r = _mod_branch.PullResult()
 
498
        r = PullResult()
620
499
        r.old_revno = 10
621
500
        r.new_revno = 20
622
501
        # this usage of results is not recommended for new code (because it
626
505
        self.assertEqual(a, "10 revisions pulled")
627
506
 
628
507
    def test_report_changed(self):
629
 
        r = _mod_branch.PullResult()
 
508
        r = PullResult()
630
509
        r.old_revid = "old-revid"
631
510
        r.old_revno = 10
632
511
        r.new_revid = "new-revid"
636
515
        self.assertEqual("Now on revision 20.\n", f.getvalue())
637
516
 
638
517
    def test_report_unchanged(self):
639
 
        r = _mod_branch.PullResult()
 
518
        r = PullResult()
640
519
        r.old_revid = "same-revid"
641
520
        r.new_revid = "same-revid"
642
521
        f = StringIO()
668
547
    """Helper for TestRunWithWriteLockedTarget."""
669
548
 
670
549
 
671
 
class TestRunWithWriteLockedTarget(tests.TestCase):
 
550
class TestRunWithWriteLockedTarget(TestCase):
672
551
    """Tests for _run_with_write_locked_target."""
673
552
 
674
553
    def setUp(self):
675
 
        tests.TestCase.setUp(self)
 
554
        TestCase.setUp(self)
676
555
        self._calls = []
677
556
 
678
557
    def func_that_returns_ok(self):
685
564
 
686
565
    def test_success_unlocks(self):
687
566
        lockable = _StubLockable(self._calls)
688
 
        result = _mod_branch._run_with_write_locked_target(
 
567
        result = _run_with_write_locked_target(
689
568
            lockable, self.func_that_returns_ok)
690
569
        self.assertEqual('ok', result)
691
570
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
693
572
    def test_exception_unlocks_and_propagates(self):
694
573
        lockable = _StubLockable(self._calls)
695
574
        self.assertRaises(_ErrorFromCallable,
696
 
                          _mod_branch._run_with_write_locked_target,
697
 
                          lockable, self.func_that_raises)
 
575
            _run_with_write_locked_target, lockable, self.func_that_raises)
698
576
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
699
577
 
700
578
    def test_callable_succeeds_but_error_during_unlock(self):
701
579
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
702
580
        self.assertRaises(_ErrorFromUnlock,
703
 
                          _mod_branch._run_with_write_locked_target,
704
 
                          lockable, self.func_that_returns_ok)
 
581
            _run_with_write_locked_target, lockable, self.func_that_returns_ok)
705
582
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
706
583
 
707
584
    def test_error_during_unlock_does_not_mask_original_error(self):
708
585
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
709
586
        self.assertRaises(_ErrorFromCallable,
710
 
                          _mod_branch._run_with_write_locked_target,
711
 
                          lockable, self.func_that_raises)
 
587
            _run_with_write_locked_target, lockable, self.func_that_raises)
712
588
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
713
589
 
714
590