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