/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1
# Copyright (C) 2005-2011, 2015, 2016 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1530.1.3 by Robert Collins
transport implementations now tested consistently.
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
#
1530.1.3 by Robert Collins
transport implementations now tested consistently.
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
#
1530.1.3 by Robert Collins
transport implementations now tested consistently.
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
1530.1.3 by Robert Collins
transport implementations now tested consistently.
16
17
"""Tests for Transport implementations.
18
19
Transport implementations tested here are supplied by
20
TransportTestProviderAdapter.
21
"""
22
7479.2.1 by Jelmer Vernooij
Drop python2 support.
23
from io import BytesIO
1530.1.3 by Robert Collins
transport implementations now tested consistently.
24
import os
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
25
import stat
26
import sys
1530.1.3 by Robert Collins
transport implementations now tested consistently.
27
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
28
from .. import (
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
29
    errors,
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
30
    osutils,
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
31
    pyutils,
3302.9.21 by Vincent Ladeuil
bzrlib.tests.test_transport_implementations use load_tests.
32
    tests,
5609.9.1 by Martin
Blindly change all users of get_transport to address the function via the transport module
33
    transport as _mod_transport,
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
34
    urlutils,
35
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
36
from ..errors import (ConnectionError,
37
                      FileExists,
38
                      NoSuchFile,
39
                      PathError,
40
                      TransportNotPossible,
41
                      )
42
from ..osutils import getcwd
43
from . import (
3010.2.2 by Martin Pool
Add missing import
44
    TestSkipped,
45
    TestNotApplicable,
4084.5.1 by Robert Collins
Bulk update all test adaptation into a single approach, using multiply_tests rather than test adapters.
46
    multiply_tests,
3010.2.2 by Martin Pool
Add missing import
47
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
48
from . import test_server
49
from .test_transport import TestTransportImplementation
50
from ..transport import (
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
51
    ConnectedTransport,
5436.3.8 by Martin Packman
Add per_transport tests for post_connection hook showing issue with smart clients
52
    Transport,
2485.8.50 by Vincent Ladeuil
merge bzr.dev @ 2584 resolving conflicts
53
    _get_transport_modules,
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
54
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
55
from ..transport.memory import MemoryTransport
56
from ..transport.remote import RemoteTransport
1530.1.3 by Robert Collins
transport implementations now tested consistently.
57
58
4084.5.1 by Robert Collins
Bulk update all test adaptation into a single approach, using multiply_tests rather than test adapters.
59
def get_transport_test_permutations(module):
60
    """Get the permutations module wants to have tested."""
61
    if getattr(module, 'get_test_permutations', None) is None:
62
        raise AssertionError(
63
            "transport module %s doesn't provide get_test_permutations()"
64
            % module.__name__)
65
        return []
66
    return module.get_test_permutations()
67
68
69
def transport_test_permutations():
70
    """Return a list of the klass, server_factory pairs to test."""
71
    result = []
72
    for module in _get_transport_modules():
73
        try:
74
            permutations = get_transport_test_permutations(
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
75
                pyutils.get_named_object(module))
4084.5.1 by Robert Collins
Bulk update all test adaptation into a single approach, using multiply_tests rather than test adapters.
76
            for (klass, server_factory) in permutations:
4725.1.1 by Vincent Ladeuil
Mention transport class name in test id.
77
                scenario = ('%s,%s' % (klass.__name__, server_factory.__name__),
7143.15.2 by Jelmer Vernooij
Run autopep8.
78
                            {"transport_class": klass,
79
                             "transport_server": server_factory})
4084.5.1 by Robert Collins
Bulk update all test adaptation into a single approach, using multiply_tests rather than test adapters.
80
                result.append(scenario)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
81
        except errors.DependencyNotPresent as e:
4084.5.1 by Robert Collins
Bulk update all test adaptation into a single approach, using multiply_tests rather than test adapters.
82
            # Continue even if a dependency prevents us
83
            # from adding this test
84
            pass
85
    return result
2553.2.5 by Robert Collins
And overhaul TransportTestProviderAdapter too.
86
87
6625.1.5 by Martin
Drop custom load_tests implementation and use unittest signature
88
def load_tests(loader, standard_tests, pattern):
3302.9.21 by Vincent Ladeuil
bzrlib.tests.test_transport_implementations use load_tests.
89
    """Multiply tests for tranport implementations."""
90
    result = loader.suiteClass()
4084.5.1 by Robert Collins
Bulk update all test adaptation into a single approach, using multiply_tests rather than test adapters.
91
    scenarios = transport_test_permutations()
92
    return multiply_tests(standard_tests, scenarios, result)
3302.9.21 by Vincent Ladeuil
bzrlib.tests.test_transport_implementations use load_tests.
93
2553.2.5 by Robert Collins
And overhaul TransportTestProviderAdapter too.
94
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
95
class TransportTests(TestTransportImplementation):
96
2018.5.24 by Andrew Bennetts
Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts)
97
    def setUp(self):
98
        super(TransportTests, self).setUp()
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
99
        self.overrideEnv('BRZ_NO_SMART_VFS', None)
2018.5.24 by Andrew Bennetts
Setting NO_SMART_VFS in environment will disable VFS methods in the smart server. (Robert Collins, John Arbash Meinel, Andrew Bennetts)
100
1530.1.3 by Robert Collins
transport implementations now tested consistently.
101
    def check_transport_contents(self, content, transport, relpath):
5602.1.1 by John Arbash Meinel
Change the per_transport tests to use .get_bytes() instead of .get().read().
102
        """Check that transport.get_bytes(relpath) == content."""
103
        self.assertEqualDiff(content, transport.get_bytes(relpath))
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
104
2475.3.2 by John Arbash Meinel
Add Transport.ensure_base()
105
    def test_ensure_base_missing(self):
106
        """.ensure_base() should create the directory if it doesn't exist"""
107
        t = self.get_transport()
108
        t_a = t.clone('a')
109
        if t_a.is_readonly():
110
            self.assertRaises(TransportNotPossible,
111
                              t_a.ensure_base)
112
            return
113
        self.assertTrue(t_a.ensure_base())
114
        self.assertTrue(t.has('a'))
115
116
    def test_ensure_base_exists(self):
117
        """.ensure_base() should just be happy if it already exists"""
118
        t = self.get_transport()
119
        if t.is_readonly():
120
            return
121
122
        t.mkdir('a')
123
        t_a = t.clone('a')
124
        # ensure_base returns False if it didn't create the base
125
        self.assertFalse(t_a.ensure_base())
126
127
    def test_ensure_base_missing_parent(self):
128
        """.ensure_base() will fail if the parent dir doesn't exist"""
129
        t = self.get_transport()
130
        if t.is_readonly():
131
            return
132
133
        t_a = t.clone('a')
134
        t_b = t_a.clone('b')
135
        self.assertRaises(NoSuchFile, t_b.ensure_base)
136
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
137
    def test_external_url(self):
138
        """.external_url either works or raises InProcessTransport."""
139
        t = self.get_transport()
140
        try:
141
            t.external_url()
142
        except errors.InProcessTransport:
143
            pass
144
1530.1.3 by Robert Collins
transport implementations now tested consistently.
145
    def test_has(self):
146
        t = self.get_transport()
147
148
        files = ['a', 'b', 'e', 'g', '%']
149
        self.build_tree(files, transport=t)
150
        self.assertEqual(True, t.has('a'))
151
        self.assertEqual(False, t.has('c'))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
152
        self.assertEqual(True, t.has(urlutils.escape('%')))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
153
        self.assertEqual(True, t.has_any(['a', 'b', 'c']))
3508.1.10 by Vincent Ladeuil
Start supporting pyftpdlib as an ftp test server.
154
        self.assertEqual(False, t.has_any(['c', 'd', 'f',
155
                                           urlutils.escape('%%')]))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
156
        self.assertEqual(False, t.has_any(['c', 'c', 'c']))
157
        self.assertEqual(True, t.has_any(['b', 'b', 'b']))
158
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
159
    def test_has_root_works(self):
5017.3.21 by Vincent Ladeuil
selftest -s bt.per_transport passing
160
        if self.transport_server is test_server.SmartTCPServer_for_testing:
2692.1.11 by Andrew Bennetts
Improve test coverage by making SmartTCPServer_for_testing by default create a server that does not serve the backing transport's root at its own root. This mirrors the way most HTTP smart servers are configured.
161
            raise TestNotApplicable(
162
                "SmartTCPServer_for_testing intentionally does not allow "
163
                "access to /.")
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
164
        current_transport = self.get_transport()
165
        self.assertTrue(current_transport.has('/'))
166
        root = current_transport.clone('/')
167
        self.assertTrue(root.has(''))
168
1530.1.3 by Robert Collins
transport implementations now tested consistently.
169
    def test_get(self):
170
        t = self.get_transport()
171
6926.1.7 by Jelmer Vernooij
Remove get_multi.
172
        files = ['a']
6973.6.2 by Jelmer Vernooij
Fix more tests.
173
        content = b'contents of a\n'
6926.1.7 by Jelmer Vernooij
Remove get_multi.
174
        self.build_tree(['a'], transport=t, line_endings='binary')
6973.6.2 by Jelmer Vernooij
Fix more tests.
175
        self.check_transport_contents(b'contents of a\n', t, 'a')
6926.1.7 by Jelmer Vernooij
Remove get_multi.
176
        f = t.get('a')
177
        self.assertEqual(content, f.read())
1530.1.3 by Robert Collins
transport implementations now tested consistently.
178
4512.1.1 by Vincent Ladeuil
Fix bug #383920 by inserting the missing Content-Length header.
179
    def test_get_unknown_file(self):
180
        t = self.get_transport()
181
        files = ['a', 'b']
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
182
        contents = [b'contents of a\n',
183
                    b'contents of b\n',
4512.1.1 by Vincent Ladeuil
Fix bug #383920 by inserting the missing Content-Length header.
184
                    ]
185
        self.build_tree(files, transport=t, line_endings='binary')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
186
        self.assertRaises(NoSuchFile, t.get, 'c')
7143.15.2 by Jelmer Vernooij
Run autopep8.
187
5807.5.1 by John Arbash Meinel
Fix bug #767177. Be more agressive with file.close() calls.
188
        def iterate_and_close(func, *args):
189
            for f in func(*args):
190
                # We call f.read() here because things like paramiko actually
191
                # spawn a thread to prefetch the content, which we want to
192
                # consume before we close the handle.
193
                content = f.read()
194
                f.close()
1530.1.3 by Robert Collins
transport implementations now tested consistently.
195
2052.6.2 by Robert Collins
Merge bzr.dev.
196
    def test_get_directory_read_gives_ReadError(self):
197
        """consistent errors for read() on a file returned by get()."""
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
198
        t = self.get_transport()
199
        if t.is_readonly():
200
            self.build_tree(['a directory/'])
201
        else:
202
            t.mkdir('a%20directory')
203
        # getting the file must either work or fail with a PathError
204
        try:
205
            a_file = t.get('a%20directory')
2052.6.2 by Robert Collins
Merge bzr.dev.
206
        except (errors.PathError, errors.RedirectRequested):
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
207
            # early failure return immediately.
208
            return
3111.1.23 by Vincent Ladeuil
Make HTTP/1.1 the default implementation reveals one more bug.
209
        # having got a file, read() must either work (i.e. http reading a dir
210
        # listing) or fail with ReadError
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
211
        try:
212
            a_file.read()
213
        except errors.ReadError:
214
            pass
215
1955.3.3 by John Arbash Meinel
Implement and test 'get_bytes'
216
    def test_get_bytes(self):
217
        t = self.get_transport()
218
219
        files = ['a', 'b', 'e', 'g']
6973.6.2 by Jelmer Vernooij
Fix more tests.
220
        contents = [b'contents of a\n',
221
                    b'contents of b\n',
222
                    b'contents of e\n',
223
                    b'contents of g\n',
1955.3.3 by John Arbash Meinel
Implement and test 'get_bytes'
224
                    ]
225
        self.build_tree(files, transport=t, line_endings='binary')
6973.6.2 by Jelmer Vernooij
Fix more tests.
226
        self.check_transport_contents(b'contents of a\n', t, 'a')
1955.3.3 by John Arbash Meinel
Implement and test 'get_bytes'
227
228
        for content, fname in zip(contents, files):
229
            self.assertEqual(content, t.get_bytes(fname))
230
4512.1.1 by Vincent Ladeuil
Fix bug #383920 by inserting the missing Content-Length header.
231
    def test_get_bytes_unknown_file(self):
232
        t = self.get_transport()
1955.3.3 by John Arbash Meinel
Implement and test 'get_bytes'
233
        self.assertRaises(NoSuchFile, t.get_bytes, 'c')
234
2671.3.9 by Robert Collins
Review feedback and fix VFat emulated transports to not claim to have unix permissions.
235
    def test_get_with_open_write_stream_sees_all_content(self):
2671.3.4 by Robert Collins
Sync up with open file streams on get/get_bytes.
236
        t = self.get_transport()
237
        if t.is_readonly():
238
            return
6973.7.5 by Jelmer Vernooij
s/file/open.
239
        with t.open_write_stream('foo') as handle:
240
            handle.write(b'b')
241
            self.assertEqual(b'b', t.get_bytes('foo'))
2671.3.4 by Robert Collins
Sync up with open file streams on get/get_bytes.
242
2671.3.9 by Robert Collins
Review feedback and fix VFat emulated transports to not claim to have unix permissions.
243
    def test_get_bytes_with_open_write_stream_sees_all_content(self):
2671.3.4 by Robert Collins
Sync up with open file streams on get/get_bytes.
244
        t = self.get_transport()
245
        if t.is_readonly():
246
            return
6973.7.5 by Jelmer Vernooij
s/file/open.
247
        with t.open_write_stream('foo') as handle:
248
            handle.write(b'b')
249
            self.assertEqual(b'b', t.get_bytes('foo'))
250
            with t.get('foo') as f:
251
                self.assertEqual(b'b', f.read())
2671.3.4 by Robert Collins
Sync up with open file streams on get/get_bytes.
252
1955.3.1 by John Arbash Meinel
Add put_bytes() and a base-level implementation for it
253
    def test_put_bytes(self):
254
        t = self.get_transport()
255
256
        if t.is_readonly():
257
            self.assertRaises(TransportNotPossible,
7143.15.2 by Jelmer Vernooij
Run autopep8.
258
                              t.put_bytes, 'a', b'some text for a\n')
1955.3.1 by John Arbash Meinel
Add put_bytes() and a base-level implementation for it
259
            return
260
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
261
        t.put_bytes('a', b'some text for a\n')
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
262
        self.assertTrue(t.has('a'))
6973.6.2 by Jelmer Vernooij
Fix more tests.
263
        self.check_transport_contents(b'some text for a\n', t, 'a')
1955.3.1 by John Arbash Meinel
Add put_bytes() and a base-level implementation for it
264
265
        # The contents should be overwritten
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
266
        t.put_bytes('a', b'new text for a\n')
6973.6.2 by Jelmer Vernooij
Fix more tests.
267
        self.check_transport_contents(b'new text for a\n', t, 'a')
1955.3.1 by John Arbash Meinel
Add put_bytes() and a base-level implementation for it
268
269
        self.assertRaises(NoSuchFile,
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
270
                          t.put_bytes, 'path/doesnt/exist/c', b'contents')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
271
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
272
    def test_put_bytes_non_atomic(self):
273
        t = self.get_transport()
274
275
        if t.is_readonly():
276
            self.assertRaises(TransportNotPossible,
7143.15.2 by Jelmer Vernooij
Run autopep8.
277
                              t.put_bytes_non_atomic, 'a', b'some text for a\n')
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
278
            return
279
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
280
        self.assertFalse(t.has('a'))
6973.6.2 by Jelmer Vernooij
Fix more tests.
281
        t.put_bytes_non_atomic('a', b'some text for a\n')
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
282
        self.assertTrue(t.has('a'))
6973.6.2 by Jelmer Vernooij
Fix more tests.
283
        self.check_transport_contents(b'some text for a\n', t, 'a')
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
284
        # Put also replaces contents
6973.6.2 by Jelmer Vernooij
Fix more tests.
285
        t.put_bytes_non_atomic('a', b'new\ncontents for\na\n')
286
        self.check_transport_contents(b'new\ncontents for\na\n', t, 'a')
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
287
288
        # Make sure we can create another file
6973.6.2 by Jelmer Vernooij
Fix more tests.
289
        t.put_bytes_non_atomic('d', b'contents for\nd\n')
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
290
        # And overwrite 'a' with empty contents
6973.6.2 by Jelmer Vernooij
Fix more tests.
291
        t.put_bytes_non_atomic('a', b'')
292
        self.check_transport_contents(b'contents for\nd\n', t, 'd')
293
        self.check_transport_contents(b'', t, 'a')
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
294
295
        self.assertRaises(NoSuchFile, t.put_bytes_non_atomic, 'no/such/path',
7143.15.2 by Jelmer Vernooij
Run autopep8.
296
                          b'contents\n')
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
297
        # Now test the create_parent flag
298
        self.assertRaises(NoSuchFile, t.put_bytes_non_atomic, 'dir/a',
7143.15.2 by Jelmer Vernooij
Run autopep8.
299
                          b'contents\n')
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
300
        self.assertFalse(t.has('dir/a'))
6973.6.2 by Jelmer Vernooij
Fix more tests.
301
        t.put_bytes_non_atomic('dir/a', b'contents for dir/a\n',
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
302
                               create_parent_dir=True)
6973.6.2 by Jelmer Vernooij
Fix more tests.
303
        self.check_transport_contents(b'contents for dir/a\n', t, 'dir/a')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
304
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
305
        # But we still get NoSuchFile if we can't make the parent dir
306
        self.assertRaises(NoSuchFile, t.put_bytes_non_atomic, 'not/there/a',
7143.15.2 by Jelmer Vernooij
Run autopep8.
307
                          b'contents\n',
308
                          create_parent_dir=True)
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
309
310
    def test_put_bytes_permissions(self):
311
        t = self.get_transport()
312
313
        if t.is_readonly():
314
            return
315
        if not t._can_roundtrip_unix_modebits():
316
            # Can't roundtrip, so no need to run this test
317
            return
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
318
        t.put_bytes('mode644', b'test text\n', mode=0o644)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
319
        self.assertTransportMode(t, 'mode644', 0o644)
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
320
        t.put_bytes('mode666', b'test text\n', mode=0o666)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
321
        self.assertTransportMode(t, 'mode666', 0o666)
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
322
        t.put_bytes('mode600', b'test text\n', mode=0o600)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
323
        self.assertTransportMode(t, 'mode600', 0o600)
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
324
        # Yes, you can put_bytes a file such that it becomes readonly
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
325
        t.put_bytes('mode400', b'test text\n', mode=0o400)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
326
        self.assertTransportMode(t, 'mode400', 0o400)
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
327
328
        # The default permissions should be based on the current umask
329
        umask = osutils.get_umask()
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
330
        t.put_bytes('nomode', b'test text\n', mode=None)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
331
        self.assertTransportMode(t, 'nomode', 0o666 & ~umask)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
332
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
333
    def test_put_bytes_non_atomic_permissions(self):
334
        t = self.get_transport()
335
336
        if t.is_readonly():
337
            return
338
        if not t._can_roundtrip_unix_modebits():
339
            # Can't roundtrip, so no need to run this test
340
            return
6973.6.2 by Jelmer Vernooij
Fix more tests.
341
        t.put_bytes_non_atomic('mode644', b'test text\n', mode=0o644)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
342
        self.assertTransportMode(t, 'mode644', 0o644)
6973.6.2 by Jelmer Vernooij
Fix more tests.
343
        t.put_bytes_non_atomic('mode666', b'test text\n', mode=0o666)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
344
        self.assertTransportMode(t, 'mode666', 0o666)
6973.6.2 by Jelmer Vernooij
Fix more tests.
345
        t.put_bytes_non_atomic('mode600', b'test text\n', mode=0o600)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
346
        self.assertTransportMode(t, 'mode600', 0o600)
6973.6.2 by Jelmer Vernooij
Fix more tests.
347
        t.put_bytes_non_atomic('mode400', b'test text\n', mode=0o400)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
348
        self.assertTransportMode(t, 'mode400', 0o400)
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
349
350
        # The default permissions should be based on the current umask
351
        umask = osutils.get_umask()
6973.6.2 by Jelmer Vernooij
Fix more tests.
352
        t.put_bytes_non_atomic('nomode', b'test text\n', mode=None)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
353
        self.assertTransportMode(t, 'nomode', 0o666 & ~umask)
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
354
355
        # We should also be able to set the mode for a parent directory
356
        # when it is created
6973.6.2 by Jelmer Vernooij
Fix more tests.
357
        t.put_bytes_non_atomic('dir700/mode664', b'test text\n', mode=0o664,
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
358
                               dir_mode=0o700, create_parent_dir=True)
359
        self.assertTransportMode(t, 'dir700', 0o700)
6973.6.2 by Jelmer Vernooij
Fix more tests.
360
        t.put_bytes_non_atomic('dir770/mode664', b'test text\n', mode=0o664,
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
361
                               dir_mode=0o770, create_parent_dir=True)
362
        self.assertTransportMode(t, 'dir770', 0o770)
6973.6.2 by Jelmer Vernooij
Fix more tests.
363
        t.put_bytes_non_atomic('dir777/mode664', b'test text\n', mode=0o664,
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
364
                               dir_mode=0o777, create_parent_dir=True)
365
        self.assertTransportMode(t, 'dir777', 0o777)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
366
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
367
    def test_put_file(self):
368
        t = self.get_transport()
369
370
        if t.is_readonly():
371
            self.assertRaises(TransportNotPossible,
7143.15.2 by Jelmer Vernooij
Run autopep8.
372
                              t.put_file, 'a', BytesIO(b'some text for a\n'))
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
373
            return
374
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
375
        result = t.put_file('a', BytesIO(b'some text for a\n'))
2745.5.2 by Robert Collins
* ``bzrlib.transport.Transport.put_file`` now returns the number of bytes
376
        # put_file returns the length of the data written
377
        self.assertEqual(16, result)
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
378
        self.assertTrue(t.has('a'))
6973.6.2 by Jelmer Vernooij
Fix more tests.
379
        self.check_transport_contents(b'some text for a\n', t, 'a')
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
380
        # Put also replaces contents
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
381
        result = t.put_file('a', BytesIO(b'new\ncontents for\na\n'))
2745.5.2 by Robert Collins
* ``bzrlib.transport.Transport.put_file`` now returns the number of bytes
382
        self.assertEqual(19, result)
6973.6.2 by Jelmer Vernooij
Fix more tests.
383
        self.check_transport_contents(b'new\ncontents for\na\n', t, 'a')
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
384
        self.assertRaises(NoSuchFile,
385
                          t.put_file, 'path/doesnt/exist/c',
7143.15.2 by Jelmer Vernooij
Run autopep8.
386
                          BytesIO(b'contents'))
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
387
388
    def test_put_file_non_atomic(self):
389
        t = self.get_transport()
390
391
        if t.is_readonly():
392
            self.assertRaises(TransportNotPossible,
7143.15.2 by Jelmer Vernooij
Run autopep8.
393
                              t.put_file_non_atomic, 'a', BytesIO(b'some text for a\n'))
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
394
            return
395
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
396
        self.assertFalse(t.has('a'))
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
397
        t.put_file_non_atomic('a', BytesIO(b'some text for a\n'))
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
398
        self.assertTrue(t.has('a'))
6973.6.2 by Jelmer Vernooij
Fix more tests.
399
        self.check_transport_contents(b'some text for a\n', t, 'a')
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
400
        # Put also replaces contents
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
401
        t.put_file_non_atomic('a', BytesIO(b'new\ncontents for\na\n'))
6973.6.2 by Jelmer Vernooij
Fix more tests.
402
        self.check_transport_contents(b'new\ncontents for\na\n', t, 'a')
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
403
404
        # Make sure we can create another file
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
405
        t.put_file_non_atomic('d', BytesIO(b'contents for\nd\n'))
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
406
        # And overwrite 'a' with empty contents
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
407
        t.put_file_non_atomic('a', BytesIO(b''))
6973.6.2 by Jelmer Vernooij
Fix more tests.
408
        self.check_transport_contents(b'contents for\nd\n', t, 'd')
409
        self.check_transport_contents(b'', t, 'a')
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
410
411
        self.assertRaises(NoSuchFile, t.put_file_non_atomic, 'no/such/path',
7143.15.2 by Jelmer Vernooij
Run autopep8.
412
                          BytesIO(b'contents\n'))
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
413
        # Now test the create_parent flag
414
        self.assertRaises(NoSuchFile, t.put_file_non_atomic, 'dir/a',
7143.15.2 by Jelmer Vernooij
Run autopep8.
415
                          BytesIO(b'contents\n'))
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
416
        self.assertFalse(t.has('dir/a'))
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
417
        t.put_file_non_atomic('dir/a', BytesIO(b'contents for dir/a\n'),
1955.3.20 by John Arbash Meinel
Add non_atomic_put_bytes() and tests for it
418
                              create_parent_dir=True)
6973.6.2 by Jelmer Vernooij
Fix more tests.
419
        self.check_transport_contents(b'contents for dir/a\n', t, 'dir/a')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
420
1946.1.8 by John Arbash Meinel
Update non_atomic_put to have a create_parent_dir flag
421
        # But we still get NoSuchFile if we can't make the parent dir
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
422
        self.assertRaises(NoSuchFile, t.put_file_non_atomic, 'not/there/a',
7143.15.2 by Jelmer Vernooij
Run autopep8.
423
                          BytesIO(b'contents\n'),
424
                          create_parent_dir=True)
1955.3.20 by John Arbash Meinel
Add non_atomic_put_bytes() and tests for it
425
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
426
    def test_put_file_permissions(self):
1955.3.18 by John Arbash Meinel
[merge] Transport.non_atomic_put()
427
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
428
        t = self.get_transport()
429
430
        if t.is_readonly():
431
            return
1711.4.32 by John Arbash Meinel
Skip permission tests on win32 no modebits
432
        if not t._can_roundtrip_unix_modebits():
433
            # Can't roundtrip, so no need to run this test
434
            return
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
435
        t.put_file('mode644', BytesIO(b'test text\n'), mode=0o644)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
436
        self.assertTransportMode(t, 'mode644', 0o644)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
437
        t.put_file('mode666', BytesIO(b'test text\n'), mode=0o666)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
438
        self.assertTransportMode(t, 'mode666', 0o666)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
439
        t.put_file('mode600', BytesIO(b'test text\n'), mode=0o600)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
440
        self.assertTransportMode(t, 'mode600', 0o600)
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
441
        # Yes, you can put a file such that it becomes readonly
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
442
        t.put_file('mode400', BytesIO(b'test text\n'), mode=0o400)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
443
        self.assertTransportMode(t, 'mode400', 0o400)
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
444
        # The default permissions should be based on the current umask
445
        umask = osutils.get_umask()
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
446
        t.put_file('nomode', BytesIO(b'test text\n'), mode=None)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
447
        self.assertTransportMode(t, 'nomode', 0o666 & ~umask)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
448
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
449
    def test_put_file_non_atomic_permissions(self):
450
        t = self.get_transport()
451
452
        if t.is_readonly():
453
            return
454
        if not t._can_roundtrip_unix_modebits():
455
            # Can't roundtrip, so no need to run this test
456
            return
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
457
        t.put_file_non_atomic('mode644', BytesIO(b'test text\n'), mode=0o644)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
458
        self.assertTransportMode(t, 'mode644', 0o644)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
459
        t.put_file_non_atomic('mode666', BytesIO(b'test text\n'), mode=0o666)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
460
        self.assertTransportMode(t, 'mode666', 0o666)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
461
        t.put_file_non_atomic('mode600', BytesIO(b'test text\n'), mode=0o600)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
462
        self.assertTransportMode(t, 'mode600', 0o600)
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
463
        # Yes, you can put_file_non_atomic a file such that it becomes readonly
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
464
        t.put_file_non_atomic('mode400', BytesIO(b'test text\n'), mode=0o400)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
465
        self.assertTransportMode(t, 'mode400', 0o400)
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
466
467
        # The default permissions should be based on the current umask
468
        umask = osutils.get_umask()
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
469
        t.put_file_non_atomic('nomode', BytesIO(b'test text\n'), mode=None)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
470
        self.assertTransportMode(t, 'nomode', 0o666 & ~umask)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
471
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
472
        # We should also be able to set the mode for a parent directory
473
        # when it is created
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
474
        sio = BytesIO()
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
475
        t.put_file_non_atomic('dir700/mode664', sio, mode=0o664,
476
                              dir_mode=0o700, create_parent_dir=True)
477
        self.assertTransportMode(t, 'dir700', 0o700)
478
        t.put_file_non_atomic('dir770/mode664', sio, mode=0o664,
479
                              dir_mode=0o770, create_parent_dir=True)
480
        self.assertTransportMode(t, 'dir770', 0o770)
481
        t.put_file_non_atomic('dir777/mode664', sio, mode=0o664,
482
                              dir_mode=0o777, create_parent_dir=True)
483
        self.assertTransportMode(t, 'dir777', 0o777)
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
484
2018.5.131 by Andrew Bennetts
Be strict about unicode passed to transport.put_{bytes,file} and SmartClient.call_with_body_bytes, fixing part of TestLockableFiles_RemoteLockDir.test_read_write.
485
    def test_put_bytes_unicode(self):
486
        t = self.get_transport()
487
        if t.is_readonly():
488
            return
489
        unicode_string = u'\u1234'
6609.2.1 by Vincent Ladeuil
Make all transport put_bytes() raises TypeError when given unicode strings rather than bytes.
490
        self.assertRaises(TypeError, t.put_bytes, 'foo', unicode_string)
2018.5.131 by Andrew Bennetts
Be strict about unicode passed to transport.put_{bytes,file} and SmartClient.call_with_body_bytes, fixing part of TestLockableFiles_RemoteLockDir.test_read_write.
491
1530.1.3 by Robert Collins
transport implementations now tested consistently.
492
    def test_mkdir(self):
493
        t = self.get_transport()
494
495
        if t.is_readonly():
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
496
            # cannot mkdir on readonly transports. We're not testing for
1530.1.3 by Robert Collins
transport implementations now tested consistently.
497
            # cache coherency because cache behaviour is not currently
498
            # defined for the transport interface.
499
            self.assertRaises(TransportNotPossible, t.mkdir, '.')
500
            self.assertRaises(TransportNotPossible, t.mkdir, 'new_dir')
7143.15.2 by Jelmer Vernooij
Run autopep8.
501
            self.assertRaises(TransportNotPossible,
502
                              t.mkdir, 'path/doesnt/exist')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
503
            return
504
        # Test mkdir
505
        t.mkdir('dir_a')
506
        self.assertEqual(t.has('dir_a'), True)
507
        self.assertEqual(t.has('dir_b'), False)
508
509
        t.mkdir('dir_b')
510
        self.assertEqual(t.has('dir_b'), True)
511
6926.1.2 by Jelmer Vernooij
Remove has_multi.
512
        self.assertEqual([t.has(n) for n in
7143.15.2 by Jelmer Vernooij
Run autopep8.
513
                          ['dir_a', 'dir_b', 'dir_q', 'dir_b']],
514
                         [True, True, False, True])
1530.1.3 by Robert Collins
transport implementations now tested consistently.
515
516
        # we were testing that a local mkdir followed by a transport
517
        # mkdir failed thusly, but given that we * in one process * do not
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
518
        # concurrently fiddle with disk dirs and then use transport to do
1530.1.3 by Robert Collins
transport implementations now tested consistently.
519
        # things, the win here seems marginal compared to the constraint on
520
        # the interface. RBC 20051227
521
        t.mkdir('dir_g')
522
        self.assertRaises(FileExists, t.mkdir, 'dir_g')
523
524
        # Test get/put in sub-directories
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
525
        t.put_bytes('dir_a/a', b'contents of dir_a/a')
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
526
        t.put_file('dir_b/b', BytesIO(b'contents of dir_b/b'))
6973.6.2 by Jelmer Vernooij
Fix more tests.
527
        self.check_transport_contents(b'contents of dir_a/a', t, 'dir_a/a')
528
        self.check_transport_contents(b'contents of dir_b/b', t, 'dir_b/b')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
529
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
530
        # mkdir of a dir with an absent parent
531
        self.assertRaises(NoSuchFile, t.mkdir, 'missing/dir')
532
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
533
    def test_mkdir_permissions(self):
534
        t = self.get_transport()
535
        if t.is_readonly():
536
            return
1608.2.7 by Martin Pool
Rename supports_unix_modebits to _can_roundtrip_unix_modebits for clarity
537
        if not t._can_roundtrip_unix_modebits():
1608.2.5 by Martin Pool
Add Transport.supports_unix_modebits, so tests can
538
            # no sense testing on this transport
539
            return
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
540
        # Test mkdir with a mode
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
541
        t.mkdir('dmode755', mode=0o755)
542
        self.assertTransportMode(t, 'dmode755', 0o755)
543
        t.mkdir('dmode555', mode=0o555)
544
        self.assertTransportMode(t, 'dmode555', 0o555)
545
        t.mkdir('dmode777', mode=0o777)
546
        self.assertTransportMode(t, 'dmode777', 0o777)
547
        t.mkdir('dmode700', mode=0o700)
548
        self.assertTransportMode(t, 'dmode700', 0o700)
6926.1.4 by Jelmer Vernooij
remove mkdir_multi.
549
        t.mkdir('mdmode755', mode=0o755)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
550
        self.assertTransportMode(t, 'mdmode755', 0o755)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
551
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
552
        # Default mode should be based on umask
553
        umask = osutils.get_umask()
554
        t.mkdir('dnomode', mode=None)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
555
        self.assertTransportMode(t, 'dnomode', 0o777 & ~umask)
1755.3.7 by John Arbash Meinel
Clean up and write tests for permissions. Now we use fstat which should be cheap, and lets us check the permissions and the file size
556
2671.3.2 by Robert Collins
Start open_file_stream logic.
557
    def test_opening_a_file_stream_creates_file(self):
558
        t = self.get_transport()
559
        if t.is_readonly():
560
            return
2671.3.9 by Robert Collins
Review feedback and fix VFat emulated transports to not claim to have unix permissions.
561
        handle = t.open_write_stream('foo')
2671.3.2 by Robert Collins
Start open_file_stream logic.
562
        try:
7045.1.1 by Jelmer Vernooij
Fix another 300 tests.
563
            self.assertEqual(b'', t.get_bytes('foo'))
2671.3.2 by Robert Collins
Start open_file_stream logic.
564
        finally:
2671.3.6 by Robert Collins
Review feedback.
565
            handle.close()
2671.3.2 by Robert Collins
Start open_file_stream logic.
566
2671.3.3 by Robert Collins
Add mode parameter to Transport.open_file_stream.
567
    def test_opening_a_file_stream_can_set_mode(self):
568
        t = self.get_transport()
569
        if t.is_readonly():
6606.3.1 by Vincent Ladeuil
Add rename() and open_write_stream() as explicitly not supported via the ReadonlyTransportDecorator to give better feedback when a decorated transport is misused
570
            self.assertRaises((TransportNotPossible, NotImplementedError),
571
                              t.open_write_stream, 'foo')
2671.3.3 by Robert Collins
Add mode parameter to Transport.open_file_stream.
572
            return
573
        if not t._can_roundtrip_unix_modebits():
574
            # Can't roundtrip, so no need to run this test
575
            return
6606.3.1 by Vincent Ladeuil
Add rename() and open_write_stream() as explicitly not supported via the ReadonlyTransportDecorator to give better feedback when a decorated transport is misused
576
2671.3.3 by Robert Collins
Add mode parameter to Transport.open_file_stream.
577
        def check_mode(name, mode, expected):
2671.3.9 by Robert Collins
Review feedback and fix VFat emulated transports to not claim to have unix permissions.
578
            handle = t.open_write_stream(name, mode=mode)
2671.3.6 by Robert Collins
Review feedback.
579
            handle.close()
2671.3.3 by Robert Collins
Add mode parameter to Transport.open_file_stream.
580
            self.assertTransportMode(t, name, expected)
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
581
        check_mode('mode644', 0o644, 0o644)
582
        check_mode('mode666', 0o666, 0o666)
583
        check_mode('mode600', 0o600, 0o600)
2671.3.3 by Robert Collins
Add mode parameter to Transport.open_file_stream.
584
        # The default permissions should be based on the current umask
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
585
        check_mode('nomode', None, 0o666 & ~osutils.get_umask())
2671.3.3 by Robert Collins
Add mode parameter to Transport.open_file_stream.
586
1530.1.3 by Robert Collins
transport implementations now tested consistently.
587
    def test_copy_to(self):
1534.4.21 by Robert Collins
Extend the copy_to tests to smoke test server-to-same-server copies to catch optimised code paths, and fix sftps optimised code path by removing dead code.
588
        # FIXME: test:   same server to same server (partly done)
589
        # same protocol two servers
590
        # and    different protocols (done for now except for MemoryTransport.
591
        # - RBC 20060122
592
593
        def simple_copy_files(transport_from, transport_to):
594
            files = ['a', 'b', 'c', 'd']
595
            self.build_tree(files, transport=transport_from)
1563.2.3 by Robert Collins
Change the return signature of transport.append and append_multi to return the length of the pre-append content.
596
            self.assertEqual(4, transport_from.copy_to(files, transport_to))
1534.4.21 by Robert Collins
Extend the copy_to tests to smoke test server-to-same-server copies to catch optimised code paths, and fix sftps optimised code path by removing dead code.
597
            for f in files:
5602.1.1 by John Arbash Meinel
Change the per_transport tests to use .get_bytes() instead of .get().read().
598
                self.check_transport_contents(transport_to.get_bytes(f),
1534.4.21 by Robert Collins
Extend the copy_to tests to smoke test server-to-same-server copies to catch optimised code paths, and fix sftps optimised code path by removing dead code.
599
                                              transport_from, f)
600
1530.1.3 by Robert Collins
transport implementations now tested consistently.
601
        t = self.get_transport()
6658.3.1 by Martin
Skip test_copy_to on SFTPTransport due to unreliablity
602
        if t.__class__.__name__ == "SFTPTransport":
603
            self.skipTest("SFTP copy_to currently too flakey to use")
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
604
        temp_transport = MemoryTransport('memory:///')
1534.4.21 by Robert Collins
Extend the copy_to tests to smoke test server-to-same-server copies to catch optimised code paths, and fix sftps optimised code path by removing dead code.
605
        simple_copy_files(t, temp_transport)
606
        if not t.is_readonly():
607
            t.mkdir('copy_to_simple')
608
            t2 = t.clone('copy_to_simple')
609
            simple_copy_files(t, t2)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
610
611
        # Test that copying into a missing directory raises
612
        # NoSuchFile
613
        if t.is_readonly():
1530.1.21 by Robert Collins
Review feedback fixes.
614
            self.build_tree(['e/', 'e/f'])
1530.1.3 by Robert Collins
transport implementations now tested consistently.
615
        else:
616
            t.mkdir('e')
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
617
            t.put_bytes('e/f', b'contents of e')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
618
        self.assertRaises(NoSuchFile, t.copy_to, ['e/f'], temp_transport)
619
        temp_transport.mkdir('e')
620
        t.copy_to(['e/f'], temp_transport)
621
622
        del temp_transport
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
623
        temp_transport = MemoryTransport('memory:///')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
624
625
        files = ['a', 'b', 'c', 'd']
626
        t.copy_to(iter(files), temp_transport)
627
        for f in files:
5602.1.1 by John Arbash Meinel
Change the per_transport tests to use .get_bytes() instead of .get().read().
628
            self.check_transport_contents(temp_transport.get_bytes(f),
1530.1.3 by Robert Collins
transport implementations now tested consistently.
629
                                          t, f)
630
        del temp_transport
631
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
632
        for mode in (0o666, 0o644, 0o600, 0o400):
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
633
            temp_transport = MemoryTransport("memory:///")
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
634
            t.copy_to(files, temp_transport, mode=mode)
635
            for f in files:
1530.1.21 by Robert Collins
Review feedback fixes.
636
                self.assertTransportMode(temp_transport, f, mode)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
637
4294.2.1 by Robert Collins
Move directory checking for bzr push options into Branch.create_clone_on_transport.
638
    def test_create_prefix(self):
639
        t = self.get_transport()
640
        sub = t.clone('foo').clone('bar')
641
        try:
642
            sub.create_prefix()
643
        except TransportNotPossible:
644
            self.assertTrue(t.is_readonly())
645
        else:
646
            self.assertTrue(t.has('foo/bar'))
647
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
648
    def test_append_file(self):
649
        t = self.get_transport()
650
651
        if t.is_readonly():
1530.1.3 by Robert Collins
transport implementations now tested consistently.
652
            self.assertRaises(TransportNotPossible,
7143.15.2 by Jelmer Vernooij
Run autopep8.
653
                              t.append_file, 'a', 'add\nsome\nmore\ncontents\n')
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
654
            return
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
655
        t.put_bytes('a', b'diff\ncontents for\na\n')
656
        t.put_bytes('b', b'contents\nfor b\n')
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
657
658
        self.assertEqual(20,
7143.15.2 by Jelmer Vernooij
Run autopep8.
659
                         t.append_file('a', BytesIO(b'add\nsome\nmore\ncontents\n')))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
660
661
        self.check_transport_contents(
7045.4.11 by Jelmer Vernooij
Some more tests fixed.
662
            b'diff\ncontents for\na\nadd\nsome\nmore\ncontents\n',
1530.1.3 by Robert Collins
transport implementations now tested consistently.
663
            t, 'a')
664
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
665
        # a file with no parent should fail..
666
        self.assertRaises(NoSuchFile,
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
667
                          t.append_file, 'missing/path', BytesIO(b'content'))
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
668
669
        # And we can create new files, too
670
        self.assertEqual(0,
7143.15.2 by Jelmer Vernooij
Run autopep8.
671
                         t.append_file('c', BytesIO(b'some text\nfor a missing file\n')))
6973.6.2 by Jelmer Vernooij
Fix more tests.
672
        self.check_transport_contents(b'some text\nfor a missing file\n',
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
673
                                      t, 'c')
674
675
    def test_append_bytes(self):
676
        t = self.get_transport()
677
678
        if t.is_readonly():
679
            self.assertRaises(TransportNotPossible,
7143.15.2 by Jelmer Vernooij
Run autopep8.
680
                              t.append_bytes, 'a', b'add\nsome\nmore\ncontents\n')
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
681
            return
682
6973.10.5 by Jelmer Vernooij
Fix use of .next.
683
        self.assertEqual(0, t.append_bytes('a', b'diff\ncontents for\na\n'))
684
        self.assertEqual(0, t.append_bytes('b', b'contents\nfor b\n'))
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
685
686
        self.assertEqual(20,
7143.15.2 by Jelmer Vernooij
Run autopep8.
687
                         t.append_bytes('a', b'add\nsome\nmore\ncontents\n'))
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
688
689
        self.check_transport_contents(
6973.10.5 by Jelmer Vernooij
Fix use of .next.
690
            b'diff\ncontents for\na\nadd\nsome\nmore\ncontents\n',
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
691
            t, 'a')
692
693
        # a file with no parent should fail..
694
        self.assertRaises(NoSuchFile,
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
695
                          t.append_bytes, 'missing/path', b'content')
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
696
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
697
    def test_append_file_mode(self):
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
698
        """Check that append accepts a mode parameter"""
1666.1.6 by Robert Collins
Make knit the default format.
699
        # check append accepts a mode
700
        t = self.get_transport()
701
        if t.is_readonly():
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
702
            self.assertRaises(TransportNotPossible,
7143.15.2 by Jelmer Vernooij
Run autopep8.
703
                              t.append_file, 'f', BytesIO(b'f'), mode=None)
1666.1.6 by Robert Collins
Make knit the default format.
704
            return
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
705
        t.append_file('f', BytesIO(b'f'), mode=None)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
706
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
707
    def test_append_bytes_mode(self):
708
        # check append_bytes accepts a mode
709
        t = self.get_transport()
710
        if t.is_readonly():
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
711
            self.assertRaises(TransportNotPossible,
7143.15.2 by Jelmer Vernooij
Run autopep8.
712
                              t.append_bytes, 'f', b'f', mode=None)
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
713
            return
7045.4.11 by Jelmer Vernooij
Some more tests fixed.
714
        t.append_bytes('f', b'f', mode=None)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
715
1530.1.3 by Robert Collins
transport implementations now tested consistently.
716
    def test_delete(self):
717
        # TODO: Test Transport.delete
718
        t = self.get_transport()
719
720
        # Not much to do with a readonly transport
721
        if t.is_readonly():
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
722
            self.assertRaises(TransportNotPossible, t.delete, 'missing')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
723
            return
724
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
725
        t.put_bytes('a', b'a little bit of text\n')
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
726
        self.assertTrue(t.has('a'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
727
        t.delete('a')
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
728
        self.assertFalse(t.has('a'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
729
730
        self.assertRaises(NoSuchFile, t.delete, 'a')
731
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
732
        t.put_bytes('a', b'a text\n')
733
        t.put_bytes('b', b'b text\n')
734
        t.put_bytes('c', b'c text\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
735
        self.assertEqual([True, True, True],
7143.15.2 by Jelmer Vernooij
Run autopep8.
736
                         [t.has(n) for n in ['a', 'b', 'c']])
6926.1.1 by Jelmer Vernooij
Remove delete_multi.
737
        t.delete('a')
738
        t.delete('c')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
739
        self.assertEqual([False, True, False],
7143.15.2 by Jelmer Vernooij
Run autopep8.
740
                         [t.has(n) for n in ['a', 'b', 'c']])
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
741
        self.assertFalse(t.has('a'))
742
        self.assertTrue(t.has('b'))
743
        self.assertFalse(t.has('c'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
744
6926.1.9 by Jelmer Vernooij
Fix tests.
745
        for name in ['a', 'c', 'd']:
6926.1.1 by Jelmer Vernooij
Remove delete_multi.
746
            self.assertRaises(NoSuchFile, t.delete, name)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
747
748
        # We should have deleted everything
749
        # SftpServer creates control files in the
750
        # working directory, so we can just do a
751
        # plain "listdir".
752
        # self.assertEqual([], os.listdir('.'))
753
2671.3.1 by Robert Collins
* New method ``bzrlib.transport.Transport.get_recommended_page_size``.
754
    def test_recommended_page_size(self):
755
        """Transports recommend a page size for partial access to files."""
756
        t = self.get_transport()
757
        self.assertIsInstance(t.recommended_page_size(), int)
758
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
759
    def test_rmdir(self):
760
        t = self.get_transport()
761
        # Not much to do with a readonly transport
762
        if t.is_readonly():
763
            self.assertRaises(TransportNotPossible, t.rmdir, 'missing')
764
            return
765
        t.mkdir('adir')
766
        t.mkdir('adir/bdir')
767
        t.rmdir('adir/bdir')
1948.3.12 by Vincent LADEUIL
Fix Aaron's third review remarks.
768
        # ftp may not be able to raise NoSuchFile for lack of
769
        # details when failing
770
        self.assertRaises((NoSuchFile, PathError), t.rmdir, 'adir/bdir')
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
771
        t.rmdir('adir')
1948.3.12 by Vincent LADEUIL
Fix Aaron's third review remarks.
772
        self.assertRaises((NoSuchFile, PathError), t.rmdir, 'adir')
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
773
1553.5.10 by Martin Pool
New DirectoryNotEmpty exception, and raise this from local and memory
774
    def test_rmdir_not_empty(self):
775
        """Deleting a non-empty directory raises an exception
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
776
1553.5.10 by Martin Pool
New DirectoryNotEmpty exception, and raise this from local and memory
777
        sftp (and possibly others) don't give us a specific "directory not
778
        empty" exception -- we can just see that the operation failed.
779
        """
780
        t = self.get_transport()
781
        if t.is_readonly():
782
            return
783
        t.mkdir('adir')
784
        t.mkdir('adir/bdir')
785
        self.assertRaises(PathError, t.rmdir, 'adir')
786
2338.5.1 by Andrew Bennetts
Fix bug in MemoryTransport.rmdir.
787
    def test_rmdir_empty_but_similar_prefix(self):
788
        """rmdir does not get confused by sibling paths.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
789
2338.5.1 by Andrew Bennetts
Fix bug in MemoryTransport.rmdir.
790
        A naive implementation of MemoryTransport would refuse to rmdir
791
        ".bzr/branch" if there is a ".bzr/branch-format" directory, because it
792
        uses "path.startswith(dir)" on all file paths to determine if directory
793
        is empty.
794
        """
795
        t = self.get_transport()
796
        if t.is_readonly():
797
            return
798
        t.mkdir('foo')
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
799
        t.put_bytes('foo-bar', b'')
2338.5.1 by Andrew Bennetts
Fix bug in MemoryTransport.rmdir.
800
        t.mkdir('foo-baz')
801
        t.rmdir('foo')
802
        self.assertRaises((NoSuchFile, PathError), t.rmdir, 'foo')
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
803
        self.assertTrue(t.has('foo-bar'))
2338.5.1 by Andrew Bennetts
Fix bug in MemoryTransport.rmdir.
804
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
805
    def test_rename_dir_succeeds(self):
806
        t = self.get_transport()
807
        if t.is_readonly():
6606.3.1 by Vincent Ladeuil
Add rename() and open_write_stream() as explicitly not supported via the ReadonlyTransportDecorator to give better feedback when a decorated transport is misused
808
            self.assertRaises((TransportNotPossible, NotImplementedError),
809
                              t.rename, 'foo', 'bar')
810
            return
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
811
        t.mkdir('adir')
812
        t.mkdir('adir/asubdir')
813
        t.rename('adir', 'bdir')
814
        self.assertTrue(t.has('bdir/asubdir'))
815
        self.assertFalse(t.has('adir'))
816
817
    def test_rename_dir_nonempty(self):
818
        """Attempting to replace a nonemtpy directory should fail"""
819
        t = self.get_transport()
820
        if t.is_readonly():
6606.3.1 by Vincent Ladeuil
Add rename() and open_write_stream() as explicitly not supported via the ReadonlyTransportDecorator to give better feedback when a decorated transport is misused
821
            self.assertRaises((TransportNotPossible, NotImplementedError),
822
                              t.rename, 'foo', 'bar')
823
            return
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
824
        t.mkdir('adir')
825
        t.mkdir('adir/asubdir')
826
        t.mkdir('bdir')
827
        t.mkdir('bdir/bsubdir')
1910.7.17 by Andrew Bennetts
Various cosmetic changes.
828
        # any kind of PathError would be OK, though we normally expect
829
        # DirectoryNotEmpty
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
830
        self.assertRaises(PathError, t.rename, 'bdir', 'adir')
831
        # nothing was changed so it should still be as before
832
        self.assertTrue(t.has('bdir/bsubdir'))
833
        self.assertFalse(t.has('adir/bdir'))
834
        self.assertFalse(t.has('adir/bsubdir'))
835
3010.2.1 by Martin Pool
Followon from MemoryTransport._abspath fix: add test_rename_across_subdirs, and fix error construction
836
    def test_rename_across_subdirs(self):
837
        t = self.get_transport()
838
        if t.is_readonly():
839
            raise TestNotApplicable("transport is readonly")
840
        t.mkdir('a')
841
        t.mkdir('b')
842
        ta = t.clone('a')
843
        tb = t.clone('b')
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
844
        ta.put_bytes('f', b'aoeu')
3010.2.1 by Martin Pool
Followon from MemoryTransport._abspath fix: add test_rename_across_subdirs, and fix error construction
845
        ta.rename('f', '../b/f')
846
        self.assertTrue(tb.has('f'))
847
        self.assertFalse(ta.has('f'))
848
        self.assertTrue(t.has('b/f'))
849
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
850
    def test_delete_tree(self):
851
        t = self.get_transport()
852
853
        # Not much to do with a readonly transport
854
        if t.is_readonly():
855
            self.assertRaises(TransportNotPossible, t.delete_tree, 'missing')
856
            return
857
858
        # and does it like listing ?
859
        t.mkdir('adir')
860
        try:
861
            t.delete_tree('adir')
862
        except TransportNotPossible:
863
            # ok, this transport does not support delete_tree
864
            return
3484.1.1 by Vincent Ladeuil
Trivial drive-by cleanups.
865
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
866
        # did it delete that trivial case?
867
        self.assertRaises(NoSuchFile, t.stat, 'adir')
868
869
        self.build_tree(['adir/',
3484.1.1 by Vincent Ladeuil
Trivial drive-by cleanups.
870
                         'adir/file',
871
                         'adir/subdir/',
872
                         'adir/subdir/file',
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
873
                         'adir/subdir2/',
874
                         'adir/subdir2/file',
875
                         ], transport=t)
876
877
        t.delete_tree('adir')
878
        # adir should be gone now.
879
        self.assertRaises(NoSuchFile, t.stat, 'adir')
880
1530.1.3 by Robert Collins
transport implementations now tested consistently.
881
    def test_move(self):
882
        t = self.get_transport()
883
884
        if t.is_readonly():
885
            return
886
887
        # TODO: I would like to use os.listdir() to
888
        # make sure there are no extra files, but SftpServer
889
        # creates control files in the working directory
890
        # perhaps all of this could be done in a subdirectory
891
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
892
        t.put_bytes('a', b'a first file\n')
6926.1.2 by Jelmer Vernooij
Remove has_multi.
893
        self.assertEqual([True, False], [t.has(n) for n in ['a', 'b']])
1530.1.3 by Robert Collins
transport implementations now tested consistently.
894
895
        t.move('a', 'b')
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
896
        self.assertTrue(t.has('b'))
897
        self.assertFalse(t.has('a'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
898
6973.6.2 by Jelmer Vernooij
Fix more tests.
899
        self.check_transport_contents(b'a first file\n', t, 'b')
6926.1.2 by Jelmer Vernooij
Remove has_multi.
900
        self.assertEqual([False, True], [t.has(n) for n in ['a', 'b']])
1530.1.3 by Robert Collins
transport implementations now tested consistently.
901
902
        # Overwrite a file
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
903
        t.put_bytes('c', b'c this file\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
904
        t.move('c', 'b')
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
905
        self.assertFalse(t.has('c'))
6973.6.2 by Jelmer Vernooij
Fix more tests.
906
        self.check_transport_contents(b'c this file\n', t, 'b')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
907
908
        # TODO: Try to write a test for atomicity
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
909
        # TODO: Test moving into a non-existent subdirectory
1530.1.3 by Robert Collins
transport implementations now tested consistently.
910
911
    def test_copy(self):
912
        t = self.get_transport()
913
914
        if t.is_readonly():
915
            return
916
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
917
        t.put_bytes('a', b'a file\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
918
        t.copy('a', 'b')
6973.6.2 by Jelmer Vernooij
Fix more tests.
919
        self.check_transport_contents(b'a file\n', t, 'b')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
920
921
        self.assertRaises(NoSuchFile, t.copy, 'c', 'd')
922
        os.mkdir('c')
923
        # What should the assert be if you try to copy a
924
        # file over a directory?
925
        #self.assertRaises(Something, t.copy, 'a', 'c')
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
926
        t.put_bytes('d', b'text in d\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
927
        t.copy('d', 'b')
6973.6.2 by Jelmer Vernooij
Fix more tests.
928
        self.check_transport_contents(b'text in d\n', t, 'b')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
929
930
    def test_connection_error(self):
1910.7.17 by Andrew Bennetts
Various cosmetic changes.
931
        """ConnectionError is raised when connection is impossible.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
932
3021.1.2 by Vincent Ladeuil
Fix bug #164567 by catching connection errors.
933
        The error should be raised from the first operation on the transport.
1910.7.17 by Andrew Bennetts
Various cosmetic changes.
934
        """
1530.1.9 by Robert Collins
Test bogus urls with http in the new infrastructure.
935
        try:
936
            url = self._server.get_bogus_url()
937
        except NotImplementedError:
938
            raise TestSkipped("Transport %s has no bogus URL support." %
939
                              self._server.__class__)
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
940
        t = _mod_transport.get_transport_from_url(url)
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
941
        self.assertRaises((ConnectionError, NoSuchFile), t.get, '.bzr/branch')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
942
943
    def test_stat(self):
944
        # TODO: Test stat, just try once, and if it throws, stop testing
945
        from stat import S_ISDIR, S_ISREG
946
947
        t = self.get_transport()
948
949
        try:
950
            st = t.stat('.')
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
951
        except TransportNotPossible as e:
1530.1.3 by Robert Collins
transport implementations now tested consistently.
952
            # This transport cannot stat
953
            return
954
955
        paths = ['a', 'b/', 'b/c', 'b/d/', 'b/d/e']
3484.1.1 by Vincent Ladeuil
Trivial drive-by cleanups.
956
        sizes = [14, 0, 16, 0, 18]
1551.2.39 by abentley
Fix line endings in tests
957
        self.build_tree(paths, transport=t, line_endings='binary')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
958
959
        for path, size in zip(paths, sizes):
960
            st = t.stat(path)
961
            if path.endswith('/'):
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
962
                self.assertTrue(S_ISDIR(st.st_mode))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
963
                # directory sizes are meaningless
964
            else:
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
965
                self.assertTrue(S_ISREG(st.st_mode))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
966
                self.assertEqual(size, st.st_size)
967
968
        self.assertRaises(NoSuchFile, t.stat, 'q')
969
        self.assertRaises(NoSuchFile, t.stat, 'b/a')
970
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
971
        self.build_tree(['subdir/', 'subdir/file'], transport=t)
972
        subdir = t.clone('subdir')
5807.5.1 by John Arbash Meinel
Fix bug #767177. Be more agressive with file.close() calls.
973
        st = subdir.stat('./file')
974
        st = subdir.stat('.')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
975
5056.1.9 by Neil Santos
Renamed link() methods to hardlink(), as per mbp's suggestion
976
    def test_hardlink(self):
5056.1.1 by Neil Santos
Added default link() and symlink() methods to Transport.
977
        from stat import ST_NLINK
978
979
        t = self.get_transport()
980
981
        source_name = "original_target"
982
        link_name = "target_link"
983
984
        self.build_tree([source_name], transport=t)
985
986
        try:
5056.1.9 by Neil Santos
Renamed link() methods to hardlink(), as per mbp's suggestion
987
            t.hardlink(source_name, link_name)
5056.1.1 by Neil Santos
Added default link() and symlink() methods to Transport.
988
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
989
            self.assertTrue(t.has(source_name))
990
            self.assertTrue(t.has(link_name))
5056.1.1 by Neil Santos
Added default link() and symlink() methods to Transport.
991
992
            st = t.stat(link_name)
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
993
            self.assertEqual(st[ST_NLINK], 2)
5056.1.1 by Neil Santos
Added default link() and symlink() methods to Transport.
994
        except TransportNotPossible:
5056.1.8 by Neil Santos
Fixed link and symlink tests to raise TestSkipped when going through non-supporting transports, rather than just returning.
995
            raise TestSkipped("Transport %s does not support hardlinks." %
996
                              self._server.__class__)
5056.1.1 by Neil Santos
Added default link() and symlink() methods to Transport.
997
998
    def test_symlink(self):
999
        from stat import S_ISLNK
1000
1001
        t = self.get_transport()
1002
1003
        source_name = "original_target"
1004
        link_name = "target_link"
1005
1006
        self.build_tree([source_name], transport=t)
1007
1008
        try:
5056.1.4 by Neil Santos
Changed stat() in SFTPTransport and LocalTransport back to calling plain stat(), instead of lstat().
1009
            t.symlink(source_name, link_name)
5056.1.1 by Neil Santos
Added default link() and symlink() methods to Transport.
1010
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1011
            self.assertTrue(t.has(source_name))
1012
            self.assertTrue(t.has(link_name))
5056.1.1 by Neil Santos
Added default link() and symlink() methods to Transport.
1013
1014
            st = t.stat(link_name)
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1015
            self.assertTrue(S_ISLNK(st.st_mode),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1016
                            "expected symlink, got mode %o" % st.st_mode)
5056.1.1 by Neil Santos
Added default link() and symlink() methods to Transport.
1017
        except TransportNotPossible:
5056.1.8 by Neil Santos
Fixed link and symlink tests to raise TestSkipped when going through non-supporting transports, rather than just returning.
1018
            raise TestSkipped("Transport %s does not support symlinks." %
1019
                              self._server.__class__)
5056.1.1 by Neil Santos
Added default link() and symlink() methods to Transport.
1020
7119.2.2 by Jelmer Vernooij
Test readlink.
1021
        self.assertEqual(source_name, t.readlink(link_name))
1022
7119.2.3 by Jelmer Vernooij
Add test for readlink.
1023
    def test_readlink_nonexistent(self):
1024
        t = self.get_transport()
1025
        try:
1026
            self.assertRaises(NoSuchFile, t.readlink, 'nonexistent')
1027
        except TransportNotPossible:
1028
            raise TestSkipped("Transport %s does not support symlinks." %
1029
                              self._server.__class__)
1030
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1031
    def test_list_dir(self):
1032
        # TODO: Test list_dir, just try once, and if it throws, stop testing
1033
        t = self.get_transport()
3484.1.1 by Vincent Ladeuil
Trivial drive-by cleanups.
1034
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1035
        if not t.listable():
1036
            self.assertRaises(TransportNotPossible, t.list_dir, '.')
1037
            return
1038
3211.6.1 by James Henstridge
* Remove relpath='' special case in MemoryTransport._abspath(), which
1039
        def sorted_list(d, transport):
6619.3.18 by Jelmer Vernooij
Run 2to3 idioms fixer.
1040
            l = sorted(transport.list_dir(d))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1041
            return l
1042
3211.6.1 by James Henstridge
* Remove relpath='' special case in MemoryTransport._abspath(), which
1043
        self.assertEqual([], sorted_list('.', t))
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
1044
        # c2 is precisely one letter longer than c here to test that
1045
        # suffixing is not confused.
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
1046
        # a%25b checks that quoting is done consistently across transports
1047
        tree_names = ['a', 'a%25b', 'b', 'c/', 'c/d', 'c/e', 'c2/']
2120.3.1 by John Arbash Meinel
Fix MemoryTransport.list_dir() implementation, and update tests
1048
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
1049
        if not t.is_readonly():
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
1050
            self.build_tree(tree_names, transport=t)
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
1051
        else:
2120.3.1 by John Arbash Meinel
Fix MemoryTransport.list_dir() implementation, and update tests
1052
            self.build_tree(tree_names)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1053
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
1054
        self.assertEqual(
3211.6.1 by James Henstridge
* Remove relpath='' special case in MemoryTransport._abspath(), which
1055
            ['a', 'a%2525b', 'b', 'c', 'c2'], sorted_list('', t))
1056
        self.assertEqual(
1057
            ['a', 'a%2525b', 'b', 'c', 'c2'], sorted_list('.', t))
1058
        self.assertEqual(['d', 'e'], sorted_list('c', t))
1059
1060
        # Cloning the transport produces an equivalent listing
1061
        self.assertEqual(['d', 'e'], sorted_list('', t.clone('c')))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1062
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
1063
        if not t.is_readonly():
1064
            t.delete('c/d')
1065
            t.delete('b')
1066
        else:
2120.3.1 by John Arbash Meinel
Fix MemoryTransport.list_dir() implementation, and update tests
1067
            os.unlink('c/d')
1068
            os.unlink('b')
3484.1.1 by Vincent Ladeuil
Trivial drive-by cleanups.
1069
3211.6.1 by James Henstridge
* Remove relpath='' special case in MemoryTransport._abspath(), which
1070
        self.assertEqual(['a', 'a%2525b', 'c', 'c2'], sorted_list('.', t))
1071
        self.assertEqual(['e'], sorted_list('c', t))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1072
1662.1.12 by Martin Pool
Translate unknown sftp errors to PathError, no NoSuchFile
1073
        self.assertListRaises(PathError, t.list_dir, 'q')
1074
        self.assertListRaises(PathError, t.list_dir, 'c/f')
3508.1.4 by Vincent Ladeuil
Ensure that ftp transport are always in binary mode.
1075
        # 'a' is a file, list_dir should raise an error
1662.1.12 by Martin Pool
Translate unknown sftp errors to PathError, no NoSuchFile
1076
        self.assertListRaises(PathError, t.list_dir, 'a')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1077
1910.7.1 by Andrew Bennetts
Make sure list_dir always returns url-escaped names.
1078
    def test_list_dir_result_is_url_escaped(self):
1079
        t = self.get_transport()
1080
        if not t.listable():
1081
            raise TestSkipped("transport not listable")
1082
1083
        if not t.is_readonly():
1084
            self.build_tree(['a/', 'a/%'], transport=t)
1085
        else:
1086
            self.build_tree(['a/', 'a/%'])
3484.1.1 by Vincent Ladeuil
Trivial drive-by cleanups.
1087
1910.7.2 by Andrew Bennetts
Also assert that list_dir returns plain str objects.
1088
        names = list(t.list_dir('a'))
1089
        self.assertEqual(['%25'], names)
7027.4.8 by Jelmer Vernooij
Fix tests, drop broken tests.
1090
        self.assertIsInstance(names[0], str)
1910.7.1 by Andrew Bennetts
Make sure list_dir always returns url-escaped names.
1091
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
1092
    def test_clone_preserve_info(self):
1093
        t1 = self.get_transport()
1094
        if not isinstance(t1, ConnectedTransport):
1095
            raise TestSkipped("not a connected transport")
1096
1097
        t2 = t1.clone('subdir')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1098
        self.assertEqual(t1._parsed_url.scheme, t2._parsed_url.scheme)
1099
        self.assertEqual(t1._parsed_url.user, t2._parsed_url.user)
1100
        self.assertEqual(t1._parsed_url.password, t2._parsed_url.password)
1101
        self.assertEqual(t1._parsed_url.host, t2._parsed_url.host)
1102
        self.assertEqual(t1._parsed_url.port, t2._parsed_url.port)
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
1103
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
1104
    def test__reuse_for(self):
1105
        t = self.get_transport()
1106
        if not isinstance(t, ConnectedTransport):
1107
            raise TestSkipped("not a connected transport")
1108
1109
        def new_url(scheme=None, user=None, password=None,
1110
                    host=None, port=None, path=None):
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1111
            """Build a new url from t.base changing only parts of it.
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
1112
1113
            Only the parameters different from None will be changed.
1114
            """
7143.15.2 by Jelmer Vernooij
Run autopep8.
1115
            if scheme is None:
1116
                scheme = t._parsed_url.scheme
1117
            if user is None:
1118
                user = t._parsed_url.user
1119
            if password is None:
1120
                password = t._parsed_url.password
1121
            if user is None:
1122
                user = t._parsed_url.user
1123
            if host is None:
1124
                host = t._parsed_url.host
1125
            if port is None:
1126
                port = t._parsed_url.port
1127
            if path is None:
1128
                path = t._parsed_url.path
5268.7.13 by Jelmer Vernooij
Use URL.
1129
            return str(urlutils.URL(scheme, user, password, host, port, path))
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
1130
6055.2.1 by Jelmer Vernooij
Add UnparsedUrl.
1131
        if t._parsed_url.scheme == 'ftp':
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1132
            scheme = 'sftp'
1133
        else:
1134
            scheme = 'ftp'
1135
        self.assertIsNot(t, t._reuse_for(new_url(scheme=scheme)))
6055.2.1 by Jelmer Vernooij
Add UnparsedUrl.
1136
        if t._parsed_url.user == 'me':
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
1137
            user = 'you'
1138
        else:
1139
            user = 'me'
1140
        self.assertIsNot(t, t._reuse_for(new_url(user=user)))
1141
        # passwords are not taken into account because:
1142
        # - it makes no sense to have two different valid passwords for the
1143
        #   same user
1144
        # - _password in ConnectedTransport is intended to collect what the
1145
        #   user specified from the command-line and there are cases where the
1146
        #   new url can contain no password (if the url was built from an
1147
        #   existing transport.base for example)
1148
        # - password are considered part of the credentials provided at
1149
        #   connection creation time and as such may not be present in the url
1150
        #   (they may be typed by the user when prompted for example)
1151
        self.assertIs(t, t._reuse_for(new_url(password='from space')))
1152
        # We will not connect, we can use a invalid host
7143.15.2 by Jelmer Vernooij
Run autopep8.
1153
        self.assertIsNot(t, t._reuse_for(
1154
            new_url(host=t._parsed_url.host + 'bar')))
6055.2.1 by Jelmer Vernooij
Add UnparsedUrl.
1155
        if t._parsed_url.port == 1234:
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
1156
            port = 4321
1157
        else:
1158
            port = 1234
1159
        self.assertIsNot(t, t._reuse_for(new_url(port=port)))
2990.2.1 by Vincent Ladeuil
ConnectedTransport._reuse_for fails to deal with local URLs.
1160
        # No point in trying to reuse a transport for a local URL
2990.2.2 by Vincent Ladeuil
Detect invalid transport reuse attempts by catching invalid URLs.
1161
        self.assertIs(None, t._reuse_for('/valid_but_not_existing'))
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
1162
2485.8.53 by Vincent Ladeuil
Apply test_connection_sharing to all transports to make smart
1163
    def test_connection_sharing(self):
1164
        t = self.get_transport()
1165
        if not isinstance(t, ConnectedTransport):
1166
            raise TestSkipped("not a connected transport")
1167
1168
        c = t.clone('subdir')
2485.8.54 by Vincent Ladeuil
Refactor medium uses by making a distinction betweem shared and real medium.
1169
        # Some transports will create the connection  only when needed
7143.15.2 by Jelmer Vernooij
Run autopep8.
1170
        t.has('surely_not')  # Force connection
2485.8.53 by Vincent Ladeuil
Apply test_connection_sharing to all transports to make smart
1171
        self.assertIs(t._get_connection(), c._get_connection())
1172
2485.8.54 by Vincent Ladeuil
Refactor medium uses by making a distinction betweem shared and real medium.
1173
        # Temporary failure, we need to create a new dummy connection
5247.2.12 by Vincent Ladeuil
Ensure that all transports close their underlying connection.
1174
        new_connection = None
2485.8.53 by Vincent Ladeuil
Apply test_connection_sharing to all transports to make smart
1175
        t._set_connection(new_connection)
2485.8.54 by Vincent Ladeuil
Refactor medium uses by making a distinction betweem shared and real medium.
1176
        # Check that both transports use the same connection
2485.8.53 by Vincent Ladeuil
Apply test_connection_sharing to all transports to make smart
1177
        self.assertIs(new_connection, t._get_connection())
1178
        self.assertIs(new_connection, c._get_connection())
1179
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
1180
    def test_reuse_connection_for_various_paths(self):
1181
        t = self.get_transport()
1182
        if not isinstance(t, ConnectedTransport):
1183
            raise TestSkipped("not a connected transport")
1184
7143.15.2 by Jelmer Vernooij
Run autopep8.
1185
        t.has('surely_not')  # Force connection
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
1186
        self.assertIsNot(None, t._get_connection())
1187
1188
        subdir = t._reuse_for(t.base + 'whatever/but/deep/down/the/path')
1189
        self.assertIsNot(t, subdir)
1190
        self.assertIs(t._get_connection(), subdir._get_connection())
1191
1192
        home = subdir._reuse_for(t.base + 'home')
1193
        self.assertIs(t._get_connection(), home._get_connection())
1194
        self.assertIs(subdir._get_connection(), home._get_connection())
1195
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1196
    def test_clone(self):
1197
        # TODO: Test that clone moves up and down the filesystem
1198
        t1 = self.get_transport()
1199
1200
        self.build_tree(['a', 'b/', 'b/c'], transport=t1)
1201
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1202
        self.assertTrue(t1.has('a'))
1203
        self.assertTrue(t1.has('b/c'))
1204
        self.assertFalse(t1.has('c'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1205
1206
        t2 = t1.clone('b')
1207
        self.assertEqual(t1.base + 'b/', t2.base)
1208
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1209
        self.assertTrue(t2.has('c'))
1210
        self.assertFalse(t2.has('a'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1211
1212
        t3 = t2.clone('..')
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1213
        self.assertTrue(t3.has('a'))
1214
        self.assertFalse(t3.has('c'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1215
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1216
        self.assertFalse(t1.has('b/d'))
1217
        self.assertFalse(t2.has('d'))
1218
        self.assertFalse(t3.has('b/d'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1219
1220
        if t1.is_readonly():
6855.4.1 by Jelmer Vernooij
Yet more bees.
1221
            self.build_tree_contents([('b/d', b'newfile\n')])
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1222
        else:
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
1223
            t2.put_bytes('d', b'newfile\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1224
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1225
        self.assertTrue(t1.has('b/d'))
1226
        self.assertTrue(t2.has('d'))
1227
        self.assertTrue(t3.has('b/d'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1228
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
1229
    def test_clone_to_root(self):
1230
        orig_transport = self.get_transport()
1231
        # Repeatedly go up to a parent directory until we're at the root
1232
        # directory of this transport
1233
        root_transport = orig_transport
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
1234
        new_transport = root_transport.clone("..")
2245.6.1 by Alexander Belchenko
win32 UNC path: recursive cloning UNC path to root stops on //HOST, not on //
1235
        # as we are walking up directories, the path must be
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
1236
        # growing less, except at the top
7143.15.2 by Jelmer Vernooij
Run autopep8.
1237
        self.assertTrue(len(new_transport.base) < len(root_transport.base) or
1238
                        new_transport.base == root_transport.base)
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
1239
        while new_transport.base != root_transport.base:
1240
            root_transport = new_transport
1241
            new_transport = root_transport.clone("..")
2245.6.1 by Alexander Belchenko
win32 UNC path: recursive cloning UNC path to root stops on //HOST, not on //
1242
            # as we are walking up directories, the path must be
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
1243
            # growing less, except at the top
7143.15.2 by Jelmer Vernooij
Run autopep8.
1244
            self.assertTrue(len(new_transport.base) < len(root_transport.base) or
1245
                            new_transport.base == root_transport.base)
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
1246
1247
        # Cloning to "/" should take us to exactly the same location.
1248
        self.assertEqual(root_transport.base, orig_transport.clone("/").base)
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
1249
        # the abspath of "/" from the original transport should be the same
1250
        # as the base at the root:
1251
        self.assertEqual(orig_transport.abspath("/"), root_transport.base)
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
1252
1910.15.5 by Andrew Bennetts
Transport behaviour at the root of the URL is now defined and tested.
1253
        # At the root, the URL must still end with / as its a directory
1254
        self.assertEqual(root_transport.base[-1], '/')
1255
1256
    def test_clone_from_root(self):
1257
        """At the root, cloning to a simple dir should just do string append."""
1258
        orig_transport = self.get_transport()
1259
        root_transport = orig_transport.clone('/')
1260
        self.assertEqual(root_transport.base + '.bzr/',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1261
                         root_transport.clone('.bzr').base)
1910.15.5 by Andrew Bennetts
Transport behaviour at the root of the URL is now defined and tested.
1262
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
1263
    def test_base_url(self):
1264
        t = self.get_transport()
1265
        self.assertEqual('/', t.base[-1])
1266
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1267
    def test_relpath(self):
1268
        t = self.get_transport()
1269
        self.assertEqual('', t.relpath(t.base))
1270
        # base ends with /
1271
        self.assertEqual('', t.relpath(t.base[:-1]))
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
1272
        # subdirs which don't exist should still give relpaths.
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1273
        self.assertEqual('foo', t.relpath(t.base + 'foo'))
1274
        # trailing slash should be the same.
1275
        self.assertEqual('foo', t.relpath(t.base + 'foo/'))
1276
1636.1.1 by Robert Collins
Fix calling relpath() and abspath() on transports at their root.
1277
    def test_relpath_at_root(self):
1278
        t = self.get_transport()
1279
        # clone all the way to the top
1280
        new_transport = t.clone('..')
1281
        while new_transport.base != t.base:
1282
            t = new_transport
1283
            new_transport = t.clone('..')
1284
        # we must be able to get a relpath below the root
1285
        self.assertEqual('', t.relpath(t.base))
1286
        # and a deeper one should work too
1287
        self.assertEqual('foo/bar', t.relpath(t.base + 'foo/bar'))
1288
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1289
    def test_abspath(self):
1290
        # smoke test for abspath. Corner cases for backends like unix fs's
1291
        # that have aliasing problems like symlinks should go in backend
1292
        # specific test cases.
1293
        transport = self.get_transport()
2485.8.21 by Vincent Ladeuil
Simplify debug.
1294
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1295
        self.assertEqual(transport.base + 'relpath',
1296
                         transport.abspath('relpath'))
1297
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
1298
        # This should work without raising an error.
1299
        transport.abspath("/")
1300
1301
        # the abspath of "/" and "/foo/.." should result in the same location
1302
        self.assertEqual(transport.abspath("/"), transport.abspath("/foo/.."))
1303
2070.3.1 by Andrew Bennetts
Fix memory_transport.abspath('/foo')
1304
        self.assertEqual(transport.clone("/").abspath('foo'),
1305
                         transport.abspath("/foo"))
1306
5609.9.1 by Martin
Blindly change all users of get_transport to address the function via the transport module
1307
    # GZ 2011-01-26: Test in per_transport but not using self.get_transport?
3693.2.2 by Mark Hammond
add a test for win32 abspath sematics, which as requested by lifeless,
1308
    def test_win32_abspath(self):
3712.1.1 by Ian Clatworthy
LocalTransport.abspath returns drive letter if transport has one (Mark Hammond)
1309
        # Note: we tried to set sys.platform='win32' so we could test on
1310
        # other platforms too, but then osutils does platform specific
1311
        # things at import time which defeated us...
3693.2.3 by Mark Hammond
Back to skipping the tests on non-windows platforms.
1312
        if sys.platform != 'win32':
1313
            raise TestSkipped(
1314
                'Testing drive letters in abspath implemented only for win32')
3693.2.2 by Mark Hammond
add a test for win32 abspath sematics, which as requested by lifeless,
1315
1316
        # smoke test for abspath on win32.
1317
        # a transport based on 'file:///' never fully qualifies the drive.
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
1318
        transport = _mod_transport.get_transport_from_url("file:///")
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1319
        self.assertEqual(transport.abspath("/"), "file:///")
3693.2.2 by Mark Hammond
add a test for win32 abspath sematics, which as requested by lifeless,
1320
1321
        # but a transport that starts with a drive spec must keep it.
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
1322
        transport = _mod_transport.get_transport_from_url("file:///C:/")
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1323
        self.assertEqual(transport.abspath("/"), "file:///C:/")
3693.2.2 by Mark Hammond
add a test for win32 abspath sematics, which as requested by lifeless,
1324
1685.1.9 by John Arbash Meinel
Updated LocalTransport so that it's base is now a URL rather than a local path. This helps consistency with all other functions. To do so, I added local_abspath() which returns the local path, and local_path_to/from_url
1325
    def test_local_abspath(self):
1326
        transport = self.get_transport()
1327
        try:
1328
            p = transport.local_abspath('.')
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
1329
        except (errors.NotLocalUrl, TransportNotPossible) as e:
2018.18.22 by Martin Pool
merge bzr.dev
1330
            # should be formattable
2018.18.4 by Martin Pool
Change Transport.local_abspath to raise NotLocalUrl, and test.
1331
            s = str(e)
1685.1.9 by John Arbash Meinel
Updated LocalTransport so that it's base is now a URL rather than a local path. This helps consistency with all other functions. To do so, I added local_abspath() which returns the local path, and local_path_to/from_url
1332
        else:
1333
            self.assertEqual(getcwd(), p)
1334
1636.1.1 by Robert Collins
Fix calling relpath() and abspath() on transports at their root.
1335
    def test_abspath_at_root(self):
1336
        t = self.get_transport()
1337
        # clone all the way to the top
1338
        new_transport = t.clone('..')
1339
        while new_transport.base != t.base:
1340
            t = new_transport
1341
            new_transport = t.clone('..')
1342
        # we must be able to get a abspath of the root when we ask for
1343
        # t.abspath('..') - this due to our choice that clone('..')
1344
        # should return the root from the root, combined with the desire that
1345
        # the url from clone('..') and from abspath('..') should be the same.
1346
        self.assertEqual(t.base, t.abspath('..'))
1347
        # '' should give us the root
1348
        self.assertEqual(t.base, t.abspath(''))
1349
        # and a path should append to the url
1350
        self.assertEqual(t.base + 'foo', t.abspath('foo'))
1351
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1352
    def test_iter_files_recursive(self):
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
1353
        transport = self.get_transport()
1354
        if not transport.listable():
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
1355
            self.assertRaises(TransportNotPossible,
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
1356
                              transport.iter_files_recursive)
1357
            return
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
1358
        self.build_tree(['isolated/',
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
1359
                         'isolated/dir/',
1360
                         'isolated/dir/foo',
1361
                         'isolated/dir/bar',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1362
                         'isolated/dir/b%25z',  # make sure quoting is correct
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
1363
                         'isolated/bar'],
1364
                        transport=transport)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1365
        paths = set(transport.iter_files_recursive())
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
1366
        # nb the directories are not converted
1367
        self.assertEqual(paths,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1368
                         {'isolated/dir/foo',
1369
                          'isolated/dir/bar',
1370
                          'isolated/dir/b%2525z',
1371
                          'isolated/bar'})
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
1372
        sub_transport = transport.clone('isolated')
1373
        paths = set(sub_transport.iter_files_recursive())
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
1374
        self.assertEqual(paths,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1375
                         {'dir/foo', 'dir/bar', 'dir/b%2525z', 'bar'})
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
1376
1377
    def test_copy_tree(self):
1378
        # TODO: test file contents and permissions are preserved. This test was
1379
        # added just to ensure that quoting was handled correctly.
1380
        # -- David Allouche 2006-08-11
1381
        transport = self.get_transport()
1382
        if not transport.listable():
1383
            self.assertRaises(TransportNotPossible,
1384
                              transport.iter_files_recursive)
1385
            return
1386
        if transport.is_readonly():
1387
            return
1388
        self.build_tree(['from/',
1389
                         'from/dir/',
1390
                         'from/dir/foo',
1391
                         'from/dir/bar',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1392
                         'from/dir/b%25z',  # make sure quoting is correct
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
1393
                         'from/bar'],
1394
                        transport=transport)
1395
        transport.copy_tree('from', 'to')
1396
        paths = set(transport.iter_files_recursive())
1397
        self.assertEqual(paths,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1398
                         {'from/dir/foo',
1399
                          'from/dir/bar',
1400
                          'from/dir/b%2525z',
1401
                          'from/bar',
1402
                          'to/dir/foo',
1403
                          'to/dir/bar',
1404
                          'to/dir/b%2525z',
1405
                          'to/bar', })
1185.85.76 by John Arbash Meinel
Adding an InvalidURL so transports can report they expect utf-8 quoted paths. Updated tests
1406
1551.21.5 by Aaron Bentley
Implement copy_tree on copy_tree_to_transport
1407
    def test_copy_tree_to_transport(self):
1408
        transport = self.get_transport()
1409
        if not transport.listable():
1410
            self.assertRaises(TransportNotPossible,
1411
                              transport.iter_files_recursive)
1412
            return
1413
        if transport.is_readonly():
1414
            return
1415
        self.build_tree(['from/',
1416
                         'from/dir/',
1417
                         'from/dir/foo',
1418
                         'from/dir/bar',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1419
                         'from/dir/b%25z',  # make sure quoting is correct
1551.21.5 by Aaron Bentley
Implement copy_tree on copy_tree_to_transport
1420
                         'from/bar'],
1421
                        transport=transport)
1422
        from_transport = transport.clone('from')
1423
        to_transport = transport.clone('to')
1424
        to_transport.ensure_base()
1425
        from_transport.copy_tree_to_transport(to_transport)
1426
        paths = set(transport.iter_files_recursive())
1427
        self.assertEqual(paths,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1428
                         {'from/dir/foo',
1429
                          'from/dir/bar',
1430
                          'from/dir/b%2525z',
1431
                          'from/bar',
1432
                          'to/dir/foo',
1433
                          'to/dir/bar',
1434
                          'to/dir/b%2525z',
1435
                          'to/bar', })
1551.21.5 by Aaron Bentley
Implement copy_tree on copy_tree_to_transport
1436
1185.85.76 by John Arbash Meinel
Adding an InvalidURL so transports can report they expect utf-8 quoted paths. Updated tests
1437
    def test_unicode_paths(self):
1685.1.57 by Martin Pool
[broken] Skip unicode blackbox tests if not supported by filesystem
1438
        """Test that we can read/write files with Unicode names."""
1185.85.76 by John Arbash Meinel
Adding an InvalidURL so transports can report they expect utf-8 quoted paths. Updated tests
1439
        t = self.get_transport()
1440
1711.7.36 by John Arbash Meinel
Use different filenames to avoid path collisions on win32 w/ FAT32
1441
        # With FAT32 and certain encodings on win32
1442
        # '\xe5' and '\xe4' actually map to the same file
1443
        # adding a suffix kicks in the 'preserving but insensitive'
1444
        # route, and maintains the right files
7143.15.2 by Jelmer Vernooij
Run autopep8.
1445
        files = [u'\xe5.1',  # a w/ circle iso-8859-1
1446
                 u'\xe4.2',  # a w/ dots iso-8859-1
1447
                 u'\u017d',  # Z with umlat iso-8859-2
1448
                 u'\u062c',  # Arabic j
1449
                 u'\u0410',  # Russian A
1450
                 u'\u65e5',  # Kanji person
1451
                 ]
1185.85.76 by John Arbash Meinel
Adding an InvalidURL so transports can report they expect utf-8 quoted paths. Updated tests
1452
4935.1.2 by Vincent Ladeuil
Fixed as per jam's review.
1453
        no_unicode_support = getattr(self._server, 'no_unicode_support', False)
4935.1.1 by Vincent Ladeuil
Support Unicode paths for ftp transport (encoded as utf8).
1454
        if no_unicode_support:
6050.1.2 by Martin
Make tests raising KnownFailure use the knownFailure method instead
1455
            self.knownFailure("test server cannot handle unicode paths")
4935.1.1 by Vincent Ladeuil
Support Unicode paths for ftp transport (encoded as utf8).
1456
1685.1.72 by Wouter van Heyst
StubSFTPServer should use bytestreams rather than unicode
1457
        try:
1711.4.13 by John Arbash Meinel
Use line_endings='binary' for win32
1458
            self.build_tree(files, transport=t, line_endings='binary')
1685.1.72 by Wouter van Heyst
StubSFTPServer should use bytestreams rather than unicode
1459
        except UnicodeError:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1460
            raise TestSkipped(
1461
                "cannot handle unicode paths in current encoding")
1185.85.76 by John Arbash Meinel
Adding an InvalidURL so transports can report they expect utf-8 quoted paths. Updated tests
1462
1463
        # A plain unicode string is not a valid url
1464
        for fname in files:
6729.6.1 by Jelmer Vernooij
Move urlutils errors.
1465
            self.assertRaises(urlutils.InvalidURL, t.get, fname)
1185.85.76 by John Arbash Meinel
Adding an InvalidURL so transports can report they expect utf-8 quoted paths. Updated tests
1466
1467
        for fname in files:
1468
            fname_utf8 = fname.encode('utf-8')
7027.3.3 by Jelmer Vernooij
Add some more bees; support writing both bytes and unicode strings in build_tree_contents.
1469
            contents = b'contents of %s\n' % (fname_utf8,)
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
1470
            self.check_transport_contents(contents, t, urlutils.escape(fname))
1185.85.76 by John Arbash Meinel
Adding an InvalidURL so transports can report they expect utf-8 quoted paths. Updated tests
1471
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1472
    def test_connect_twice_is_same_content(self):
2485.8.21 by Vincent Ladeuil
Simplify debug.
1473
        # check that our server (whatever it is) is accessible reliably
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1474
        # via get_transport and multiple connections share content.
1475
        transport = self.get_transport()
1476
        if transport.is_readonly():
1477
            return
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
1478
        transport.put_bytes('foo', b'bar')
2485.8.21 by Vincent Ladeuil
Simplify debug.
1479
        transport3 = self.get_transport()
6973.6.2 by Jelmer Vernooij
Fix more tests.
1480
        self.check_transport_contents(b'bar', transport3, 'foo')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1481
1482
        # now opening at a relative url should give use a sane result:
1483
        transport.mkdir('newdir')
3508.1.13 by Vincent Ladeuil
Fix last failing tests under python2.6.
1484
        transport5 = self.get_transport('newdir')
2485.8.21 by Vincent Ladeuil
Simplify debug.
1485
        transport6 = transport5.clone('..')
6973.6.2 by Jelmer Vernooij
Fix more tests.
1486
        self.check_transport_contents(b'bar', transport6, 'foo')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1487
1488
    def test_lock_write(self):
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1489
        """Test transport-level write locks.
1490
1491
        These are deprecated and transports may decline to support them.
1492
        """
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1493
        transport = self.get_transport()
1494
        if transport.is_readonly():
7143.15.2 by Jelmer Vernooij
Run autopep8.
1495
            self.assertRaises(TransportNotPossible,
1496
                              transport.lock_write, 'foo')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1497
            return
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
1498
        transport.put_bytes('lock', b'')
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1499
        try:
1500
            lock = transport.lock_write('lock')
1752.3.6 by Andrew Bennetts
Merge from test-tweaks
1501
        except TransportNotPossible:
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1502
            return
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1503
        # TODO make this consistent on all platforms:
1504
        # self.assertRaises(LockError, transport.lock_write, 'lock')
1505
        lock.unlock()
1506
1507
    def test_lock_read(self):
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1508
        """Test transport-level read locks.
1509
1510
        These are deprecated and transports may decline to support them.
1511
        """
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1512
        transport = self.get_transport()
1513
        if transport.is_readonly():
6973.7.5 by Jelmer Vernooij
s/file/open.
1514
            open('lock', 'w').close()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1515
        else:
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
1516
            transport.put_bytes('lock', b'')
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1517
        try:
1518
            lock = transport.lock_read('lock')
1752.3.6 by Andrew Bennetts
Merge from test-tweaks
1519
        except TransportNotPossible:
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1520
            return
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1521
        # TODO make this consistent on all platforms:
1522
        # self.assertRaises(LockError, transport.lock_read, 'lock')
1523
        lock.unlock()
1185.85.80 by John Arbash Meinel
[merge] jam-integration 1527, including branch-formats, help text, misc bug fixes.
1524
1594.2.5 by Robert Collins
Readv patch from Johan Rydberg giving knits partial download support.
1525
    def test_readv(self):
1526
        transport = self.get_transport()
1527
        if transport.is_readonly():
7143.15.2 by Jelmer Vernooij
Run autopep8.
1528
            with open('a', 'w') as f:
1529
                f.write('0123456789')
1594.2.5 by Robert Collins
Readv patch from Johan Rydberg giving knits partial download support.
1530
        else:
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
1531
            transport.put_bytes('a', b'0123456789')
1185.85.76 by John Arbash Meinel
Adding an InvalidURL so transports can report they expect utf-8 quoted paths. Updated tests
1532
2004.1.22 by v.ladeuil+lp at free
Implements Range header handling for GET requests. Fix a test.
1533
        d = list(transport.readv('a', ((0, 1),)))
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
1534
        self.assertEqual(d[0], (0, b'0'))
2004.1.22 by v.ladeuil+lp at free
Implements Range header handling for GET requests. Fix a test.
1535
1594.2.17 by Robert Collins
Better readv coalescing, now with test, and progress during knit index reading.
1536
        d = list(transport.readv('a', ((0, 1), (1, 1), (3, 2), (9, 1))))
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
1537
        self.assertEqual(d[0], (0, b'0'))
1538
        self.assertEqual(d[1], (1, b'1'))
1539
        self.assertEqual(d[2], (3, b'34'))
1540
        self.assertEqual(d[3], (9, b'9'))
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
1541
1864.5.2 by John Arbash Meinel
always read in sorted order, and return in requested order, but only cache what is currently out of order
1542
    def test_readv_out_of_order(self):
1543
        transport = self.get_transport()
1544
        if transport.is_readonly():
7143.15.2 by Jelmer Vernooij
Run autopep8.
1545
            with open('a', 'w') as f:
1546
                f.write('0123456789')
1864.5.2 by John Arbash Meinel
always read in sorted order, and return in requested order, but only cache what is currently out of order
1547
        else:
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
1548
            transport.put_bytes('a', b'01234567890')
1864.5.2 by John Arbash Meinel
always read in sorted order, and return in requested order, but only cache what is currently out of order
1549
1550
        d = list(transport.readv('a', ((1, 1), (9, 1), (0, 1), (3, 2))))
6855.4.5 by Jelmer Vernooij
Fix more bees, use with rather than try/finally for some files.
1551
        self.assertEqual(d[0], (1, b'1'))
1552
        self.assertEqual(d[1], (9, b'9'))
1553
        self.assertEqual(d[2], (0, b'0'))
1554
        self.assertEqual(d[3], (3, b'34'))
1752.2.40 by Andrew Bennetts
Merge from bzr.dev.
1555
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
1556
    def test_readv_with_adjust_for_latency(self):
1557
        transport = self.get_transport()
1558
        # the adjust for latency flag expands the data region returned
1559
        # according to a per-transport heuristic, so testing is a little
1560
        # tricky as we need more data than the largest combining that our
1561
        # transports do. To accomodate this we generate random data and cross
1562
        # reference the returned data with the random data. To avoid doing
1563
        # multiple large random byte look ups we do several tests on the same
1564
        # backing data.
7143.15.2 by Jelmer Vernooij
Run autopep8.
1565
        content = osutils.rand_bytes(200 * 1024)
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
1566
        content_size = len(content)
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
1567
        if transport.is_readonly():
3693.1.2 by John Arbash Meinel
Use build_tree_contents instead of direct open().write()
1568
            self.build_tree_contents([('a', content)])
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
1569
        else:
1570
            transport.put_bytes('a', content)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1571
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
1572
        def check_result_data(result_vector):
1573
            for item in result_vector:
1574
                data_len = len(item[1])
1575
                self.assertEqual(content[item[0]:item[0] + data_len], item[1])
1576
1577
        # start corner case
1578
        result = list(transport.readv('a', ((0, 30),),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1579
                                      adjust_for_latency=True, upper_limit=content_size))
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
1580
        # we expect 1 result, from 0, to something > 30
1581
        self.assertEqual(1, len(result))
1582
        self.assertEqual(0, result[0][0])
1583
        self.assertTrue(len(result[0][1]) >= 30)
1584
        check_result_data(result)
1585
        # end of file corner case
1586
        result = list(transport.readv('a', ((204700, 100),),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1587
                                      adjust_for_latency=True, upper_limit=content_size))
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
1588
        # we expect 1 result, from 204800- its length, to the end
1589
        self.assertEqual(1, len(result))
1590
        data_len = len(result[0][1])
7143.15.2 by Jelmer Vernooij
Run autopep8.
1591
        self.assertEqual(204800 - data_len, result[0][0])
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
1592
        self.assertTrue(data_len >= 100)
1593
        check_result_data(result)
1594
        # out of order ranges are made in order
1595
        result = list(transport.readv('a', ((204700, 100), (0, 50)),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1596
                                      adjust_for_latency=True, upper_limit=content_size))
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
1597
        # we expect 2 results, in order, start and end.
1598
        self.assertEqual(2, len(result))
1599
        # start
1600
        data_len = len(result[0][1])
1601
        self.assertEqual(0, result[0][0])
1602
        self.assertTrue(data_len >= 30)
1603
        # end
1604
        data_len = len(result[1][1])
7143.15.2 by Jelmer Vernooij
Run autopep8.
1605
        self.assertEqual(204800 - data_len, result[1][0])
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
1606
        self.assertTrue(data_len >= 100)
1607
        check_result_data(result)
1608
        # close ranges get combined (even if out of order)
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
1609
        for request_vector in [((400, 50), (800, 234)), ((800, 234), (400, 50))]:
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
1610
            result = list(transport.readv('a', request_vector,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1611
                                          adjust_for_latency=True, upper_limit=content_size))
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
1612
            self.assertEqual(1, len(result))
1613
            data_len = len(result[0][1])
3059.2.18 by Vincent Ladeuil
Take spiv review comments into account.
1614
            # minimum length is from 400 to 1034 - 634
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
1615
            self.assertTrue(data_len >= 634)
1616
            # must contain the region 400 to 1034
1617
            self.assertTrue(result[0][0] <= 400)
1618
            self.assertTrue(result[0][0] + data_len >= 1034)
1619
            check_result_data(result)
3469.1.1 by Vincent Ladeuil
Split test to achieve better defect localization :)
1620
1621
    def test_readv_with_adjust_for_latency_with_big_file(self):
1622
        transport = self.get_transport()
2890.1.2 by Robert Collins
More readv adjust for latency tests and bugfixes.
1623
        # test from observed failure case.
1624
        if transport.is_readonly():
7143.15.2 by Jelmer Vernooij
Run autopep8.
1625
            with open('a', 'w') as f:
1626
                f.write('a' * 1024 * 1024)
2890.1.2 by Robert Collins
More readv adjust for latency tests and bugfixes.
1627
        else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
1628
            transport.put_bytes('a', b'a' * 1024 * 1024)
2890.1.2 by Robert Collins
More readv adjust for latency tests and bugfixes.
1629
        broken_vector = [(465219, 800), (225221, 800), (445548, 800),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1630
                         (225037, 800), (221357, 800), (437077, 800), (947670, 800),
1631
                         (465373, 800), (947422, 800)]
1632
        results = list(transport.readv('a', broken_vector, True, 1024 * 1024))
1633
        found_items = [False] * 9
2890.1.2 by Robert Collins
More readv adjust for latency tests and bugfixes.
1634
        for pos, (start, length) in enumerate(broken_vector):
1635
            # check the range is covered by the result
1636
            for offset, data in results:
1637
                if offset <= start and start + length <= offset + len(data):
1638
                    found_items[pos] = True
7143.15.2 by Jelmer Vernooij
Run autopep8.
1639
        self.assertEqual([True] * 9, found_items)
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
1640
2671.3.9 by Robert Collins
Review feedback and fix VFat emulated transports to not claim to have unix permissions.
1641
    def test_get_with_open_write_stream_sees_all_content(self):
2671.3.5 by Robert Collins
* New methods on ``bzrlib.transport.Transport`` ``open_file_stream`` and
1642
        t = self.get_transport()
1643
        if t.is_readonly():
1644
            return
6973.7.5 by Jelmer Vernooij
s/file/open.
1645
        with t.open_write_stream('foo') as handle:
1646
            handle.write(b'bcd')
7143.15.2 by Jelmer Vernooij
Run autopep8.
1647
            self.assertEqual([(0, b'b'), (2, b'd')], list(
1648
                t.readv('foo', ((0, 1), (2, 1)))))
2671.3.5 by Robert Collins
* New methods on ``bzrlib.transport.Transport`` ``open_file_stream`` and
1649
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
1650
    def test_get_smart_medium(self):
1651
        """All transports must either give a smart medium, or know they can't.
1652
        """
1653
        transport = self.get_transport()
1654
        try:
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
1655
            client_medium = transport.get_smart_medium()
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
1656
        except errors.NoSmartMedium:
1657
            # as long as we got it we're fine
1658
            pass
7490.53.1 by Jelmer Vernooij
Move more files.
1659
        else:
1660
            from ..bzr.smart import medium
1661
            self.assertIsInstance(client_medium, medium.SmartClientMedium)
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
1662
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
1663
    def test_readv_short_read(self):
1664
        transport = self.get_transport()
1665
        if transport.is_readonly():
7143.15.2 by Jelmer Vernooij
Run autopep8.
1666
            with open('a', 'w') as f:
1667
                f.write('0123456789')
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
1668
        else:
6855.2.2 by Jelmer Vernooij
Format strings are bytes.
1669
            transport.put_bytes('a', b'01234567890')
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
1670
1671
        # This is intentionally reading off the end of the file
1672
        # since we are sure that it cannot get there
2000.3.9 by v.ladeuil+lp at free
The tests that would have help avoid bug #73948 and all that mess :)
1673
        self.assertListRaises((errors.ShortReadvError, errors.InvalidRange,
1674
                               # Can be raised by paramiko
1675
                               AssertionError),
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
1676
                              transport.readv, 'a', [(1, 1), (8, 10)])
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
1677
1678
        # This is trying to seek past the end of the file, it should
1679
        # also raise a special error
2000.3.9 by v.ladeuil+lp at free
The tests that would have help avoid bug #73948 and all that mess :)
1680
        self.assertListRaises((errors.ShortReadvError, errors.InvalidRange),
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
1681
                              transport.readv, 'a', [(12, 2)])
5268.7.1 by Jelmer Vernooij
Fix segment_parameters for most transports.
1682
5268.7.2 by Jelmer Vernooij
merge bzr.dev.
1683
    def test_no_segment_parameters(self):
1684
        """Segment parameters should be stripped and stored in
1685
        transport.segment_parameters."""
1686
        transport = self.get_transport("foo")
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1687
        self.assertEqual({}, transport.get_segment_parameters())
5268.7.2 by Jelmer Vernooij
merge bzr.dev.
1688
5268.7.1 by Jelmer Vernooij
Fix segment_parameters for most transports.
1689
    def test_segment_parameters(self):
1690
        """Segment parameters should be stripped and stored in
5268.7.5 by Jelmer Vernooij
Use accessor for segment parameters.
1691
        transport.get_segment_parameters()."""
5268.7.1 by Jelmer Vernooij
Fix segment_parameters for most transports.
1692
        base_url = self._server.get_url()
5268.7.2 by Jelmer Vernooij
merge bzr.dev.
1693
        parameters = {"key1": "val1", "key2": "val2"}
1694
        url = urlutils.join_segment_parameters(base_url, parameters)
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
1695
        transport = _mod_transport.get_transport_from_url(url)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1696
        self.assertEqual(parameters, transport.get_segment_parameters())
5268.7.2 by Jelmer Vernooij
merge bzr.dev.
1697
6240.2.5 by Jelmer Vernooij
Add Transport.set_segment_parameter.
1698
    def test_set_segment_parameters(self):
1699
        """Segment parameters can be set and show up in base."""
1700
        transport = self.get_transport("foo")
1701
        orig_base = transport.base
1702
        transport.set_segment_parameter("arm", "board")
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1703
        self.assertEqual("%s,arm=board" % orig_base, transport.base)
1704
        self.assertEqual({"arm": "board"}, transport.get_segment_parameters())
6240.2.5 by Jelmer Vernooij
Add Transport.set_segment_parameter.
1705
        transport.set_segment_parameter("arm", None)
1706
        transport.set_segment_parameter("nonexistant", None)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1707
        self.assertEqual({}, transport.get_segment_parameters())
1708
        self.assertEqual(orig_base, transport.base)
6240.2.5 by Jelmer Vernooij
Add Transport.set_segment_parameter.
1709
5349.2.3 by Martin Pool
Stat on a transport directly pointing to a symlink tells you about the symlink
1710
    def test_stat_symlink(self):
1711
        # if a transport points directly to a symlink (and supports symlinks
1712
        # at all) you can tell this.  helps with bug 32669.
1713
        t = self.get_transport()
1714
        try:
1715
            t.symlink('target', 'link')
1716
        except TransportNotPossible:
1717
            raise TestSkipped("symlinks not supported")
1718
        t2 = t.clone('link')
1719
        st = t2.stat('')
1720
        self.assertTrue(stat.S_ISLNK(st.st_mode))
6061.1.1 by Martin Packman
Add per_transport tests for url unquoting, which pathfilter fails on
1721
1722
    def test_abspath_url_unquote_unreserved(self):
6061.1.7 by Martin Packman
Add more reasoning and bug number to test docstrings, as suggested by poolie in review
1723
        """URLs from abspath should have unreserved characters unquoted
7143.15.2 by Jelmer Vernooij
Run autopep8.
1724
6061.1.7 by Martin Packman
Add more reasoning and bug number to test docstrings, as suggested by poolie in review
1725
        Need consistent quoting notably for tildes, see lp:842223 for more.
1726
        """
6061.1.1 by Martin Packman
Add per_transport tests for url unquoting, which pathfilter fails on
1727
        t = self.get_transport()
1728
        needlessly_escaped_dir = "%2D%2E%30%39%41%5A%5F%61%7A%7E/"
1729
        self.assertEqual(t.base + "-.09AZ_az~",
7143.15.2 by Jelmer Vernooij
Run autopep8.
1730
                         t.abspath(needlessly_escaped_dir))
6061.1.1 by Martin Packman
Add per_transport tests for url unquoting, which pathfilter fails on
1731
1732
    def test_clone_url_unquote_unreserved(self):
6061.1.7 by Martin Packman
Add more reasoning and bug number to test docstrings, as suggested by poolie in review
1733
        """Base URL of a cloned branch needs unreserved characters unquoted
7143.15.2 by Jelmer Vernooij
Run autopep8.
1734
6061.1.7 by Martin Packman
Add more reasoning and bug number to test docstrings, as suggested by poolie in review
1735
        Cloned transports should be prefix comparable for things like the
1736
        isolation checking of tests, see lp:842223 for more.
1737
        """
6061.1.1 by Martin Packman
Add per_transport tests for url unquoting, which pathfilter fails on
1738
        t1 = self.get_transport()
1739
        needlessly_escaped_dir = "%2D%2E%30%39%41%5A%5F%61%7A%7E/"
1740
        self.build_tree([needlessly_escaped_dir], transport=t1)
1741
        t2 = t1.clone(needlessly_escaped_dir)
1742
        self.assertEqual(t1.base + "-.09AZ_az~/", t2.base)
5436.3.8 by Martin Packman
Add per_transport tests for post_connection hook showing issue with smart clients
1743
1744
    def test_hook_post_connection_one(self):
1745
        """Fire post_connect hook after a ConnectedTransport is first used"""
1746
        log = []
1747
        Transport.hooks.install_named_hook("post_connect", log.append, None)
1748
        t = self.get_transport()
1749
        self.assertEqual([], log)
1750
        t.has("non-existant")
5436.3.10 by Martin Packman
Accept and document passing the medium rather than transport for smart connections
1751
        if isinstance(t, RemoteTransport):
1752
            self.assertEqual([t.get_smart_medium()], log)
1753
        elif isinstance(t, ConnectedTransport):
5436.3.8 by Martin Packman
Add per_transport tests for post_connection hook showing issue with smart clients
1754
            self.assertEqual([t], log)
1755
        else:
1756
            self.assertEqual([], log)
1757
1758
    def test_hook_post_connection_multi(self):
1759
        """Fire post_connect hook once per unshared underlying connection"""
1760
        log = []
1761
        Transport.hooks.install_named_hook("post_connect", log.append, None)
1762
        t1 = self.get_transport()
1763
        t2 = t1.clone(".")
1764
        t3 = self.get_transport()
1765
        self.assertEqual([], log)
1766
        t1.has("x")
1767
        t2.has("x")
1768
        t3.has("x")
5436.3.10 by Martin Packman
Accept and document passing the medium rather than transport for smart connections
1769
        if isinstance(t1, RemoteTransport):
1770
            self.assertEqual([t.get_smart_medium() for t in [t1, t3]], log)
1771
        elif isinstance(t1, ConnectedTransport):
5436.3.8 by Martin Packman
Add per_transport tests for post_connection hook showing issue with smart clients
1772
            self.assertEqual([t1, t3], log)
1773
        else:
1774
            self.assertEqual([], log)