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