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