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