~bzr-pqm/bzr/bzr.dev

5439.2.3 by John Arbash Meinel
Merge bzr.dev to resolve NEWS
1
# Copyright (C) 2007, 2009, 2010 Canonical Ltd
2353.3.1 by John Arbash Meinel
Add some basic locking tests which should currently pass on all platforms.
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2353.3.1 by John Arbash Meinel
Add some basic locking tests which should currently pass on all platforms.
16
17
"""Tests for OS level locks."""
18
19
from bzrlib import (
2353.3.2 by John Arbash Meinel
Add a tests that multiple write locks raise the right kind of error.
20
    errors,
2353.3.3 by John Arbash Meinel
Define an explicit error when trying to grab a write lock on a readonly file.
21
    osutils,
2353.3.1 by John Arbash Meinel
Add some basic locking tests which should currently pass on all platforms.
22
    )
23
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
24
from bzrlib.tests import (
25
    features,
26
    )
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
27
from bzrlib.tests.per_lock import TestCaseWithLock
28
29
30
class TestLock(TestCaseWithLock):
2353.3.1 by John Arbash Meinel
Add some basic locking tests which should currently pass on all platforms.
31
32
    def setUp(self):
33
        super(TestLock, self).setUp()
34
        self.build_tree(['a-file'])
35
36
    def test_read_lock(self):
37
        """Smoke test for read locks."""
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
38
        a_lock = self.read_lock('a-file')
2353.3.1 by John Arbash Meinel
Add some basic locking tests which should currently pass on all platforms.
39
        self.addCleanup(a_lock.unlock)
40
        # The lock file should be opened for reading
41
        txt = a_lock.f.read()
42
        self.assertEqual('contents of a-file\n', txt)
43
44
    def test_create_if_needed_read(self):
45
        """We will create the file if it doesn't exist yet."""
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
46
        a_lock = self.read_lock('other-file')
2353.3.1 by John Arbash Meinel
Add some basic locking tests which should currently pass on all platforms.
47
        self.addCleanup(a_lock.unlock)
48
        txt = a_lock.f.read()
49
        self.assertEqual('', txt)
50
51
    def test_create_if_needed_write(self):
52
        """We will create the file if it doesn't exist yet."""
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
53
        a_lock = self.write_lock('other-file')
2353.3.1 by John Arbash Meinel
Add some basic locking tests which should currently pass on all platforms.
54
        self.addCleanup(a_lock.unlock)
55
        txt = a_lock.f.read()
56
        self.assertEqual('', txt)
2353.3.13 by John Arbash Meinel
Cleanup according to Alexander's review comments.
57
        a_lock.f.seek(0)
2353.3.1 by John Arbash Meinel
Add some basic locking tests which should currently pass on all platforms.
58
        a_lock.f.write('foo\n')
59
        a_lock.f.seek(0)
60
        txt = a_lock.f.read()
61
        self.assertEqual('foo\n', txt)
62
2353.3.3 by John Arbash Meinel
Define an explicit error when trying to grab a write lock on a readonly file.
63
    def test_readonly_file(self):
64
        """If the file is readonly, we can take a read lock.
65
66
        But we shouldn't be able to take a write lock.
67
        """
4797.70.1 by Vincent Ladeuil
Skip chmodbits dependent tests when running as root
68
        self.requireFeature(features.not_running_as_root)
2353.3.3 by John Arbash Meinel
Define an explicit error when trying to grab a write lock on a readonly file.
69
        osutils.make_readonly('a-file')
70
        # Make sure the file is read-only (on all platforms)
71
        self.assertRaises(IOError, open, 'a-file', 'rb+')
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
72
        a_lock = self.read_lock('a-file')
2353.3.3 by John Arbash Meinel
Define an explicit error when trying to grab a write lock on a readonly file.
73
        a_lock.unlock()
74
2872.5.1 by Martin Pool
Avoid internal error tracebacks on failure to lock on readonly transport (#129701).
75
        self.assertRaises(errors.LockFailed, self.write_lock, 'a-file')
2353.3.3 by John Arbash Meinel
Define an explicit error when trying to grab a write lock on a readonly file.
76
2353.3.1 by John Arbash Meinel
Add some basic locking tests which should currently pass on all platforms.
77
    def test_write_lock(self):
78
        """Smoke test for write locks."""
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
79
        a_lock = self.write_lock('a-file')
2353.3.1 by John Arbash Meinel
Add some basic locking tests which should currently pass on all platforms.
80
        self.addCleanup(a_lock.unlock)
81
        # You should be able to read and write to the lock file.
82
        txt = a_lock.f.read()
83
        self.assertEqual('contents of a-file\n', txt)
2353.3.6 by John Arbash Meinel
On Win32 if you have a file opened in read+write mode, you must call seek() when switching
84
        # Win32 requires that you call seek() when switching between a read
85
        # operation and a write operation.
86
        a_lock.f.seek(0, 2)
2353.3.1 by John Arbash Meinel
Add some basic locking tests which should currently pass on all platforms.
87
        a_lock.f.write('more content\n')
88
        a_lock.f.seek(0)
89
        txt = a_lock.f.read()
90
        self.assertEqual('contents of a-file\nmore content\n', txt)
91
92
    def test_multiple_read_locks(self):
93
        """You can take out more than one read lock on the same file."""
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
94
        a_lock = self.read_lock('a-file')
2353.3.1 by John Arbash Meinel
Add some basic locking tests which should currently pass on all platforms.
95
        self.addCleanup(a_lock.unlock)
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
96
        b_lock = self.read_lock('a-file')
2353.3.1 by John Arbash Meinel
Add some basic locking tests which should currently pass on all platforms.
97
        self.addCleanup(b_lock.unlock)
98
2353.3.2 by John Arbash Meinel
Add a tests that multiple write locks raise the right kind of error.
99
    def test_multiple_write_locks_exclude(self):
100
        """Taking out more than one write lock should fail."""
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
101
        a_lock = self.write_lock('a-file')
2353.3.2 by John Arbash Meinel
Add a tests that multiple write locks raise the right kind of error.
102
        self.addCleanup(a_lock.unlock)
103
        # Taking out a lock on a locked file should raise LockContention
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
104
        self.assertRaises(errors.LockContention, self.write_lock, 'a-file')
2353.3.3 by John Arbash Meinel
Define an explicit error when trying to grab a write lock on a readonly file.
105
2363.3.3 by John Arbash Meinel
make Write locks not block on Read locks, so that revert tests don't fail
106
    def _disabled_test_read_then_write_excludes(self):
2353.3.3 by John Arbash Meinel
Define an explicit error when trying to grab a write lock on a readonly file.
107
        """If a file is read-locked, taking out a write lock should fail."""
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
108
        a_lock = self.read_lock('a-file')
2353.3.3 by John Arbash Meinel
Define an explicit error when trying to grab a write lock on a readonly file.
109
        self.addCleanup(a_lock.unlock)
110
        # Taking out a lock on a locked file should raise LockContention
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
111
        self.assertRaises(errors.LockContention, self.write_lock, 'a-file')
2353.3.3 by John Arbash Meinel
Define an explicit error when trying to grab a write lock on a readonly file.
112
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
113
    def test_read_unlock_write(self):
114
        """Make sure that unlocking allows us to lock write"""
2353.4.2 by John Arbash Meinel
[merge] LockCleanup changes.
115
        a_lock = self.read_lock('a-file')
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
116
        a_lock.unlock()
2353.4.2 by John Arbash Meinel
[merge] LockCleanup changes.
117
        a_lock = self.write_lock('a-file')
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
118
        a_lock.unlock()
119
2363.3.2 by John Arbash Meinel
Disable read locks blocking on write locks.
120
    # TODO: jam 20070319 fcntl read locks are not currently fully
121
    #       mutually exclusive with write locks. This will be fixed
122
    #       in the next release.
123
    def _disabled_test_write_then_read_excludes(self):
2353.3.3 by John Arbash Meinel
Define an explicit error when trying to grab a write lock on a readonly file.
124
        """If a file is write-locked, taking out a read lock should fail.
125
126
        The file is exclusively owned by the write lock, so we shouldn't be
127
        able to take out a shared read lock.
128
        """
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
129
        a_lock = self.write_lock('a-file')
2353.3.3 by John Arbash Meinel
Define an explicit error when trying to grab a write lock on a readonly file.
130
        self.addCleanup(a_lock.unlock)
131
        # Taking out a lock on a locked file should raise LockContention
2353.3.9 by John Arbash Meinel
Update the lock code and test code so that if more than one
132
        self.assertRaises(errors.LockContention, self.read_lock, 'a-file')
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
133
2363.3.3 by John Arbash Meinel
make Write locks not block on Read locks, so that revert tests don't fail
134
    # TODO: jam 20070319 fcntl write locks are not currently fully
135
    #       mutually exclusive with read locks. This will be fixed
136
    #       in the next release.
137
    def _disabled_test_write_unlock_read(self):
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
138
        """If we have removed the write lock, we can grab a read lock."""
2353.4.2 by John Arbash Meinel
[merge] LockCleanup changes.
139
        a_lock = self.write_lock('a-file')
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
140
        a_lock.unlock()
2353.4.2 by John Arbash Meinel
[merge] LockCleanup changes.
141
        a_lock = self.read_lock('a-file')
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
142
        a_lock.unlock()
143
2363.3.3 by John Arbash Meinel
make Write locks not block on Read locks, so that revert tests don't fail
144
    def _disabled_test_multiple_read_unlock_write(self):
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
145
        """We can only grab a write lock if all read locks are done."""
146
        a_lock = b_lock = c_lock = None
147
        try:
2353.4.2 by John Arbash Meinel
[merge] LockCleanup changes.
148
            a_lock = self.read_lock('a-file')
149
            b_lock = self.read_lock('a-file')
150
            self.assertRaises(errors.LockContention, self.write_lock, 'a-file')
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
151
            a_lock.unlock()
152
            a_lock = None
2353.4.2 by John Arbash Meinel
[merge] LockCleanup changes.
153
            self.assertRaises(errors.LockContention, self.write_lock, 'a-file')
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
154
            b_lock.unlock()
155
            b_lock = None
2353.4.2 by John Arbash Meinel
[merge] LockCleanup changes.
156
            c_lock = self.write_lock('a-file')
2353.4.1 by John Arbash Meinel
(broken) Change fcntl locks to be properly exclusive within the same process.
157
            c_lock.unlock()
158
            c_lock = None
159
        finally:
160
            # Cleanup as needed
161
            if a_lock is not None:
162
                a_lock.unlock()
163
            if b_lock is not None:
164
                b_lock.unlock()
165
            if c_lock is not None:
166
                c_lock.unlock()
4513.1.1 by Alexander Belchenko
improved unicode support for OS locks @ win32.
167
168
169
class TestLockUnicodePath(TestCaseWithLock):
170
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
171
    _test_needs_features = [features.UnicodeFilenameFeature]
4513.1.1 by Alexander Belchenko
improved unicode support for OS locks @ win32.
172
173
    def test_read_lock(self):
174
        self.build_tree([u'\u1234'])
175
        u_lock = self.read_lock(u'\u1234')
176
        self.addCleanup(u_lock.unlock)
177
178
    def test_write_lock(self):
179
        self.build_tree([u'\u1234'])
180
        u_lock = self.write_lock(u'\u1234')
181
        self.addCleanup(u_lock.unlock)