~bzr-pqm/bzr/bzr.dev

5557.1.7 by John Arbash Meinel
Merge in the bzr.dev 5582
1
# Copyright (C) 2009, 2011 Canonical Ltd
4523.4.1 by John Arbash Meinel
Start adding some direct testing for read and write locks.
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 (
4523.4.7 by John Arbash Meinel
Change the fcntl locks so they are only exclusive with -Dlock.
21
    debug,
22
    errors,
4523.4.1 by John Arbash Meinel
Start adding some direct testing for read and write locks.
23
    lock,
24
    tests,
25
    )
5559.2.2 by Martin Pool
Change to using standard load_tests_apply_scenarios.
26
from bzrlib.tests.scenarios import load_tests_apply_scenarios
27
28
29
load_tests = load_tests_apply_scenarios
4523.4.1 by John Arbash Meinel
Start adding some direct testing for read and write locks.
30
31
32
class TestOSLock(tests.TestCaseInTempDir):
33
5559.2.2 by Martin Pool
Change to using standard load_tests_apply_scenarios.
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
4523.4.1 by John Arbash Meinel
Start adding some direct testing for read and write locks.
40
    read_lock = None
41
    write_lock = None
42
4523.4.2 by John Arbash Meinel
Some more tests about lock behavior.
43
    def setUp(self):
44
        super(TestOSLock, self).setUp()
45
        self.build_tree(['a-lock-file'])
46
4523.4.1 by John Arbash Meinel
Start adding some direct testing for read and write locks.
47
    def test_create_read_lock(self):
4523.4.2 by John Arbash Meinel
Some more tests about lock behavior.
48
        r_lock = self.read_lock('a-lock-file')
49
        r_lock.unlock()
4523.4.1 by John Arbash Meinel
Start adding some direct testing for read and write locks.
50
51
    def test_create_write_lock(self):
4523.4.2 by John Arbash Meinel
Some more tests about lock behavior.
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()
4523.4.1 by John Arbash Meinel
Start adding some direct testing for read and write locks.
62
63
    def test_write_locks_are_exclusive(self):
4523.4.2 by John Arbash Meinel
Some more tests about lock behavior.
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:
4523.4.7 by John Arbash Meinel
Change the fcntl locks so they are only exclusive with -Dlock.
74
            if lock.have_fcntl and self.write_lock is lock._fcntl_WriteLock:
75
                # With -Dlock, fcntl locks are properly exclusive
4523.4.14 by John Arbash Meinel
Fix the direct lock tests.
76
                debug.debug_flags.add('strict_locks')
4523.4.7 by John Arbash Meinel
Change the fcntl locks so they are only exclusive with -Dlock.
77
                self.assertRaises(errors.LockContention,
78
                                  self.write_lock, 'a-lock-file')
79
                # But not without it
4523.4.14 by John Arbash Meinel
Fix the direct lock tests.
80
                debug.debug_flags.remove('strict_locks')
4523.4.7 by John Arbash Meinel
Change the fcntl locks so they are only exclusive with -Dlock.
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')
4523.4.2 by John Arbash Meinel
Some more tests about lock behavior.
93
        finally:
94
            r_lock.unlock()
95
4523.4.3 by John Arbash Meinel
Having a write lock should block a read lock and vice-versa.
96
    def test_write_locks_block_read_lock(self):
97
        w_lock = self.write_lock('a-lock-file')
98
        try:
4523.4.7 by John Arbash Meinel
Change the fcntl locks so they are only exclusive with -Dlock.
99
            if lock.have_fcntl and self.read_lock is lock._fcntl_ReadLock:
100
                # With -Dlock, fcntl locks are properly exclusive
4523.4.14 by John Arbash Meinel
Fix the direct lock tests.
101
                debug.debug_flags.add('strict_locks')
4523.4.7 by John Arbash Meinel
Change the fcntl locks so they are only exclusive with -Dlock.
102
                self.assertRaises(errors.LockContention,
103
                                  self.read_lock, 'a-lock-file')
104
                # But not without it
4523.4.14 by John Arbash Meinel
Fix the direct lock tests.
105
                debug.debug_flags.remove('strict_locks')
4523.4.7 by John Arbash Meinel
Change the fcntl locks so they are only exclusive with -Dlock.
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')
4523.4.3 by John Arbash Meinel
Having a write lock should block a read lock and vice-versa.
118
        finally:
119
            w_lock.unlock()
120
121
4523.4.2 by John Arbash Meinel
Some more tests about lock behavior.
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()