/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2004, 2005, 2006 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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tests for Transport implementations.
18
19
Transport implementations tested here are supplied by
20
TransportTestProviderAdapter.
21
"""
22
23
import os
24
from cStringIO import StringIO
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.
25
from StringIO import StringIO as pyStringIO
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
26
import stat
27
import sys
1530.1.3 by Robert Collins
transport implementations now tested consistently.
28
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
29
from bzrlib import (
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
30
    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
31
    osutils,
32
    urlutils,
33
    )
2400.2.1 by Robert Collins
Split out the improvement to Transport.local_abspath to raise NotLocalURL from the hpss-faster-copy branch. (Martin Pool, Ian Clatworthy)
34
from bzrlib.errors import (ConnectionError,
35
                           DirectoryNotEmpty,
36
                           FileExists,
37
                           InvalidURL,
38
                           LockError,
39
                           NoSmartServer,
40
                           NoSuchFile,
41
                           NotLocalUrl,
42
                           PathError,
43
                           TransportNotPossible,
44
                           )
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
45
from bzrlib.osutils import getcwd
2018.5.139 by Andrew Bennetts
Merge from bzr.dev, resolving conflicts.
46
from bzrlib.smart import medium
1955.3.29 by John Arbash Meinel
Use applyDeprecated instead of callDeprecated
47
from bzrlib.symbol_versioning import zero_eleven
1530.1.9 by Robert Collins
Test bogus urls with http in the new infrastructure.
48
from bzrlib.tests import TestCaseInTempDir, TestSkipped
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
49
from bzrlib.tests.test_transport import TestTransportImplementation
2400.1.1 by Andrew Bennetts
Rename bzrlib/transport/smart.py to bzrlib/transport/remote.py.
50
from bzrlib.transport import memory, remote
1530.1.3 by Robert Collins
transport implementations now tested consistently.
51
import bzrlib.transport
52
53
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
54
class TransportTests(TestTransportImplementation):
55
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)
56
    def setUp(self):
57
        super(TransportTests, self).setUp()
2402.1.2 by Andrew Bennetts
Deal with review comments.
58
        self._captureVar('BZR_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)
59
1530.1.3 by Robert Collins
transport implementations now tested consistently.
60
    def check_transport_contents(self, content, transport, relpath):
61
        """Check that transport.get(relpath).read() == content."""
1530.1.21 by Robert Collins
Review feedback fixes.
62
        self.assertEqualDiff(content, transport.get(relpath).read())
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
63
1530.1.3 by Robert Collins
transport implementations now tested consistently.
64
    def test_has(self):
65
        t = self.get_transport()
66
67
        files = ['a', 'b', 'e', 'g', '%']
68
        self.build_tree(files, transport=t)
69
        self.assertEqual(True, t.has('a'))
70
        self.assertEqual(False, t.has('c'))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
71
        self.assertEqual(True, t.has(urlutils.escape('%')))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
72
        self.assertEqual(list(t.has_multi(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])),
73
                [True, True, False, False, True, False, True, False])
74
        self.assertEqual(True, t.has_any(['a', 'b', 'c']))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
75
        self.assertEqual(False, t.has_any(['c', 'd', 'f', urlutils.escape('%%')]))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
76
        self.assertEqual(list(t.has_multi(iter(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']))),
77
                [True, True, False, False, True, False, True, False])
78
        self.assertEqual(False, t.has_any(['c', 'c', 'c']))
79
        self.assertEqual(True, t.has_any(['b', 'b', 'b']))
80
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
81
    def test_has_root_works(self):
82
        current_transport = self.get_transport()
83
        self.assertTrue(current_transport.has('/'))
84
        root = current_transport.clone('/')
85
        self.assertTrue(root.has(''))
86
1530.1.3 by Robert Collins
transport implementations now tested consistently.
87
    def test_get(self):
88
        t = self.get_transport()
89
90
        files = ['a', 'b', 'e', 'g']
91
        contents = ['contents of a\n',
92
                    'contents of b\n',
93
                    'contents of e\n',
94
                    'contents of g\n',
95
                    ]
1551.2.39 by abentley
Fix line endings in tests
96
        self.build_tree(files, transport=t, line_endings='binary')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
97
        self.check_transport_contents('contents of a\n', t, 'a')
98
        content_f = t.get_multi(files)
99
        for content, f in zip(contents, content_f):
100
            self.assertEqual(content, f.read())
101
102
        content_f = t.get_multi(iter(files))
103
        for content, f in zip(contents, content_f):
104
            self.assertEqual(content, f.read())
105
106
        self.assertRaises(NoSuchFile, t.get, 'c')
107
        self.assertListRaises(NoSuchFile, t.get_multi, ['a', 'b', 'c'])
108
        self.assertListRaises(NoSuchFile, t.get_multi, iter(['a', 'b', 'c']))
109
1955.3.3 by John Arbash Meinel
Implement and test 'get_bytes'
110
    def test_get_bytes(self):
111
        t = self.get_transport()
112
113
        files = ['a', 'b', 'e', 'g']
114
        contents = ['contents of a\n',
115
                    'contents of b\n',
116
                    'contents of e\n',
117
                    'contents of g\n',
118
                    ]
119
        self.build_tree(files, transport=t, line_endings='binary')
120
        self.check_transport_contents('contents of a\n', t, 'a')
121
122
        for content, fname in zip(contents, files):
123
            self.assertEqual(content, t.get_bytes(fname))
124
125
        self.assertRaises(NoSuchFile, t.get_bytes, 'c')
126
1530.1.3 by Robert Collins
transport implementations now tested consistently.
127
    def test_put(self):
128
        t = self.get_transport()
129
130
        if t.is_readonly():
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
131
            return
132
1955.3.29 by John Arbash Meinel
Use applyDeprecated instead of callDeprecated
133
        self.applyDeprecated(zero_eleven, t.put, 'a', 'string\ncontents\n')
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
134
        self.check_transport_contents('string\ncontents\n', t, 'a')
135
1955.3.29 by John Arbash Meinel
Use applyDeprecated instead of callDeprecated
136
        self.applyDeprecated(zero_eleven,
137
                             t.put, 'b', StringIO('file-like\ncontents\n'))
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
138
        self.check_transport_contents('file-like\ncontents\n', t, 'b')
139
1910.15.6 by Andrew Bennetts
Merge from bzr.dev
140
        self.assertRaises(NoSuchFile,
1910.19.14 by Robert Collins
Fix up all tests to pass, remove a couple more deprecated function calls, and break the dependency on sftp for the smart transport.
141
            self.applyDeprecated,
142
            zero_eleven,
143
            t.put, 'path/doesnt/exist/c', StringIO('contents'))
1910.15.6 by Andrew Bennetts
Merge from bzr.dev
144
1955.3.1 by John Arbash Meinel
Add put_bytes() and a base-level implementation for it
145
    def test_put_bytes(self):
146
        t = self.get_transport()
147
148
        if t.is_readonly():
149
            self.assertRaises(TransportNotPossible,
150
                    t.put_bytes, 'a', 'some text for a\n')
151
            return
152
153
        t.put_bytes('a', 'some text for a\n')
154
        self.failUnless(t.has('a'))
155
        self.check_transport_contents('some text for a\n', t, 'a')
156
157
        # The contents should be overwritten
158
        t.put_bytes('a', 'new text for a\n')
159
        self.check_transport_contents('new text for a\n', t, 'a')
160
161
        self.assertRaises(NoSuchFile,
162
                          t.put_bytes, 'path/doesnt/exist/c', 'contents')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
163
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
164
    def test_put_bytes_non_atomic(self):
165
        t = self.get_transport()
166
167
        if t.is_readonly():
168
            self.assertRaises(TransportNotPossible,
169
                    t.put_bytes_non_atomic, 'a', 'some text for a\n')
170
            return
171
172
        self.failIf(t.has('a'))
173
        t.put_bytes_non_atomic('a', 'some text for a\n')
174
        self.failUnless(t.has('a'))
175
        self.check_transport_contents('some text for a\n', t, 'a')
176
        # Put also replaces contents
177
        t.put_bytes_non_atomic('a', 'new\ncontents for\na\n')
178
        self.check_transport_contents('new\ncontents for\na\n', t, 'a')
179
180
        # Make sure we can create another file
181
        t.put_bytes_non_atomic('d', 'contents for\nd\n')
182
        # And overwrite 'a' with empty contents
183
        t.put_bytes_non_atomic('a', '')
184
        self.check_transport_contents('contents for\nd\n', t, 'd')
185
        self.check_transport_contents('', t, 'a')
186
187
        self.assertRaises(NoSuchFile, t.put_bytes_non_atomic, 'no/such/path',
188
                                       'contents\n')
189
        # Now test the create_parent flag
190
        self.assertRaises(NoSuchFile, t.put_bytes_non_atomic, 'dir/a',
191
                                       'contents\n')
192
        self.failIf(t.has('dir/a'))
193
        t.put_bytes_non_atomic('dir/a', 'contents for dir/a\n',
194
                               create_parent_dir=True)
195
        self.check_transport_contents('contents for dir/a\n', t, 'dir/a')
196
        
197
        # But we still get NoSuchFile if we can't make the parent dir
198
        self.assertRaises(NoSuchFile, t.put_bytes_non_atomic, 'not/there/a',
199
                                       'contents\n',
200
                                       create_parent_dir=True)
201
202
    def test_put_bytes_permissions(self):
203
        t = self.get_transport()
204
205
        if t.is_readonly():
206
            return
207
        if not t._can_roundtrip_unix_modebits():
208
            # Can't roundtrip, so no need to run this test
209
            return
210
        t.put_bytes('mode644', 'test text\n', mode=0644)
211
        self.assertTransportMode(t, 'mode644', 0644)
212
        t.put_bytes('mode666', 'test text\n', mode=0666)
213
        self.assertTransportMode(t, 'mode666', 0666)
214
        t.put_bytes('mode600', 'test text\n', mode=0600)
215
        self.assertTransportMode(t, 'mode600', 0600)
216
        # Yes, you can put_bytes a file such that it becomes readonly
217
        t.put_bytes('mode400', 'test text\n', mode=0400)
218
        self.assertTransportMode(t, 'mode400', 0400)
219
220
        # The default permissions should be based on the current umask
221
        umask = osutils.get_umask()
222
        t.put_bytes('nomode', 'test text\n', mode=None)
223
        self.assertTransportMode(t, 'nomode', 0666 & ~umask)
224
        
225
    def test_put_bytes_non_atomic_permissions(self):
226
        t = self.get_transport()
227
228
        if t.is_readonly():
229
            return
230
        if not t._can_roundtrip_unix_modebits():
231
            # Can't roundtrip, so no need to run this test
232
            return
233
        t.put_bytes_non_atomic('mode644', 'test text\n', mode=0644)
234
        self.assertTransportMode(t, 'mode644', 0644)
235
        t.put_bytes_non_atomic('mode666', 'test text\n', mode=0666)
236
        self.assertTransportMode(t, 'mode666', 0666)
237
        t.put_bytes_non_atomic('mode600', 'test text\n', mode=0600)
238
        self.assertTransportMode(t, 'mode600', 0600)
239
        t.put_bytes_non_atomic('mode400', 'test text\n', mode=0400)
240
        self.assertTransportMode(t, 'mode400', 0400)
241
242
        # The default permissions should be based on the current umask
243
        umask = osutils.get_umask()
244
        t.put_bytes_non_atomic('nomode', 'test text\n', mode=None)
245
        self.assertTransportMode(t, 'nomode', 0666 & ~umask)
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
246
247
        # We should also be able to set the mode for a parent directory
248
        # when it is created
249
        t.put_bytes_non_atomic('dir700/mode664', 'test text\n', mode=0664,
250
                               dir_mode=0700, create_parent_dir=True)
251
        self.assertTransportMode(t, 'dir700', 0700)
252
        t.put_bytes_non_atomic('dir770/mode664', 'test text\n', mode=0664,
253
                               dir_mode=0770, create_parent_dir=True)
254
        self.assertTransportMode(t, 'dir770', 0770)
255
        t.put_bytes_non_atomic('dir777/mode664', 'test text\n', mode=0664,
256
                               dir_mode=0777, create_parent_dir=True)
257
        self.assertTransportMode(t, 'dir777', 0777)
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
258
        
259
    def test_put_file(self):
260
        t = self.get_transport()
261
262
        if t.is_readonly():
263
            self.assertRaises(TransportNotPossible,
264
                    t.put_file, 'a', StringIO('some text for a\n'))
265
            return
266
267
        t.put_file('a', StringIO('some text for a\n'))
268
        self.failUnless(t.has('a'))
269
        self.check_transport_contents('some text for a\n', t, 'a')
270
        # Put also replaces contents
271
        t.put_file('a', StringIO('new\ncontents for\na\n'))
272
        self.check_transport_contents('new\ncontents for\na\n', t, 'a')
273
        self.assertRaises(NoSuchFile,
274
                          t.put_file, 'path/doesnt/exist/c',
275
                              StringIO('contents'))
276
277
    def test_put_file_non_atomic(self):
278
        t = self.get_transport()
279
280
        if t.is_readonly():
281
            self.assertRaises(TransportNotPossible,
282
                    t.put_file_non_atomic, 'a', StringIO('some text for a\n'))
283
            return
284
285
        self.failIf(t.has('a'))
286
        t.put_file_non_atomic('a', StringIO('some text for a\n'))
287
        self.failUnless(t.has('a'))
288
        self.check_transport_contents('some text for a\n', t, 'a')
289
        # Put also replaces contents
290
        t.put_file_non_atomic('a', StringIO('new\ncontents for\na\n'))
291
        self.check_transport_contents('new\ncontents for\na\n', t, 'a')
292
293
        # Make sure we can create another file
294
        t.put_file_non_atomic('d', StringIO('contents for\nd\n'))
295
        # And overwrite 'a' with empty contents
296
        t.put_file_non_atomic('a', StringIO(''))
297
        self.check_transport_contents('contents for\nd\n', t, 'd')
298
        self.check_transport_contents('', t, 'a')
299
300
        self.assertRaises(NoSuchFile, t.put_file_non_atomic, 'no/such/path',
301
                                       StringIO('contents\n'))
302
        # Now test the create_parent flag
303
        self.assertRaises(NoSuchFile, t.put_file_non_atomic, 'dir/a',
304
                                       StringIO('contents\n'))
305
        self.failIf(t.has('dir/a'))
306
        t.put_file_non_atomic('dir/a', StringIO('contents for dir/a\n'),
1955.3.20 by John Arbash Meinel
Add non_atomic_put_bytes() and tests for it
307
                              create_parent_dir=True)
1946.1.8 by John Arbash Meinel
Update non_atomic_put to have a create_parent_dir flag
308
        self.check_transport_contents('contents for dir/a\n', t, 'dir/a')
309
        
310
        # 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
311
        self.assertRaises(NoSuchFile, t.put_file_non_atomic, 'not/there/a',
1955.3.20 by John Arbash Meinel
Add non_atomic_put_bytes() and tests for it
312
                                       StringIO('contents\n'),
313
                                       create_parent_dir=True)
314
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
315
    def test_put_file_permissions(self):
1955.3.18 by John Arbash Meinel
[merge] Transport.non_atomic_put()
316
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
317
        t = self.get_transport()
318
319
        if t.is_readonly():
320
            return
1711.4.32 by John Arbash Meinel
Skip permission tests on win32 no modebits
321
        if not t._can_roundtrip_unix_modebits():
322
            # Can't roundtrip, so no need to run this test
323
            return
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
324
        t.put_file('mode644', StringIO('test text\n'), mode=0644)
1530.1.21 by Robert Collins
Review feedback fixes.
325
        self.assertTransportMode(t, 'mode644', 0644)
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
326
        t.put_file('mode666', StringIO('test text\n'), mode=0666)
1530.1.21 by Robert Collins
Review feedback fixes.
327
        self.assertTransportMode(t, 'mode666', 0666)
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
328
        t.put_file('mode600', StringIO('test text\n'), mode=0600)
1530.1.21 by Robert Collins
Review feedback fixes.
329
        self.assertTransportMode(t, 'mode600', 0600)
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
330
        # Yes, you can put a file such that it becomes readonly
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
331
        t.put_file('mode400', StringIO('test text\n'), mode=0400)
1530.1.21 by Robert Collins
Review feedback fixes.
332
        self.assertTransportMode(t, 'mode400', 0400)
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
333
334
        # XXX: put_multi is deprecated, so do we really care anymore?
1955.3.29 by John Arbash Meinel
Use applyDeprecated instead of callDeprecated
335
        self.applyDeprecated(zero_eleven, t.put_multi,
336
                             [('mmode644', StringIO('text\n'))], mode=0644)
1530.1.21 by Robert Collins
Review feedback fixes.
337
        self.assertTransportMode(t, 'mmode644', 0644)
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
338
339
        # The default permissions should be based on the current umask
340
        umask = osutils.get_umask()
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
341
        t.put_file('nomode', StringIO('test text\n'), mode=None)
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
342
        self.assertTransportMode(t, 'nomode', 0666 & ~umask)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
343
        
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
344
    def test_put_file_non_atomic_permissions(self):
345
        t = self.get_transport()
346
347
        if t.is_readonly():
348
            return
349
        if not t._can_roundtrip_unix_modebits():
350
            # Can't roundtrip, so no need to run this test
351
            return
352
        t.put_file_non_atomic('mode644', StringIO('test text\n'), mode=0644)
353
        self.assertTransportMode(t, 'mode644', 0644)
354
        t.put_file_non_atomic('mode666', StringIO('test text\n'), mode=0666)
355
        self.assertTransportMode(t, 'mode666', 0666)
356
        t.put_file_non_atomic('mode600', StringIO('test text\n'), mode=0600)
357
        self.assertTransportMode(t, 'mode600', 0600)
358
        # Yes, you can put_file_non_atomic a file such that it becomes readonly
359
        t.put_file_non_atomic('mode400', StringIO('test text\n'), mode=0400)
360
        self.assertTransportMode(t, 'mode400', 0400)
361
362
        # The default permissions should be based on the current umask
363
        umask = osutils.get_umask()
364
        t.put_file_non_atomic('nomode', StringIO('test text\n'), mode=None)
365
        self.assertTransportMode(t, 'nomode', 0666 & ~umask)
366
        
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
367
        # We should also be able to set the mode for a parent directory
368
        # when it is created
369
        sio = StringIO()
370
        t.put_file_non_atomic('dir700/mode664', sio, mode=0664,
371
                              dir_mode=0700, create_parent_dir=True)
372
        self.assertTransportMode(t, 'dir700', 0700)
373
        t.put_file_non_atomic('dir770/mode664', sio, mode=0664,
374
                              dir_mode=0770, create_parent_dir=True)
375
        self.assertTransportMode(t, 'dir770', 0770)
376
        t.put_file_non_atomic('dir777/mode664', sio, mode=0664,
377
                              dir_mode=0777, create_parent_dir=True)
378
        self.assertTransportMode(t, 'dir777', 0777)
379
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.
380
    def test_put_bytes_unicode(self):
381
        # Expect put_bytes to raise AssertionError or UnicodeEncodeError if
382
        # given unicode "bytes".  UnicodeEncodeError doesn't really make sense
383
        # (we don't want to encode unicode here at all, callers should be
384
        # strictly passing bytes to put_bytes), but we allow it for backwards
385
        # compatibility.  At some point we should use a specific exception.
2414.1.2 by Andrew Bennetts
Deal with review comments.
386
        # See https://bugs.launchpad.net/bzr/+bug/106898.
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.
387
        t = self.get_transport()
388
        if t.is_readonly():
389
            return
390
        unicode_string = u'\u1234'
391
        self.assertRaises(
392
            (AssertionError, UnicodeEncodeError),
393
            t.put_bytes, 'foo', unicode_string)
394
395
    def test_put_file_unicode(self):
396
        # Like put_bytes, except with a StringIO.StringIO of a unicode string.
397
        # This situation can happen (and has) if code is careless about the type
398
        # of "string" they initialise/write to a StringIO with.  We cannot use
399
        # cStringIO, because it never returns unicode from read.
400
        # Like put_bytes, UnicodeEncodeError isn't quite the right exception to
401
        # raise, but we raise it for hysterical raisins.
402
        t = self.get_transport()
403
        if t.is_readonly():
404
            return
405
        unicode_file = pyStringIO(u'\u1234')
406
        self.assertRaises(UnicodeEncodeError, t.put_file, 'foo', unicode_file)
407
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
408
    def test_put_multi(self):
409
        t = self.get_transport()
410
411
        if t.is_readonly():
412
            return
1955.3.29 by John Arbash Meinel
Use applyDeprecated instead of callDeprecated
413
        self.assertEqual(2, self.applyDeprecated(zero_eleven,
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
414
            t.put_multi, [('a', StringIO('new\ncontents for\na\n')),
415
                          ('d', StringIO('contents\nfor d\n'))]
416
            ))
417
        self.assertEqual(list(t.has_multi(['a', 'b', 'c', 'd'])),
418
                [True, False, False, True])
419
        self.check_transport_contents('new\ncontents for\na\n', t, 'a')
420
        self.check_transport_contents('contents\nfor d\n', t, 'd')
421
1955.3.29 by John Arbash Meinel
Use applyDeprecated instead of callDeprecated
422
        self.assertEqual(2, self.applyDeprecated(zero_eleven,
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
423
            t.put_multi, iter([('a', StringIO('diff\ncontents for\na\n')),
424
                              ('d', StringIO('another contents\nfor d\n'))])
425
            ))
426
        self.check_transport_contents('diff\ncontents for\na\n', t, 'a')
427
        self.check_transport_contents('another contents\nfor d\n', t, 'd')
428
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
429
    def test_put_permissions(self):
430
        t = self.get_transport()
431
432
        if t.is_readonly():
433
            return
1711.4.32 by John Arbash Meinel
Skip permission tests on win32 no modebits
434
        if not t._can_roundtrip_unix_modebits():
435
            # Can't roundtrip, so no need to run this test
436
            return
1910.15.6 by Andrew Bennetts
Merge from bzr.dev
437
        self.applyDeprecated(zero_eleven, t.put, 'mode644',
438
                             StringIO('test text\n'), mode=0644)
1530.1.21 by Robert Collins
Review feedback fixes.
439
        self.assertTransportMode(t, 'mode644', 0644)
1910.15.6 by Andrew Bennetts
Merge from bzr.dev
440
        self.applyDeprecated(zero_eleven, t.put, 'mode666',
441
                             StringIO('test text\n'), mode=0666)
1530.1.21 by Robert Collins
Review feedback fixes.
442
        self.assertTransportMode(t, 'mode666', 0666)
1910.15.6 by Andrew Bennetts
Merge from bzr.dev
443
        self.applyDeprecated(zero_eleven, t.put, 'mode600',
444
                             StringIO('test text\n'), mode=0600)
1530.1.21 by Robert Collins
Review feedback fixes.
445
        self.assertTransportMode(t, 'mode600', 0600)
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
446
        # Yes, you can put a file such that it becomes readonly
1910.15.6 by Andrew Bennetts
Merge from bzr.dev
447
        self.applyDeprecated(zero_eleven, t.put, 'mode400',
448
                             StringIO('test text\n'), mode=0400)
1530.1.21 by Robert Collins
Review feedback fixes.
449
        self.assertTransportMode(t, 'mode400', 0400)
1910.15.6 by Andrew Bennetts
Merge from bzr.dev
450
        self.applyDeprecated(zero_eleven, t.put_multi,
451
                             [('mmode644', StringIO('text\n'))], mode=0644)
1530.1.21 by Robert Collins
Review feedback fixes.
452
        self.assertTransportMode(t, 'mmode644', 0644)
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
453
454
        # The default permissions should be based on the current umask
455
        umask = osutils.get_umask()
1910.15.6 by Andrew Bennetts
Merge from bzr.dev
456
        self.applyDeprecated(zero_eleven, t.put, 'nomode',
457
                             StringIO('test text\n'), mode=None)
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
458
        self.assertTransportMode(t, 'nomode', 0666 & ~umask)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
459
        
1530.1.3 by Robert Collins
transport implementations now tested consistently.
460
    def test_mkdir(self):
461
        t = self.get_transport()
462
463
        if t.is_readonly():
464
            # cannot mkdir on readonly transports. We're not testing for 
465
            # cache coherency because cache behaviour is not currently
466
            # defined for the transport interface.
467
            self.assertRaises(TransportNotPossible, t.mkdir, '.')
468
            self.assertRaises(TransportNotPossible, t.mkdir, 'new_dir')
469
            self.assertRaises(TransportNotPossible, t.mkdir_multi, ['new_dir'])
470
            self.assertRaises(TransportNotPossible, t.mkdir, 'path/doesnt/exist')
471
            return
472
        # Test mkdir
473
        t.mkdir('dir_a')
474
        self.assertEqual(t.has('dir_a'), True)
475
        self.assertEqual(t.has('dir_b'), False)
476
477
        t.mkdir('dir_b')
478
        self.assertEqual(t.has('dir_b'), True)
479
480
        t.mkdir_multi(['dir_c', 'dir_d'])
481
482
        t.mkdir_multi(iter(['dir_e', 'dir_f']))
483
        self.assertEqual(list(t.has_multi(
484
            ['dir_a', 'dir_b', 'dir_c', 'dir_q',
485
             'dir_d', 'dir_e', 'dir_f', 'dir_b'])),
486
            [True, True, True, False,
487
             True, True, True, True])
488
489
        # we were testing that a local mkdir followed by a transport
490
        # mkdir failed thusly, but given that we * in one process * do not
491
        # concurrently fiddle with disk dirs and then use transport to do 
492
        # things, the win here seems marginal compared to the constraint on
493
        # the interface. RBC 20051227
494
        t.mkdir('dir_g')
495
        self.assertRaises(FileExists, t.mkdir, 'dir_g')
496
497
        # Test get/put in sub-directories
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
498
        t.put_bytes('dir_a/a', 'contents of dir_a/a')
499
        t.put_file('dir_b/b', StringIO('contents of dir_b/b'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
500
        self.check_transport_contents('contents of dir_a/a', t, 'dir_a/a')
501
        self.check_transport_contents('contents of dir_b/b', t, 'dir_b/b')
502
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
503
        # mkdir of a dir with an absent parent
504
        self.assertRaises(NoSuchFile, t.mkdir, 'missing/dir')
505
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
506
    def test_mkdir_permissions(self):
507
        t = self.get_transport()
508
        if t.is_readonly():
509
            return
1608.2.7 by Martin Pool
Rename supports_unix_modebits to _can_roundtrip_unix_modebits for clarity
510
        if not t._can_roundtrip_unix_modebits():
1608.2.5 by Martin Pool
Add Transport.supports_unix_modebits, so tests can
511
            # no sense testing on this transport
512
            return
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
513
        # Test mkdir with a mode
514
        t.mkdir('dmode755', mode=0755)
1530.1.21 by Robert Collins
Review feedback fixes.
515
        self.assertTransportMode(t, 'dmode755', 0755)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
516
        t.mkdir('dmode555', mode=0555)
1530.1.21 by Robert Collins
Review feedback fixes.
517
        self.assertTransportMode(t, 'dmode555', 0555)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
518
        t.mkdir('dmode777', mode=0777)
1530.1.21 by Robert Collins
Review feedback fixes.
519
        self.assertTransportMode(t, 'dmode777', 0777)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
520
        t.mkdir('dmode700', mode=0700)
1530.1.21 by Robert Collins
Review feedback fixes.
521
        self.assertTransportMode(t, 'dmode700', 0700)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
522
        t.mkdir_multi(['mdmode755'], mode=0755)
1530.1.21 by Robert Collins
Review feedback fixes.
523
        self.assertTransportMode(t, 'mdmode755', 0755)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
524
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
525
        # Default mode should be based on umask
526
        umask = osutils.get_umask()
527
        t.mkdir('dnomode', mode=None)
528
        self.assertTransportMode(t, 'dnomode', 0777 & ~umask)
529
1530.1.3 by Robert Collins
transport implementations now tested consistently.
530
    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.
531
        # FIXME: test:   same server to same server (partly done)
532
        # same protocol two servers
533
        # and    different protocols (done for now except for MemoryTransport.
534
        # - RBC 20060122
1530.1.3 by Robert Collins
transport implementations now tested consistently.
535
        from bzrlib.transport.memory import MemoryTransport
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.
536
537
        def simple_copy_files(transport_from, transport_to):
538
            files = ['a', 'b', 'c', 'd']
539
            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.
540
            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.
541
            for f in files:
542
                self.check_transport_contents(transport_to.get(f).read(),
543
                                              transport_from, f)
544
1530.1.3 by Robert Collins
transport implementations now tested consistently.
545
        t = self.get_transport()
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
546
        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.
547
        simple_copy_files(t, temp_transport)
548
        if not t.is_readonly():
549
            t.mkdir('copy_to_simple')
550
            t2 = t.clone('copy_to_simple')
551
            simple_copy_files(t, t2)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
552
553
554
        # Test that copying into a missing directory raises
555
        # NoSuchFile
556
        if t.is_readonly():
1530.1.21 by Robert Collins
Review feedback fixes.
557
            self.build_tree(['e/', 'e/f'])
1530.1.3 by Robert Collins
transport implementations now tested consistently.
558
        else:
559
            t.mkdir('e')
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
560
            t.put_bytes('e/f', 'contents of e')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
561
        self.assertRaises(NoSuchFile, t.copy_to, ['e/f'], temp_transport)
562
        temp_transport.mkdir('e')
563
        t.copy_to(['e/f'], temp_transport)
564
565
        del temp_transport
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
566
        temp_transport = MemoryTransport('memory:///')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
567
568
        files = ['a', 'b', 'c', 'd']
569
        t.copy_to(iter(files), temp_transport)
570
        for f in files:
571
            self.check_transport_contents(temp_transport.get(f).read(),
572
                                          t, f)
573
        del temp_transport
574
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
575
        for mode in (0666, 0644, 0600, 0400):
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
576
            temp_transport = MemoryTransport("memory:///")
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
577
            t.copy_to(files, temp_transport, mode=mode)
578
            for f in files:
1530.1.21 by Robert Collins
Review feedback fixes.
579
                self.assertTransportMode(temp_transport, f, mode)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
580
1530.1.3 by Robert Collins
transport implementations now tested consistently.
581
    def test_append(self):
582
        t = self.get_transport()
583
584
        if t.is_readonly():
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
585
            return
586
        t.put_bytes('a', 'diff\ncontents for\na\n')
587
        t.put_bytes('b', 'contents\nfor b\n')
588
1955.3.29 by John Arbash Meinel
Use applyDeprecated instead of callDeprecated
589
        self.assertEqual(20, self.applyDeprecated(zero_eleven,
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
590
            t.append, 'a', StringIO('add\nsome\nmore\ncontents\n')))
591
592
        self.check_transport_contents(
593
            'diff\ncontents for\na\nadd\nsome\nmore\ncontents\n',
594
            t, 'a')
595
596
        # And we can create new files, too
1955.3.29 by John Arbash Meinel
Use applyDeprecated instead of callDeprecated
597
        self.assertEqual(0, self.applyDeprecated(zero_eleven,
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
598
            t.append, 'c', StringIO('some text\nfor a missing file\n')))
599
        self.check_transport_contents('some text\nfor a missing file\n',
600
                                      t, 'c')
601
    def test_append_file(self):
602
        t = self.get_transport()
603
604
        if t.is_readonly():
1530.1.3 by Robert Collins
transport implementations now tested consistently.
605
            self.assertRaises(TransportNotPossible,
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
606
                    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
607
            return
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
608
        t.put_bytes('a', 'diff\ncontents for\na\n')
609
        t.put_bytes('b', 'contents\nfor b\n')
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
610
611
        self.assertEqual(20,
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
612
            t.append_file('a', StringIO('add\nsome\nmore\ncontents\n')))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
613
614
        self.check_transport_contents(
615
            'diff\ncontents for\na\nadd\nsome\nmore\ncontents\n',
616
            t, 'a')
617
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
618
        # a file with no parent should fail..
619
        self.assertRaises(NoSuchFile,
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
620
                          t.append_file, 'missing/path', StringIO('content'))
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
621
622
        # And we can create new files, too
623
        self.assertEqual(0,
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
624
            t.append_file('c', StringIO('some text\nfor a missing file\n')))
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
625
        self.check_transport_contents('some text\nfor a missing file\n',
626
                                      t, 'c')
627
628
    def test_append_bytes(self):
629
        t = self.get_transport()
630
631
        if t.is_readonly():
632
            self.assertRaises(TransportNotPossible,
633
                    t.append_bytes, 'a', 'add\nsome\nmore\ncontents\n')
634
            return
635
636
        self.assertEqual(0, t.append_bytes('a', 'diff\ncontents for\na\n'))
637
        self.assertEqual(0, t.append_bytes('b', 'contents\nfor b\n'))
638
639
        self.assertEqual(20,
640
            t.append_bytes('a', 'add\nsome\nmore\ncontents\n'))
641
642
        self.check_transport_contents(
643
            'diff\ncontents for\na\nadd\nsome\nmore\ncontents\n',
644
            t, 'a')
645
646
        # a file with no parent should fail..
647
        self.assertRaises(NoSuchFile,
648
                          t.append_bytes, 'missing/path', 'content')
649
650
    def test_append_multi(self):
651
        t = self.get_transport()
652
653
        if t.is_readonly():
654
            return
655
        t.put_bytes('a', 'diff\ncontents for\na\n'
656
                         'add\nsome\nmore\ncontents\n')
657
        t.put_bytes('b', 'contents\nfor b\n')
658
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
659
        self.assertEqual((43, 15),
660
            t.append_multi([('a', StringIO('and\nthen\nsome\nmore\n')),
661
                            ('b', StringIO('some\nmore\nfor\nb\n'))]))
662
1530.1.3 by Robert Collins
transport implementations now tested consistently.
663
        self.check_transport_contents(
664
            'diff\ncontents for\na\n'
665
            'add\nsome\nmore\ncontents\n'
666
            'and\nthen\nsome\nmore\n',
667
            t, 'a')
668
        self.check_transport_contents(
669
                'contents\nfor b\n'
670
                'some\nmore\nfor\nb\n',
671
                t, 'b')
672
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
673
        self.assertEqual((62, 31),
674
            t.append_multi(iter([('a', StringIO('a little bit more\n')),
675
                                 ('b', StringIO('from an iterator\n'))])))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
676
        self.check_transport_contents(
677
            'diff\ncontents for\na\n'
678
            'add\nsome\nmore\ncontents\n'
679
            'and\nthen\nsome\nmore\n'
680
            'a little bit more\n',
681
            t, 'a')
682
        self.check_transport_contents(
683
                'contents\nfor b\n'
684
                'some\nmore\nfor\nb\n'
685
                'from an iterator\n',
686
                t, 'b')
687
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
688
        self.assertEqual((80, 0),
689
            t.append_multi([('a', StringIO('some text in a\n')),
690
                            ('d', StringIO('missing file r\n'))]))
691
1530.1.3 by Robert Collins
transport implementations now tested consistently.
692
        self.check_transport_contents(
693
            'diff\ncontents for\na\n'
694
            'add\nsome\nmore\ncontents\n'
695
            'and\nthen\nsome\nmore\n'
696
            'a little bit more\n'
697
            'some text in a\n',
698
            t, 'a')
699
        self.check_transport_contents('missing file r\n', t, 'd')
700
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
701
    def test_append_file_mode(self):
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
702
        """Check that append accepts a mode parameter"""
1666.1.6 by Robert Collins
Make knit the default format.
703
        # check append accepts a mode
704
        t = self.get_transport()
705
        if t.is_readonly():
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
706
            self.assertRaises(TransportNotPossible,
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
707
                t.append_file, 'f', StringIO('f'), mode=None)
1666.1.6 by Robert Collins
Make knit the default format.
708
            return
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
709
        t.append_file('f', StringIO('f'), mode=None)
1666.1.6 by Robert Collins
Make knit the default format.
710
        
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
711
    def test_append_bytes_mode(self):
712
        # check append_bytes accepts a mode
713
        t = self.get_transport()
714
        if t.is_readonly():
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
715
            self.assertRaises(TransportNotPossible,
716
                t.append_bytes, 'f', 'f', mode=None)
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
717
            return
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
718
        t.append_bytes('f', 'f', mode=None)
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
719
        
1530.1.3 by Robert Collins
transport implementations now tested consistently.
720
    def test_delete(self):
721
        # TODO: Test Transport.delete
722
        t = self.get_transport()
723
724
        # Not much to do with a readonly transport
725
        if t.is_readonly():
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
726
            self.assertRaises(TransportNotPossible, t.delete, 'missing')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
727
            return
728
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
729
        t.put_bytes('a', 'a little bit of text\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
730
        self.failUnless(t.has('a'))
731
        t.delete('a')
732
        self.failIf(t.has('a'))
733
734
        self.assertRaises(NoSuchFile, t.delete, 'a')
735
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
736
        t.put_bytes('a', 'a text\n')
737
        t.put_bytes('b', 'b text\n')
738
        t.put_bytes('c', 'c text\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
739
        self.assertEqual([True, True, True],
740
                list(t.has_multi(['a', 'b', 'c'])))
741
        t.delete_multi(['a', 'c'])
742
        self.assertEqual([False, True, False],
743
                list(t.has_multi(['a', 'b', 'c'])))
744
        self.failIf(t.has('a'))
745
        self.failUnless(t.has('b'))
746
        self.failIf(t.has('c'))
747
748
        self.assertRaises(NoSuchFile,
749
                t.delete_multi, ['a', 'b', 'c'])
750
751
        self.assertRaises(NoSuchFile,
752
                t.delete_multi, iter(['a', 'b', 'c']))
753
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
754
        t.put_bytes('a', 'another a text\n')
755
        t.put_bytes('c', 'another c text\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
756
        t.delete_multi(iter(['a', 'b', 'c']))
757
758
        # We should have deleted everything
759
        # SftpServer creates control files in the
760
        # working directory, so we can just do a
761
        # plain "listdir".
762
        # self.assertEqual([], os.listdir('.'))
763
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
764
    def test_rmdir(self):
765
        t = self.get_transport()
766
        # Not much to do with a readonly transport
767
        if t.is_readonly():
768
            self.assertRaises(TransportNotPossible, t.rmdir, 'missing')
769
            return
770
        t.mkdir('adir')
771
        t.mkdir('adir/bdir')
772
        t.rmdir('adir/bdir')
1948.3.12 by Vincent LADEUIL
Fix Aaron's third review remarks.
773
        # ftp may not be able to raise NoSuchFile for lack of
774
        # details when failing
775
        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.
776
        t.rmdir('adir')
1948.3.12 by Vincent LADEUIL
Fix Aaron's third review remarks.
777
        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.
778
1553.5.10 by Martin Pool
New DirectoryNotEmpty exception, and raise this from local and memory
779
    def test_rmdir_not_empty(self):
780
        """Deleting a non-empty directory raises an exception
781
        
782
        sftp (and possibly others) don't give us a specific "directory not
783
        empty" exception -- we can just see that the operation failed.
784
        """
785
        t = self.get_transport()
786
        if t.is_readonly():
787
            return
788
        t.mkdir('adir')
789
        t.mkdir('adir/bdir')
790
        self.assertRaises(PathError, t.rmdir, 'adir')
791
2338.5.1 by Andrew Bennetts
Fix bug in MemoryTransport.rmdir.
792
    def test_rmdir_empty_but_similar_prefix(self):
793
        """rmdir does not get confused by sibling paths.
794
        
795
        A naive implementation of MemoryTransport would refuse to rmdir
796
        ".bzr/branch" if there is a ".bzr/branch-format" directory, because it
797
        uses "path.startswith(dir)" on all file paths to determine if directory
798
        is empty.
799
        """
800
        t = self.get_transport()
801
        if t.is_readonly():
802
            return
803
        t.mkdir('foo')
804
        t.put_bytes('foo-bar', '')
805
        t.mkdir('foo-baz')
806
        t.rmdir('foo')
807
        self.assertRaises((NoSuchFile, PathError), t.rmdir, 'foo')
808
        self.failUnless(t.has('foo-bar'))
809
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
810
    def test_rename_dir_succeeds(self):
811
        t = self.get_transport()
812
        if t.is_readonly():
813
            raise TestSkipped("transport is readonly")
814
        t.mkdir('adir')
815
        t.mkdir('adir/asubdir')
816
        t.rename('adir', 'bdir')
817
        self.assertTrue(t.has('bdir/asubdir'))
818
        self.assertFalse(t.has('adir'))
819
820
    def test_rename_dir_nonempty(self):
821
        """Attempting to replace a nonemtpy directory should fail"""
822
        t = self.get_transport()
823
        if t.is_readonly():
824
            raise TestSkipped("transport is readonly")
825
        t.mkdir('adir')
826
        t.mkdir('adir/asubdir')
827
        t.mkdir('bdir')
828
        t.mkdir('bdir/bsubdir')
1910.7.17 by Andrew Bennetts
Various cosmetic changes.
829
        # any kind of PathError would be OK, though we normally expect
830
        # DirectoryNotEmpty
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
831
        self.assertRaises(PathError, t.rename, 'bdir', 'adir')
832
        # nothing was changed so it should still be as before
833
        self.assertTrue(t.has('bdir/bsubdir'))
834
        self.assertFalse(t.has('adir/bdir'))
835
        self.assertFalse(t.has('adir/bsubdir'))
836
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
837
    def test_delete_tree(self):
838
        t = self.get_transport()
839
840
        # Not much to do with a readonly transport
841
        if t.is_readonly():
842
            self.assertRaises(TransportNotPossible, t.delete_tree, 'missing')
843
            return
844
845
        # and does it like listing ?
846
        t.mkdir('adir')
847
        try:
848
            t.delete_tree('adir')
849
        except TransportNotPossible:
850
            # ok, this transport does not support delete_tree
851
            return
852
        
853
        # did it delete that trivial case?
854
        self.assertRaises(NoSuchFile, t.stat, 'adir')
855
856
        self.build_tree(['adir/',
857
                         'adir/file', 
858
                         'adir/subdir/', 
859
                         'adir/subdir/file', 
860
                         'adir/subdir2/',
861
                         'adir/subdir2/file',
862
                         ], transport=t)
863
864
        t.delete_tree('adir')
865
        # adir should be gone now.
866
        self.assertRaises(NoSuchFile, t.stat, 'adir')
867
1530.1.3 by Robert Collins
transport implementations now tested consistently.
868
    def test_move(self):
869
        t = self.get_transport()
870
871
        if t.is_readonly():
872
            return
873
874
        # TODO: I would like to use os.listdir() to
875
        # make sure there are no extra files, but SftpServer
876
        # creates control files in the working directory
877
        # perhaps all of this could be done in a subdirectory
878
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
879
        t.put_bytes('a', 'a first file\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
880
        self.assertEquals([True, False], list(t.has_multi(['a', 'b'])))
881
882
        t.move('a', 'b')
883
        self.failUnless(t.has('b'))
884
        self.failIf(t.has('a'))
885
886
        self.check_transport_contents('a first file\n', t, 'b')
887
        self.assertEquals([False, True], list(t.has_multi(['a', 'b'])))
888
889
        # Overwrite a file
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
890
        t.put_bytes('c', 'c this file\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
891
        t.move('c', 'b')
892
        self.failIf(t.has('c'))
893
        self.check_transport_contents('c this file\n', t, 'b')
894
895
        # TODO: Try to write a test for atomicity
896
        # TODO: Test moving into a non-existant subdirectory
897
        # TODO: Test Transport.move_multi
898
899
    def test_copy(self):
900
        t = self.get_transport()
901
902
        if t.is_readonly():
903
            return
904
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
905
        t.put_bytes('a', 'a file\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
906
        t.copy('a', 'b')
907
        self.check_transport_contents('a file\n', t, 'b')
908
909
        self.assertRaises(NoSuchFile, t.copy, 'c', 'd')
910
        os.mkdir('c')
911
        # What should the assert be if you try to copy a
912
        # file over a directory?
913
        #self.assertRaises(Something, t.copy, 'a', 'c')
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
914
        t.put_bytes('d', 'text in d\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
915
        t.copy('d', 'b')
916
        self.check_transport_contents('text in d\n', t, 'b')
917
918
        # TODO: test copy_multi
919
920
    def test_connection_error(self):
1910.7.17 by Andrew Bennetts
Various cosmetic changes.
921
        """ConnectionError is raised when connection is impossible.
922
        
923
        The error may be raised from either the constructor or the first
924
        operation on the transport.
925
        """
1530.1.9 by Robert Collins
Test bogus urls with http in the new infrastructure.
926
        try:
927
            url = self._server.get_bogus_url()
928
        except NotImplementedError:
929
            raise TestSkipped("Transport %s has no bogus URL support." %
930
                              self._server.__class__)
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
931
        # This should be:  but SSH still connects on construction. No COOKIE!
932
        # self.assertRaises((ConnectionError, NoSuchFile), t.get, '.bzr/branch')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
933
        try:
1711.2.42 by John Arbash Meinel
enable bogus_url support for SFTP tests
934
            t = bzrlib.transport.get_transport(url)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
935
            t.get('.bzr/branch')
936
        except (ConnectionError, NoSuchFile), e:
937
            pass
938
        except (Exception), e:
1786.1.27 by John Arbash Meinel
Fix up the http transports so that tests pass with the new configuration.
939
            self.fail('Wrong exception thrown (%s.%s): %s' 
940
                        % (e.__class__.__module__, e.__class__.__name__, e))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
941
        else:
1707.3.11 by John Arbash Meinel
fixing more tests.
942
            self.fail('Did not get the expected ConnectionError or NoSuchFile.')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
943
944
    def test_stat(self):
945
        # TODO: Test stat, just try once, and if it throws, stop testing
946
        from stat import S_ISDIR, S_ISREG
947
948
        t = self.get_transport()
949
950
        try:
951
            st = t.stat('.')
952
        except TransportNotPossible, e:
953
            # This transport cannot stat
954
            return
955
956
        paths = ['a', 'b/', 'b/c', 'b/d/', 'b/d/e']
957
        sizes = [14, 0, 16, 0, 18] 
1551.2.39 by abentley
Fix line endings in tests
958
        self.build_tree(paths, transport=t, line_endings='binary')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
959
960
        for path, size in zip(paths, sizes):
961
            st = t.stat(path)
962
            if path.endswith('/'):
963
                self.failUnless(S_ISDIR(st.st_mode))
964
                # directory sizes are meaningless
965
            else:
966
                self.failUnless(S_ISREG(st.st_mode))
967
                self.assertEqual(size, st.st_size)
968
969
        remote_stats = list(t.stat_multi(paths))
970
        remote_iter_stats = list(t.stat_multi(iter(paths)))
971
972
        self.assertRaises(NoSuchFile, t.stat, 'q')
973
        self.assertRaises(NoSuchFile, t.stat, 'b/a')
974
975
        self.assertListRaises(NoSuchFile, t.stat_multi, ['a', 'c', 'd'])
976
        self.assertListRaises(NoSuchFile, t.stat_multi, iter(['a', 'c', 'd']))
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
977
        self.build_tree(['subdir/', 'subdir/file'], transport=t)
978
        subdir = t.clone('subdir')
979
        subdir.stat('./file')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
980
        subdir.stat('.')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
981
982
    def test_list_dir(self):
983
        # TODO: Test list_dir, just try once, and if it throws, stop testing
984
        t = self.get_transport()
985
        
986
        if not t.listable():
987
            self.assertRaises(TransportNotPossible, t.list_dir, '.')
988
            return
989
990
        def sorted_list(d):
991
            l = list(t.list_dir(d))
992
            l.sort()
993
            return l
994
1910.7.1 by Andrew Bennetts
Make sure list_dir always returns url-escaped names.
995
        self.assertEqual([], sorted_list('.'))
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
996
        # c2 is precisely one letter longer than c here to test that
997
        # suffixing is not confused.
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
998
        # a%25b checks that quoting is done consistently across transports
999
        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
1000
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
1001
        if not t.is_readonly():
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
1002
            self.build_tree(tree_names, transport=t)
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
1003
        else:
2120.3.1 by John Arbash Meinel
Fix MemoryTransport.list_dir() implementation, and update tests
1004
            self.build_tree(tree_names)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1005
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
1006
        self.assertEqual(
1959.2.3 by John Arbash Meinel
Remove some unicode string notations
1007
            ['a', 'a%2525b', 'b', 'c', 'c2'], sorted_list('.'))
1910.7.1 by Andrew Bennetts
Make sure list_dir always returns url-escaped names.
1008
        self.assertEqual(['d', 'e'], sorted_list('c'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1009
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
1010
        if not t.is_readonly():
1011
            t.delete('c/d')
1012
            t.delete('b')
1013
        else:
2120.3.1 by John Arbash Meinel
Fix MemoryTransport.list_dir() implementation, and update tests
1014
            os.unlink('c/d')
1015
            os.unlink('b')
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
1016
            
1959.2.3 by John Arbash Meinel
Remove some unicode string notations
1017
        self.assertEqual(['a', 'a%2525b', 'c', 'c2'], sorted_list('.'))
1910.7.1 by Andrew Bennetts
Make sure list_dir always returns url-escaped names.
1018
        self.assertEqual(['e'], sorted_list('c'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1019
1662.1.12 by Martin Pool
Translate unknown sftp errors to PathError, no NoSuchFile
1020
        self.assertListRaises(PathError, t.list_dir, 'q')
1021
        self.assertListRaises(PathError, t.list_dir, 'c/f')
1022
        self.assertListRaises(PathError, t.list_dir, 'a')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1023
1910.7.1 by Andrew Bennetts
Make sure list_dir always returns url-escaped names.
1024
    def test_list_dir_result_is_url_escaped(self):
1025
        t = self.get_transport()
1026
        if not t.listable():
1027
            raise TestSkipped("transport not listable")
1028
1029
        if not t.is_readonly():
1030
            self.build_tree(['a/', 'a/%'], transport=t)
1031
        else:
1032
            self.build_tree(['a/', 'a/%'])
1033
        
1910.7.2 by Andrew Bennetts
Also assert that list_dir returns plain str objects.
1034
        names = list(t.list_dir('a'))
1035
        self.assertEqual(['%25'], names)
1036
        self.assertIsInstance(names[0], str)
1910.7.1 by Andrew Bennetts
Make sure list_dir always returns url-escaped names.
1037
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1038
    def test_clone(self):
1039
        # TODO: Test that clone moves up and down the filesystem
1040
        t1 = self.get_transport()
1041
1042
        self.build_tree(['a', 'b/', 'b/c'], transport=t1)
1043
1044
        self.failUnless(t1.has('a'))
1045
        self.failUnless(t1.has('b/c'))
1046
        self.failIf(t1.has('c'))
1047
1048
        t2 = t1.clone('b')
1049
        self.assertEqual(t1.base + 'b/', t2.base)
1050
1051
        self.failUnless(t2.has('c'))
1052
        self.failIf(t2.has('a'))
1053
1054
        t3 = t2.clone('..')
1055
        self.failUnless(t3.has('a'))
1056
        self.failIf(t3.has('c'))
1057
1058
        self.failIf(t1.has('b/d'))
1059
        self.failIf(t2.has('d'))
1060
        self.failIf(t3.has('b/d'))
1061
1062
        if t1.is_readonly():
1063
            open('b/d', 'wb').write('newfile\n')
1064
        else:
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
1065
            t2.put_bytes('d', 'newfile\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1066
1067
        self.failUnless(t1.has('b/d'))
1068
        self.failUnless(t2.has('d'))
1069
        self.failUnless(t3.has('b/d'))
1070
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
1071
    def test_clone_to_root(self):
1072
        orig_transport = self.get_transport()
1073
        # Repeatedly go up to a parent directory until we're at the root
1074
        # directory of this transport
1075
        root_transport = orig_transport
1986.1.10 by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports.
1076
        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 //
1077
        # 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.
1078
        # growing less, except at the top
1079
        self.assertTrue(len(new_transport.base) < len(root_transport.base)
1080
            or new_transport.base == root_transport.base)
1081
        while new_transport.base != root_transport.base:
1082
            root_transport = new_transport
1083
            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 //
1084
            # 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.
1085
            # growing less, except at the top
1086
            self.assertTrue(len(new_transport.base) < len(root_transport.base)
1087
                or new_transport.base == root_transport.base)
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
1088
1089
        # Cloning to "/" should take us to exactly the same location.
1090
        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.
1091
        # the abspath of "/" from the original transport should be the same
1092
        # as the base at the root:
1093
        self.assertEqual(orig_transport.abspath("/"), root_transport.base)
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
1094
1910.15.5 by Andrew Bennetts
Transport behaviour at the root of the URL is now defined and tested.
1095
        # At the root, the URL must still end with / as its a directory
1096
        self.assertEqual(root_transport.base[-1], '/')
1097
1098
    def test_clone_from_root(self):
1099
        """At the root, cloning to a simple dir should just do string append."""
1100
        orig_transport = self.get_transport()
1101
        root_transport = orig_transport.clone('/')
1102
        self.assertEqual(root_transport.base + '.bzr/',
1103
            root_transport.clone('.bzr').base)
1104
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
1105
    def test_base_url(self):
1106
        t = self.get_transport()
1107
        self.assertEqual('/', t.base[-1])
1108
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1109
    def test_relpath(self):
1110
        t = self.get_transport()
1111
        self.assertEqual('', t.relpath(t.base))
1112
        # base ends with /
1113
        self.assertEqual('', t.relpath(t.base[:-1]))
1114
        # subdirs which dont exist should still give relpaths.
1115
        self.assertEqual('foo', t.relpath(t.base + 'foo'))
1116
        # trailing slash should be the same.
1117
        self.assertEqual('foo', t.relpath(t.base + 'foo/'))
1118
1636.1.1 by Robert Collins
Fix calling relpath() and abspath() on transports at their root.
1119
    def test_relpath_at_root(self):
1120
        t = self.get_transport()
1121
        # clone all the way to the top
1122
        new_transport = t.clone('..')
1123
        while new_transport.base != t.base:
1124
            t = new_transport
1125
            new_transport = t.clone('..')
1126
        # we must be able to get a relpath below the root
1127
        self.assertEqual('', t.relpath(t.base))
1128
        # and a deeper one should work too
1129
        self.assertEqual('foo/bar', t.relpath(t.base + 'foo/bar'))
1130
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1131
    def test_abspath(self):
1132
        # smoke test for abspath. Corner cases for backends like unix fs's
1133
        # that have aliasing problems like symlinks should go in backend
1134
        # specific test cases.
1135
        transport = self.get_transport()
1540.3.24 by Martin Pool
Add new protocol 'http+pycurl' that always uses PyCurl.
1136
        
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1137
        self.assertEqual(transport.base + 'relpath',
1138
                         transport.abspath('relpath'))
1139
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
1140
        # This should work without raising an error.
1141
        transport.abspath("/")
1142
1143
        # the abspath of "/" and "/foo/.." should result in the same location
1144
        self.assertEqual(transport.abspath("/"), transport.abspath("/foo/.."))
1145
2070.3.1 by Andrew Bennetts
Fix memory_transport.abspath('/foo')
1146
        self.assertEqual(transport.clone("/").abspath('foo'),
1147
                         transport.abspath("/foo"))
1148
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
1149
    def test_local_abspath(self):
1150
        transport = self.get_transport()
1151
        try:
1152
            p = transport.local_abspath('.')
2400.2.1 by Robert Collins
Split out the improvement to Transport.local_abspath to raise NotLocalURL from the hpss-faster-copy branch. (Martin Pool, Ian Clatworthy)
1153
        except NotLocalUrl:
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
1154
            pass # This is not a local transport
1155
        else:
1156
            self.assertEqual(getcwd(), p)
1157
1636.1.1 by Robert Collins
Fix calling relpath() and abspath() on transports at their root.
1158
    def test_abspath_at_root(self):
1159
        t = self.get_transport()
1160
        # clone all the way to the top
1161
        new_transport = t.clone('..')
1162
        while new_transport.base != t.base:
1163
            t = new_transport
1164
            new_transport = t.clone('..')
1165
        # we must be able to get a abspath of the root when we ask for
1166
        # t.abspath('..') - this due to our choice that clone('..')
1167
        # should return the root from the root, combined with the desire that
1168
        # the url from clone('..') and from abspath('..') should be the same.
1169
        self.assertEqual(t.base, t.abspath('..'))
1170
        # '' should give us the root
1171
        self.assertEqual(t.base, t.abspath(''))
1172
        # and a path should append to the url
1173
        self.assertEqual(t.base + 'foo', t.abspath('foo'))
1174
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1175
    def test_iter_files_recursive(self):
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
1176
        transport = self.get_transport()
1177
        if not transport.listable():
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
1178
            self.assertRaises(TransportNotPossible,
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
1179
                              transport.iter_files_recursive)
1180
            return
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
1181
        self.build_tree(['isolated/',
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
1182
                         'isolated/dir/',
1183
                         'isolated/dir/foo',
1184
                         'isolated/dir/bar',
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
1185
                         'isolated/dir/b%25z', # make sure quoting is correct
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
1186
                         'isolated/bar'],
1187
                        transport=transport)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1188
        paths = set(transport.iter_files_recursive())
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
1189
        # nb the directories are not converted
1190
        self.assertEqual(paths,
1191
                    set(['isolated/dir/foo',
1192
                         'isolated/dir/bar',
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
1193
                         'isolated/dir/b%2525z',
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
1194
                         'isolated/bar']))
1195
        sub_transport = transport.clone('isolated')
1196
        paths = set(sub_transport.iter_files_recursive())
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
1197
        self.assertEqual(paths,
1198
            set(['dir/foo', 'dir/bar', 'dir/b%2525z', 'bar']))
1199
1200
    def test_copy_tree(self):
1201
        # TODO: test file contents and permissions are preserved. This test was
1202
        # added just to ensure that quoting was handled correctly.
1203
        # -- David Allouche 2006-08-11
1204
        transport = self.get_transport()
1205
        if not transport.listable():
1206
            self.assertRaises(TransportNotPossible,
1207
                              transport.iter_files_recursive)
1208
            return
1209
        if transport.is_readonly():
1210
            return
1211
        self.build_tree(['from/',
1212
                         'from/dir/',
1213
                         'from/dir/foo',
1214
                         'from/dir/bar',
1215
                         'from/dir/b%25z', # make sure quoting is correct
1216
                         'from/bar'],
1217
                        transport=transport)
1218
        transport.copy_tree('from', 'to')
1219
        paths = set(transport.iter_files_recursive())
1220
        self.assertEqual(paths,
1221
                    set(['from/dir/foo',
1222
                         'from/dir/bar',
1223
                         'from/dir/b%2525z',
1224
                         'from/bar',
1225
                         'to/dir/foo',
1226
                         'to/dir/bar',
1227
                         'to/dir/b%2525z',
1228
                         'to/bar',]))
1185.85.76 by John Arbash Meinel
Adding an InvalidURL so transports can report they expect utf-8 quoted paths. Updated tests
1229
1230
    def test_unicode_paths(self):
1685.1.57 by Martin Pool
[broken] Skip unicode blackbox tests if not supported by filesystem
1231
        """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
1232
        t = self.get_transport()
1233
1711.7.36 by John Arbash Meinel
Use different filenames to avoid path collisions on win32 w/ FAT32
1234
        # With FAT32 and certain encodings on win32
1235
        # '\xe5' and '\xe4' actually map to the same file
1236
        # adding a suffix kicks in the 'preserving but insensitive'
1237
        # route, and maintains the right files
1238
        files = [u'\xe5.1', # a w/ circle iso-8859-1
1239
                 u'\xe4.2', # a w/ dots iso-8859-1
1185.85.76 by John Arbash Meinel
Adding an InvalidURL so transports can report they expect utf-8 quoted paths. Updated tests
1240
                 u'\u017d', # Z with umlat iso-8859-2
1241
                 u'\u062c', # Arabic j
1242
                 u'\u0410', # Russian A
1243
                 u'\u65e5', # Kanji person
1244
                ]
1245
1685.1.72 by Wouter van Heyst
StubSFTPServer should use bytestreams rather than unicode
1246
        try:
1711.4.13 by John Arbash Meinel
Use line_endings='binary' for win32
1247
            self.build_tree(files, transport=t, line_endings='binary')
1685.1.72 by Wouter van Heyst
StubSFTPServer should use bytestreams rather than unicode
1248
        except UnicodeError:
1249
            raise TestSkipped("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
1250
1251
        # A plain unicode string is not a valid url
1252
        for fname in files:
1253
            self.assertRaises(InvalidURL, t.get, fname)
1254
1255
        for fname in files:
1256
            fname_utf8 = fname.encode('utf-8')
1257
            contents = 'contents of %s\n' % (fname_utf8,)
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
1258
            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
1259
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1260
    def test_connect_twice_is_same_content(self):
1261
        # check that our server (whatever it is) is accessable reliably
1262
        # via get_transport and multiple connections share content.
1263
        transport = self.get_transport()
1264
        if transport.is_readonly():
1265
            return
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
1266
        transport.put_bytes('foo', 'bar')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1267
        transport2 = self.get_transport()
1268
        self.check_transport_contents('bar', transport2, 'foo')
1269
        # its base should be usable.
1270
        transport2 = bzrlib.transport.get_transport(transport.base)
1271
        self.check_transport_contents('bar', transport2, 'foo')
1272
1273
        # now opening at a relative url should give use a sane result:
1274
        transport.mkdir('newdir')
1275
        transport2 = bzrlib.transport.get_transport(transport.base + "newdir")
1276
        transport2 = transport2.clone('..')
1277
        self.check_transport_contents('bar', transport2, 'foo')
1278
1279
    def test_lock_write(self):
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1280
        """Test transport-level write locks.
1281
1282
        These are deprecated and transports may decline to support them.
1283
        """
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1284
        transport = self.get_transport()
1285
        if transport.is_readonly():
1286
            self.assertRaises(TransportNotPossible, transport.lock_write, 'foo')
1287
            return
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
1288
        transport.put_bytes('lock', '')
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1289
        try:
1290
            lock = transport.lock_write('lock')
1752.3.6 by Andrew Bennetts
Merge from test-tweaks
1291
        except TransportNotPossible:
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1292
            return
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1293
        # TODO make this consistent on all platforms:
1294
        # self.assertRaises(LockError, transport.lock_write, 'lock')
1295
        lock.unlock()
1296
1297
    def test_lock_read(self):
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1298
        """Test transport-level read locks.
1299
1300
        These are deprecated and transports may decline to support them.
1301
        """
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1302
        transport = self.get_transport()
1303
        if transport.is_readonly():
1304
            file('lock', 'w').close()
1305
        else:
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
1306
            transport.put_bytes('lock', '')
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1307
        try:
1308
            lock = transport.lock_read('lock')
1752.3.6 by Andrew Bennetts
Merge from test-tweaks
1309
        except TransportNotPossible:
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1310
            return
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1311
        # TODO make this consistent on all platforms:
1312
        # self.assertRaises(LockError, transport.lock_read, 'lock')
1313
        lock.unlock()
1185.85.80 by John Arbash Meinel
[merge] jam-integration 1527, including branch-formats, help text, misc bug fixes.
1314
1594.2.5 by Robert Collins
Readv patch from Johan Rydberg giving knits partial download support.
1315
    def test_readv(self):
1316
        transport = self.get_transport()
1317
        if transport.is_readonly():
1318
            file('a', 'w').write('0123456789')
1319
        else:
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
1320
            transport.put_bytes('a', '0123456789')
1185.85.76 by John Arbash Meinel
Adding an InvalidURL so transports can report they expect utf-8 quoted paths. Updated tests
1321
2004.1.22 by v.ladeuil+lp at free
Implements Range header handling for GET requests. Fix a test.
1322
        d = list(transport.readv('a', ((0, 1),)))
1323
        self.assertEqual(d[0], (0, '0'))
1324
1594.2.17 by Robert Collins
Better readv coalescing, now with test, and progress during knit index reading.
1325
        d = list(transport.readv('a', ((0, 1), (1, 1), (3, 2), (9, 1))))
1594.2.5 by Robert Collins
Readv patch from Johan Rydberg giving knits partial download support.
1326
        self.assertEqual(d[0], (0, '0'))
1594.2.17 by Robert Collins
Better readv coalescing, now with test, and progress during knit index reading.
1327
        self.assertEqual(d[1], (1, '1'))
1328
        self.assertEqual(d[2], (3, '34'))
1329
        self.assertEqual(d[3], (9, '9'))
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
1330
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
1331
    def test_readv_out_of_order(self):
1332
        transport = self.get_transport()
1333
        if transport.is_readonly():
1334
            file('a', 'w').write('0123456789')
1335
        else:
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
1336
            transport.put_bytes('a', '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
1337
1338
        d = list(transport.readv('a', ((1, 1), (9, 1), (0, 1), (3, 2))))
1339
        self.assertEqual(d[0], (1, '1'))
1340
        self.assertEqual(d[1], (9, '9'))
1341
        self.assertEqual(d[2], (0, '0'))
1342
        self.assertEqual(d[3], (3, '34'))
1752.2.40 by Andrew Bennetts
Merge from bzr.dev.
1343
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
1344
    def test_get_smart_medium(self):
1345
        """All transports must either give a smart medium, or know they can't.
1346
        """
1347
        transport = self.get_transport()
1348
        try:
2018.5.2 by Andrew Bennetts
Start splitting bzrlib/transport/smart.py into a package.
1349
            client_medium = transport.get_smart_medium()
1350
            self.assertIsInstance(client_medium, medium.SmartClientMedium)
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
1351
        except errors.NoSmartMedium:
1352
            # as long as we got it we're fine
1353
            pass
1354
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
1355
    def test_readv_short_read(self):
1356
        transport = self.get_transport()
1357
        if transport.is_readonly():
1358
            file('a', 'w').write('0123456789')
1359
        else:
1360
            transport.put_bytes('a', '01234567890')
1361
1362
        # This is intentionally reading off the end of the file
1363
        # 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 :)
1364
        self.assertListRaises((errors.ShortReadvError, errors.InvalidRange,
1365
                               # Can be raised by paramiko
1366
                               AssertionError),
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
1367
                              transport.readv, 'a', [(1,1), (8,10)])
1368
1369
        # This is trying to seek past the end of the file, it should
1370
        # 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 :)
1371
        self.assertListRaises((errors.ShortReadvError, errors.InvalidRange),
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
1372
                              transport.readv, 'a', [(12,2)])