~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_lock.py

(jameinel) Allow 'bzr serve' to interpret SIGHUP as a graceful shutdown.
 (bug #795025) (John A Meinel)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2009, 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
"""Tests for OS Locks."""
 
18
 
 
19
 
 
20
from bzrlib import (
 
21
    debug,
 
22
    errors,
 
23
    lock,
 
24
    tests,
 
25
    )
 
26
from bzrlib.tests.scenarios import load_tests_apply_scenarios
 
27
 
 
28
 
 
29
load_tests = load_tests_apply_scenarios
 
30
 
 
31
 
 
32
class TestOSLock(tests.TestCaseInTempDir):
 
33
 
 
34
    scenarios = [(
 
35
        name, {
 
36
            'write_lock': write_lock,
 
37
            'read_lock': read_lock})
 
38
        for name, write_lock, read_lock in lock._lock_classes]
 
39
 
 
40
    read_lock = None
 
41
    write_lock = None
 
42
 
 
43
    def setUp(self):
 
44
        super(TestOSLock, self).setUp()
 
45
        self.build_tree(['a-lock-file'])
 
46
 
 
47
    def test_create_read_lock(self):
 
48
        r_lock = self.read_lock('a-lock-file')
 
49
        r_lock.unlock()
 
50
 
 
51
    def test_create_write_lock(self):
 
52
        w_lock = self.write_lock('a-lock-file')
 
53
        w_lock.unlock()
 
54
 
 
55
    def test_read_locks_share(self):
 
56
        r_lock = self.read_lock('a-lock-file')
 
57
        try:
 
58
            lock2 = self.read_lock('a-lock-file')
 
59
            lock2.unlock()
 
60
        finally:
 
61
            r_lock.unlock()
 
62
 
 
63
    def test_write_locks_are_exclusive(self):
 
64
        w_lock = self.write_lock('a-lock-file')
 
65
        try:
 
66
            self.assertRaises(errors.LockContention,
 
67
                              self.write_lock, 'a-lock-file')
 
68
        finally:
 
69
            w_lock.unlock()
 
70
 
 
71
    def test_read_locks_block_write_locks(self):
 
72
        r_lock = self.read_lock('a-lock-file')
 
73
        try:
 
74
            if lock.have_fcntl and self.write_lock is lock._fcntl_WriteLock:
 
75
                # With -Dlock, fcntl locks are properly exclusive
 
76
                debug.debug_flags.add('strict_locks')
 
77
                self.assertRaises(errors.LockContention,
 
78
                                  self.write_lock, 'a-lock-file')
 
79
                # But not without it
 
80
                debug.debug_flags.remove('strict_locks')
 
81
                try:
 
82
                    w_lock = self.write_lock('a-lock-file')
 
83
                except errors.LockContention:
 
84
                    self.fail('Unexpected success. fcntl read locks'
 
85
                              ' do not usually block write locks')
 
86
                else:
 
87
                    w_lock.unlock()
 
88
                    self.knownFailure('fcntl read locks don\'t'
 
89
                                      ' block write locks without -Dlock')
 
90
            else:
 
91
                self.assertRaises(errors.LockContention,
 
92
                                  self.write_lock, 'a-lock-file')
 
93
        finally:
 
94
            r_lock.unlock()
 
95
 
 
96
    def test_write_locks_block_read_lock(self):
 
97
        w_lock = self.write_lock('a-lock-file')
 
98
        try:
 
99
            if lock.have_fcntl and self.read_lock is lock._fcntl_ReadLock:
 
100
                # With -Dlock, fcntl locks are properly exclusive
 
101
                debug.debug_flags.add('strict_locks')
 
102
                self.assertRaises(errors.LockContention,
 
103
                                  self.read_lock, 'a-lock-file')
 
104
                # But not without it
 
105
                debug.debug_flags.remove('strict_locks')
 
106
                try:
 
107
                    r_lock = self.read_lock('a-lock-file')
 
108
                except errors.LockContention:
 
109
                    self.fail('Unexpected success. fcntl write locks'
 
110
                              ' do not usually block read locks')
 
111
                else:
 
112
                    r_lock.unlock()
 
113
                    self.knownFailure('fcntl write locks don\'t'
 
114
                                      ' block read locks without -Dlock')
 
115
            else:
 
116
                self.assertRaises(errors.LockContention,
 
117
                                  self.read_lock, 'a-lock-file')
 
118
        finally:
 
119
            w_lock.unlock()
 
120
 
 
121
 
 
122
    def test_temporary_write_lock(self):
 
123
        r_lock = self.read_lock('a-lock-file')
 
124
        try:
 
125
            status, w_lock = r_lock.temporary_write_lock()
 
126
            self.assertTrue(status)
 
127
            # This should block another write lock
 
128
            try:
 
129
                self.assertRaises(errors.LockContention,
 
130
                                  self.write_lock, 'a-lock-file')
 
131
            finally:
 
132
                r_lock = w_lock.restore_read_lock()
 
133
            # We should be able to take a read lock now
 
134
            r_lock2 = self.read_lock('a-lock-file')
 
135
            r_lock2.unlock()
 
136
        finally:
 
137
            r_lock.unlock()
 
138
 
 
139
    def test_temporary_write_lock_fails(self):
 
140
        r_lock = self.read_lock('a-lock-file')
 
141
        try:
 
142
            r_lock2 = self.read_lock('a-lock-file')
 
143
            try:
 
144
                status, w_lock = r_lock.temporary_write_lock()
 
145
                self.assertFalse(status)
 
146
                # Taking out the lock requires unlocking and locking again, so
 
147
                # we have to replace the original object
 
148
                r_lock = w_lock
 
149
            finally:
 
150
                r_lock2.unlock()
 
151
            # We should be able to take a read lock now
 
152
            r_lock2 = self.read_lock('a-lock-file')
 
153
            r_lock2.unlock()
 
154
        finally:
 
155
            r_lock.unlock()