104
109
"""Fail to create lock on readonly transport"""
105
110
t = self.get_readonly_transport()
106
111
lf = LockDir(t, 'test_lock')
107
self.assertRaises(UnlockableTransport, lf.create)
112
self.assertRaises(LockFailed, lf.create)
109
114
def test_12_lock_readonly_transport(self):
110
115
"""Fail to lock on readonly transport"""
111
116
lf = LockDir(self.get_transport(), 'test_lock')
113
118
lf = LockDir(self.get_readonly_transport(), 'test_lock')
114
self.assertRaises(UnlockableTransport, lf.attempt_lock)
119
self.assertRaises(LockFailed, lf.attempt_lock)
116
121
def test_20_lock_contested(self):
117
122
"""Contention to get a lock"""
180
185
after = time.time()
181
186
# it should only take about 0.4 seconds, but we allow more time in
182
187
# case the machine is heavily loaded
183
self.assertTrue(after - before <= 8.0,
188
self.assertTrue(after - before <= 8.0,
184
189
"took %f seconds to detect lock contention" % (after - before))
187
192
lock_base = lf2.transport.abspath(lf2.path)
188
193
self.assertEqual(1, len(self._logged_reports))
194
lock_url = lf2.transport.abspath(lf2.path)
189
195
self.assertEqual('%s %s\n'
191
'Will continue to try until %s\n',
197
'Will continue to try until %s, unless '
199
'If you\'re sure that it\'s not being '
200
'modified, use bzr break-lock %s',
192
201
self._logged_reports[0][0])
193
202
args = self._logged_reports[0][1]
194
203
self.assertEqual('Unable to obtain', args[0])
217
226
def test_32_lock_wait_succeed(self):
218
227
"""Succeed when trying to acquire a lock that gets released
220
One thread holds on a lock and then releases it; another
229
One thread holds on a lock and then releases it; another
221
230
tries to lock it.
232
# This test sometimes fails like this:
233
# Traceback (most recent call last):
235
# File "/home/pqm/bzr-pqm-workdir/home/+trunk/bzrlib/tests/
236
# test_lockdir.py", line 247, in test_32_lock_wait_succeed
237
# self.assertEqual(1, len(self._logged_reports))
238
# AssertionError: not equal:
241
raise tests.TestSkipped("Test fails intermittently")
223
242
t = self.get_transport()
224
243
lf1 = LockDir(t, 'test_lock')
257
276
self.assertEndsWith(args[3], ' ago')
258
277
self.assertContainsRe(args[4], r'\d\d:\d\d:\d\d')
260
def test_33_wait(self):
261
"""Succeed when waiting on a lock that gets released
263
The difference from test_32_lock_wait_succeed is that the second
264
caller does not actually acquire the lock, but just waits for it
265
to be released. This is done over a readonly transport.
267
t = self.get_transport()
268
lf1 = LockDir(t, 'test_lock')
272
def wait_and_unlock():
275
unlocker = Thread(target=wait_and_unlock)
278
lf2 = LockDir(self.get_readonly_transport(), 'test_lock')
280
# wait but don't lock
281
lf2.wait(timeout=0.4, poll=0.1)
283
self.assertTrue(after - before <= 1.0)
287
279
def test_34_lock_write_waits(self):
288
"""LockDir.lock_write() will wait for the lock."""
280
"""LockDir.lock_write() will wait for the lock."""
289
281
# the test suite sets the default to 0 to make deadlocks fail fast.
290
282
# change it for this test, as we want to try a manual deadlock.
283
raise tests.TestSkipped('Timing-sensitive test')
291
284
bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = 300
292
285
t = self.get_transport()
293
286
lf1 = LockDir(t, 'test_lock')
328
321
def test_35_wait_lock_changing(self):
329
322
"""LockDir.wait_lock() will report if the lock changes underneath.
331
324
This is the stages we want to happen:
333
326
0) Synchronization locks are created and locked.
334
327
1) Lock1 obtains the lockdir, and releases the 'check' lock.
335
328
2) Lock2 grabs the 'check' lock, and checks the lockdir.
336
It sees the lockdir is already acquired, reports the fact,
329
It sees the lockdir is already acquired, reports the fact,
337
330
and unsets the 'checked' lock.
338
331
3) Thread1 blocks on acquiring the 'checked' lock, and then tells
339
332
Lock1 to release and acquire the lockdir. This resets the 'check'
341
334
4) Lock2 acquires the 'check' lock, and checks again. It notices
342
that the holder of the lock has changed, and so reports a new
335
that the holder of the lock has changed, and so reports a new
344
337
5) Thread1 blocks on the 'checked' lock, this time, it completely
345
338
unlocks the lockdir, allowing Lock2 to acquire the lock.
341
raise tests.KnownFailure(
342
"timing dependency in lock tests (#213182)")
348
344
wait_to_check_lock = Lock()
349
345
wait_until_checked_lock = Lock()
418
414
# There should be 2 reports, because the lock changed
419
415
lock_base = lf2.transport.abspath(lf2.path)
420
416
self.assertEqual(2, len(self._logged_reports))
417
lock_url = lf2.transport.abspath(lf2.path)
422
418
self.assertEqual('%s %s\n'
424
'Will continue to try until %s\n',
420
'Will continue to try until %s, unless '
422
'If you\'re sure that it\'s not being '
423
'modified, use bzr break-lock %s',
425
424
self._logged_reports[0][0])
426
425
args = self._logged_reports[0][1]
427
426
self.assertEqual('Unable to obtain', args[0])
614
616
lock_path = ld1.transport.local_abspath('test_lock')
615
617
os.mkdir(lock_path)
616
618
osutils.make_readonly(lock_path)
617
self.assertRaises(errors.PermissionDenied, ld1.attempt_lock)
619
self.assertRaises(errors.LockFailed, ld1.attempt_lock)
621
def test_lock_by_token(self):
622
ld1 = self.get_lock()
623
token = ld1.lock_write()
624
self.assertNotEqual(None, token)
625
ld2 = self.get_lock()
626
t2 = ld2.lock_write(token)
627
self.assertEqual(token, t2)
629
def test_lock_with_buggy_rename(self):
630
# test that lock acquisition handles servers which pretend they
631
# renamed correctly but that actually fail
632
t = transport.get_transport('brokenrename+' + self.get_url())
633
ld1 = LockDir(t, 'test_lock')
636
ld2 = LockDir(t, 'test_lock')
637
# we should fail to lock
638
e = self.assertRaises(errors.LockContention, ld2.attempt_lock)
639
# now the original caller should succeed in unlocking
641
# and there should be nothing left over
642
self.assertEquals([], t.list_dir('test_lock'))
644
def test_failed_lock_leaves_no_trash(self):
645
# if we fail to acquire the lock, we don't leave pending directories
646
# behind -- https://bugs.launchpad.net/bzr/+bug/109169
647
ld1 = self.get_lock()
648
ld2 = self.get_lock()
649
# should be nothing before we start
651
t = self.get_transport().clone('test_lock')
653
self.assertEquals(a, t.list_dir('.'))
655
# when held, that's all we see
658
# second guy should fail
659
self.assertRaises(errors.LockContention, ld2.attempt_lock)
663
def record_hook(self, result):
664
self._calls.append(result)
666
def reset_hooks(self):
667
self._old_hooks = lock.Lock.hooks
668
self.addCleanup(self.restore_hooks)
669
lock.Lock.hooks = lock.LockHooks()
671
def restore_hooks(self):
672
lock.Lock.hooks = self._old_hooks
674
def test_LockDir_acquired_success(self):
675
# the LockDir.lock_acquired hook fires when a lock is acquired.
678
LockDir.hooks.install_named_hook('lock_acquired',
679
self.record_hook, 'record_hook')
682
self.assertEqual([], self._calls)
683
result = ld.attempt_lock()
684
lock_path = ld.transport.abspath(ld.path)
685
self.assertEqual([lock.LockResult(lock_path, result)], self._calls)
687
self.assertEqual([lock.LockResult(lock_path, result)], self._calls)
689
def test_LockDir_acquired_fail(self):
690
# the LockDir.lock_acquired hook does not fire on failure.
695
ld2 = self.get_lock()
697
# install a lock hook now, when the disk lock is locked
698
LockDir.hooks.install_named_hook('lock_acquired',
699
self.record_hook, 'record_hook')
700
self.assertRaises(errors.LockContention, ld.attempt_lock)
701
self.assertEqual([], self._calls)
703
self.assertEqual([], self._calls)
705
def test_LockDir_released_success(self):
706
# the LockDir.lock_released hook fires when a lock is acquired.
709
LockDir.hooks.install_named_hook('lock_released',
710
self.record_hook, 'record_hook')
713
self.assertEqual([], self._calls)
714
result = ld.attempt_lock()
715
self.assertEqual([], self._calls)
717
lock_path = ld.transport.abspath(ld.path)
718
self.assertEqual([lock.LockResult(lock_path, result)], self._calls)
720
def test_LockDir_released_fail(self):
721
# the LockDir.lock_released hook does not fire on failure.
726
ld2 = self.get_lock()
728
ld2.force_break(ld2.peek())
729
LockDir.hooks.install_named_hook('lock_released',
730
self.record_hook, 'record_hook')
731
self.assertRaises(LockBroken, ld.unlock)
732
self.assertEqual([], self._calls)