/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/branch_implementations/test_locking.py

merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
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
16
16
 
17
17
"""Test locks across all branch implemenations"""
18
18
 
32
32
 
33
33
    def get_instrumented_branch(self):
34
34
        """Get a Branch object which has been instrumented"""
35
 
        # TODO: jam 20060630 It may be that not all formats have a 
 
35
        # TODO: jam 20060630 It may be that not all formats have a
36
36
        # 'control_files' member. So we should fail gracefully if
37
 
        # not there. But assuming it has them lets us test the exact 
 
37
        # not there. But assuming it has them lets us test the exact
38
38
        # lock/unlock order.
39
39
        self.locks = []
40
40
        b = LockWrapper(self.locks, self.get_branch(), 'b')
42
42
        bcf = b.control_files
43
43
        rcf = getattr(b.repository, 'control_files', None)
44
44
        if rcf is None:
45
 
            raise TestSkipped(
46
 
                "This tests depends on being able to instrument "
47
 
                "repository.control_files, but %r doesn't have control_files."
48
 
                % (b.repository,))
49
 
 
50
 
        # Look out for branch types that reuse their control files
51
 
        self.combined_control = bcf is rcf
52
 
 
53
 
        b.control_files = LockWrapper(self.locks, b.control_files, 'bc')
54
 
        b.repository.control_files = \
55
 
            LockWrapper(self.locks, b.repository.control_files, 'rc')
 
45
            self.combined_branch = False
 
46
        else:
 
47
            # Look out for branch types that reuse their control files
 
48
            self.combined_control = bcf is rcf
 
49
        try:
 
50
            b.control_files = LockWrapper(self.locks, b.control_files, 'bc')
 
51
        except AttributeError:
 
52
            # RemoteBranch seems to trigger this.
 
53
            raise TestSkipped("Could not instrument branch control files.")
 
54
        if self.combined_control:
 
55
            # instrument the repository control files too to ensure its worked
 
56
            # with correctly. When they are not shared, we trust the repository
 
57
            # API and only instrument the repository itself.
 
58
            b.repository.control_files = \
 
59
                LockWrapper(self.locks, b.repository.control_files, 'rc')
56
60
        return b
57
61
 
58
62
    def test_01_lock_read(self):
70
74
        self.assertFalse(b.is_locked())
71
75
        self.assertFalse(b.repository.is_locked())
72
76
 
73
 
        self.assertEqual([('b', 'lr', True),
74
 
                          ('r', 'lr', True),
75
 
                          ('rc', 'lr', True),
76
 
                          ('bc', 'lr', True),
77
 
                          ('b', 'ul', True),
78
 
                          ('bc', 'ul', True),
79
 
                          ('r', 'ul', True),
80
 
                          ('rc', 'ul', True),
81
 
                         ], self.locks)
 
77
        if self.combined_control:
 
78
            self.assertEqual([('b', 'lr', True),
 
79
                              ('r', 'lr', True),
 
80
                              ('rc', 'lr', True),
 
81
                              ('bc', 'lr', True),
 
82
                              ('b', 'ul', True),
 
83
                              ('bc', 'ul', True),
 
84
                              ('r', 'ul', True),
 
85
                              ('rc', 'ul', True),
 
86
                             ], self.locks)
 
87
        else:
 
88
            self.assertEqual([('b', 'lr', True),
 
89
                              ('r', 'lr', True),
 
90
                              ('bc', 'lr', True),
 
91
                              ('b', 'ul', True),
 
92
                              ('bc', 'ul', True),
 
93
                              ('r', 'ul', True),
 
94
                             ], self.locks)
82
95
 
83
96
    def test_02_lock_write(self):
84
97
        # Test that locking occurs in the correct order
95
108
        self.assertFalse(b.is_locked())
96
109
        self.assertFalse(b.repository.is_locked())
97
110
 
98
 
        self.assertEqual([('b', 'lw', True),
99
 
                          ('r', 'lw', True),
100
 
                          ('rc', 'lw', True),
101
 
                          ('bc', 'lw', True),
102
 
                          ('b', 'ul', True),
103
 
                          ('bc', 'ul', True),
104
 
                          ('r', 'ul', True),
105
 
                          ('rc', 'ul', True),
106
 
                         ], self.locks)
 
111
        if self.combined_control:
 
112
            self.assertEqual([('b', 'lw', True),
 
113
                              ('r', 'lw', True),
 
114
                              ('rc', 'lw', True),
 
115
                              ('bc', 'lw', True),
 
116
                              ('b', 'ul', True),
 
117
                              ('bc', 'ul', True),
 
118
                              ('r', 'ul', True),
 
119
                              ('rc', 'ul', True),
 
120
                             ], self.locks)
 
121
        else:
 
122
            self.assertEqual([('b', 'lw', True),
 
123
                              ('r', 'lw', True),
 
124
                              ('bc', 'lw', True),
 
125
                              ('b', 'ul', True),
 
126
                              ('bc', 'ul', True),
 
127
                              ('r', 'ul', True),
 
128
                             ], self.locks)
107
129
 
108
130
    def test_03_lock_fail_unlock_repo(self):
109
131
        # Make sure branch.unlock() is called, even if there is a
124
146
                self.assertFalse(b.is_locked())
125
147
            self.assertTrue(b.repository.is_locked())
126
148
 
127
 
            # We unlock the branch control files, even if 
 
149
            # We unlock the branch control files, even if
128
150
            # we fail to unlock the repository
129
 
            self.assertEqual([('b', 'lw', True),
130
 
                              ('r', 'lw', True),
131
 
                              ('rc', 'lw', True),
132
 
                              ('bc', 'lw', True),
133
 
                              ('b', 'ul', True),
134
 
                              ('bc', 'ul', True),
135
 
                              ('r', 'ul', False), 
136
 
                             ], self.locks)
 
151
            if self.combined_control:
 
152
                self.assertEqual([('b', 'lw', True),
 
153
                                  ('r', 'lw', True),
 
154
                                  ('rc', 'lw', True),
 
155
                                  ('bc', 'lw', True),
 
156
                                  ('b', 'ul', True),
 
157
                                  ('bc', 'ul', True),
 
158
                                  ('r', 'ul', False),
 
159
                                 ], self.locks)
 
160
            else:
 
161
                self.assertEqual([('b', 'lw', True),
 
162
                                  ('r', 'lw', True),
 
163
                                  ('bc', 'lw', True),
 
164
                                  ('b', 'ul', True),
 
165
                                  ('bc', 'ul', True),
 
166
                                  ('r', 'ul', False),
 
167
                                 ], self.locks)
137
168
 
138
169
        finally:
139
170
            # For cleanup purposes, make sure we are unlocked
140
171
            b.repository._other.unlock()
141
172
 
142
173
    def test_04_lock_fail_unlock_control(self):
143
 
        # Make sure repository.unlock() is called, if we fail to unlock self
 
174
        # Make sure repository.unlock() is not called, if we fail to unlock
 
175
        # self leaving ourselves still locked, so that attempts to recover
 
176
        # don't encounter an unlocked repository.
144
177
        b = self.get_instrumented_branch()
145
178
        b.control_files.disable_unlock()
146
179
 
152
185
            self.assertTrue(b.repository.is_locked())
153
186
            self.assertRaises(TestPreventLocking, b.unlock)
154
187
            self.assertTrue(b.is_locked())
155
 
            if self.combined_control:
156
 
                self.assertTrue(b.repository.is_locked())
157
 
            else:
158
 
                self.assertFalse(b.repository.is_locked())
 
188
            self.assertTrue(b.repository.is_locked())
159
189
 
160
 
            # We unlock the repository even if 
 
190
            # We unlock the repository even if
161
191
            # we fail to unlock the control files
162
 
            self.assertEqual([('b', 'lw', True),
163
 
                              ('r', 'lw', True),
164
 
                              ('rc', 'lw', True),
165
 
                              ('bc', 'lw', True),
166
 
                              ('b', 'ul', True),
167
 
                              ('bc', 'ul', False),
168
 
                              ('r', 'ul', True), 
169
 
                              ('rc', 'ul', True), 
170
 
                             ], self.locks)
 
192
            if self.combined_control:
 
193
                self.assertEqual([('b', 'lw', True),
 
194
                                  ('r', 'lw', True),
 
195
                                  ('rc', 'lw', True),
 
196
                                  ('bc', 'lw', True),
 
197
                                  ('b', 'ul', True),
 
198
                                  ('bc', 'ul', False),
 
199
                                  ('r', 'ul', True),
 
200
                                  ('rc', 'ul', True),
 
201
                                 ], self.locks)
 
202
            else:
 
203
                self.assertEqual([('b', 'lw', True),
 
204
                                  ('r', 'lw', True),
 
205
                                  ('bc', 'lw', True),
 
206
                                  ('b', 'ul', True),
 
207
                                  ('bc', 'ul', False),
 
208
                                 ], self.locks)
171
209
 
172
210
        finally:
173
211
            # For cleanup purposes, make sure we are unlocked
183
221
        self.assertFalse(b.repository.is_locked())
184
222
 
185
223
        self.assertEqual([('b', 'lr', True),
186
 
                          ('r', 'lr', False), 
 
224
                          ('r', 'lr', False),
187
225
                         ], self.locks)
188
226
 
189
227
    def test_06_lock_write_fail_repo(self):
196
234
        self.assertFalse(b.repository.is_locked())
197
235
 
198
236
        self.assertEqual([('b', 'lw', True),
199
 
                          ('r', 'lw', False), 
 
237
                          ('r', 'lw', False),
200
238
                         ], self.locks)
201
239
 
202
240
    def test_07_lock_read_fail_control(self):
208
246
        self.assertFalse(b.is_locked())
209
247
        self.assertFalse(b.repository.is_locked())
210
248
 
211
 
        self.assertEqual([('b', 'lr', True),
212
 
                          ('r', 'lr', True),
213
 
                          ('rc', 'lr', True),
214
 
                          ('bc', 'lr', False),
215
 
                          ('r', 'ul', True),
216
 
                          ('rc', 'ul', True),
217
 
                         ], self.locks)
 
249
        if self.combined_control:
 
250
            self.assertEqual([('b', 'lr', True),
 
251
                              ('r', 'lr', True),
 
252
                              ('rc', 'lr', True),
 
253
                              ('bc', 'lr', False),
 
254
                              ('r', 'ul', True),
 
255
                              ('rc', 'ul', True),
 
256
                             ], self.locks)
 
257
        else:
 
258
            self.assertEqual([('b', 'lr', True),
 
259
                              ('r', 'lr', True),
 
260
                              ('bc', 'lr', False),
 
261
                              ('r', 'ul', True),
 
262
                             ], self.locks)
218
263
 
219
264
    def test_08_lock_write_fail_control(self):
220
265
        # Test the repository is unlocked if we can't lock self
224
269
        self.assertRaises(TestPreventLocking, b.lock_write)
225
270
        self.assertFalse(b.is_locked())
226
271
        self.assertFalse(b.repository.is_locked())
227
 
 
228
 
        self.assertEqual([('b', 'lw', True),
229
 
                          ('r', 'lw', True),
230
 
                          ('rc', 'lw', True),
231
 
                          ('bc', 'lw', False),
232
 
                          ('r', 'ul', True),
233
 
                          ('rc', 'ul', True),
234
 
                         ], self.locks)
 
272
        if self.combined_control:
 
273
            self.assertEqual([('b', 'lw', True),
 
274
                              ('r', 'lw', True),
 
275
                              ('rc', 'lw', True),
 
276
                              ('bc', 'lw', False),
 
277
                              ('r', 'ul', True),
 
278
                              ('rc', 'ul', True),
 
279
                             ], self.locks)
 
280
        else:
 
281
            self.assertEqual([('b', 'lw', True),
 
282
                              ('r', 'lw', True),
 
283
                              ('bc', 'lw', False),
 
284
                              ('r', 'ul', True),
 
285
                             ], self.locks)
235
286
 
236
287
    def test_lock_write_returns_None_refuses_token(self):
237
288
        branch = self.make_branch('b')
381
432
            branch.unlock()
382
433
        # We should be unable to relock the repo.
383
434
        self.assertRaises(errors.LockContention, branch.lock_write)
 
435
        # Cleanup
 
436
        branch.lock_write(token)
 
437
        branch.dont_leave_lock_in_place()
 
438
        branch.unlock()
384
439
 
385
440
    def test_dont_leave_lock_in_place(self):
386
441
        branch = self.make_branch('b')
398
453
            except NotImplementedError:
399
454
                # This branch doesn't support this API.
400
455
                return
401
 
            branch.repository.leave_lock_in_place()
402
 
            repo_token = branch.repository.lock_write()
403
 
            branch.repository.unlock()
 
456
            try:
 
457
                branch.repository.leave_lock_in_place()
 
458
            except NotImplementedError:
 
459
                # This repo doesn't support leaving locks around,
 
460
                # assume it is essentially lock-free.
 
461
                repo_token = None
 
462
            else:
 
463
                repo_token = branch.repository.lock_write()
 
464
                branch.repository.unlock()
404
465
        finally:
405
466
            branch.unlock()
406
467
        # Reacquire the lock (with a different branch object) by using the
407
468
        # tokens.
408
469
        new_branch = branch.bzrdir.open_branch()
409
 
        # We have to explicitly lock the repository first.
410
 
        new_branch.repository.lock_write(token=repo_token)
 
470
        if repo_token is not None:
 
471
            # We have to explicitly lock the repository first.
 
472
            new_branch.repository.lock_write(token=repo_token)
411
473
        new_branch.lock_write(token=token)
412
 
        # Now we don't need our own repository lock anymore (the branch is
413
 
        # holding it for us).
414
 
        new_branch.repository.unlock()
 
474
        if repo_token is not None:
 
475
            # Now we don't need our own repository lock anymore (the branch is
 
476
            # holding it for us).
 
477
            new_branch.repository.unlock()
415
478
        # Call dont_leave_lock_in_place, so that the lock will be released by
416
479
        # this instance, even though the lock wasn't originally acquired by it.
417
480
        new_branch.dont_leave_lock_in_place()
418
 
        new_branch.repository.dont_leave_lock_in_place()
 
481
        if repo_token is not None:
 
482
            new_branch.repository.dont_leave_lock_in_place()
419
483
        new_branch.unlock()
420
484
        # Now the branch (and repository) is unlocked.  Test this by locking it
421
485
        # without tokens.
437
501
        branch = branch.bzrdir.open_branch()
438
502
        branch.lock_write()
439
503
        try:
440
 
            # Now the branch.repository is locked, so we can't lock it with a new
441
 
            # repository without a token.
 
504
            # The branch should have asked the repository to lock.
 
505
            self.assertTrue(branch.repository.is_write_locked())
 
506
            # Does the repository type actually lock?
 
507
            if not branch.repository.get_physical_lock_status():
 
508
                # The test was successfully applied, so it was applicable.
 
509
                return
 
510
            # Now the branch.repository is physically locked, so we can't lock
 
511
            # it with a new repository instance.
442
512
            new_repo = branch.bzrdir.open_repository()
443
513
            self.assertRaises(errors.LockContention, new_repo.lock_write)
444
514
            # We can call lock_write on the original repository object though,
447
517
            branch.repository.unlock()
448
518
        finally:
449
519
            branch.unlock()
 
520
 
 
521
    def test_lock_and_unlock_leaves_repo_unlocked(self):
 
522
        branch = self.make_branch('b')
 
523
        branch.lock_write()
 
524
        branch.unlock()
 
525
        self.assertRaises(errors.LockNotHeld, branch.repository.unlock)
 
526