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
17
17
"""Tests for LockDir"""
19
19
from cStringIO import StringIO
21
20
from threading import Thread, Lock
25
24
from bzrlib import (
32
28
from bzrlib.errors import (
40
from bzrlib.lockdir import LockDir
30
LockContention, LockError, UnlockableTransport,
31
LockNotHeld, LockBroken
33
from bzrlib.lockdir import LockDir, _DEFAULT_TIMEOUT_SECONDS
41
34
from bzrlib.tests import TestCaseWithTransport
42
35
from bzrlib.trace import note
108
101
"""Fail to create lock on readonly transport"""
109
102
t = self.get_readonly_transport()
110
103
lf = LockDir(t, 'test_lock')
111
self.assertRaises(LockFailed, lf.create)
104
self.assertRaises(UnlockableTransport, lf.create)
113
106
def test_12_lock_readonly_transport(self):
114
107
"""Fail to lock on readonly transport"""
115
108
lf = LockDir(self.get_transport(), 'test_lock')
117
110
lf = LockDir(self.get_readonly_transport(), 'test_lock')
118
self.assertRaises(LockFailed, lf.attempt_lock)
111
self.assertRaises(UnlockableTransport, lf.attempt_lock)
120
113
def test_20_lock_contested(self):
121
114
"""Contention to get a lock"""
224
217
One thread holds on a lock and then releases it; another
225
218
tries to lock it.
227
# This test sometimes fails like this:
228
# Traceback (most recent call last):
230
# File "/home/pqm/bzr-pqm-workdir/home/+trunk/bzrlib/tests/
231
# test_lockdir.py", line 247, in test_32_lock_wait_succeed
232
# self.assertEqual(1, len(self._logged_reports))
233
# AssertionError: not equal:
236
raise tests.TestSkipped("Test fails intermittently")
237
220
t = self.get_transport()
238
221
lf1 = LockDir(t, 'test_lock')
271
254
self.assertEndsWith(args[3], ' ago')
272
255
self.assertContainsRe(args[4], r'\d\d:\d\d:\d\d')
257
def test_33_wait(self):
258
"""Succeed when waiting on a lock that gets released
260
The difference from test_32_lock_wait_succeed is that the second
261
caller does not actually acquire the lock, but just waits for it
262
to be released. This is done over a readonly transport.
264
t = self.get_transport()
265
lf1 = LockDir(t, 'test_lock')
269
def wait_and_unlock():
272
unlocker = Thread(target=wait_and_unlock)
275
lf2 = LockDir(self.get_readonly_transport(), 'test_lock')
277
# wait but don't lock
278
lf2.wait(timeout=0.4, poll=0.1)
280
self.assertTrue(after - before <= 1.0)
274
284
def test_34_lock_write_waits(self):
275
285
"""LockDir.lock_write() will wait for the lock."""
276
# the test suite sets the default to 0 to make deadlocks fail fast.
277
# change it for this test, as we want to try a manual deadlock.
278
raise tests.TestSkipped('Timing-sensitive test')
279
bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = 300
280
286
t = self.get_transport()
281
287
lf1 = LockDir(t, 'test_lock')
598
def test_lock_permission(self):
599
if not osutils.supports_posix_readonly():
600
raise tests.TestSkipped('Cannot induce a permission failure')
601
ld1 = self.get_lock()
602
lock_path = ld1.transport.local_abspath('test_lock')
604
osutils.make_readonly(lock_path)
605
self.assertRaises(errors.LockFailed, ld1.attempt_lock)
607
def test_lock_by_token(self):
608
ld1 = self.get_lock()
609
token = ld1.lock_write()
610
self.assertNotEqual(None, token)
611
ld2 = self.get_lock()
612
t2 = ld2.lock_write(token)
613
self.assertEqual(token, t2)
615
def test_lock_with_buggy_rename(self):
616
# test that lock acquisition handles servers which pretend they
617
# renamed correctly but that actually fail
618
t = transport.get_transport('brokenrename+' + self.get_url())
619
ld1 = LockDir(t, 'test_lock')
622
ld2 = LockDir(t, 'test_lock')
623
# we should fail to lock
624
e = self.assertRaises(errors.LockContention, ld2.attempt_lock)
625
# now the original caller should succeed in unlocking
627
# and there should be nothing left over
628
self.assertEquals([], t.list_dir('test_lock'))
630
def test_failed_lock_leaves_no_trash(self):
631
# if we fail to acquire the lock, we don't leave pending directories
632
# behind -- https://bugs.launchpad.net/bzr/+bug/109169
633
ld1 = self.get_lock()
634
ld2 = self.get_lock()
635
# should be nothing before we start
637
t = self.get_transport().clone('test_lock')
639
self.assertEquals(a, t.list_dir('.'))
641
# when held, that's all we see
644
# second guy should fail
645
self.assertRaises(errors.LockContention, ld2.attempt_lock)