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