/brz/remove-bazaar

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