~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/workingtree_implementations/test_locking.py

  • Committer: John Arbash Meinel
  • Author(s): Mark Hammond
  • Date: 2008-09-09 17:02:21 UTC
  • mto: This revision was merged to the branch mainline in revision 3697.
  • Revision ID: john@arbash-meinel.com-20080909170221-svim3jw2mrz0amp3
An updated transparent icon for bzr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2008, 2009, 2010 Canonical Ltd
 
1
# Copyright (C) 2006 Canonical Ltd
2
2
#
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
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Tests for the (un)lock interfaces on all working tree implemenations."""
18
18
 
19
 
import sys
20
 
 
21
19
from bzrlib import (
22
20
    branch,
23
21
    errors,
 
22
    lockdir,
24
23
    )
25
 
from bzrlib.tests import TestSkipped
26
 
from bzrlib.tests.matchers import *
27
 
from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
 
24
from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
28
25
 
29
26
 
30
27
class TestWorkingTreeLocking(TestCaseWithWorkingTree):
44
41
        self.assertFalse(wt.is_locked())
45
42
        self.assertFalse(wt.branch.is_locked())
46
43
 
47
 
    def test_lock_read_returns_unlocker(self):
48
 
        wt = self.make_branch_and_tree('.')
49
 
        self.assertThat(wt.lock_read, ReturnsUnlockable(wt))
50
 
 
51
44
    def test_trivial_lock_write_unlock(self):
52
45
        """Locking for write and unlocking should work trivially."""
53
46
        wt = self.make_branch_and_tree('.')
62
55
            wt.unlock()
63
56
        self.assertFalse(wt.is_locked())
64
57
        self.assertFalse(wt.branch.is_locked())
65
 
 
66
 
    def test_lock_write_returns_unlocker(self):
67
 
        wt = self.make_branch_and_tree('.')
68
 
        self.assertThat(wt.lock_write, ReturnsUnlockable(wt))
69
 
 
 
58
        
70
59
    def test_trivial_lock_tree_write_unlock(self):
71
60
        """Locking for tree write is ok when the branch is not locked."""
72
61
        wt = self.make_branch_and_tree('.')
81
70
            wt.unlock()
82
71
        self.assertFalse(wt.is_locked())
83
72
        self.assertFalse(wt.branch.is_locked())
84
 
 
85
 
    def test_lock_tree_write_returns_unlocker(self):
86
 
        wt = self.make_branch_and_tree('.')
87
 
        self.assertThat(wt.lock_tree_write, ReturnsUnlockable(wt))
88
 
 
 
73
        
89
74
    def test_trivial_lock_tree_write_branch_read_locked(self):
90
75
        """It is ok to lock_tree_write when the branch is read locked."""
91
76
        wt = self.make_branch_and_tree('.')
96
81
        try:
97
82
            wt.lock_tree_write()
98
83
        except errors.ReadOnlyError:
99
 
            # When ReadOnlyError is raised, it indicates that the
 
84
            # When ReadOnlyError is raised, it indicates that the 
100
85
            # workingtree shares its lock with the branch, which is what
101
86
            # the git/hg/bzr0.6 formats do.
102
87
            # in this case, no lock should have been taken - but the tree
114
99
        self.assertFalse(wt.is_locked())
115
100
        self.assertTrue(wt.branch.is_locked())
116
101
        wt.branch.unlock()
117
 
 
 
102
        
118
103
    def _test_unlock_with_lock_method(self, methodname):
119
104
        """Create a tree and then test its unlocking behaviour.
120
105
 
121
106
        :param methodname: The lock method to use to establish locks.
122
107
        """
123
 
        if sys.platform == "win32":
124
 
            raise TestSkipped("don't use oslocks on win32 in unix manner")
125
 
        # This helper takes a write lock on the source tree, then opens a
126
 
        # second copy and tries to grab a read lock. This works on Unix and is
127
 
        # a reasonable way to detect when the file is actually written to, but
128
 
        # it won't work (as a test) on Windows. It might be nice to instead
129
 
        # stub out the functions used to write and that way do both less work
130
 
        # and also be able to execute on Windows.
131
 
        self.thisFailsStrictLockCheck()
132
108
        # when unlocking the last lock count from tree_write_lock,
133
109
        # the tree should do a flush().
134
110
        # we test that by changing the inventory using set_root_id
135
111
        tree = self.make_branch_and_tree('tree')
136
 
        # prepare for a series of changes that will modify the
 
112
        # prepare for a series of changes that will modify the 
137
113
        # inventory
138
114
        getattr(tree, methodname)()
139
115
        # note that we dont have a try:finally here because of two reasons:
140
 
        # firstly there will only be errors reported if the test fails, and
 
116
        # firstly there will only be errors reported if the test fails, and 
141
117
        # when it fails thats ok as long as the test suite cleanup still works,
142
 
        # which it will as the lock objects are released (thats where the
143
 
        # warning comes from.  Secondly, it is hard in this test to be
 
118
        # which it will as the lock objects are released (thats where the 
 
119
        # warning comes from.  Secondly, it is hard in this test to be 
144
120
        # sure that we've got the right interactions between try:finally
145
121
        # and the lock/unlocks we are doing.
146
122
        getattr(tree, methodname)()
147
123
        # this should really do something within the public api
148
124
        # e.g. mkdir('foo') but all the mutating methods at the
149
 
        # moment trigger inventory writes and thus will not
 
125
        # moment trigger inventory writes and thus will not 
150
126
        # let us trigger a read-when-dirty situation.
151
127
        old_root = tree.get_root_id()
152
128
        tree.set_root_id('new-root')
153
129
        # to detect that the inventory is written by unlock, we
154
130
        # first check that it was not written yet.
155
 
        # TODO: This requires taking a read lock while we are holding the above
156
 
        #       write lock, which shouldn't actually be possible
157
131
        reference_tree = tree.bzrdir.open_workingtree()
158
132
        self.assertEqual(old_root, reference_tree.get_root_id())
159
133
        # now unlock the second held lock, which should do nothing.
168
142
 
169
143
    def test_unlock_from_tree_write_lock_flushes(self):
170
144
        self._test_unlock_with_lock_method("lock_tree_write")
171
 
 
 
145
        
172
146
    def test_unlock_from_write_lock_flushes(self):
173
147
        self._test_unlock_with_lock_method("lock_write")
174
 
 
 
148
        
175
149
    def test_unlock_branch_failures(self):
176
150
        """If the branch unlock fails the tree must still unlock."""
177
151
        # The public interface for WorkingTree requires a branch, but
181
155
        # in order to test that implementations which *do* unlock via the branch
182
156
        # do so correctly, we unlock the branch after locking the working tree.
183
157
        # The next unlock on working tree should trigger a LockNotHeld exception
184
 
        # from the branch object, which must be exposed to the caller. To meet
 
158
        # from the branch object, which must be exposed to the caller. To meet 
185
159
        # our object model - where locking a tree locks its branch, and
186
 
        # unlocking a branch does not unlock a working tree, *even* for
 
160
        # unlocking a branch does not unlock a working tree, *even* for 
187
161
        # all-in-one implementations like bzr 0.6, git, and hg, implementations
188
 
        # must have some separate counter for each object, so our explicit
189
 
        # unlock should trigger some error on all implementations, and
 
162
        # must have some separate counter for each object, so our explicit 
 
163
        # unlock should trigger some error on all implementations, and 
190
164
        # requiring that to be LockNotHeld seems reasonable.
191
165
        #
192
166
        # we use this approach rather than decorating the Branch, because the
193
167
        # public interface of WorkingTree does not permit altering the branch
194
 
        # object - and we cannot tell which attribute might allow us to
 
168
        # object - and we cannot tell which attribute might allow us to 
195
169
        # backdoor-in and change it reliably. For implementation specific tests
196
170
        # we can do such skullduggery, but not for interface specific tests.
197
171
        # And, its simpler :)
229
203
            try:
230
204
                wt.lock_read()
231
205
            except errors.LockError:
232
 
                # any error here means the locks are exclusive in some
 
206
                # any error here means the locks are exclusive in some 
233
207
                # manner
234
208
                self.assertFalse(wt.is_locked())
235
209
                self.assertFalse(wt.branch.is_locked())
243
217
 
244
218
    def test_failing_to_lock_write_branch_does_not_lock(self):
245
219
        """If the branch cannot be write locked, dont lock the tree."""
246
 
        # all implementations of branch are required to treat write
 
220
        # all implementations of branch are required to treat write 
247
221
        # locks as blocking (compare to repositories which are not required
248
222
        # to do so).
249
223
        # Accordingly we test this by opening the branch twice, and locking the
279
253
            try:
280
254
                wt.lock_tree_write()
281
255
            except errors.LockError:
282
 
                # any error here means the locks are exclusive in some
 
256
                # any error here means the locks are exclusive in some 
283
257
                # manner
284
258
                self.assertFalse(wt.is_locked())
285
259
                self.assertFalse(wt.branch.is_locked())