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