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