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