~bzr-pqm/bzr/bzr.dev

4988.10.5 by John Arbash Meinel
Merge bzr.dev 5021 to resolve NEWS
1
# Copyright (C) 2005-2010 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
907.1.48 by John Arbash Meinel
Updated LocalTransport by passing it through the transport_test suite, and got it to pass.
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
#
907.1.48 by John Arbash Meinel
Updated LocalTransport by passing it through the transport_test suite, and got it to pass.
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
#
907.1.48 by John Arbash Meinel
Updated LocalTransport by passing it through the transport_test suite, and got it to pass.
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
907.1.48 by John Arbash Meinel
Updated LocalTransport by passing it through the transport_test suite, and got it to pass.
16
17
1185.11.22 by John Arbash Meinel
Major refactoring of testtransport.
18
from cStringIO import StringIO
4700.1.1 by Robert Collins
Focus and move out of blackbox the acceptance test for bzr+ssh connection handshake/process spawning.
19
import os
20
import subprocess
21
import sys
22
import threading
1442.1.44 by Robert Collins
Many transport related tweaks:
23
2018.18.4 by Martin Pool
Change Transport.local_abspath to raise NotLocalUrl, and test.
24
from bzrlib import (
25
    errors,
2804.4.1 by Alexander Belchenko
some win32-specific fixes for selftest
26
    osutils,
4700.1.1 by Robert Collins
Focus and move out of blackbox the acceptance test for bzr+ssh connection handshake/process spawning.
27
    tests,
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
28
    transport,
2018.18.4 by Martin Pool
Change Transport.local_abspath to raise NotLocalUrl, and test.
29
    urlutils,
30
    )
4634.108.13 by John Arbash Meinel
Add a test case.
31
from bzrlib.transport import (
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
32
    chroot,
4946.1.2 by John Arbash Meinel
Clean up a few more imports.
33
    fakenfs,
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
34
    local,
4634.108.13 by John Arbash Meinel
Add a test case.
35
    memory,
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
36
    pathfilter,
4946.1.2 by John Arbash Meinel
Clean up a few more imports.
37
    readonly,
4634.108.13 by John Arbash Meinel
Add a test case.
38
    )
5017.3.22 by Vincent Ladeuil
selftest -s bt.test_transport passing
39
from bzrlib.tests import (
40
    features,
41
    test_server,
42
    )
1951.2.1 by Martin Pool
Change to using LocalURLServer for testing.
43
44
45
# TODO: Should possibly split transport-specific tests into their own files.
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
46
47
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
48
class TestTransport(tests.TestCase):
1185.58.3 by John Arbash Meinel
code cleanup
49
    """Test the non transport-concrete class functionality."""
50
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
51
    # FIXME: These tests should use addCleanup() and/or overrideAttr() instead
52
    # of try/finally -- vila 20100205
53
2241.3.1 by ghigo
uncomment test test__get_set_protocol_handlers
54
    def test__get_set_protocol_handlers(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
55
        handlers = transport._get_protocol_handlers()
2241.3.1 by ghigo
uncomment test test__get_set_protocol_handlers
56
        self.assertNotEqual([], handlers.keys( ))
57
        try:
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
58
            transport._clear_protocol_handlers()
59
            self.assertEqual([], transport._get_protocol_handlers().keys())
2241.3.1 by ghigo
uncomment test test__get_set_protocol_handlers
60
        finally:
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
61
            transport._set_protocol_handlers(handlers)
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
62
63
    def test_get_transport_modules(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
64
        handlers = transport._get_protocol_handlers()
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
65
        # don't pollute the current handlers
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
66
        transport._clear_protocol_handlers()
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
67
        class SampleHandler(object):
68
            """I exist, isnt that enough?"""
69
        try:
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
70
            transport._clear_protocol_handlers()
71
            transport.register_transport_proto('foo')
72
            transport.register_lazy_transport('foo',
73
                                              'bzrlib.tests.test_transport',
74
                                              'TestTransport.SampleHandler')
75
            transport.register_transport_proto('bar')
76
            transport.register_lazy_transport('bar',
77
                                              'bzrlib.tests.test_transport',
78
                                              'TestTransport.SampleHandler')
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
79
            self.assertEqual([SampleHandler.__module__,
4634.43.21 by Andrew Bennetts
Update test_get_transport_modules for pathfilter.
80
                              'bzrlib.transport.chroot',
81
                              'bzrlib.transport.pathfilter'],
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
82
                             transport._get_transport_modules())
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
83
        finally:
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
84
            transport._set_protocol_handlers(handlers)
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
85
86
    def test_transport_dependency(self):
87
        """Transport with missing dependency causes no error"""
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
88
        saved_handlers = transport._get_protocol_handlers()
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
89
        # don't pollute the current handlers
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
90
        transport._clear_protocol_handlers()
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
91
        try:
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
92
            transport.register_transport_proto('foo')
93
            transport.register_lazy_transport(
94
                'foo', 'bzrlib.tests.test_transport', 'BadTransportHandler')
1843.1.1 by John Arbash Meinel
Update get_transport to raise a nicer error which includes dependency info
95
            try:
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
96
                transport.get_transport('foo://fooserver/foo')
97
            except errors.UnsupportedProtocol, e:
1843.1.1 by John Arbash Meinel
Update get_transport to raise a nicer error which includes dependency info
98
                e_str = str(e)
99
                self.assertEquals('Unsupported protocol'
100
                                  ' for url "foo://fooserver/foo":'
101
                                  ' Unable to import library "some_lib":'
102
                                  ' testing missing dependency', str(e))
103
            else:
104
                self.fail('Did not raise UnsupportedProtocol')
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
105
        finally:
1540.3.10 by Martin Pool
[broken] keep hooking pycurl into test framework
106
            # restore original values
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
107
            transport._set_protocol_handlers(saved_handlers)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
108
1540.3.10 by Martin Pool
[broken] keep hooking pycurl into test framework
109
    def test_transport_fallback(self):
110
        """Transport with missing dependency causes no error"""
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
111
        saved_handlers = transport._get_protocol_handlers()
1540.3.10 by Martin Pool
[broken] keep hooking pycurl into test framework
112
        try:
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
113
            transport._clear_protocol_handlers()
114
            transport.register_transport_proto('foo')
115
            transport.register_lazy_transport(
116
                'foo', 'bzrlib.tests.test_transport', 'BackupTransportHandler')
117
            transport.register_lazy_transport(
118
                'foo', 'bzrlib.tests.test_transport', 'BadTransportHandler')
119
            t = transport.get_transport('foo://fooserver/foo')
1540.3.10 by Martin Pool
[broken] keep hooking pycurl into test framework
120
            self.assertTrue(isinstance(t, BackupTransportHandler))
121
        finally:
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
122
            transport._set_protocol_handlers(saved_handlers)
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
123
4011.4.1 by Jelmer Vernooij
Point out bzr+ssh:// to the user when they use ssh://.
124
    def test_ssh_hints(self):
125
        """Transport ssh:// should raise an error pointing out bzr+ssh://"""
126
        try:
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
127
            transport.get_transport('ssh://fooserver/foo')
128
        except errors.UnsupportedProtocol, e:
4011.4.1 by Jelmer Vernooij
Point out bzr+ssh:// to the user when they use ssh://.
129
            e_str = str(e)
130
            self.assertEquals('Unsupported protocol'
131
                              ' for url "ssh://fooserver/foo":'
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
132
                              ' bzr supports bzr+ssh to operate over ssh,'
133
                              ' use "bzr+ssh://fooserver/foo".',
4011.4.1 by Jelmer Vernooij
Point out bzr+ssh:// to the user when they use ssh://.
134
                              str(e))
135
        else:
136
            self.fail('Did not raise UnsupportedProtocol')
137
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
138
    def test_LateReadError(self):
139
        """The LateReadError helper should raise on read()."""
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
140
        a_file = transport.LateReadError('a path')
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
141
        try:
142
            a_file.read()
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
143
        except errors.ReadError, error:
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
144
            self.assertEqual('a path', error.path)
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
145
        self.assertRaises(errors.ReadError, a_file.read, 40)
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
146
        a_file.close()
147
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
148
    def test__combine_paths(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
149
        t = transport.Transport('/')
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
150
        self.assertEqual('/home/sarah/project/foo',
151
                         t._combine_paths('/home/sarah', 'project/foo'))
152
        self.assertEqual('/etc',
153
                         t._combine_paths('/home/sarah', '../../etc'))
2070.3.2 by Andrew Bennetts
Merge from bzr.dev
154
        self.assertEqual('/etc',
155
                         t._combine_paths('/home/sarah', '../../../etc'))
156
        self.assertEqual('/etc',
157
                         t._combine_paths('/home/sarah', '/etc'))
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
158
2018.18.4 by Martin Pool
Change Transport.local_abspath to raise NotLocalUrl, and test.
159
    def test_local_abspath_non_local_transport(self):
160
        # the base implementation should throw
4634.108.13 by John Arbash Meinel
Add a test case.
161
        t = memory.MemoryTransport()
2018.18.4 by Martin Pool
Change Transport.local_abspath to raise NotLocalUrl, and test.
162
        e = self.assertRaises(errors.NotLocalUrl, t.local_abspath, 't')
163
        self.assertEqual('memory:///t is not a local path.', str(e))
164
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
165
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
166
class TestCoalesceOffsets(tests.TestCase):
3059.2.17 by Vincent Ladeuil
Limit GET requests by body size instead of number of ranges.
167
168
    def check(self, expected, offsets, limit=0, max_size=0, fudge=0):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
169
        coalesce = transport.Transport._coalesce_offsets
170
        exp = [transport._CoalescedOffset(*x) for x in expected]
3059.2.17 by Vincent Ladeuil
Limit GET requests by body size instead of number of ranges.
171
        out = list(coalesce(offsets, limit=limit, fudge_factor=fudge,
172
                            max_size=max_size))
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
173
        self.assertEqual(exp, out)
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
174
175
    def test_coalesce_empty(self):
176
        self.check([], [])
177
178
    def test_coalesce_simple(self):
179
        self.check([(0, 10, [(0, 10)])], [(0, 10)])
180
181
    def test_coalesce_unrelated(self):
182
        self.check([(0, 10, [(0, 10)]),
183
                    (20, 10, [(0, 10)]),
184
                   ], [(0, 10), (20, 10)])
3059.2.17 by Vincent Ladeuil
Limit GET requests by body size instead of number of ranges.
185
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
186
    def test_coalesce_unsorted(self):
187
        self.check([(20, 10, [(0, 10)]),
188
                    (0, 10, [(0, 10)]),
189
                   ], [(20, 10), (0, 10)])
190
191
    def test_coalesce_nearby(self):
192
        self.check([(0, 20, [(0, 10), (10, 10)])],
193
                   [(0, 10), (10, 10)])
194
195
    def test_coalesce_overlapped(self):
3686.1.9 by John Arbash Meinel
Overlapping ranges are not allowed anymore.
196
        self.assertRaises(ValueError,
197
            self.check, [(0, 15, [(0, 10), (5, 10)])],
198
                        [(0, 10), (5, 10)])
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
199
200
    def test_coalesce_limit(self):
201
        self.check([(10, 50, [(0, 10), (10, 10), (20, 10),
202
                              (30, 10), (40, 10)]),
203
                    (60, 50, [(0, 10), (10, 10), (20, 10),
204
                              (30, 10), (40, 10)]),
205
                   ], [(10, 10), (20, 10), (30, 10), (40, 10),
206
                       (50, 10), (60, 10), (70, 10), (80, 10),
207
                       (90, 10), (100, 10)],
208
                    limit=5)
209
210
    def test_coalesce_no_limit(self):
211
        self.check([(10, 100, [(0, 10), (10, 10), (20, 10),
212
                               (30, 10), (40, 10), (50, 10),
213
                               (60, 10), (70, 10), (80, 10),
214
                               (90, 10)]),
215
                   ], [(10, 10), (20, 10), (30, 10), (40, 10),
216
                       (50, 10), (60, 10), (70, 10), (80, 10),
217
                       (90, 10), (100, 10)])
218
1864.5.3 by John Arbash Meinel
Allow collapsing ranges even if they are just 'close'
219
    def test_coalesce_fudge(self):
220
        self.check([(10, 30, [(0, 10), (20, 10)]),
221
                    (100, 10, [(0, 10),]),
222
                   ], [(10, 10), (30, 10), (100, 10)],
223
                   fudge=10
224
                  )
3059.2.17 by Vincent Ladeuil
Limit GET requests by body size instead of number of ranges.
225
    def test_coalesce_max_size(self):
226
        self.check([(10, 20, [(0, 10), (10, 10)]),
227
                    (30, 50, [(0, 50)]),
228
                    # If one range is above max_size, it gets its own coalesced
229
                    # offset
230
                    (100, 80, [(0, 80),]),],
231
                   [(10, 10), (20, 10), (30, 50), (100, 80)],
232
                   max_size=50
233
                  )
234
235
    def test_coalesce_no_max_size(self):
236
        self.check([(10, 170, [(0, 10), (10, 10), (20, 50), (70, 100)]),],
237
                   [(10, 10), (20, 10), (30, 50), (80, 100)],
238
                  )
1864.5.3 by John Arbash Meinel
Allow collapsing ranges even if they are just 'close'
239
3876.1.2 by John Arbash Meinel
Add a test case that checks the 100MB limit.
240
    def test_coalesce_default_limit(self):
241
        # By default we use a 100MB max size.
242
        ten_mb = 10*1024*1024
243
        self.check([(0, 10*ten_mb, [(i*ten_mb, ten_mb) for i in range(10)]),
244
                    (10*ten_mb, ten_mb, [(0, ten_mb)])],
245
                   [(i*ten_mb, ten_mb) for i in range(11)])
246
        self.check([(0, 11*ten_mb, [(i*ten_mb, ten_mb) for i in range(11)]),],
247
                   [(i*ten_mb, ten_mb) for i in range(11)],
248
                   max_size=1*1024*1024*1024)
249
1540.3.3 by Martin Pool
Review updates of pycurl transport
250
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
251
class TestMemoryServer(tests.TestCase):
4634.108.13 by John Arbash Meinel
Add a test case.
252
253
    def test_create_server(self):
5017.3.45 by Vincent Ladeuil
Move MemoryServer back into bzrlib.transport.memory as it's needed as soon as a MemoryTransport is used. Add a NEWS entry.
254
        server = memory.MemoryServer()
4946.1.2 by John Arbash Meinel
Clean up a few more imports.
255
        server.start_server()
4634.108.13 by John Arbash Meinel
Add a test case.
256
        url = server.get_url()
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
257
        self.assertTrue(url in transport.transport_list_registry)
258
        t = transport.get_transport(url)
4634.108.13 by John Arbash Meinel
Add a test case.
259
        del t
4946.1.2 by John Arbash Meinel
Clean up a few more imports.
260
        server.stop_server()
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
261
        self.assertFalse(url in transport.transport_list_registry)
4634.108.13 by John Arbash Meinel
Add a test case.
262
        self.assertRaises(errors.UnsupportedProtocol,
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
263
                          transport.get_transport, url)
264
265
266
class TestMemoryTransport(tests.TestCase):
1442.1.44 by Robert Collins
Many transport related tweaks:
267
268
    def test_get_transport(self):
4634.108.13 by John Arbash Meinel
Add a test case.
269
        memory.MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
270
271
    def test_clone(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
272
        t = memory.MemoryTransport()
273
        self.assertTrue(isinstance(t, memory.MemoryTransport))
274
        self.assertEqual("memory:///", t.clone("/").base)
1442.1.44 by Robert Collins
Many transport related tweaks:
275
276
    def test_abspath(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
277
        t = memory.MemoryTransport()
278
        self.assertEqual("memory:///relpath", t.abspath('relpath'))
1442.1.44 by Robert Collins
Many transport related tweaks:
279
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
280
    def test_abspath_of_root(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
281
        t = memory.MemoryTransport()
282
        self.assertEqual("memory:///", t.base)
283
        self.assertEqual("memory:///", t.abspath('/'))
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
284
2070.3.1 by Andrew Bennetts
Fix memory_transport.abspath('/foo')
285
    def test_abspath_of_relpath_starting_at_root(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
286
        t = memory.MemoryTransport()
287
        self.assertEqual("memory:///foo", t.abspath('/foo'))
1442.1.44 by Robert Collins
Many transport related tweaks:
288
289
    def test_append_and_get(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
290
        t = memory.MemoryTransport()
291
        t.append_bytes('path', 'content')
292
        self.assertEqual(t.get('path').read(), 'content')
293
        t.append_file('path', StringIO('content'))
294
        self.assertEqual(t.get('path').read(), 'contentcontent')
1442.1.44 by Robert Collins
Many transport related tweaks:
295
296
    def test_put_and_get(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
297
        t = memory.MemoryTransport()
298
        t.put_file('path', StringIO('content'))
299
        self.assertEqual(t.get('path').read(), 'content')
300
        t.put_bytes('path', 'content')
301
        self.assertEqual(t.get('path').read(), 'content')
1442.1.44 by Robert Collins
Many transport related tweaks:
302
303
    def test_append_without_dir_fails(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
304
        t = memory.MemoryTransport()
305
        self.assertRaises(errors.NoSuchFile,
306
                          t.append_bytes, 'dir/path', 'content')
1442.1.44 by Robert Collins
Many transport related tweaks:
307
308
    def test_put_without_dir_fails(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
309
        t = memory.MemoryTransport()
310
        self.assertRaises(errors.NoSuchFile,
311
                          t.put_file, 'dir/path', StringIO('content'))
1442.1.44 by Robert Collins
Many transport related tweaks:
312
313
    def test_get_missing(self):
4634.108.13 by John Arbash Meinel
Add a test case.
314
        transport = memory.MemoryTransport()
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
315
        self.assertRaises(errors.NoSuchFile, transport.get, 'foo')
1442.1.44 by Robert Collins
Many transport related tweaks:
316
317
    def test_has_missing(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
318
        t = memory.MemoryTransport()
319
        self.assertEquals(False, t.has('foo'))
1442.1.44 by Robert Collins
Many transport related tweaks:
320
321
    def test_has_present(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
322
        t = memory.MemoryTransport()
323
        t.append_bytes('foo', 'content')
324
        self.assertEquals(True, t.has('foo'))
1442.1.44 by Robert Collins
Many transport related tweaks:
325
2120.3.1 by John Arbash Meinel
Fix MemoryTransport.list_dir() implementation, and update tests
326
    def test_list_dir(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
327
        t = memory.MemoryTransport()
328
        t.put_bytes('foo', 'content')
329
        t.mkdir('dir')
330
        t.put_bytes('dir/subfoo', 'content')
331
        t.put_bytes('dirlike', 'content')
2120.3.1 by John Arbash Meinel
Fix MemoryTransport.list_dir() implementation, and update tests
332
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
333
        self.assertEquals(['dir', 'dirlike', 'foo'], sorted(t.list_dir('.')))
334
        self.assertEquals(['subfoo'], sorted(t.list_dir('dir')))
2120.3.1 by John Arbash Meinel
Fix MemoryTransport.list_dir() implementation, and update tests
335
1442.1.44 by Robert Collins
Many transport related tweaks:
336
    def test_mkdir(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
337
        t = memory.MemoryTransport()
338
        t.mkdir('dir')
339
        t.append_bytes('dir/path', 'content')
340
        self.assertEqual(t.get('dir/path').read(), 'content')
1442.1.44 by Robert Collins
Many transport related tweaks:
341
342
    def test_mkdir_missing_parent(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
343
        t = memory.MemoryTransport()
344
        self.assertRaises(errors.NoSuchFile, t.mkdir, 'dir/dir')
1442.1.44 by Robert Collins
Many transport related tweaks:
345
346
    def test_mkdir_twice(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
347
        t = memory.MemoryTransport()
348
        t.mkdir('dir')
349
        self.assertRaises(errors.FileExists, t.mkdir, 'dir')
1530.1.5 by Robert Collins
Reinstate Memory parameter tests.
350
351
    def test_parameters(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
352
        t = memory.MemoryTransport()
353
        self.assertEqual(True, t.listable())
354
        self.assertEqual(False, t.is_readonly())
1442.1.44 by Robert Collins
Many transport related tweaks:
355
356
    def test_iter_files_recursive(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
357
        t = memory.MemoryTransport()
358
        t.mkdir('dir')
359
        t.put_bytes('dir/foo', 'content')
360
        t.put_bytes('dir/bar', 'content')
361
        t.put_bytes('bar', 'content')
362
        paths = set(t.iter_files_recursive())
1442.1.44 by Robert Collins
Many transport related tweaks:
363
        self.assertEqual(set(['dir/foo', 'dir/bar', 'bar']), paths)
364
365
    def test_stat(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
366
        t = memory.MemoryTransport()
367
        t.put_bytes('foo', 'content')
368
        t.put_bytes('bar', 'phowar')
369
        self.assertEqual(7, t.stat('foo').st_size)
370
        self.assertEqual(6, t.stat('bar').st_size)
371
372
373
class ChrootDecoratorTransportTest(tests.TestCase):
2070.5.1 by Andrew Bennetts
Add ChrootTransportDecorator.
374
    """Chroot decoration specific tests."""
375
2018.5.54 by Andrew Bennetts
Fix ChrootTransportDecorator's abspath method to be consistent with its clone
376
    def test_abspath(self):
377
        # The abspath is always relative to the chroot_url.
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
378
        server = chroot.ChrootServer(
379
            transport.get_transport('memory:///foo/bar/'))
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
380
        self.start_server(server)
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
381
        t = transport.get_transport(server.get_url())
382
        self.assertEqual(server.get_url(), t.abspath('/'))
2018.5.54 by Andrew Bennetts
Fix ChrootTransportDecorator's abspath method to be consistent with its clone
383
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
384
        subdir_t = t.clone('subdir')
385
        self.assertEqual(server.get_url(), subdir_t.abspath('/'))
2379.2.1 by Robert Collins
Rewritten chroot transport that prevents accidental chroot escapes when
386
387
    def test_clone(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
388
        server = chroot.ChrootServer(
389
            transport.get_transport('memory:///foo/bar/'))
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
390
        self.start_server(server)
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
391
        t = transport.get_transport(server.get_url())
2018.5.42 by Robert Collins
Various hopefully improvements, but wsgi is broken, handing over to spiv :).
392
        # relpath from root and root path are the same
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
393
        relpath_cloned = t.clone('foo')
394
        abspath_cloned = t.clone('/foo')
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
395
        self.assertEqual(server, relpath_cloned.server)
396
        self.assertEqual(server, abspath_cloned.server)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
397
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
398
    def test_chroot_url_preserves_chroot(self):
399
        """Calling get_transport on a chroot transport's base should produce a
400
        transport with exactly the same behaviour as the original chroot
401
        transport.
402
403
        This is so that it is not possible to escape a chroot by doing::
404
            url = chroot_transport.base
405
            parent_url = urlutils.join(url, '..')
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
406
            new_t = transport.get_transport(parent_url)
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
407
        """
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
408
        server = chroot.ChrootServer(
409
            transport.get_transport('memory:///path/subpath'))
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
410
        self.start_server(server)
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
411
        t = transport.get_transport(server.get_url())
412
        new_t = transport.get_transport(t.base)
413
        self.assertEqual(t.server, new_t.server)
414
        self.assertEqual(t.base, new_t.base)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
415
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
416
    def test_urljoin_preserves_chroot(self):
417
        """Using urlutils.join(url, '..') on a chroot URL should not produce a
418
        URL that escapes the intended chroot.
419
420
        This is so that it is not possible to escape a chroot by doing::
421
            url = chroot_transport.base
422
            parent_url = urlutils.join(url, '..')
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
423
            new_t = transport.get_transport(parent_url)
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
424
        """
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
425
        server = chroot.ChrootServer(transport.get_transport('memory:///path/'))
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
426
        self.start_server(server)
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
427
        t = transport.get_transport(server.get_url())
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
428
        self.assertRaises(
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
429
            errors.InvalidURLJoin, urlutils.join, t.base, '..')
430
431
432
class TestChrootServer(tests.TestCase):
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
433
434
    def test_construct(self):
4634.108.13 by John Arbash Meinel
Add a test case.
435
        backing_transport = memory.MemoryTransport()
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
436
        server = chroot.ChrootServer(backing_transport)
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
437
        self.assertEqual(backing_transport, server.backing_transport)
438
439
    def test_setUp(self):
4634.108.13 by John Arbash Meinel
Add a test case.
440
        backing_transport = memory.MemoryTransport()
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
441
        server = chroot.ChrootServer(backing_transport)
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
442
        server.start_server()
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
443
        try:
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
444
            self.assertTrue(server.scheme
445
                            in transport._get_protocol_handlers().keys())
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
446
        finally:
4934.3.1 by Martin Pool
Rename Server.tearDown to .stop_server
447
            server.stop_server()
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
448
4934.3.1 by Martin Pool
Rename Server.tearDown to .stop_server
449
    def test_stop_server(self):
4634.108.13 by John Arbash Meinel
Add a test case.
450
        backing_transport = memory.MemoryTransport()
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
451
        server = chroot.ChrootServer(backing_transport)
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
452
        server.start_server()
4934.3.1 by Martin Pool
Rename Server.tearDown to .stop_server
453
        server.stop_server()
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
454
        self.assertFalse(server.scheme
455
                         in transport._get_protocol_handlers().keys())
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
456
457
    def test_get_url(self):
4634.108.13 by John Arbash Meinel
Add a test case.
458
        backing_transport = memory.MemoryTransport()
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
459
        server = chroot.ChrootServer(backing_transport)
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
460
        server.start_server()
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
461
        try:
462
            self.assertEqual('chroot-%d:///' % id(server), server.get_url())
463
        finally:
4934.3.1 by Martin Pool
Rename Server.tearDown to .stop_server
464
            server.stop_server()
2018.5.53 by Andrew Bennetts
Small fix to urlutils.joinpath that was causing a misbehaviour in
465
2156.2.1 by v.ladeuil+lp at free
Make the tests windows compatible.
466
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
467
class PathFilteringDecoratorTransportTest(tests.TestCase):
4634.44.1 by Andrew Bennetts
First draft of a generic path-filtering transport decorator.
468
    """Pathfilter decoration specific tests."""
469
470
    def test_abspath(self):
471
        # The abspath is always relative to the base of the backing transport.
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
472
        server = pathfilter.PathFilteringServer(
473
            transport.get_transport('memory:///foo/bar/'),
4634.44.1 by Andrew Bennetts
First draft of a generic path-filtering transport decorator.
474
            lambda x: x)
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
475
        server.start_server()
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
476
        t = transport.get_transport(server.get_url())
477
        self.assertEqual(server.get_url(), t.abspath('/'))
4634.44.1 by Andrew Bennetts
First draft of a generic path-filtering transport decorator.
478
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
479
        subdir_t = t.clone('subdir')
480
        self.assertEqual(server.get_url(), subdir_t.abspath('/'))
4934.3.1 by Martin Pool
Rename Server.tearDown to .stop_server
481
        server.stop_server()
4634.44.1 by Andrew Bennetts
First draft of a generic path-filtering transport decorator.
482
483
    def make_pf_transport(self, filter_func=None):
484
        """Make a PathFilteringTransport backed by a MemoryTransport.
485
        
486
        :param filter_func: by default this will be a no-op function.  Use this
487
            parameter to override it."""
488
        if filter_func is None:
489
            filter_func = lambda x: x
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
490
        server = pathfilter.PathFilteringServer(
491
            transport.get_transport('memory:///foo/bar/'), filter_func)
4934.3.3 by Martin Pool
Rename Server.setUp to Server.start_server
492
        server.start_server()
4934.3.1 by Martin Pool
Rename Server.tearDown to .stop_server
493
        self.addCleanup(server.stop_server)
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
494
        return transport.get_transport(server.get_url())
4634.44.1 by Andrew Bennetts
First draft of a generic path-filtering transport decorator.
495
496
    def test__filter(self):
497
        # _filter (with an identity func as filter_func) always returns
498
        # paths relative to the base of the backing transport.
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
499
        t = self.make_pf_transport()
500
        self.assertEqual('foo', t._filter('foo'))
501
        self.assertEqual('foo/bar', t._filter('foo/bar'))
502
        self.assertEqual('', t._filter('..'))
503
        self.assertEqual('', t._filter('/'))
4634.44.1 by Andrew Bennetts
First draft of a generic path-filtering transport decorator.
504
        # The base of the pathfiltering transport is taken into account too.
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
505
        t = t.clone('subdir1/subdir2')
506
        self.assertEqual('subdir1/subdir2/foo', t._filter('foo'))
507
        self.assertEqual('subdir1/subdir2/foo/bar', t._filter('foo/bar'))
508
        self.assertEqual('subdir1', t._filter('..'))
509
        self.assertEqual('', t._filter('/'))
4634.44.1 by Andrew Bennetts
First draft of a generic path-filtering transport decorator.
510
4634.44.2 by Andrew Bennetts
Add another test.
511
    def test_filter_invocation(self):
512
        filter_log = []
513
        def filter(path):
514
            filter_log.append(path)
515
            return path
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
516
        t = self.make_pf_transport(filter)
517
        t.has('abc')
4634.44.2 by Andrew Bennetts
Add another test.
518
        self.assertEqual(['abc'], filter_log)
519
        del filter_log[:]
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
520
        t.clone('abc').has('xyz')
4634.44.2 by Andrew Bennetts
Add another test.
521
        self.assertEqual(['abc/xyz'], filter_log)
522
        del filter_log[:]
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
523
        t.has('/abc')
4634.44.2 by Andrew Bennetts
Add another test.
524
        self.assertEqual(['abc'], filter_log)
525
4634.44.1 by Andrew Bennetts
First draft of a generic path-filtering transport decorator.
526
    def test_clone(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
527
        t = self.make_pf_transport()
4634.44.2 by Andrew Bennetts
Add another test.
528
        # relpath from root and root path are the same
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
529
        relpath_cloned = t.clone('foo')
530
        abspath_cloned = t.clone('/foo')
531
        self.assertEqual(t.server, relpath_cloned.server)
532
        self.assertEqual(t.server, abspath_cloned.server)
4634.44.1 by Andrew Bennetts
First draft of a generic path-filtering transport decorator.
533
534
    def test_url_preserves_pathfiltering(self):
535
        """Calling get_transport on a pathfiltered transport's base should
536
        produce a transport with exactly the same behaviour as the original
537
        pathfiltered transport.
538
539
        This is so that it is not possible to escape (accidentally or
540
        otherwise) the filtering by doing::
541
            url = filtered_transport.base
542
            parent_url = urlutils.join(url, '..')
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
543
            new_t = transport.get_transport(parent_url)
4634.44.1 by Andrew Bennetts
First draft of a generic path-filtering transport decorator.
544
        """
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
545
        t = self.make_pf_transport()
546
        new_t = transport.get_transport(t.base)
547
        self.assertEqual(t.server, new_t.server)
548
        self.assertEqual(t.base, new_t.base)
549
550
551
class ReadonlyDecoratorTransportTest(tests.TestCase):
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
552
    """Readonly decoration specific tests."""
553
554
    def test_local_parameters(self):
555
        # connect to . in readonly mode
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
556
        t = readonly.ReadonlyTransportDecorator('readonly+.')
557
        self.assertEqual(True, t.listable())
558
        self.assertEqual(True, t.is_readonly())
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
559
560
    def test_http_parameters(self):
2929.3.7 by Vincent Ladeuil
Rename bzrlib/test/HttpServer.py to bzrlib/tests/http_server.py and fix uses.
561
        from bzrlib.tests.http_server import HttpServer
562
        # connect to '.' via http which is not listable
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
563
        server = HttpServer()
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
564
        self.start_server(server)
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
565
        t = transport.get_transport('readonly+' + server.get_url())
566
        self.failUnless(isinstance(t, readonly.ReadonlyTransportDecorator))
567
        self.assertEqual(False, t.listable())
568
        self.assertEqual(True, t.is_readonly())
569
570
571
class FakeNFSDecoratorTests(tests.TestCaseInTempDir):
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
572
    """NFS decorator specific tests."""
573
574
    def get_nfs_transport(self, url):
575
        # connect to url with nfs decoration
576
        return fakenfs.FakeNFSTransportDecorator('fakenfs+' + url)
577
578
    def test_local_parameters(self):
2701.1.1 by Martin Pool
Remove Transport.should_cache.
579
        # the listable and is_readonly parameters
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
580
        # are not changed by the fakenfs decorator
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
581
        t = self.get_nfs_transport('.')
582
        self.assertEqual(True, t.listable())
583
        self.assertEqual(False, t.is_readonly())
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
584
585
    def test_http_parameters(self):
2701.1.1 by Martin Pool
Remove Transport.should_cache.
586
        # the listable and is_readonly parameters
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
587
        # are not changed by the fakenfs decorator
2929.3.7 by Vincent Ladeuil
Rename bzrlib/test/HttpServer.py to bzrlib/tests/http_server.py and fix uses.
588
        from bzrlib.tests.http_server import HttpServer
589
        # connect to '.' via http which is not listable
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
590
        server = HttpServer()
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
591
        self.start_server(server)
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
592
        t = self.get_nfs_transport(server.get_url())
593
        self.assertIsInstance(t, fakenfs.FakeNFSTransportDecorator)
594
        self.assertEqual(False, t.listable())
595
        self.assertEqual(True, t.is_readonly())
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
596
597
    def test_fakenfs_server_default(self):
598
        # a FakeNFSServer() should bring up a local relpath server for itself
5017.3.22 by Vincent Ladeuil
selftest -s bt.test_transport passing
599
        server = test_server.FakeNFSServer()
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
600
        self.start_server(server)
601
        # the url should be decorated appropriately
602
        self.assertStartsWith(server.get_url(), 'fakenfs+')
603
        # and we should be able to get a transport for it
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
604
        t = transport.get_transport(server.get_url())
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
605
        # which must be a FakeNFSTransportDecorator instance.
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
606
        self.assertIsInstance(t, fakenfs.FakeNFSTransportDecorator)
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
607
608
    def test_fakenfs_rename_semantics(self):
609
        # a FakeNFS transport must mangle the way rename errors occur to
610
        # look like NFS problems.
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
611
        t = self.get_nfs_transport('.')
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
612
        self.build_tree(['from/', 'from/foo', 'to/', 'to/bar'],
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
613
                        transport=t)
614
        self.assertRaises(errors.ResourceBusy, t.rename, 'from', 'to')
615
616
617
class FakeVFATDecoratorTests(tests.TestCaseInTempDir):
1608.2.4 by Martin Pool
[broken] Add FakeFVATTransport
618
    """Tests for simulation of VFAT restrictions"""
619
620
    def get_vfat_transport(self, url):
621
        """Return vfat-backed transport for test directory"""
622
        from bzrlib.transport.fakevfat import FakeVFATTransportDecorator
623
        return FakeVFATTransportDecorator('vfat+' + url)
624
625
    def test_transport_creation(self):
626
        from bzrlib.transport.fakevfat import FakeVFATTransportDecorator
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
627
        t = self.get_vfat_transport('.')
628
        self.assertIsInstance(t, FakeVFATTransportDecorator)
1608.2.4 by Martin Pool
[broken] Add FakeFVATTransport
629
630
    def test_transport_mkdir(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
631
        t = self.get_vfat_transport('.')
632
        t.mkdir('HELLO')
633
        self.assertTrue(t.has('hello'))
634
        self.assertTrue(t.has('Hello'))
1608.2.4 by Martin Pool
[broken] Add FakeFVATTransport
635
1608.2.11 by Martin Pool
(FakeVFAT) add test for detection of invalid characters
636
    def test_forbidden_chars(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
637
        t = self.get_vfat_transport('.')
638
        self.assertRaises(ValueError, t.has, "<NU>")
639
640
641
class BadTransportHandler(transport.Transport):
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
642
    def __init__(self, base_url):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
643
        raise errors.DependencyNotPresent('some_lib',
644
                                          'testing missing dependency')
645
646
647
class BackupTransportHandler(transport.Transport):
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
648
    """Test transport that works as a backup for the BadTransportHandler"""
1540.3.10 by Martin Pool
[broken] keep hooking pycurl into test framework
649
    pass
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
650
651
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
652
class TestTransportImplementation(tests.TestCaseInTempDir):
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
653
    """Implementation verification for transports.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
654
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
655
    To verify a transport we need a server factory, which is a callable
656
    that accepts no parameters and returns an implementation of
657
    bzrlib.transport.Server.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
658
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
659
    That Server is then used to construct transport instances and test
660
    the transport via loopback activity.
661
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
662
    Currently this assumes that the Transport object is connected to the
663
    current working directory.  So that whatever is done
664
    through the transport, should show up in the working
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
665
    directory, and vice-versa. This is a bug, because its possible to have
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
666
    URL schemes which provide access to something that may not be
667
    result in storage on the local disk, i.e. due to file system limits, or
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
668
    due to it being a database or some other non-filesystem tool.
669
670
    This also tests to make sure that the functions work with both
671
    generators and lists (assuming iter(list) is effectively a generator)
672
    """
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
673
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
674
    def setUp(self):
675
        super(TestTransportImplementation, self).setUp()
676
        self._server = self.transport_server()
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
677
        self.start_server(self._server)
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
678
2520.3.1 by Vincent Ladeuil
Fix 110448 by adding a relpath parameter to get_transport.
679
    def get_transport(self, relpath=None):
680
        """Return a connected transport to the local directory.
681
682
        :param relpath: a path relative to the base url.
683
        """
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
684
        base_url = self._server.get_url()
2520.3.1 by Vincent Ladeuil
Fix 110448 by adding a relpath parameter to get_transport.
685
        url = self._adjust_url(base_url, relpath)
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
686
        # try getting the transport via the regular interface:
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
687
        t = transport.get_transport(url)
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
688
        # vila--20070607 if the following are commented out the test suite
689
        # still pass. Is this really still needed or was it a forgotten
690
        # temporary fix ?
1986.2.5 by Robert Collins
Unbreak transport tests.
691
        if not isinstance(t, self.transport_class):
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
692
            # we did not get the correct transport class type. Override the
693
            # regular connection behaviour by direct construction.
2520.3.1 by Vincent Ladeuil
Fix 110448 by adding a relpath parameter to get_transport.
694
            t = self.transport_class(url)
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
695
        return t
1951.2.1 by Martin Pool
Change to using LocalURLServer for testing.
696
697
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
698
class TestLocalTransports(tests.TestCase):
1951.2.1 by Martin Pool
Change to using LocalURLServer for testing.
699
700
    def test_get_transport_from_abspath(self):
2804.4.1 by Alexander Belchenko
some win32-specific fixes for selftest
701
        here = osutils.abspath('.')
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
702
        t = transport.get_transport(here)
703
        self.assertIsInstance(t, local.LocalTransport)
1951.2.1 by Martin Pool
Change to using LocalURLServer for testing.
704
        self.assertEquals(t.base, urlutils.local_path_to_url(here) + '/')
705
706
    def test_get_transport_from_relpath(self):
2804.4.1 by Alexander Belchenko
some win32-specific fixes for selftest
707
        here = osutils.abspath('.')
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
708
        t = transport.get_transport('.')
709
        self.assertIsInstance(t, local.LocalTransport)
1951.2.3 by Martin Pool
Localtransport cleanup review (john)
710
        self.assertEquals(t.base, urlutils.local_path_to_url('.') + '/')
1951.2.1 by Martin Pool
Change to using LocalURLServer for testing.
711
712
    def test_get_transport_from_local_url(self):
2804.4.1 by Alexander Belchenko
some win32-specific fixes for selftest
713
        here = osutils.abspath('.')
1951.2.1 by Martin Pool
Change to using LocalURLServer for testing.
714
        here_url = urlutils.local_path_to_url(here) + '/'
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
715
        t = transport.get_transport(here_url)
716
        self.assertIsInstance(t, local.LocalTransport)
1951.2.1 by Martin Pool
Change to using LocalURLServer for testing.
717
        self.assertEquals(t.base, here_url)
2245.6.1 by Alexander Belchenko
win32 UNC path: recursive cloning UNC path to root stops on //HOST, not on //
718
2018.18.4 by Martin Pool
Change Transport.local_abspath to raise NotLocalUrl, and test.
719
    def test_local_abspath(self):
2804.4.1 by Alexander Belchenko
some win32-specific fixes for selftest
720
        here = osutils.abspath('.')
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
721
        t = transport.get_transport(here)
2018.18.4 by Martin Pool
Change Transport.local_abspath to raise NotLocalUrl, and test.
722
        self.assertEquals(t.local_abspath(''), here)
723
2245.6.1 by Alexander Belchenko
win32 UNC path: recursive cloning UNC path to root stops on //HOST, not on //
724
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
725
class TestWin32LocalTransport(tests.TestCase):
2245.6.1 by Alexander Belchenko
win32 UNC path: recursive cloning UNC path to root stops on //HOST, not on //
726
727
    def test_unc_clone_to_root(self):
728
        # Win32 UNC path like \\HOST\path
729
        # clone to root should stop at least at \\HOST part
730
        # not on \\
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
731
        t = local.EmulatedWin32LocalTransport('file://HOST/path/to/some/dir/')
2245.6.1 by Alexander Belchenko
win32 UNC path: recursive cloning UNC path to root stops on //HOST, not on //
732
        for i in xrange(4):
733
            t = t.clone('..')
734
        self.assertEquals(t.base, 'file://HOST/')
735
        # make sure we reach the root
736
        t = t.clone('..')
737
        self.assertEquals(t.base, 'file://HOST/')
2477.1.7 by Martin Pool
test_transport must provide get_test_permutations
738
2485.8.61 by Vincent Ladeuil
From review comments, use a private scheme for testing.
739
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
740
class TestConnectedTransport(tests.TestCase):
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
741
    """Tests for connected to remote server transports"""
742
743
    def test_parse_url(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
744
        t = transport.ConnectedTransport(
745
            'http://simple.example.com/home/source')
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
746
        self.assertEquals(t._host, 'simple.example.com')
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
747
        self.assertEquals(t._port, None)
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
748
        self.assertEquals(t._path, '/home/source/')
749
        self.failUnless(t._user is None)
750
        self.failUnless(t._password is None)
751
2892.1.1 by Andrew Bennetts
Fix bug 146715: bzr+ssh:// and sftp:// should not assume port-not-specified means port 22
752
        self.assertEquals(t.base, 'http://simple.example.com/home/source/')
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
753
3498.2.1 by Neil Martinsen-Burrell
Fix bug 228058: user names with @ signs should work
754
    def test_parse_url_with_at_in_user(self):
755
        # Bug 228058
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
756
        t = transport.ConnectedTransport('ftp://user@host.com@www.host.com/')
3498.2.1 by Neil Martinsen-Burrell
Fix bug 228058: user names with @ signs should work
757
        self.assertEquals(t._user, 'user@host.com')
758
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
759
    def test_parse_quoted_url(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
760
        t = transport.ConnectedTransport(
761
            'http://ro%62ey:h%40t@ex%41mple.com:2222/path')
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
762
        self.assertEquals(t._host, 'exAmple.com')
763
        self.assertEquals(t._port, 2222)
764
        self.assertEquals(t._user, 'robey')
765
        self.assertEquals(t._password, 'h@t')
766
        self.assertEquals(t._path, '/path/')
767
768
        # Base should not keep track of the password
769
        self.assertEquals(t.base, 'http://robey@exAmple.com:2222/path/')
770
771
    def test_parse_invalid_url(self):
772
        self.assertRaises(errors.InvalidURL,
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
773
                          transport.ConnectedTransport,
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
774
                          'sftp://lily.org:~janneke/public/bzr/gub')
775
776
    def test_relpath(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
777
        t = transport.ConnectedTransport('sftp://user@host.com/abs/path')
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
778
779
        self.assertEquals(t.relpath('sftp://user@host.com/abs/path/sub'), 'sub')
780
        self.assertRaises(errors.PathNotChild, t.relpath,
781
                          'http://user@host.com/abs/path/sub')
782
        self.assertRaises(errors.PathNotChild, t.relpath,
783
                          'sftp://user2@host.com/abs/path/sub')
784
        self.assertRaises(errors.PathNotChild, t.relpath,
785
                          'sftp://user@otherhost.com/abs/path/sub')
786
        self.assertRaises(errors.PathNotChild, t.relpath,
787
                          'sftp://user@host.com:33/abs/path/sub')
788
        # Make sure it works when we don't supply a username
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
789
        t = transport.ConnectedTransport('sftp://host.com/abs/path')
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
790
        self.assertEquals(t.relpath('sftp://host.com/abs/path/sub'), 'sub')
791
792
        # Make sure it works when parts of the path will be url encoded
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
793
        t = transport.ConnectedTransport('sftp://host.com/dev/%path')
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
794
        self.assertEquals(t.relpath('sftp://host.com/dev/%path/sub'), 'sub')
795
2485.8.32 by Vincent Ladeuil
Keep credentials used at connection creation for reconnection purposes.
796
    def test_connection_sharing_propagate_credentials(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
797
        t = transport.ConnectedTransport('ftp://user@host.com/abs/path')
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
798
        self.assertEquals('user', t._user)
799
        self.assertEquals('host.com', t._host)
2485.8.32 by Vincent Ladeuil
Keep credentials used at connection creation for reconnection purposes.
800
        self.assertIs(None, t._get_connection())
801
        self.assertIs(None, t._password)
802
        c = t.clone('subdir')
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
803
        self.assertIs(None, c._get_connection())
2485.8.32 by Vincent Ladeuil
Keep credentials used at connection creation for reconnection purposes.
804
        self.assertIs(None, t._password)
805
806
        # Simulate the user entering a password
807
        password = 'secret'
808
        connection = object()
809
        t._set_connection(connection, password)
810
        self.assertIs(connection, t._get_connection())
811
        self.assertIs(password, t._get_credentials())
812
        self.assertIs(connection, c._get_connection())
813
        self.assertIs(password, c._get_credentials())
2485.8.30 by Vincent Ladeuil
Implement reliable connection sharing.
814
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
815
        # credentials can be updated
816
        new_password = 'even more secret'
817
        c._update_credentials(new_password)
818
        self.assertIs(connection, t._get_connection())
819
        self.assertIs(new_password, t._get_credentials())
820
        self.assertIs(connection, c._get_connection())
821
        self.assertIs(new_password, c._get_credentials())
822
2477.1.7 by Martin Pool
test_transport must provide get_test_permutations
823
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
824
class TestReusedTransports(tests.TestCase):
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
825
    """Tests for transport reuse"""
2476.3.5 by Vincent Ladeuil
Naive implementation of transport reuse by Transport.get_transport().
826
827
    def test_reuse_same_transport(self):
1551.18.10 by Aaron Bentley
get_transport appends to possible_transports if it's an empty list
828
        possible_transports = []
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
829
        t1 = transport.get_transport('http://foo/',
830
                                     possible_transports=possible_transports)
1551.18.10 by Aaron Bentley
get_transport appends to possible_transports if it's an empty list
831
        self.assertEqual([t1], possible_transports)
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
832
        t2 = transport.get_transport('http://foo/',
833
                                     possible_transports=[t1])
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
834
        self.assertIs(t1, t2)
835
836
        # Also check that final '/' are handled correctly
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
837
        t3 = transport.get_transport('http://foo/path/')
838
        t4 = transport.get_transport('http://foo/path',
839
                                     possible_transports=[t3])
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
840
        self.assertIs(t3, t4)
841
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
842
        t5 = transport.get_transport('http://foo/path')
843
        t6 = transport.get_transport('http://foo/path/',
844
                                     possible_transports=[t5])
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
845
        self.assertIs(t5, t6)
2476.3.5 by Vincent Ladeuil
Naive implementation of transport reuse by Transport.get_transport().
846
847
    def test_don_t_reuse_different_transport(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
848
        t1 = transport.get_transport('http://foo/path')
849
        t2 = transport.get_transport('http://bar/path',
850
                                     possible_transports=[t1])
2485.8.40 by Vincent Ladeuil
Fix typo.
851
        self.assertIsNot(t1, t2)
2476.3.13 by Vincent Ladeuil
merge bzr.dev@2495
852
853
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
854
class TestTransportTrace(tests.TestCase):
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
855
856
    def test_get(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
857
        t = transport.get_transport('trace+memory://')
858
        self.assertIsInstance(t, bzrlib.transport.trace.TransportTraceDecorator)
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
859
860
    def test_clone_preserves_activity(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
861
        t = transport.get_transport('trace+memory://')
862
        t2 = t.clone('.')
863
        self.assertTrue(t is not t2)
864
        self.assertTrue(t._activity is t2._activity)
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
865
866
    # the following specific tests are for the operations that have made use of
867
    # logging in tests; we could test every single operation but doing that
868
    # still won't cause a test failure when the top level Transport API
869
    # changes; so there is little return doing that.
870
    def test_get(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
871
        t = transport.get_transport('trace+memory:///')
872
        t.put_bytes('foo', 'barish')
873
        t.get('foo')
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
874
        expected_result = []
875
        # put_bytes records the bytes, not the content to avoid memory
876
        # pressure.
877
        expected_result.append(('put_bytes', 'foo', 6, None))
878
        # get records the file name only.
879
        expected_result.append(('get', 'foo'))
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
880
        self.assertEqual(expected_result, t._activity)
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
881
882
    def test_readv(self):
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
883
        t = transport.get_transport('trace+memory:///')
884
        t.put_bytes('foo', 'barish')
885
        list(t.readv('foo', [(0, 1), (3, 2)],
886
                     adjust_for_latency=True, upper_limit=6))
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
887
        expected_result = []
888
        # put_bytes records the bytes, not the content to avoid memory
889
        # pressure.
890
        expected_result.append(('put_bytes', 'foo', 6, None))
891
        # readv records the supplied offset request
892
        expected_result.append(('readv', 'foo', [(0, 1), (3, 2)], True, 6))
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
893
        self.assertEqual(expected_result, t._activity)
4700.1.1 by Robert Collins
Focus and move out of blackbox the acceptance test for bzr+ssh connection handshake/process spawning.
894
895
896
class TestSSHConnections(tests.TestCaseWithTransport):
897
898
    def test_bzr_connect_to_bzr_ssh(self):
899
        """User acceptance that get_transport of a bzr+ssh:// behaves correctly.
900
901
        bzr+ssh:// should cause bzr to run a remote bzr smart server over SSH.
902
        """
903
        # This test actually causes a bzr instance to be invoked, which is very
904
        # expensive: it should be the only such test in the test suite.
905
        # A reasonable evolution for this would be to simply check inside
906
        # check_channel_exec_request that the command is appropriate, and then
907
        # satisfy requests in-process.
4913.2.16 by John Arbash Meinel
Move bzrlib.tests.ParamikoFeature to bzrlib.tests.features.paramiko
908
        self.requireFeature(features.paramiko)
4700.1.1 by Robert Collins
Focus and move out of blackbox the acceptance test for bzr+ssh connection handshake/process spawning.
909
        # SFTPFullAbsoluteServer has a get_url method, and doesn't
910
        # override the interface (doesn't change self._vendor).
911
        # Note that this does encryption, so can be slow.
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
912
        from bzrlib.tests import stub_sftp
4700.1.1 by Robert Collins
Focus and move out of blackbox the acceptance test for bzr+ssh connection handshake/process spawning.
913
914
        # Start an SSH server
915
        self.command_executed = []
916
        # XXX: This is horrible -- we define a really dumb SSH server that
917
        # executes commands, and manage the hooking up of stdin/out/err to the
918
        # SSH channel ourselves.  Surely this has already been implemented
919
        # elsewhere?
4857.2.2 by John Arbash Meinel
Change the connect-to-bzr test so that it cleans itself up.
920
        started = []
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
921
        class StubSSHServer(stub_sftp.StubServer):
4700.1.1 by Robert Collins
Focus and move out of blackbox the acceptance test for bzr+ssh connection handshake/process spawning.
922
923
            test = self
924
925
            def check_channel_exec_request(self, channel, command):
926
                self.test.command_executed.append(command)
927
                proc = subprocess.Popen(
928
                    command, shell=True, stdin=subprocess.PIPE,
929
                    stdout=subprocess.PIPE, stderr=subprocess.PIPE)
930
931
                # XXX: horribly inefficient, not to mention ugly.
932
                # Start a thread for each of stdin/out/err, and relay bytes from
933
                # the subprocess to channel and vice versa.
934
                def ferry_bytes(read, write, close):
935
                    while True:
936
                        bytes = read(1)
937
                        if bytes == '':
938
                            close()
939
                            break
940
                        write(bytes)
941
942
                file_functions = [
943
                    (channel.recv, proc.stdin.write, proc.stdin.close),
944
                    (proc.stdout.read, channel.sendall, channel.close),
945
                    (proc.stderr.read, channel.sendall_stderr, channel.close)]
4857.2.2 by John Arbash Meinel
Change the connect-to-bzr test so that it cleans itself up.
946
                started.append(proc)
4700.1.1 by Robert Collins
Focus and move out of blackbox the acceptance test for bzr+ssh connection handshake/process spawning.
947
                for read, write, close in file_functions:
948
                    t = threading.Thread(
949
                        target=ferry_bytes, args=(read, write, close))
950
                    t.start()
4857.2.2 by John Arbash Meinel
Change the connect-to-bzr test so that it cleans itself up.
951
                    started.append(t)
4700.1.1 by Robert Collins
Focus and move out of blackbox the acceptance test for bzr+ssh connection handshake/process spawning.
952
953
                return True
954
4797.11.2 by Vincent Ladeuil
Stop requiring testtools for sftp use.
955
        ssh_server = stub_sftp.SFTPFullAbsoluteServer(StubSSHServer)
4700.1.1 by Robert Collins
Focus and move out of blackbox the acceptance test for bzr+ssh connection handshake/process spawning.
956
        # We *don't* want to override the default SSH vendor: the detected one
957
        # is the one to use.
958
        self.start_server(ssh_server)
959
        port = ssh_server._listener.port
960
961
        if sys.platform == 'win32':
962
            bzr_remote_path = sys.executable + ' ' + self.get_bzr_path()
963
        else:
964
            bzr_remote_path = self.get_bzr_path()
965
        os.environ['BZR_REMOTE_PATH'] = bzr_remote_path
966
967
        # Access the branch via a bzr+ssh URL.  The BZR_REMOTE_PATH environment
968
        # variable is used to tell bzr what command to run on the remote end.
969
        path_to_branch = osutils.abspath('.')
970
        if sys.platform == 'win32':
4700.1.2 by Robert Collins
Review feedback.
971
            # On Windows, we export all drives as '/C:/, etc. So we need to
972
            # prefix a '/' to get the right path.
973
            path_to_branch = '/' + path_to_branch
974
        url = 'bzr+ssh://fred:secret@localhost:%d%s' % (port, path_to_branch)
5010.2.10 by Vincent Ladeuil
Fix test_transport.py imports.
975
        t = transport.get_transport(url)
4700.1.2 by Robert Collins
Review feedback.
976
        self.permit_url(t.base)
4700.1.1 by Robert Collins
Focus and move out of blackbox the acceptance test for bzr+ssh connection handshake/process spawning.
977
        t.mkdir('foo')
978
979
        self.assertEqual(
980
            ['%s serve --inet --directory=/ --allow-writes' % bzr_remote_path],
981
            self.command_executed)
4857.2.2 by John Arbash Meinel
Change the connect-to-bzr test so that it cleans itself up.
982
        # Make sure to disconnect, so that the remote process can stop, and we
983
        # can cleanup. Then pause the test until everything is shutdown
984
        t._client._medium.disconnect()
985
        if not started:
986
            return
987
        # First wait for the subprocess
988
        started[0].wait()
989
        # And the rest are threads
990
        for t in started[1:]:
991
            t.join()