/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1711.8.5 by John Arbash Meinel
Move the new locking tests into their own files, and move the helper functions into a test helper.
1
# Copyright (C) 2006 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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1711.8.5 by John Arbash Meinel
Move the new locking tests into their own files, and move the helper functions into a test helper.
16
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
17
"""Tests for the (un)lock interfaces on all working tree implemenations."""
1711.8.5 by John Arbash Meinel
Move the new locking tests into their own files, and move the helper functions into a test helper.
18
1957.1.17 by John Arbash Meinel
Change tests that expect locking to fail to timeout sooner.
19
from bzrlib import (
20
    branch,
21
    errors,
22
    lockdir,
23
    )
4523.1.4 by Martin Pool
Rename remaining *_implementations tests
24
from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
1711.8.5 by John Arbash Meinel
Move the new locking tests into their own files, and move the helper functions into a test helper.
25
26
27
class TestWorkingTreeLocking(TestCaseWithWorkingTree):
28
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
29
    def test_trivial_lock_read_unlock(self):
30
        """Locking and unlocking should work trivially."""
1711.8.5 by John Arbash Meinel
Move the new locking tests into their own files, and move the helper functions into a test helper.
31
        wt = self.make_branch_and_tree('.')
32
33
        self.assertFalse(wt.is_locked())
34
        self.assertFalse(wt.branch.is_locked())
35
        wt.lock_read()
36
        try:
37
            self.assertTrue(wt.is_locked())
38
            self.assertTrue(wt.branch.is_locked())
39
        finally:
40
            wt.unlock()
41
        self.assertFalse(wt.is_locked())
42
        self.assertFalse(wt.branch.is_locked())
43
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
44
    def test_trivial_lock_write_unlock(self):
45
        """Locking for write and unlocking should work trivially."""
46
        wt = self.make_branch_and_tree('.')
1711.8.5 by John Arbash Meinel
Move the new locking tests into their own files, and move the helper functions into a test helper.
47
48
        self.assertFalse(wt.is_locked())
49
        self.assertFalse(wt.branch.is_locked())
50
        wt.lock_write()
51
        try:
52
            self.assertTrue(wt.is_locked())
53
            self.assertTrue(wt.branch.is_locked())
54
        finally:
55
            wt.unlock()
56
        self.assertFalse(wt.is_locked())
57
        self.assertFalse(wt.branch.is_locked())
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
58
1997.1.1 by Robert Collins
Add WorkingTree.lock_tree_write.
59
    def test_trivial_lock_tree_write_unlock(self):
60
        """Locking for tree write is ok when the branch is not locked."""
61
        wt = self.make_branch_and_tree('.')
62
63
        self.assertFalse(wt.is_locked())
64
        self.assertFalse(wt.branch.is_locked())
65
        wt.lock_tree_write()
66
        try:
67
            self.assertTrue(wt.is_locked())
68
            self.assertTrue(wt.branch.is_locked())
69
        finally:
70
            wt.unlock()
71
        self.assertFalse(wt.is_locked())
72
        self.assertFalse(wt.branch.is_locked())
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
73
1997.1.1 by Robert Collins
Add WorkingTree.lock_tree_write.
74
    def test_trivial_lock_tree_write_branch_read_locked(self):
75
        """It is ok to lock_tree_write when the branch is read locked."""
76
        wt = self.make_branch_and_tree('.')
77
78
        self.assertFalse(wt.is_locked())
79
        self.assertFalse(wt.branch.is_locked())
80
        wt.branch.lock_read()
81
        try:
82
            wt.lock_tree_write()
83
        except errors.ReadOnlyError:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
84
            # When ReadOnlyError is raised, it indicates that the
1997.1.1 by Robert Collins
Add WorkingTree.lock_tree_write.
85
            # workingtree shares its lock with the branch, which is what
86
            # the git/hg/bzr0.6 formats do.
87
            # in this case, no lock should have been taken - but the tree
88
            # will have been locked because they share a lock. Unlocking
89
            # just the branch should make everything match again correctly.
90
            wt.branch.unlock()
91
            self.assertFalse(wt.is_locked())
92
            self.assertFalse(wt.branch.is_locked())
93
            return
94
        try:
95
            self.assertTrue(wt.is_locked())
96
            self.assertTrue(wt.branch.is_locked())
97
        finally:
98
            wt.unlock()
99
        self.assertFalse(wt.is_locked())
100
        self.assertTrue(wt.branch.is_locked())
101
        wt.branch.unlock()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
102
1986.5.3 by Robert Collins
New method ``WorkingTree.flush()`` which will write the current memory
103
    def _test_unlock_with_lock_method(self, methodname):
104
        """Create a tree and then test its unlocking behaviour.
105
106
        :param methodname: The lock method to use to establish locks.
107
        """
4523.4.17 by John Arbash Meinel
Now we got to the per-workingtree tests, etc.
108
        # This write locks the local tree, and then grabs a read lock on a
109
        # copy, which is bogus and the test just needs to be rewritten.
110
        self.thisFailsStrictLockCheck()
1986.5.3 by Robert Collins
New method ``WorkingTree.flush()`` which will write the current memory
111
        # when unlocking the last lock count from tree_write_lock,
112
        # the tree should do a flush().
113
        # we test that by changing the inventory using set_root_id
114
        tree = self.make_branch_and_tree('tree')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
115
        # prepare for a series of changes that will modify the
1986.5.3 by Robert Collins
New method ``WorkingTree.flush()`` which will write the current memory
116
        # inventory
117
        getattr(tree, methodname)()
118
        # note that we dont have a try:finally here because of two reasons:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
119
        # firstly there will only be errors reported if the test fails, and
1986.5.3 by Robert Collins
New method ``WorkingTree.flush()`` which will write the current memory
120
        # when it fails thats ok as long as the test suite cleanup still works,
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
121
        # which it will as the lock objects are released (thats where the
122
        # warning comes from.  Secondly, it is hard in this test to be
1986.5.3 by Robert Collins
New method ``WorkingTree.flush()`` which will write the current memory
123
        # sure that we've got the right interactions between try:finally
124
        # and the lock/unlocks we are doing.
125
        getattr(tree, methodname)()
126
        # this should really do something within the public api
127
        # e.g. mkdir('foo') but all the mutating methods at the
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
128
        # moment trigger inventory writes and thus will not
1986.5.3 by Robert Collins
New method ``WorkingTree.flush()`` which will write the current memory
129
        # let us trigger a read-when-dirty situation.
130
        old_root = tree.get_root_id()
131
        tree.set_root_id('new-root')
132
        # to detect that the inventory is written by unlock, we
133
        # first check that it was not written yet.
4523.4.17 by John Arbash Meinel
Now we got to the per-workingtree tests, etc.
134
        # TODO: This requires taking a read lock while we are holding the above
135
        #       write lock, which shouldn't actually be possible
1986.5.3 by Robert Collins
New method ``WorkingTree.flush()`` which will write the current memory
136
        reference_tree = tree.bzrdir.open_workingtree()
137
        self.assertEqual(old_root, reference_tree.get_root_id())
138
        # now unlock the second held lock, which should do nothing.
139
        tree.unlock()
140
        reference_tree = tree.bzrdir.open_workingtree()
141
        self.assertEqual(old_root, reference_tree.get_root_id())
142
        # unlocking the first lock we took will now flush.
143
        tree.unlock()
144
        # and check it was written using another reference tree
145
        reference_tree = tree.bzrdir.open_workingtree()
146
        self.assertEqual('new-root', reference_tree.get_root_id())
147
148
    def test_unlock_from_tree_write_lock_flushes(self):
149
        self._test_unlock_with_lock_method("lock_tree_write")
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
150
1986.5.3 by Robert Collins
New method ``WorkingTree.flush()`` which will write the current memory
151
    def test_unlock_from_write_lock_flushes(self):
152
        self._test_unlock_with_lock_method("lock_write")
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
153
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
154
    def test_unlock_branch_failures(self):
155
        """If the branch unlock fails the tree must still unlock."""
156
        # The public interface for WorkingTree requires a branch, but
157
        # does not require that the working tree use the branch - its
158
        # implementation specific how the WorkingTree, Branch, and Repository
159
        # hang together.
160
        # in order to test that implementations which *do* unlock via the branch
161
        # do so correctly, we unlock the branch after locking the working tree.
162
        # The next unlock on working tree should trigger a LockNotHeld exception
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
163
        # from the branch object, which must be exposed to the caller. To meet
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
164
        # our object model - where locking a tree locks its branch, and
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
165
        # unlocking a branch does not unlock a working tree, *even* for
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
166
        # all-in-one implementations like bzr 0.6, git, and hg, implementations
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
167
        # must have some separate counter for each object, so our explicit
168
        # unlock should trigger some error on all implementations, and
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
169
        # requiring that to be LockNotHeld seems reasonable.
170
        #
171
        # we use this approach rather than decorating the Branch, because the
172
        # public interface of WorkingTree does not permit altering the branch
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
173
        # object - and we cannot tell which attribute might allow us to
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
174
        # backdoor-in and change it reliably. For implementation specific tests
175
        # we can do such skullduggery, but not for interface specific tests.
176
        # And, its simpler :)
177
        wt = self.make_branch_and_tree('.')
178
179
        self.assertFalse(wt.is_locked())
180
        self.assertFalse(wt.branch.is_locked())
181
        wt.lock_write()
182
        self.assertTrue(wt.is_locked())
183
        self.assertTrue(wt.branch.is_locked())
184
185
        # manually unlock the branch, preparing a LockNotHeld error.
186
        wt.branch.unlock()
187
        # the branch *may* still be locked here, if its an all-in-one
1852.4.6 by Robert Collins
Review feedback.
188
        # implementation because there is a single lock object with three
189
        # references on it, and unlocking the branch only drops this by two
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
190
        self.assertRaises(errors.LockNotHeld, wt.unlock)
191
        # but now, the tree must be unlocked
192
        self.assertFalse(wt.is_locked())
193
        # and the branch too.
194
        self.assertFalse(wt.branch.is_locked())
195
196
    def test_failing_to_lock_branch_does_not_lock(self):
197
        """If the branch cannot be locked, dont lock the tree."""
198
        # Many implementations treat read-locks as non-blocking, but some
199
        # treat them as blocking with writes.. Accordingly we test this by
200
        # opening the branch twice, and locking the branch for write in the
201
        # second instance.  Our lock contract requires separate instances to
202
        # mutually exclude if a lock is exclusive at all: If we get no error
203
        # locking, the test still passes.
204
        wt = self.make_branch_and_tree('.')
205
        branch_copy = branch.Branch.open('.')
206
        branch_copy.lock_write()
207
        try:
208
            try:
209
                wt.lock_read()
1852.4.5 by Robert Collins
Change bare except in working tree locking tests to catch LockError only.
210
            except errors.LockError:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
211
                # any error here means the locks are exclusive in some
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
212
                # manner
213
                self.assertFalse(wt.is_locked())
214
                self.assertFalse(wt.branch.is_locked())
215
                return
216
            else:
217
                # no error - the branch allows read locks while writes
218
                # are taken, just pass.
219
                wt.unlock()
220
        finally:
221
            branch_copy.unlock()
222
223
    def test_failing_to_lock_write_branch_does_not_lock(self):
224
        """If the branch cannot be write locked, dont lock the tree."""
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
225
        # all implementations of branch are required to treat write
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
226
        # locks as blocking (compare to repositories which are not required
227
        # to do so).
228
        # Accordingly we test this by opening the branch twice, and locking the
229
        # branch for write in the second instance.  Our lock contract requires
230
        # separate instances to mutually exclude.
231
        wt = self.make_branch_and_tree('.')
232
        branch_copy = branch.Branch.open('.')
233
        branch_copy.lock_write()
234
        try:
235
            try:
3287.4.2 by Martin Pool
Change more tests to use reduceLockdirTimeout
236
                self.assertRaises(errors.LockError, wt.lock_write)
1852.4.3 by Robert Collins
Alter working tree lock and unlock tests to test via the interface rather than via unpublished internals.
237
                self.assertFalse(wt.is_locked())
238
                self.assertFalse(wt.branch.is_locked())
239
            finally:
240
                if wt.is_locked():
241
                    wt.unlock()
242
        finally:
243
            branch_copy.unlock()
1997.1.1 by Robert Collins
Add WorkingTree.lock_tree_write.
244
245
    def test_failing_to_lock_tree_write_branch_does_not_lock(self):
246
        """If the branch cannot be read locked, dont lock the tree."""
247
        # Many implementations treat read-locks as non-blocking, but some
248
        # treat them as blocking with writes.. Accordingly we test this by
249
        # opening the branch twice, and locking the branch for write in the
250
        # second instance.  Our lock contract requires separate instances to
251
        # mutually exclude if a lock is exclusive at all: If we get no error
252
        # locking, the test still passes.
253
        wt = self.make_branch_and_tree('.')
254
        branch_copy = branch.Branch.open('.')
1957.1.17 by John Arbash Meinel
Change tests that expect locking to fail to timeout sooner.
255
1997.1.1 by Robert Collins
Add WorkingTree.lock_tree_write.
256
        branch_copy.lock_write()
257
        try:
258
            try:
259
                wt.lock_tree_write()
260
            except errors.LockError:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
261
                # any error here means the locks are exclusive in some
1997.1.1 by Robert Collins
Add WorkingTree.lock_tree_write.
262
                # manner
263
                self.assertFalse(wt.is_locked())
264
                self.assertFalse(wt.branch.is_locked())
265
                return
266
            else:
267
                # no error - the branch allows read locks while writes
268
                # are taken, just pass.
269
                wt.unlock()
270
        finally:
271
            branch_copy.unlock()