/brz/remove-bazaar

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