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