~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Andrew Bennetts
  • Date: 2010-01-12 03:53:21 UTC
  • mfrom: (4948 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4964.
  • Revision ID: andrew.bennetts@canonical.com-20100112035321-hofpz5p10224ryj3
Merge lp:bzr, resolving conflicts.

Show diffs side-by-side

added added

removed removed

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