/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1711.8.5 by John Arbash Meinel
Move the new locking tests into their own files, and move the helper functions into a test helper.
1
# Copyright (C) 2006 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
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
16
17
"""Test locks across all branch implemenations"""
18
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
19
from bzrlib import errors
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
20
from bzrlib.branch import BzrBranchFormat4
2018.13.1 by Andrew Bennetts
Skip some branch_implementation tests that use branch.control_files if testing RemoteBranches.
21
from bzrlib.remote import RemoteBranchFormat
22
from bzrlib.tests import TestSkipped
1711.8.5 by John Arbash Meinel
Move the new locking tests into their own files, and move the helper functions into a test helper.
23
from bzrlib.tests.branch_implementations.test_branch import TestCaseWithBranch
1711.8.7 by John Arbash Meinel
Renaming LockHelpers.py to lock_helpers.py
24
from bzrlib.tests.lock_helpers import TestPreventLocking, LockWrapper
1711.8.5 by John Arbash Meinel
Move the new locking tests into their own files, and move the helper functions into a test helper.
25
26
27
class TestBranchLocking(TestCaseWithBranch):
28
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
29
    def setUp(self):
30
        TestCaseWithBranch.setUp(self)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
31
        self.reduceLockdirTimeout()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
32
1711.8.5 by John Arbash Meinel
Move the new locking tests into their own files, and move the helper functions into a test helper.
33
    def get_instrumented_branch(self):
34
        """Get a Branch object which has been instrumented"""
35
        # TODO: jam 20060630 It may be that not all formats have a 
36
        # 'control_files' member. So we should fail gracefully if
37
        # not there. But assuming it has them lets us test the exact 
38
        # lock/unlock order.
2018.13.1 by Andrew Bennetts
Skip some branch_implementation tests that use branch.control_files if testing RemoteBranches.
39
        if isinstance(self.branch_format, RemoteBranchFormat):
40
            raise TestSkipped(
41
                "RemoteBranches don't have 'control_files'.")
1711.8.5 by John Arbash Meinel
Move the new locking tests into their own files, and move the helper functions into a test helper.
42
        self.locks = []
43
        b = LockWrapper(self.locks, self.get_branch(), 'b')
44
        b.repository = LockWrapper(self.locks, b.repository, 'r')
45
        bcf = b.control_files
46
        rcf = b.repository.control_files
47
48
        # Look out for branch types that reuse their control files
49
        self.combined_control = bcf is rcf
50
51
        b.control_files = LockWrapper(self.locks, b.control_files, 'bc')
52
        b.repository.control_files = \
53
            LockWrapper(self.locks, b.repository.control_files, 'rc')
54
        return b
55
56
    def test_01_lock_read(self):
57
        # Test that locking occurs in the correct order
58
        b = self.get_instrumented_branch()
59
60
        self.assertFalse(b.is_locked())
61
        self.assertFalse(b.repository.is_locked())
62
        b.lock_read()
63
        try:
64
            self.assertTrue(b.is_locked())
65
            self.assertTrue(b.repository.is_locked())
66
        finally:
67
            b.unlock()
68
        self.assertFalse(b.is_locked())
69
        self.assertFalse(b.repository.is_locked())
70
71
        self.assertEqual([('b', 'lr', True),
72
                          ('r', 'lr', True),
73
                          ('rc', 'lr', True),
74
                          ('bc', 'lr', True),
75
                          ('b', 'ul', True),
76
                          ('bc', 'ul', True),
77
                          ('r', 'ul', True),
78
                          ('rc', 'ul', True),
79
                         ], self.locks)
80
81
    def test_02_lock_write(self):
82
        # Test that locking occurs in the correct order
83
        b = self.get_instrumented_branch()
84
85
        self.assertFalse(b.is_locked())
86
        self.assertFalse(b.repository.is_locked())
87
        b.lock_write()
88
        try:
89
            self.assertTrue(b.is_locked())
90
            self.assertTrue(b.repository.is_locked())
91
        finally:
92
            b.unlock()
93
        self.assertFalse(b.is_locked())
94
        self.assertFalse(b.repository.is_locked())
95
96
        self.assertEqual([('b', 'lw', True),
97
                          ('r', 'lw', True),
98
                          ('rc', 'lw', True),
99
                          ('bc', 'lw', True),
100
                          ('b', 'ul', True),
101
                          ('bc', 'ul', True),
102
                          ('r', 'ul', True),
103
                          ('rc', 'ul', True),
104
                         ], self.locks)
105
106
    def test_03_lock_fail_unlock_repo(self):
107
        # Make sure branch.unlock() is called, even if there is a
108
        # failure while unlocking the repository.
109
        b = self.get_instrumented_branch()
110
        b.repository.disable_unlock()
111
112
        self.assertFalse(b.is_locked())
113
        self.assertFalse(b.repository.is_locked())
114
        b.lock_write()
115
        try:
116
            self.assertTrue(b.is_locked())
117
            self.assertTrue(b.repository.is_locked())
118
            self.assertRaises(TestPreventLocking, b.unlock)
119
            if self.combined_control:
120
                self.assertTrue(b.is_locked())
121
            else:
122
                self.assertFalse(b.is_locked())
123
            self.assertTrue(b.repository.is_locked())
124
125
            # We unlock the branch control files, even if 
126
            # we fail to unlock the repository
127
            self.assertEqual([('b', 'lw', True),
128
                              ('r', 'lw', True),
129
                              ('rc', 'lw', True),
130
                              ('bc', 'lw', True),
131
                              ('b', 'ul', True),
132
                              ('bc', 'ul', True),
133
                              ('r', 'ul', False), 
134
                             ], self.locks)
135
136
        finally:
137
            # For cleanup purposes, make sure we are unlocked
138
            b.repository._other.unlock()
139
140
    def test_04_lock_fail_unlock_control(self):
141
        # Make sure repository.unlock() is called, if we fail to unlock self
142
        b = self.get_instrumented_branch()
143
        b.control_files.disable_unlock()
144
145
        self.assertFalse(b.is_locked())
146
        self.assertFalse(b.repository.is_locked())
147
        b.lock_write()
148
        try:
149
            self.assertTrue(b.is_locked())
150
            self.assertTrue(b.repository.is_locked())
151
            self.assertRaises(TestPreventLocking, b.unlock)
152
            self.assertTrue(b.is_locked())
153
            if self.combined_control:
154
                self.assertTrue(b.repository.is_locked())
155
            else:
156
                self.assertFalse(b.repository.is_locked())
157
158
            # We unlock the repository even if 
159
            # we fail to unlock the control files
160
            self.assertEqual([('b', 'lw', True),
161
                              ('r', 'lw', True),
162
                              ('rc', 'lw', True),
163
                              ('bc', 'lw', True),
164
                              ('b', 'ul', True),
165
                              ('bc', 'ul', False),
166
                              ('r', 'ul', True), 
167
                              ('rc', 'ul', True), 
168
                             ], self.locks)
169
170
        finally:
171
            # For cleanup purposes, make sure we are unlocked
172
            b.control_files._other.unlock()
173
174
    def test_05_lock_read_fail_repo(self):
175
        # Test that the branch is not locked if it cannot lock the repository
176
        b = self.get_instrumented_branch()
177
        b.repository.disable_lock_read()
178
179
        self.assertRaises(TestPreventLocking, b.lock_read)
180
        self.assertFalse(b.is_locked())
181
        self.assertFalse(b.repository.is_locked())
182
183
        self.assertEqual([('b', 'lr', True),
184
                          ('r', 'lr', False), 
185
                         ], self.locks)
186
187
    def test_06_lock_write_fail_repo(self):
188
        # Test that the branch is not locked if it cannot lock the repository
189
        b = self.get_instrumented_branch()
190
        b.repository.disable_lock_write()
191
192
        self.assertRaises(TestPreventLocking, b.lock_write)
193
        self.assertFalse(b.is_locked())
194
        self.assertFalse(b.repository.is_locked())
195
196
        self.assertEqual([('b', 'lw', True),
197
                          ('r', 'lw', False), 
198
                         ], self.locks)
199
200
    def test_07_lock_read_fail_control(self):
201
        # Test the repository is unlocked if we can't lock self
202
        b = self.get_instrumented_branch()
203
        b.control_files.disable_lock_read()
204
205
        self.assertRaises(TestPreventLocking, b.lock_read)
206
        self.assertFalse(b.is_locked())
207
        self.assertFalse(b.repository.is_locked())
208
209
        self.assertEqual([('b', 'lr', True),
210
                          ('r', 'lr', True),
211
                          ('rc', 'lr', True),
212
                          ('bc', 'lr', False),
213
                          ('r', 'ul', True),
214
                          ('rc', 'ul', True),
215
                         ], self.locks)
216
217
    def test_08_lock_write_fail_control(self):
218
        # Test the repository is unlocked if we can't lock self
219
        b = self.get_instrumented_branch()
220
        b.control_files.disable_lock_write()
221
222
        self.assertRaises(TestPreventLocking, b.lock_write)
223
        self.assertFalse(b.is_locked())
224
        self.assertFalse(b.repository.is_locked())
225
226
        self.assertEqual([('b', 'lw', True),
227
                          ('r', 'lw', True),
228
                          ('rc', 'lw', True),
229
                          ('bc', 'lw', False),
230
                          ('r', 'ul', True),
231
                          ('rc', 'ul', True),
232
                         ], self.locks)
233
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
234
    def test_lock_write_returns_None_refuses_token(self):
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
235
        branch = self.make_branch('b')
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
236
        token = branch.lock_write()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
237
        try:
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
238
            if token is not None:
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
239
                # This test does not apply, because this lockable supports
240
                # tokens.
241
                return
242
            self.assertRaises(errors.TokenLockingNotSupported,
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
243
                              branch.lock_write, token='token')
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
244
        finally:
245
            branch.unlock()
246
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
247
    def test_reentering_lock_write_raises_on_token_mismatch(self):
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
248
        branch = self.make_branch('b')
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
249
        token = branch.lock_write()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
250
        try:
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
251
            if token is None:
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
252
                # This test does not apply, because this lockable refuses
253
                # tokens.
254
                return
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
255
            different_branch_token = token + 'xxx'
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
256
            # Re-using the same lockable instance with a different branch token
257
            # will raise TokenMismatch.
258
            self.assertRaises(errors.TokenMismatch,
259
                              branch.lock_write,
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
260
                              token=different_branch_token)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
261
        finally:
262
            branch.unlock()
263
264
    def test_lock_write_with_nonmatching_token(self):
265
        branch = self.make_branch('b')
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
266
        token = branch.lock_write()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
267
        try:
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
268
            if token is None:
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
269
                # This test does not apply, because this branch refuses
270
                # tokens.
271
                return
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
272
            different_branch_token = token + 'xxx'
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
273
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
274
            new_branch = branch.bzrdir.open_branch()
275
            # We only want to test the relocking abilities of branch, so use the
276
            # existing repository object which is already locked.
277
            new_branch.repository = branch.repository
278
            self.assertRaises(errors.TokenMismatch,
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
279
                              new_branch.lock_write,
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
280
                              token=different_branch_token)
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
281
        finally:
282
            branch.unlock()
283
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
284
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
285
    def test_lock_write_with_matching_token(self):
286
        """Test that a branch can be locked with a token, if it is already
287
        locked by that token."""
288
        branch = self.make_branch('b')
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
289
        token = branch.lock_write()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
290
        try:
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
291
            if token is None:
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
292
                # This test does not apply, because this branch refuses tokens.
293
                return
294
            # The same instance will accept a second lock_write if the specified
295
            # token matches.
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
296
            branch.lock_write(token=token)
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
297
            branch.unlock()
298
            # Calling lock_write on a new instance for the same lockable will
299
            # also succeed.
300
            new_branch = branch.bzrdir.open_branch()
301
            # We only want to test the relocking abilities of branch, so use the
302
            # existing repository object which is already locked.
303
            new_branch.repository = branch.repository
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
304
            new_branch.lock_write(token=token)
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
305
            new_branch.unlock()
306
        finally:
307
            branch.unlock()
308
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
309
    def test_unlock_after_lock_write_with_token(self):
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
310
        # If lock_write did not physically acquire the lock (because it was
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
311
        # passed some tokens), then unlock should not physically release it.
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
312
        branch = self.make_branch('b')
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
313
        token = branch.lock_write()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
314
        try:
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
315
            if token is None:
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
316
                # This test does not apply, because this lockable refuses
317
                # tokens.
318
                return
319
            new_branch = branch.bzrdir.open_branch()
320
            # We only want to test the relocking abilities of branch, so use the
321
            # existing repository object which is already locked.
322
            new_branch.repository = branch.repository
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
323
            new_branch.lock_write(token=token)
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
324
            new_branch.unlock()
325
            self.assertTrue(branch.get_physical_lock_status()) #XXX
326
        finally:
327
            branch.unlock()
328
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
329
    def test_lock_write_with_token_fails_when_unlocked(self):
330
        # First, lock and then unlock to get superficially valid tokens.  This
331
        # mimics a likely programming error, where a caller accidentally tries
332
        # to lock with a token that is no longer valid (because the original
333
        # lock was released).
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
334
        branch = self.make_branch('b')
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
335
        token = branch.lock_write()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
336
        branch.unlock()
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
337
        if token is None:
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
338
            # This test does not apply, because this lockable refuses
339
            # tokens.
340
            return
341
342
        self.assertRaises(errors.TokenMismatch,
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
343
                          branch.lock_write, token=token)
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
344
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
345
    def test_lock_write_reenter_with_token(self):
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
346
        branch = self.make_branch('b')
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
347
        token = branch.lock_write()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
348
        try:
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
349
            if token is None:
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
350
                # This test does not apply, because this lockable refuses
351
                # tokens.
352
                return
353
            # Relock with a token.
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
354
            branch.lock_write(token=token)
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
355
            branch.unlock()
356
        finally:
357
            branch.unlock()
358
        # The lock should be unlocked on disk.  Verify that with a new lock
359
        # instance.
360
        new_branch = branch.bzrdir.open_branch()
361
        # Calling lock_write now should work, rather than raise LockContention.
362
        new_branch.lock_write()
363
        new_branch.unlock()
364
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
365
    def test_leave_lock_in_place(self):
366
        branch = self.make_branch('b')
367
        # Lock the branch, then use leave_lock_in_place so that when we
368
        # unlock the branch the lock is still held on disk.
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
369
        token = branch.lock_write()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
370
        try:
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
371
            if token is None:
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
372
                # This test does not apply, because this repository refuses lock
373
                # tokens.
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
374
                self.assertRaises(NotImplementedError,
375
                                  branch.leave_lock_in_place)
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
376
                return
377
            branch.leave_lock_in_place()
378
        finally:
379
            branch.unlock()
380
        # We should be unable to relock the repo.
381
        self.assertRaises(errors.LockContention, branch.lock_write)
382
383
    def test_dont_leave_lock_in_place(self):
384
        branch = self.make_branch('b')
385
        # Create a lock on disk.
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
386
        token = branch.lock_write()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
387
        try:
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
388
            if token is None:
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
389
                # This test does not apply, because this branch refuses lock
390
                # tokens.
391
                self.assertRaises(NotImplementedError,
392
                                  branch.dont_leave_lock_in_place)
393
                return
394
            try:
395
                branch.leave_lock_in_place()
396
            except NotImplementedError:
397
                # This branch doesn't support this API.
398
                return
399
            branch.repository.leave_lock_in_place()
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
400
            repo_token = branch.repository.lock_write()
401
            branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
402
        finally:
403
            branch.unlock()
404
        # Reacquire the lock (with a different branch object) by using the
405
        # tokens.
406
        new_branch = branch.bzrdir.open_branch()
2018.5.142 by Andrew Bennetts
Change Branch.lock_token to only accept and receive the branch lock token (rather than the branch and repo lock tokens).
407
        # We have to explicitly lock the repository first.
408
        new_branch.repository.lock_write(token=repo_token)
409
        new_branch.lock_write(token=token)
410
        # Now we don't need our own repository lock anymore (the branch is
411
        # holding it for us).
412
        new_branch.repository.unlock()
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
413
        # Call dont_leave_lock_in_place, so that the lock will be released by
414
        # this instance, even though the lock wasn't originally acquired by it.
415
        new_branch.dont_leave_lock_in_place()
416
        new_branch.repository.dont_leave_lock_in_place()
417
        new_branch.unlock()
2018.15.1 by Andrew Bennetts
All branch_implementations/test_locking tests passing.
418
        # Now the branch (and repository) is unlocked.  Test this by locking it
419
        # without tokens.
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
420
        branch.lock_write()
421
        branch.unlock()
422
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
423
    def test_lock_read_then_unlock(self):
424
        # Calling lock_read then unlocking should work without errors.
425
        branch = self.make_branch('b')
426
        branch.lock_read()
427
        branch.unlock()
428
429
    def test_lock_write_locks_repo_too(self):
430
        if isinstance(self.branch_format, BzrBranchFormat4):
431
            # Branch format 4 is combined with the repository, so this test
432
            # doesn't apply.
433
            return
434
        branch = self.make_branch('b')
435
        branch = branch.bzrdir.open_branch()
436
        branch.lock_write()
437
        try:
438
            # Now the branch.repository is locked, so we can't lock it with a new
439
            # repository without a token.
440
            new_repo = branch.bzrdir.open_repository()
441
            self.assertRaises(errors.LockContention, new_repo.lock_write)
442
            # We can call lock_write on the original repository object though,
443
            # because it is already locked.
444
            branch.repository.lock_write()
445
            branch.repository.unlock()
446
        finally:
447
            branch.unlock()