~bzr-pqm/bzr/bzr.dev

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