1
# Copyright (C) 2006, 2007 Canonical Ltd
1
# Copyright (C) 2006 Canonical Ltd
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
32
31
from bzrlib.errors import (
40
from bzrlib.lockdir import LockDir
33
LockContention, LockError, UnlockableTransport,
34
LockNotHeld, LockBroken
36
from bzrlib.lockdir import LockDir, _DEFAULT_TIMEOUT_SECONDS
41
37
from bzrlib.tests import TestCaseWithTransport
42
38
from bzrlib.trace import note
108
104
"""Fail to create lock on readonly transport"""
109
105
t = self.get_readonly_transport()
110
106
lf = LockDir(t, 'test_lock')
111
self.assertRaises(LockFailed, lf.create)
107
self.assertRaises(UnlockableTransport, lf.create)
113
109
def test_12_lock_readonly_transport(self):
114
110
"""Fail to lock on readonly transport"""
115
111
lf = LockDir(self.get_transport(), 'test_lock')
117
113
lf = LockDir(self.get_readonly_transport(), 'test_lock')
118
self.assertRaises(LockFailed, lf.attempt_lock)
114
self.assertRaises(UnlockableTransport, lf.attempt_lock)
120
116
def test_20_lock_contested(self):
121
117
"""Contention to get a lock"""
191
187
lock_base = lf2.transport.abspath(lf2.path)
192
188
self.assertEqual(1, len(self._logged_reports))
193
lock_url = lf2.transport.abspath(lf2.path)
194
189
self.assertEqual('%s %s\n'
196
'Will continue to try until %s, unless '
198
'If you\'re sure that it\'s not being '
199
'modified, use bzr break-lock %s',
191
'Will continue to try until %s\n',
200
192
self._logged_reports[0][0])
201
193
args = self._logged_reports[0][1]
202
194
self.assertEqual('Unable to obtain', args[0])
228
220
One thread holds on a lock and then releases it; another
229
221
tries to lock it.
231
# This test sometimes fails like this:
232
# Traceback (most recent call last):
234
# File "/home/pqm/bzr-pqm-workdir/home/+trunk/bzrlib/tests/
235
# test_lockdir.py", line 247, in test_32_lock_wait_succeed
236
# self.assertEqual(1, len(self._logged_reports))
237
# AssertionError: not equal:
240
raise tests.TestSkipped("Test fails intermittently")
241
223
t = self.get_transport()
242
224
lf1 = LockDir(t, 'test_lock')
275
257
self.assertEndsWith(args[3], ' ago')
276
258
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)
278
287
def test_34_lock_write_waits(self):
279
288
"""LockDir.lock_write() will wait for the lock."""
280
# the test suite sets the default to 0 to make deadlocks fail fast.
281
# change it for this test, as we want to try a manual deadlock.
282
raise tests.TestSkipped('Timing-sensitive test')
283
bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = 300
284
289
t = self.get_transport()
285
290
lf1 = LockDir(t, 'test_lock')
337
342
unlocks the lockdir, allowing Lock2 to acquire the lock.
340
raise tests.KnownFailure(
341
"timing dependency in lock tests (#213182)")
343
345
wait_to_check_lock = Lock()
344
346
wait_until_checked_lock = Lock()
413
415
# There should be 2 reports, because the lock changed
414
416
lock_base = lf2.transport.abspath(lf2.path)
415
417
self.assertEqual(2, len(self._logged_reports))
416
lock_url = lf2.transport.abspath(lf2.path)
417
419
self.assertEqual('%s %s\n'
419
'Will continue to try until %s, unless '
421
'If you\'re sure that it\'s not being '
422
'modified, use bzr break-lock %s',
421
'Will continue to try until %s\n',
423
422
self._logged_reports[0][0])
424
423
args = self._logged_reports[0][1]
425
424
self.assertEqual('Unable to obtain', args[0])
432
431
self.assertEqual('%s %s\n'
434
'Will continue to try until %s, unless '
436
'If you\'re sure that it\'s not being '
437
'modified, use bzr break-lock %s',
433
'Will continue to try until %s\n',
438
434
self._logged_reports[1][0])
439
435
args = self._logged_reports[1][1]
440
436
self.assertEqual('Lock owner changed for', args[0])
615
611
lock_path = ld1.transport.local_abspath('test_lock')
616
612
os.mkdir(lock_path)
617
613
osutils.make_readonly(lock_path)
618
self.assertRaises(errors.LockFailed, ld1.attempt_lock)
620
def test_lock_by_token(self):
621
ld1 = self.get_lock()
622
token = ld1.lock_write()
623
self.assertNotEqual(None, token)
624
ld2 = self.get_lock()
625
t2 = ld2.lock_write(token)
626
self.assertEqual(token, t2)
628
def test_lock_with_buggy_rename(self):
629
# test that lock acquisition handles servers which pretend they
630
# renamed correctly but that actually fail
631
t = transport.get_transport('brokenrename+' + self.get_url())
632
ld1 = LockDir(t, 'test_lock')
635
ld2 = LockDir(t, 'test_lock')
636
# we should fail to lock
637
e = self.assertRaises(errors.LockContention, ld2.attempt_lock)
638
# now the original caller should succeed in unlocking
640
# and there should be nothing left over
641
self.assertEquals([], t.list_dir('test_lock'))
643
def test_failed_lock_leaves_no_trash(self):
644
# if we fail to acquire the lock, we don't leave pending directories
645
# behind -- https://bugs.launchpad.net/bzr/+bug/109169
646
ld1 = self.get_lock()
647
ld2 = self.get_lock()
648
# should be nothing before we start
650
t = self.get_transport().clone('test_lock')
652
self.assertEquals(a, t.list_dir('.'))
654
# when held, that's all we see
657
# second guy should fail
658
self.assertRaises(errors.LockContention, ld2.attempt_lock)
614
self.assertRaises(errors.PermissionDenied, ld1.attempt_lock)