~bzr-pqm/bzr/bzr.dev

3388.2.1 by Martin Pool
Deprecate LockableFiles.get_utf8
1
# Copyright (C) 2005, 2006, 2008 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.67.4 by Aaron Bentley
Throw if we try to write to a LockableFiles with no write lock
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.67.4 by Aaron Bentley
Throw if we try to write to a LockableFiles with no write lock
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.67.4 by Aaron Bentley
Throw if we try to write to a LockableFiles with no write lock
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
1185.67.4 by Aaron Bentley
Throw if we try to write to a LockableFiles with no write lock
16
1185.70.2 by Martin Pool
Fix funny mistake
17
from StringIO import StringIO
18
1687.1.6 by Robert Collins
Extend LockableFiles to support break_lock() calls.
19
import bzrlib
3107.2.1 by John Arbash Meinel
Fix LockableFiles to not use modes that allow the user to write to things they create.
20
from bzrlib import (
21
    errors,
22
    lockdir,
23
    osutils,
24
    )
1185.65.29 by Robert Collins
Implement final review suggestions.
25
from bzrlib.errors import BzrBadParameterNotString, NoSuchFile, ReadOnlyError
1553.5.63 by Martin Pool
Lock type is now mandatory for LockableFiles constructor
26
from bzrlib.lockable_files import LockableFiles, TransportLock
3388.2.1 by Martin Pool
Deprecate LockableFiles.get_utf8
27
from bzrlib.symbol_versioning import (
28
    deprecated_in,
29
    )
3474.1.1 by Martin Pool
Better reporting of inapplicable lockable_files tests
30
from bzrlib.tests import (
31
    TestCaseInTempDir,
32
    TestNotApplicable,
33
    )
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
34
from bzrlib.tests.test_smart import TestCaseWithSmartMedium
1594.2.22 by Robert Collins
Ensure that lockable files calls finish() on transactions.:
35
from bzrlib.tests.test_transactions import DummyWeave
1563.2.34 by Robert Collins
Remove the commit and rollback transaction methods as misleading, and implement a WriteTransaction
36
from bzrlib.transactions import (PassThroughTransaction,
37
                                 ReadOnlyTransaction,
38
                                 WriteTransaction,
39
                                 )
1185.67.4 by Aaron Bentley
Throw if we try to write to a LockableFiles with no write lock
40
from bzrlib.transport import get_transport
1185.65.23 by Robert Collins
update tests somewhat
41
1553.5.42 by Martin Pool
Start to parameterize LockableFiles test cases.
42
43
# these tests are applied in each parameterized suite for LockableFiles
3388.2.1 by Martin Pool
Deprecate LockableFiles.get_utf8
44
#
45
# they use an old style of parameterization, but we want to remove this class
46
# so won't modernize them now. - mbp 20080430
1553.5.42 by Martin Pool
Start to parameterize LockableFiles test cases.
47
class _TestLockableFiles_mixin(object):
1185.67.4 by Aaron Bentley
Throw if we try to write to a LockableFiles with no write lock
48
1185.67.6 by Aaron Bentley
Added tests and fixes for LockableFiles.put_utf8(); imported IterableFile
49
    def test_read_write(self):
3407.2.1 by Martin Pool
Deprecate LockableFiles.get
50
        self.assertRaises(NoSuchFile,
51
            self.applyDeprecated,
52
            deprecated_in((1, 5, 0)),
53
            self.lockable.get, 'foo')
3388.2.1 by Martin Pool
Deprecate LockableFiles.get_utf8
54
        self.assertRaises(NoSuchFile,
55
            self.applyDeprecated,
56
            deprecated_in((1, 5, 0)),
57
            self.lockable.get_utf8, 'foo')
1185.67.6 by Aaron Bentley
Added tests and fixes for LockableFiles.put_utf8(); imported IterableFile
58
        self.lockable.lock_write()
4327.1.7 by Vincent Ladeuil
Fix 2 more lock-related test failures.
59
        self.addCleanup(self.lockable.unlock)
60
        unicode_string = u'bar\u1234'
61
        self.assertEqual(4, len(unicode_string))
62
        byte_string = unicode_string.encode('utf-8')
63
        self.assertEqual(6, len(byte_string))
64
        self.assertRaises(UnicodeEncodeError,
65
            self.applyDeprecated,
66
            deprecated_in((1, 6, 0)),
67
            self.lockable.put, 'foo',
68
            StringIO(unicode_string))
69
        self.applyDeprecated(
70
            deprecated_in((1, 6, 0)),
71
            self.lockable.put,
72
            'foo', StringIO(byte_string))
73
        byte_stream = self.applyDeprecated(
74
            deprecated_in((1, 5, 0)),
75
            self.lockable.get,
76
            'foo')
77
        self.assertEqual(byte_string, byte_stream.read())
78
        unicode_stream = self.applyDeprecated(
79
            deprecated_in((1, 5, 0)),
80
            self.lockable.get_utf8,
81
            'foo')
82
        self.assertEqual(unicode_string,
83
            unicode_stream.read())
84
        self.assertRaises(BzrBadParameterNotString,
85
            self.applyDeprecated,
86
            deprecated_in((1, 6, 0)),
87
            self.lockable.put_utf8,
88
            'bar',
89
            StringIO(unicode_string))
90
        self.applyDeprecated(
91
            deprecated_in((1, 6, 0)),
92
            self.lockable.put_utf8,
93
            'bar',
94
            unicode_string)
95
        unicode_stream = self.applyDeprecated(
96
            deprecated_in((1, 5, 0)),
97
            self.lockable.get_utf8,
98
            'bar')
99
        self.assertEqual(unicode_string,
100
            unicode_stream.read())
101
        byte_stream = self.applyDeprecated(
102
            deprecated_in((1, 5, 0)),
103
            self.lockable.get,
104
            'bar')
105
        self.assertEqual(byte_string, byte_stream.read())
106
        self.applyDeprecated(
107
            deprecated_in((1, 6, 0)),
108
            self.lockable.put_bytes,
109
            'raw', 'raw\xffbytes')
110
        byte_stream = self.applyDeprecated(
111
            deprecated_in((1, 5, 0)),
112
            self.lockable.get,
113
            'raw')
114
        self.assertEqual('raw\xffbytes', byte_stream.read())
1185.67.6 by Aaron Bentley
Added tests and fixes for LockableFiles.put_utf8(); imported IterableFile
115
1185.67.4 by Aaron Bentley
Throw if we try to write to a LockableFiles with no write lock
116
    def test_locks(self):
1185.67.8 by Aaron Bentley
Test and fix read locks
117
        self.lockable.lock_read()
4327.1.7 by Vincent Ladeuil
Fix 2 more lock-related test failures.
118
        self.addCleanup(self.lockable.unlock)
119
        self.assertRaises(ReadOnlyError, self.lockable.put, 'foo',
120
                          StringIO('bar\u1234'))
1185.68.1 by Aaron Bentley
test transactions
121
122
    def test_transactions(self):
123
        self.assertIs(self.lockable.get_transaction().__class__,
124
                      PassThroughTransaction)
125
        self.lockable.lock_read()
126
        try:
127
            self.assertIs(self.lockable.get_transaction().__class__,
128
                          ReadOnlyTransaction)
129
        finally:
130
            self.lockable.unlock()
131
        self.assertIs(self.lockable.get_transaction().__class__,
132
                      PassThroughTransaction)
133
        self.lockable.lock_write()
134
        self.assertIs(self.lockable.get_transaction().__class__,
1563.2.34 by Robert Collins
Remove the commit and rollback transaction methods as misleading, and implement a WriteTransaction
135
                      WriteTransaction)
1594.2.22 by Robert Collins
Ensure that lockable files calls finish() on transactions.:
136
        # check that finish is called:
137
        vf = DummyWeave('a')
138
        self.lockable.get_transaction().register_dirty(vf)
1185.68.1 by Aaron Bentley
test transactions
139
        self.lockable.unlock()
1594.2.22 by Robert Collins
Ensure that lockable files calls finish() on transactions.:
140
        self.assertTrue(vf.finished)
1185.65.23 by Robert Collins
update tests somewhat
141
142
    def test__escape(self):
143
        self.assertEqual('%25', self.lockable._escape('%'))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
144
1185.65.23 by Robert Collins
update tests somewhat
145
    def test__escape_empty(self):
146
        self.assertEqual('', self.lockable._escape(''))
147
1687.1.6 by Robert Collins
Extend LockableFiles to support break_lock() calls.
148
    def test_break_lock(self):
149
        # some locks are not breakable
150
        self.lockable.lock_write()
151
        try:
152
            self.assertRaises(AssertionError, self.lockable.break_lock)
153
        except NotImplementedError:
154
            # this lock cannot be broken
155
            self.lockable.unlock()
3474.1.1 by Martin Pool
Better reporting of inapplicable lockable_files tests
156
            raise TestNotApplicable("%r is not breakable" % (self.lockable,))
1687.1.6 by Robert Collins
Extend LockableFiles to support break_lock() calls.
157
        l2 = self.get_lockable()
158
        orig_factory = bzrlib.ui.ui_factory
159
        # silent ui - no need for stdout
4449.3.27 by Martin Pool
More test updates to use CannedInputUIFactory
160
        bzrlib.ui.ui_factory = bzrlib.ui.CannedInputUIFactory([True])
1687.1.6 by Robert Collins
Extend LockableFiles to support break_lock() calls.
161
        try:
162
            l2.break_lock()
163
        finally:
164
            bzrlib.ui.ui_factory = orig_factory
165
        try:
166
            l2.lock_write()
167
            l2.unlock()
168
        finally:
169
            self.assertRaises(errors.LockBroken, self.lockable.unlock)
170
            self.assertFalse(self.lockable.is_locked())
171
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
172
    def test_lock_write_returns_None_refuses_token(self):
173
        token = self.lockable.lock_write()
4327.1.7 by Vincent Ladeuil
Fix 2 more lock-related test failures.
174
        self.addCleanup(self.lockable.unlock)
175
        if token is not None:
176
            # This test does not apply, because this lockable supports
177
            # tokens.
178
            raise TestNotApplicable("%r uses tokens" % (self.lockable,))
179
        self.assertRaises(errors.TokenLockingNotSupported,
180
                          self.lockable.lock_write, token='token')
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
181
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
182
    def test_lock_write_returns_token_when_given_token(self):
183
        token = self.lockable.lock_write()
4327.1.7 by Vincent Ladeuil
Fix 2 more lock-related test failures.
184
        self.addCleanup(self.lockable.unlock)
185
        if token is None:
186
            # This test does not apply, because this lockable refuses
187
            # tokens.
188
            return
189
        new_lockable = self.get_lockable()
190
        token_from_new_lockable = new_lockable.lock_write(token=token)
191
        self.addCleanup(new_lockable.unlock)
192
        self.assertEqual(token, token_from_new_lockable)
2018.5.78 by Andrew Bennetts
Implement RemoteRepository.lock_write/unlock to expect and send tokens over the
193
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
194
    def test_lock_write_raises_on_token_mismatch(self):
195
        token = self.lockable.lock_write()
4327.1.7 by Vincent Ladeuil
Fix 2 more lock-related test failures.
196
        self.addCleanup(self.lockable.unlock)
197
        if token is None:
198
            # This test does not apply, because this lockable refuses
199
            # tokens.
200
            return
201
        different_token = token + 'xxx'
202
        # Re-using the same lockable instance with a different token will
203
        # raise TokenMismatch.
204
        self.assertRaises(errors.TokenMismatch,
205
                          self.lockable.lock_write, token=different_token)
206
        # A separate instance for the same lockable will also raise
207
        # TokenMismatch.
208
        # This detects the case where a caller claims to have a lock (via
209
        # the token) for an external resource, but doesn't (the token is
210
        # different).  Clients need a separate lock object to make sure the
211
        # external resource is probed, whereas the existing lock object
212
        # might cache.
213
        new_lockable = self.get_lockable()
214
        self.assertRaises(errors.TokenMismatch,
215
                          new_lockable.lock_write, token=different_token)
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
216
217
    def test_lock_write_with_matching_token(self):
218
        # If the token matches, so no exception is raised by lock_write.
219
        token = self.lockable.lock_write()
4327.1.7 by Vincent Ladeuil
Fix 2 more lock-related test failures.
220
        self.addCleanup(self.lockable.unlock)
221
        if token is None:
222
            # This test does not apply, because this lockable refuses
223
            # tokens.
224
            return
225
        # The same instance will accept a second lock_write if the specified
226
        # token matches.
227
        self.lockable.lock_write(token=token)
228
        self.lockable.unlock()
229
        # Calling lock_write on a new instance for the same lockable will
230
        # also succeed.
231
        new_lockable = self.get_lockable()
232
        new_lockable.lock_write(token=token)
233
        new_lockable.unlock()
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
234
235
    def test_unlock_after_lock_write_with_token(self):
236
        # If lock_write did not physically acquire the lock (because it was
237
        # passed a token), then unlock should not physically release it.
238
        token = self.lockable.lock_write()
4327.1.7 by Vincent Ladeuil
Fix 2 more lock-related test failures.
239
        self.addCleanup(self.lockable.unlock)
240
        if token is None:
241
            # This test does not apply, because this lockable refuses
242
            # tokens.
243
            return
244
        new_lockable = self.get_lockable()
245
        new_lockable.lock_write(token=token)
246
        new_lockable.unlock()
247
        self.assertTrue(self.lockable.get_physical_lock_status())
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
248
249
    def test_lock_write_with_token_fails_when_unlocked(self):
250
        # Lock and unlock to get a superficially valid token.  This mimics a
251
        # likely programming error, where a caller accidentally tries to lock
252
        # with a token that is no longer valid (because the original lock was
253
        # released).
254
        token = self.lockable.lock_write()
255
        self.lockable.unlock()
256
        if token is None:
257
            # This test does not apply, because this lockable refuses
258
            # tokens.
259
            return
260
261
        self.assertRaises(errors.TokenMismatch,
262
                          self.lockable.lock_write, token=token)
263
264
    def test_lock_write_reenter_with_token(self):
265
        token = self.lockable.lock_write()
266
        try:
267
            if token is None:
268
                # This test does not apply, because this lockable refuses
269
                # tokens.
270
                return
271
            # Relock with a token.
2018.5.79 by Andrew Bennetts
Implement RemoteBranch.lock_write/unlock as smart operations.
272
            token_from_reentry = self.lockable.lock_write(token=token)
273
            try:
274
                self.assertEqual(token, token_from_reentry)
275
            finally:
276
                self.lockable.unlock()
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
277
        finally:
278
            self.lockable.unlock()
279
        # The lock should be unlocked on disk.  Verify that with a new lock
280
        # instance.
281
        new_lockable = self.get_lockable()
282
        # Calling lock_write now should work, rather than raise LockContention.
283
        new_lockable.lock_write()
284
        new_lockable.unlock()
285
2279.7.11 by Andrew Bennetts
Remove some XXXs.
286
    def test_second_lock_write_returns_same_token(self):
287
        first_token = self.lockable.lock_write()
288
        try:
289
            if first_token is None:
290
                # This test does not apply, because this lockable refuses
291
                # tokens.
292
                return
293
            # Relock the already locked lockable.  It should return the same
294
            # token.
295
            second_token = self.lockable.lock_write()
296
            try:
297
                self.assertEqual(first_token, second_token)
298
            finally:
299
                self.lockable.unlock()
300
        finally:
301
            self.lockable.unlock()
302
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
303
    def test_leave_in_place(self):
304
        token = self.lockable.lock_write()
305
        try:
306
            if token is None:
307
                # This test does not apply, because this lockable refuses
308
                # tokens.
309
                return
310
            self.lockable.leave_in_place()
311
        finally:
312
            self.lockable.unlock()
313
        # At this point, the lock is still in place on disk
314
        self.assertRaises(errors.LockContention, self.lockable.lock_write)
315
        # But should be relockable with a token.
316
        self.lockable.lock_write(token=token)
317
        self.lockable.unlock()
4327.1.7 by Vincent Ladeuil
Fix 2 more lock-related test failures.
318
        # Cleanup: we should still be able to get the lock, but we restore the
319
        # behavior to clearing the lock when unlocking.
320
        self.lockable.lock_write(token=token)
321
        self.lockable.dont_leave_in_place()
322
        self.lockable.unlock()
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
323
324
    def test_dont_leave_in_place(self):
325
        token = self.lockable.lock_write()
326
        try:
327
            if token is None:
328
                # This test does not apply, because this lockable refuses
329
                # tokens.
330
                return
331
            self.lockable.leave_in_place()
332
        finally:
333
            self.lockable.unlock()
334
        # At this point, the lock is still in place on disk.
335
        # Acquire the existing lock with the token, and ask that it is removed
336
        # when this object unlocks, and unlock to trigger that removal.
337
        new_lockable = self.get_lockable()
338
        new_lockable.lock_write(token=token)
339
        new_lockable.dont_leave_in_place()
340
        new_lockable.unlock()
341
        # At this point, the lock is no longer on disk, so we can lock it.
342
        third_lockable = self.get_lockable()
343
        third_lockable.lock_write()
344
        third_lockable.unlock()
2279.7.7 by Andrew Bennetts
LockDir, Repository and Branch lock token changes from the hpss branch.
345
346
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
347
# This method of adapting tests to parameters is different to
348
# the TestProviderAdapters used elsewhere, but seems simpler for this
349
# case.
1553.5.45 by Martin Pool
Clean up Transport-based locks for old branches
350
class TestLockableFiles_TransportLock(TestCaseInTempDir,
351
                                      _TestLockableFiles_mixin):
1553.5.42 by Martin Pool
Start to parameterize LockableFiles test cases.
352
353
    def setUp(self):
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
354
        TestCaseInTempDir.setUp(self)
1553.5.42 by Martin Pool
Start to parameterize LockableFiles test cases.
355
        transport = get_transport('.')
356
        transport.mkdir('.bzr')
1687.1.6 by Robert Collins
Extend LockableFiles to support break_lock() calls.
357
        self.sub_transport = transport.clone('.bzr')
358
        self.lockable = self.get_lockable()
1553.5.61 by Martin Pool
Locks protecting LockableFiles must now be explicitly created before use.
359
        self.lockable.create_lock()
1687.1.6 by Robert Collins
Extend LockableFiles to support break_lock() calls.
360
361
    def tearDown(self):
362
        super(TestLockableFiles_TransportLock, self).tearDown()
1687.1.15 by Robert Collins
Review comments.
363
        # free the subtransport so that we do not get a 5 second
364
        # timeout due to the SFTP connection cache.
3474.1.1 by Martin Pool
Better reporting of inapplicable lockable_files tests
365
        try:
366
            del self.sub_transport
367
        except AttributeError:
368
            pass
1687.1.6 by Robert Collins
Extend LockableFiles to support break_lock() calls.
369
370
    def get_lockable(self):
371
        return LockableFiles(self.sub_transport, 'my-lock', TransportLock)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
372
1553.5.43 by Martin Pool
Get LockableFiles tests running against LockDir
373
374
class TestLockableFiles_LockDir(TestCaseInTempDir,
375
                              _TestLockableFiles_mixin):
376
    """LockableFile tests run with LockDir underneath"""
377
378
    def setUp(self):
2279.7.1 by Andrew Bennetts
``LockableFiles.lock_write()`` now accepts a ``token`` keyword argument, so that
379
        TestCaseInTempDir.setUp(self)
1553.5.61 by Martin Pool
Locks protecting LockableFiles must now be explicitly created before use.
380
        self.transport = get_transport('.')
1687.1.6 by Robert Collins
Extend LockableFiles to support break_lock() calls.
381
        self.lockable = self.get_lockable()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
382
        # the lock creation here sets mode - test_permissions on branch
383
        # tests that implicitly, but it might be a good idea to factor
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
384
        # out the mode checking logic and have it applied to loackable files
385
        # directly. RBC 20060418
1553.5.61 by Martin Pool
Locks protecting LockableFiles must now be explicitly created before use.
386
        self.lockable.create_lock()
1553.5.43 by Martin Pool
Get LockableFiles tests running against LockDir
387
1687.1.6 by Robert Collins
Extend LockableFiles to support break_lock() calls.
388
    def get_lockable(self):
3107.2.1 by John Arbash Meinel
Fix LockableFiles to not use modes that allow the user to write to things they create.
389
        return LockableFiles(self.transport, 'my-lock', lockdir.LockDir)
1553.5.60 by Martin Pool
New LockableFiles.create_lock() method
390
391
    def test_lock_created(self):
1553.5.61 by Martin Pool
Locks protecting LockableFiles must now be explicitly created before use.
392
        self.assertTrue(self.transport.has('my-lock'))
393
        self.lockable.lock_write()
394
        self.assertTrue(self.transport.has('my-lock/held/info'))
395
        self.lockable.unlock()
396
        self.assertFalse(self.transport.has('my-lock/held/info'))
397
        self.assertTrue(self.transport.has('my-lock'))
398
3107.2.1 by John Arbash Meinel
Fix LockableFiles to not use modes that allow the user to write to things they create.
399
    def test__file_modes(self):
400
        self.transport.mkdir('readonly')
401
        osutils.make_readonly('readonly')
402
        lockable = LockableFiles(self.transport.clone('readonly'), 'test-lock',
403
                                 lockdir.LockDir)
404
        # The directory mode should be read-write-execute for the current user
405
        self.assertEqual(00700, lockable._dir_mode & 00700)
406
        # Files should be read-write for the current user
407
        self.assertEqual(00600, lockable._file_mode & 00700)
1553.5.61 by Martin Pool
Locks protecting LockableFiles must now be explicitly created before use.
408
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
409
410
class TestLockableFiles_RemoteLockDir(TestCaseWithSmartMedium,
411
                              _TestLockableFiles_mixin):
412
    """LockableFile tests run with RemoteLockDir on a branch."""
413
414
    def setUp(self):
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
415
        TestCaseWithSmartMedium.setUp(self)
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
416
        # can only get a RemoteLockDir with some RemoteObject...
417
        # use a branch as thats what we want. These mixin tests test the end
418
        # to end behaviour, so stubbing out the backend and simulating would
419
        # defeat the purpose. We test the protocol implementation separately
420
        # in test_remote and test_smart as usual.
2018.5.171 by Andrew Bennetts
Disconnect RemoteTransports in some tests to avoid tripping up test_strace with leftover threads from previous tests.
421
        b = self.make_branch('foo')
422
        self.addCleanup(b.bzrdir.transport.disconnect)
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
423
        self.transport = get_transport('.')
424
        self.lockable = self.get_lockable()
425
426
    def get_lockable(self):
427
        # getting a new lockable involves opening a new instance of the branch
428
        branch = bzrlib.branch.Branch.open(self.get_url('foo'))
2018.5.171 by Andrew Bennetts
Disconnect RemoteTransports in some tests to avoid tripping up test_strace with leftover threads from previous tests.
429
        self.addCleanup(branch.bzrdir.transport.disconnect)
2018.5.59 by Robert Collins
Get BranchConfig working somewhat on RemoteBranches (Robert Collins, Vincent Ladeuil).
430
        return branch.control_files