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