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