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