/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,
1185.85.84 by John Arbash Meinel
[merge] bzr.dev 1573, lots of updates
33
                           LockError, 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
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
40
from bzrlib.transport import memory
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,
148
                          t.put, 'path/doesnt/exist/c', StringIO('contents'))
149
1955.3.1 by John Arbash Meinel
Add put_bytes() and a base-level implementation for it
150
    def test_put_bytes(self):
151
        t = self.get_transport()
152
153
        if t.is_readonly():
154
            self.assertRaises(TransportNotPossible,
155
                    t.put_bytes, 'a', 'some text for a\n')
156
            return
157
158
        t.put_bytes('a', 'some text for a\n')
159
        self.failUnless(t.has('a'))
160
        self.check_transport_contents('some text for a\n', t, 'a')
161
162
        # The contents should be overwritten
163
        t.put_bytes('a', 'new text for a\n')
164
        self.check_transport_contents('new text for a\n', t, 'a')
165
166
        self.assertRaises(NoSuchFile,
167
                          t.put_bytes, 'path/doesnt/exist/c', 'contents')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
168
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
169
    def test_put_bytes_non_atomic(self):
170
        t = self.get_transport()
171
172
        if t.is_readonly():
173
            self.assertRaises(TransportNotPossible,
174
                    t.put_bytes_non_atomic, 'a', 'some text for a\n')
175
            return
176
177
        self.failIf(t.has('a'))
178
        t.put_bytes_non_atomic('a', 'some text for a\n')
179
        self.failUnless(t.has('a'))
180
        self.check_transport_contents('some text for a\n', t, 'a')
181
        # Put also replaces contents
182
        t.put_bytes_non_atomic('a', 'new\ncontents for\na\n')
183
        self.check_transport_contents('new\ncontents for\na\n', t, 'a')
184
185
        # Make sure we can create another file
186
        t.put_bytes_non_atomic('d', 'contents for\nd\n')
187
        # And overwrite 'a' with empty contents
188
        t.put_bytes_non_atomic('a', '')
189
        self.check_transport_contents('contents for\nd\n', t, 'd')
190
        self.check_transport_contents('', t, 'a')
191
192
        self.assertRaises(NoSuchFile, t.put_bytes_non_atomic, 'no/such/path',
193
                                       'contents\n')
194
        # Now test the create_parent flag
195
        self.assertRaises(NoSuchFile, t.put_bytes_non_atomic, 'dir/a',
196
                                       'contents\n')
197
        self.failIf(t.has('dir/a'))
198
        t.put_bytes_non_atomic('dir/a', 'contents for dir/a\n',
199
                               create_parent_dir=True)
200
        self.check_transport_contents('contents for dir/a\n', t, 'dir/a')
201
        
202
        # But we still get NoSuchFile if we can't make the parent dir
203
        self.assertRaises(NoSuchFile, t.put_bytes_non_atomic, 'not/there/a',
204
                                       'contents\n',
205
                                       create_parent_dir=True)
206
207
    def test_put_bytes_permissions(self):
208
        t = self.get_transport()
209
210
        if t.is_readonly():
211
            return
212
        if not t._can_roundtrip_unix_modebits():
213
            # Can't roundtrip, so no need to run this test
214
            return
215
        t.put_bytes('mode644', 'test text\n', mode=0644)
216
        self.assertTransportMode(t, 'mode644', 0644)
217
        t.put_bytes('mode666', 'test text\n', mode=0666)
218
        self.assertTransportMode(t, 'mode666', 0666)
219
        t.put_bytes('mode600', 'test text\n', mode=0600)
220
        self.assertTransportMode(t, 'mode600', 0600)
221
        # Yes, you can put_bytes a file such that it becomes readonly
222
        t.put_bytes('mode400', 'test text\n', mode=0400)
223
        self.assertTransportMode(t, 'mode400', 0400)
224
225
        # The default permissions should be based on the current umask
226
        umask = osutils.get_umask()
227
        t.put_bytes('nomode', 'test text\n', mode=None)
228
        self.assertTransportMode(t, 'nomode', 0666 & ~umask)
229
        
230
    def test_put_bytes_non_atomic_permissions(self):
231
        t = self.get_transport()
232
233
        if t.is_readonly():
234
            return
235
        if not t._can_roundtrip_unix_modebits():
236
            # Can't roundtrip, so no need to run this test
237
            return
238
        t.put_bytes_non_atomic('mode644', 'test text\n', mode=0644)
239
        self.assertTransportMode(t, 'mode644', 0644)
240
        t.put_bytes_non_atomic('mode666', 'test text\n', mode=0666)
241
        self.assertTransportMode(t, 'mode666', 0666)
242
        t.put_bytes_non_atomic('mode600', 'test text\n', mode=0600)
243
        self.assertTransportMode(t, 'mode600', 0600)
244
        t.put_bytes_non_atomic('mode400', 'test text\n', mode=0400)
245
        self.assertTransportMode(t, 'mode400', 0400)
246
247
        # The default permissions should be based on the current umask
248
        umask = osutils.get_umask()
249
        t.put_bytes_non_atomic('nomode', 'test text\n', mode=None)
250
        self.assertTransportMode(t, 'nomode', 0666 & ~umask)
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
251
252
        # We should also be able to set the mode for a parent directory
253
        # when it is created
254
        t.put_bytes_non_atomic('dir700/mode664', 'test text\n', mode=0664,
255
                               dir_mode=0700, create_parent_dir=True)
256
        self.assertTransportMode(t, 'dir700', 0700)
257
        t.put_bytes_non_atomic('dir770/mode664', 'test text\n', mode=0664,
258
                               dir_mode=0770, create_parent_dir=True)
259
        self.assertTransportMode(t, 'dir770', 0770)
260
        t.put_bytes_non_atomic('dir777/mode664', 'test text\n', mode=0664,
261
                               dir_mode=0777, create_parent_dir=True)
262
        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
263
        
264
    def test_put_file(self):
265
        t = self.get_transport()
266
267
        if t.is_readonly():
268
            self.assertRaises(TransportNotPossible,
269
                    t.put_file, 'a', StringIO('some text for a\n'))
270
            return
271
272
        t.put_file('a', StringIO('some text for a\n'))
273
        self.failUnless(t.has('a'))
274
        self.check_transport_contents('some text for a\n', t, 'a')
275
        # Put also replaces contents
276
        t.put_file('a', StringIO('new\ncontents for\na\n'))
277
        self.check_transport_contents('new\ncontents for\na\n', t, 'a')
278
        self.assertRaises(NoSuchFile,
279
                          t.put_file, 'path/doesnt/exist/c',
280
                              StringIO('contents'))
281
282
    def test_put_file_non_atomic(self):
283
        t = self.get_transport()
284
285
        if t.is_readonly():
286
            self.assertRaises(TransportNotPossible,
287
                    t.put_file_non_atomic, 'a', StringIO('some text for a\n'))
288
            return
289
290
        self.failIf(t.has('a'))
291
        t.put_file_non_atomic('a', StringIO('some text for a\n'))
292
        self.failUnless(t.has('a'))
293
        self.check_transport_contents('some text for a\n', t, 'a')
294
        # Put also replaces contents
295
        t.put_file_non_atomic('a', StringIO('new\ncontents for\na\n'))
296
        self.check_transport_contents('new\ncontents for\na\n', t, 'a')
297
298
        # Make sure we can create another file
299
        t.put_file_non_atomic('d', StringIO('contents for\nd\n'))
300
        # And overwrite 'a' with empty contents
301
        t.put_file_non_atomic('a', StringIO(''))
302
        self.check_transport_contents('contents for\nd\n', t, 'd')
303
        self.check_transport_contents('', t, 'a')
304
305
        self.assertRaises(NoSuchFile, t.put_file_non_atomic, 'no/such/path',
306
                                       StringIO('contents\n'))
307
        # Now test the create_parent flag
308
        self.assertRaises(NoSuchFile, t.put_file_non_atomic, 'dir/a',
309
                                       StringIO('contents\n'))
310
        self.failIf(t.has('dir/a'))
311
        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
312
                              create_parent_dir=True)
1946.1.8 by John Arbash Meinel
Update non_atomic_put to have a create_parent_dir flag
313
        self.check_transport_contents('contents for dir/a\n', t, 'dir/a')
314
        
315
        # 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
316
        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
317
                                       StringIO('contents\n'),
318
                                       create_parent_dir=True)
319
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
320
    def test_put_file_permissions(self):
1955.3.18 by John Arbash Meinel
[merge] Transport.non_atomic_put()
321
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
322
        t = self.get_transport()
323
324
        if t.is_readonly():
325
            return
1711.4.32 by John Arbash Meinel
Skip permission tests on win32 no modebits
326
        if not t._can_roundtrip_unix_modebits():
327
            # Can't roundtrip, so no need to run this test
328
            return
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
329
        t.put_file('mode644', StringIO('test text\n'), mode=0644)
1530.1.21 by Robert Collins
Review feedback fixes.
330
        self.assertTransportMode(t, 'mode644', 0644)
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
331
        t.put_file('mode666', StringIO('test text\n'), mode=0666)
1530.1.21 by Robert Collins
Review feedback fixes.
332
        self.assertTransportMode(t, 'mode666', 0666)
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
333
        t.put_file('mode600', StringIO('test text\n'), mode=0600)
1530.1.21 by Robert Collins
Review feedback fixes.
334
        self.assertTransportMode(t, 'mode600', 0600)
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
335
        # 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
336
        t.put_file('mode400', StringIO('test text\n'), mode=0400)
1530.1.21 by Robert Collins
Review feedback fixes.
337
        self.assertTransportMode(t, 'mode400', 0400)
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
338
339
        # XXX: put_multi is deprecated, so do we really care anymore?
1955.3.29 by John Arbash Meinel
Use applyDeprecated instead of callDeprecated
340
        self.applyDeprecated(zero_eleven, t.put_multi,
341
                             [('mmode644', StringIO('text\n'))], mode=0644)
1530.1.21 by Robert Collins
Review feedback fixes.
342
        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
343
344
        # The default permissions should be based on the current umask
345
        umask = osutils.get_umask()
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
346
        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
347
        self.assertTransportMode(t, 'nomode', 0666 & ~umask)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
348
        
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
349
    def test_put_file_non_atomic_permissions(self):
350
        t = self.get_transport()
351
352
        if t.is_readonly():
353
            return
354
        if not t._can_roundtrip_unix_modebits():
355
            # Can't roundtrip, so no need to run this test
356
            return
357
        t.put_file_non_atomic('mode644', StringIO('test text\n'), mode=0644)
358
        self.assertTransportMode(t, 'mode644', 0644)
359
        t.put_file_non_atomic('mode666', StringIO('test text\n'), mode=0666)
360
        self.assertTransportMode(t, 'mode666', 0666)
361
        t.put_file_non_atomic('mode600', StringIO('test text\n'), mode=0600)
362
        self.assertTransportMode(t, 'mode600', 0600)
363
        # Yes, you can put_file_non_atomic a file such that it becomes readonly
364
        t.put_file_non_atomic('mode400', StringIO('test text\n'), mode=0400)
365
        self.assertTransportMode(t, 'mode400', 0400)
366
367
        # The default permissions should be based on the current umask
368
        umask = osutils.get_umask()
369
        t.put_file_non_atomic('nomode', StringIO('test text\n'), mode=None)
370
        self.assertTransportMode(t, 'nomode', 0666 & ~umask)
371
        
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
372
        # We should also be able to set the mode for a parent directory
373
        # when it is created
374
        sio = StringIO()
375
        t.put_file_non_atomic('dir700/mode664', sio, mode=0664,
376
                              dir_mode=0700, create_parent_dir=True)
377
        self.assertTransportMode(t, 'dir700', 0700)
378
        t.put_file_non_atomic('dir770/mode664', sio, mode=0664,
379
                              dir_mode=0770, create_parent_dir=True)
380
        self.assertTransportMode(t, 'dir770', 0770)
381
        t.put_file_non_atomic('dir777/mode664', sio, mode=0664,
382
                              dir_mode=0777, create_parent_dir=True)
383
        self.assertTransportMode(t, 'dir777', 0777)
384
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
385
    def test_put_multi(self):
386
        t = self.get_transport()
387
388
        if t.is_readonly():
389
            return
1955.3.29 by John Arbash Meinel
Use applyDeprecated instead of callDeprecated
390
        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
391
            t.put_multi, [('a', StringIO('new\ncontents for\na\n')),
392
                          ('d', StringIO('contents\nfor d\n'))]
393
            ))
394
        self.assertEqual(list(t.has_multi(['a', 'b', 'c', 'd'])),
395
                [True, False, False, True])
396
        self.check_transport_contents('new\ncontents for\na\n', t, 'a')
397
        self.check_transport_contents('contents\nfor d\n', t, 'd')
398
1955.3.29 by John Arbash Meinel
Use applyDeprecated instead of callDeprecated
399
        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
400
            t.put_multi, iter([('a', StringIO('diff\ncontents for\na\n')),
401
                              ('d', StringIO('another contents\nfor d\n'))])
402
            ))
403
        self.check_transport_contents('diff\ncontents for\na\n', t, 'a')
404
        self.check_transport_contents('another contents\nfor d\n', t, 'd')
405
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
406
    def test_put_permissions(self):
407
        t = self.get_transport()
408
409
        if t.is_readonly():
410
            return
1711.4.32 by John Arbash Meinel
Skip permission tests on win32 no modebits
411
        if not t._can_roundtrip_unix_modebits():
412
            # Can't roundtrip, so no need to run this test
413
            return
1910.15.6 by Andrew Bennetts
Merge from bzr.dev
414
        self.applyDeprecated(zero_eleven, t.put, 'mode644',
415
                             StringIO('test text\n'), mode=0644)
1530.1.21 by Robert Collins
Review feedback fixes.
416
        self.assertTransportMode(t, 'mode644', 0644)
1910.15.6 by Andrew Bennetts
Merge from bzr.dev
417
        self.applyDeprecated(zero_eleven, t.put, 'mode666',
418
                             StringIO('test text\n'), mode=0666)
1530.1.21 by Robert Collins
Review feedback fixes.
419
        self.assertTransportMode(t, 'mode666', 0666)
1910.15.6 by Andrew Bennetts
Merge from bzr.dev
420
        self.applyDeprecated(zero_eleven, t.put, 'mode600',
421
                             StringIO('test text\n'), mode=0600)
1530.1.21 by Robert Collins
Review feedback fixes.
422
        self.assertTransportMode(t, 'mode600', 0600)
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
423
        # Yes, you can put a file such that it becomes readonly
1910.15.6 by Andrew Bennetts
Merge from bzr.dev
424
        self.applyDeprecated(zero_eleven, t.put, 'mode400',
425
                             StringIO('test text\n'), mode=0400)
1530.1.21 by Robert Collins
Review feedback fixes.
426
        self.assertTransportMode(t, 'mode400', 0400)
1910.15.6 by Andrew Bennetts
Merge from bzr.dev
427
        self.applyDeprecated(zero_eleven, t.put_multi,
428
                             [('mmode644', StringIO('text\n'))], mode=0644)
1530.1.21 by Robert Collins
Review feedback fixes.
429
        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
430
431
        # The default permissions should be based on the current umask
432
        umask = osutils.get_umask()
1910.15.6 by Andrew Bennetts
Merge from bzr.dev
433
        self.applyDeprecated(zero_eleven, t.put, 'nomode',
434
                             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
435
        self.assertTransportMode(t, 'nomode', 0666 & ~umask)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
436
        
1530.1.3 by Robert Collins
transport implementations now tested consistently.
437
    def test_mkdir(self):
438
        t = self.get_transport()
439
440
        if t.is_readonly():
441
            # cannot mkdir on readonly transports. We're not testing for 
442
            # cache coherency because cache behaviour is not currently
443
            # defined for the transport interface.
444
            self.assertRaises(TransportNotPossible, t.mkdir, '.')
445
            self.assertRaises(TransportNotPossible, t.mkdir, 'new_dir')
446
            self.assertRaises(TransportNotPossible, t.mkdir_multi, ['new_dir'])
447
            self.assertRaises(TransportNotPossible, t.mkdir, 'path/doesnt/exist')
448
            return
449
        # Test mkdir
450
        t.mkdir('dir_a')
451
        self.assertEqual(t.has('dir_a'), True)
452
        self.assertEqual(t.has('dir_b'), False)
453
454
        t.mkdir('dir_b')
455
        self.assertEqual(t.has('dir_b'), True)
456
457
        t.mkdir_multi(['dir_c', 'dir_d'])
458
459
        t.mkdir_multi(iter(['dir_e', 'dir_f']))
460
        self.assertEqual(list(t.has_multi(
461
            ['dir_a', 'dir_b', 'dir_c', 'dir_q',
462
             'dir_d', 'dir_e', 'dir_f', 'dir_b'])),
463
            [True, True, True, False,
464
             True, True, True, True])
465
466
        # we were testing that a local mkdir followed by a transport
467
        # mkdir failed thusly, but given that we * in one process * do not
468
        # concurrently fiddle with disk dirs and then use transport to do 
469
        # things, the win here seems marginal compared to the constraint on
470
        # the interface. RBC 20051227
471
        t.mkdir('dir_g')
472
        self.assertRaises(FileExists, t.mkdir, 'dir_g')
473
474
        # 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
475
        t.put_bytes('dir_a/a', 'contents of dir_a/a')
476
        t.put_file('dir_b/b', StringIO('contents of dir_b/b'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
477
        self.check_transport_contents('contents of dir_a/a', t, 'dir_a/a')
478
        self.check_transport_contents('contents of dir_b/b', t, 'dir_b/b')
479
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
480
        # mkdir of a dir with an absent parent
481
        self.assertRaises(NoSuchFile, t.mkdir, 'missing/dir')
482
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
483
    def test_mkdir_permissions(self):
484
        t = self.get_transport()
485
        if t.is_readonly():
486
            return
1608.2.7 by Martin Pool
Rename supports_unix_modebits to _can_roundtrip_unix_modebits for clarity
487
        if not t._can_roundtrip_unix_modebits():
1608.2.5 by Martin Pool
Add Transport.supports_unix_modebits, so tests can
488
            # no sense testing on this transport
489
            return
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
490
        # Test mkdir with a mode
491
        t.mkdir('dmode755', mode=0755)
1530.1.21 by Robert Collins
Review feedback fixes.
492
        self.assertTransportMode(t, 'dmode755', 0755)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
493
        t.mkdir('dmode555', mode=0555)
1530.1.21 by Robert Collins
Review feedback fixes.
494
        self.assertTransportMode(t, 'dmode555', 0555)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
495
        t.mkdir('dmode777', mode=0777)
1530.1.21 by Robert Collins
Review feedback fixes.
496
        self.assertTransportMode(t, 'dmode777', 0777)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
497
        t.mkdir('dmode700', mode=0700)
1530.1.21 by Robert Collins
Review feedback fixes.
498
        self.assertTransportMode(t, 'dmode700', 0700)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
499
        t.mkdir_multi(['mdmode755'], mode=0755)
1530.1.21 by Robert Collins
Review feedback fixes.
500
        self.assertTransportMode(t, 'mdmode755', 0755)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
501
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
502
        # Default mode should be based on umask
503
        umask = osutils.get_umask()
504
        t.mkdir('dnomode', mode=None)
505
        self.assertTransportMode(t, 'dnomode', 0777 & ~umask)
506
1530.1.3 by Robert Collins
transport implementations now tested consistently.
507
    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.
508
        # FIXME: test:   same server to same server (partly done)
509
        # same protocol two servers
510
        # and    different protocols (done for now except for MemoryTransport.
511
        # - RBC 20060122
1530.1.3 by Robert Collins
transport implementations now tested consistently.
512
        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.
513
514
        def simple_copy_files(transport_from, transport_to):
515
            files = ['a', 'b', 'c', 'd']
516
            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.
517
            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.
518
            for f in files:
519
                self.check_transport_contents(transport_to.get(f).read(),
520
                                              transport_from, f)
521
1530.1.3 by Robert Collins
transport implementations now tested consistently.
522
        t = self.get_transport()
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
523
        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.
524
        simple_copy_files(t, temp_transport)
525
        if not t.is_readonly():
526
            t.mkdir('copy_to_simple')
527
            t2 = t.clone('copy_to_simple')
528
            simple_copy_files(t, t2)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
529
530
531
        # Test that copying into a missing directory raises
532
        # NoSuchFile
533
        if t.is_readonly():
1530.1.21 by Robert Collins
Review feedback fixes.
534
            self.build_tree(['e/', 'e/f'])
1530.1.3 by Robert Collins
transport implementations now tested consistently.
535
        else:
536
            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
537
            t.put_bytes('e/f', 'contents of e')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
538
        self.assertRaises(NoSuchFile, t.copy_to, ['e/f'], temp_transport)
539
        temp_transport.mkdir('e')
540
        t.copy_to(['e/f'], temp_transport)
541
542
        del temp_transport
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
543
        temp_transport = MemoryTransport('memory:///')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
544
545
        files = ['a', 'b', 'c', 'd']
546
        t.copy_to(iter(files), temp_transport)
547
        for f in files:
548
            self.check_transport_contents(temp_transport.get(f).read(),
549
                                          t, f)
550
        del temp_transport
551
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
552
        for mode in (0666, 0644, 0600, 0400):
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
553
            temp_transport = MemoryTransport("memory:///")
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
554
            t.copy_to(files, temp_transport, mode=mode)
555
            for f in files:
1530.1.21 by Robert Collins
Review feedback fixes.
556
                self.assertTransportMode(temp_transport, f, mode)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
557
1530.1.3 by Robert Collins
transport implementations now tested consistently.
558
    def test_append(self):
559
        t = self.get_transport()
560
561
        if t.is_readonly():
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
562
            return
563
        t.put_bytes('a', 'diff\ncontents for\na\n')
564
        t.put_bytes('b', 'contents\nfor b\n')
565
1955.3.29 by John Arbash Meinel
Use applyDeprecated instead of callDeprecated
566
        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
567
            t.append, 'a', StringIO('add\nsome\nmore\ncontents\n')))
568
569
        self.check_transport_contents(
570
            'diff\ncontents for\na\nadd\nsome\nmore\ncontents\n',
571
            t, 'a')
572
573
        # And we can create new files, too
1955.3.29 by John Arbash Meinel
Use applyDeprecated instead of callDeprecated
574
        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
575
            t.append, 'c', StringIO('some text\nfor a missing file\n')))
576
        self.check_transport_contents('some text\nfor a missing file\n',
577
                                      t, 'c')
578
    def test_append_file(self):
579
        t = self.get_transport()
580
581
        if t.is_readonly():
1530.1.3 by Robert Collins
transport implementations now tested consistently.
582
            self.assertRaises(TransportNotPossible,
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
583
                    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
584
            return
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
585
        t.put_bytes('a', 'diff\ncontents for\na\n')
586
        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
587
588
        self.assertEqual(20,
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
589
            t.append_file('a', StringIO('add\nsome\nmore\ncontents\n')))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
590
591
        self.check_transport_contents(
592
            'diff\ncontents for\na\nadd\nsome\nmore\ncontents\n',
593
            t, 'a')
594
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
595
        # a file with no parent should fail..
596
        self.assertRaises(NoSuchFile,
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
597
                          t.append_file, 'missing/path', StringIO('content'))
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
598
599
        # And we can create new files, too
600
        self.assertEqual(0,
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
601
            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
602
        self.check_transport_contents('some text\nfor a missing file\n',
603
                                      t, 'c')
604
605
    def test_append_bytes(self):
606
        t = self.get_transport()
607
608
        if t.is_readonly():
609
            self.assertRaises(TransportNotPossible,
610
                    t.append_bytes, 'a', 'add\nsome\nmore\ncontents\n')
611
            return
612
613
        self.assertEqual(0, t.append_bytes('a', 'diff\ncontents for\na\n'))
614
        self.assertEqual(0, t.append_bytes('b', 'contents\nfor b\n'))
615
616
        self.assertEqual(20,
617
            t.append_bytes('a', 'add\nsome\nmore\ncontents\n'))
618
619
        self.check_transport_contents(
620
            'diff\ncontents for\na\nadd\nsome\nmore\ncontents\n',
621
            t, 'a')
622
623
        # a file with no parent should fail..
624
        self.assertRaises(NoSuchFile,
625
                          t.append_bytes, 'missing/path', 'content')
626
627
    def test_append_multi(self):
628
        t = self.get_transport()
629
630
        if t.is_readonly():
631
            return
632
        t.put_bytes('a', 'diff\ncontents for\na\n'
633
                         'add\nsome\nmore\ncontents\n')
634
        t.put_bytes('b', 'contents\nfor b\n')
635
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
636
        self.assertEqual((43, 15),
637
            t.append_multi([('a', StringIO('and\nthen\nsome\nmore\n')),
638
                            ('b', StringIO('some\nmore\nfor\nb\n'))]))
639
1530.1.3 by Robert Collins
transport implementations now tested consistently.
640
        self.check_transport_contents(
641
            'diff\ncontents for\na\n'
642
            'add\nsome\nmore\ncontents\n'
643
            'and\nthen\nsome\nmore\n',
644
            t, 'a')
645
        self.check_transport_contents(
646
                'contents\nfor b\n'
647
                'some\nmore\nfor\nb\n',
648
                t, 'b')
649
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
650
        self.assertEqual((62, 31),
651
            t.append_multi(iter([('a', StringIO('a little bit more\n')),
652
                                 ('b', StringIO('from an iterator\n'))])))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
653
        self.check_transport_contents(
654
            'diff\ncontents for\na\n'
655
            'add\nsome\nmore\ncontents\n'
656
            'and\nthen\nsome\nmore\n'
657
            'a little bit more\n',
658
            t, 'a')
659
        self.check_transport_contents(
660
                'contents\nfor b\n'
661
                'some\nmore\nfor\nb\n'
662
                'from an iterator\n',
663
                t, 'b')
664
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
665
        self.assertEqual((80, 0),
666
            t.append_multi([('a', StringIO('some text in a\n')),
667
                            ('d', StringIO('missing file r\n'))]))
668
1530.1.3 by Robert Collins
transport implementations now tested consistently.
669
        self.check_transport_contents(
670
            'diff\ncontents for\na\n'
671
            'add\nsome\nmore\ncontents\n'
672
            'and\nthen\nsome\nmore\n'
673
            'a little bit more\n'
674
            'some text in a\n',
675
            t, 'a')
676
        self.check_transport_contents('missing file r\n', t, 'd')
677
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
678
    def test_append_file_mode(self):
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
679
        """Check that append accepts a mode parameter"""
1666.1.6 by Robert Collins
Make knit the default format.
680
        # check append accepts a mode
681
        t = self.get_transport()
682
        if t.is_readonly():
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
683
            self.assertRaises(TransportNotPossible,
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
684
                t.append_file, 'f', StringIO('f'), mode=None)
1666.1.6 by Robert Collins
Make knit the default format.
685
            return
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
        
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
688
    def test_append_bytes_mode(self):
689
        # check append_bytes accepts a mode
690
        t = self.get_transport()
691
        if t.is_readonly():
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
692
            self.assertRaises(TransportNotPossible,
693
                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
694
            return
1955.3.10 by John Arbash Meinel
clean up append, append_bytes, and append_multi tests
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
        
1530.1.3 by Robert Collins
transport implementations now tested consistently.
697
    def test_delete(self):
698
        # TODO: Test Transport.delete
699
        t = self.get_transport()
700
701
        # Not much to do with a readonly transport
702
        if t.is_readonly():
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
703
            self.assertRaises(TransportNotPossible, t.delete, 'missing')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
704
            return
705
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
706
        t.put_bytes('a', 'a little bit of text\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
707
        self.failUnless(t.has('a'))
708
        t.delete('a')
709
        self.failIf(t.has('a'))
710
711
        self.assertRaises(NoSuchFile, t.delete, 'a')
712
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
713
        t.put_bytes('a', 'a text\n')
714
        t.put_bytes('b', 'b text\n')
715
        t.put_bytes('c', 'c text\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
716
        self.assertEqual([True, True, True],
717
                list(t.has_multi(['a', 'b', 'c'])))
718
        t.delete_multi(['a', 'c'])
719
        self.assertEqual([False, True, False],
720
                list(t.has_multi(['a', 'b', 'c'])))
721
        self.failIf(t.has('a'))
722
        self.failUnless(t.has('b'))
723
        self.failIf(t.has('c'))
724
725
        self.assertRaises(NoSuchFile,
726
                t.delete_multi, ['a', 'b', 'c'])
727
728
        self.assertRaises(NoSuchFile,
729
                t.delete_multi, iter(['a', 'b', 'c']))
730
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
731
        t.put_bytes('a', 'another a text\n')
732
        t.put_bytes('c', 'another c text\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
733
        t.delete_multi(iter(['a', 'b', 'c']))
734
735
        # We should have deleted everything
736
        # SftpServer creates control files in the
737
        # working directory, so we can just do a
738
        # plain "listdir".
739
        # self.assertEqual([], os.listdir('.'))
740
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
741
    def test_rmdir(self):
742
        t = self.get_transport()
743
        # Not much to do with a readonly transport
744
        if t.is_readonly():
745
            self.assertRaises(TransportNotPossible, t.rmdir, 'missing')
746
            return
747
        t.mkdir('adir')
748
        t.mkdir('adir/bdir')
749
        t.rmdir('adir/bdir')
1948.3.12 by Vincent LADEUIL
Fix Aaron's third review remarks.
750
        # ftp may not be able to raise NoSuchFile for lack of
751
        # details when failing
752
        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.
753
        t.rmdir('adir')
1948.3.12 by Vincent LADEUIL
Fix Aaron's third review remarks.
754
        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.
755
1553.5.10 by Martin Pool
New DirectoryNotEmpty exception, and raise this from local and memory
756
    def test_rmdir_not_empty(self):
757
        """Deleting a non-empty directory raises an exception
758
        
759
        sftp (and possibly others) don't give us a specific "directory not
760
        empty" exception -- we can just see that the operation failed.
761
        """
762
        t = self.get_transport()
763
        if t.is_readonly():
764
            return
765
        t.mkdir('adir')
766
        t.mkdir('adir/bdir')
767
        self.assertRaises(PathError, t.rmdir, 'adir')
768
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
769
    def test_rename_dir_succeeds(self):
770
        t = self.get_transport()
771
        if t.is_readonly():
772
            raise TestSkipped("transport is readonly")
773
        t.mkdir('adir')
774
        t.mkdir('adir/asubdir')
775
        t.rename('adir', 'bdir')
776
        self.assertTrue(t.has('bdir/asubdir'))
777
        self.assertFalse(t.has('adir'))
778
779
    def test_rename_dir_nonempty(self):
780
        """Attempting to replace a nonemtpy directory should fail"""
781
        t = self.get_transport()
782
        if t.is_readonly():
783
            raise TestSkipped("transport is readonly")
784
        t.mkdir('adir')
785
        t.mkdir('adir/asubdir')
786
        t.mkdir('bdir')
787
        t.mkdir('bdir/bsubdir')
1910.7.17 by Andrew Bennetts
Various cosmetic changes.
788
        # any kind of PathError would be OK, though we normally expect
789
        # DirectoryNotEmpty
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
790
        self.assertRaises(PathError, t.rename, 'bdir', 'adir')
791
        # nothing was changed so it should still be as before
792
        self.assertTrue(t.has('bdir/bsubdir'))
793
        self.assertFalse(t.has('adir/bdir'))
794
        self.assertFalse(t.has('adir/bsubdir'))
795
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
796
    def test_delete_tree(self):
797
        t = self.get_transport()
798
799
        # Not much to do with a readonly transport
800
        if t.is_readonly():
801
            self.assertRaises(TransportNotPossible, t.delete_tree, 'missing')
802
            return
803
804
        # and does it like listing ?
805
        t.mkdir('adir')
806
        try:
807
            t.delete_tree('adir')
808
        except TransportNotPossible:
809
            # ok, this transport does not support delete_tree
810
            return
811
        
812
        # did it delete that trivial case?
813
        self.assertRaises(NoSuchFile, t.stat, 'adir')
814
815
        self.build_tree(['adir/',
816
                         'adir/file', 
817
                         'adir/subdir/', 
818
                         'adir/subdir/file', 
819
                         'adir/subdir2/',
820
                         'adir/subdir2/file',
821
                         ], transport=t)
822
823
        t.delete_tree('adir')
824
        # adir should be gone now.
825
        self.assertRaises(NoSuchFile, t.stat, 'adir')
826
1530.1.3 by Robert Collins
transport implementations now tested consistently.
827
    def test_move(self):
828
        t = self.get_transport()
829
830
        if t.is_readonly():
831
            return
832
833
        # TODO: I would like to use os.listdir() to
834
        # make sure there are no extra files, but SftpServer
835
        # creates control files in the working directory
836
        # perhaps all of this could be done in a subdirectory
837
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
838
        t.put_bytes('a', 'a first file\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
839
        self.assertEquals([True, False], list(t.has_multi(['a', 'b'])))
840
841
        t.move('a', 'b')
842
        self.failUnless(t.has('b'))
843
        self.failIf(t.has('a'))
844
845
        self.check_transport_contents('a first file\n', t, 'b')
846
        self.assertEquals([False, True], list(t.has_multi(['a', 'b'])))
847
848
        # 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
849
        t.put_bytes('c', 'c this file\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
850
        t.move('c', 'b')
851
        self.failIf(t.has('c'))
852
        self.check_transport_contents('c this file\n', t, 'b')
853
854
        # TODO: Try to write a test for atomicity
855
        # TODO: Test moving into a non-existant subdirectory
856
        # TODO: Test Transport.move_multi
857
858
    def test_copy(self):
859
        t = self.get_transport()
860
861
        if t.is_readonly():
862
            return
863
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
864
        t.put_bytes('a', 'a file\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
865
        t.copy('a', 'b')
866
        self.check_transport_contents('a file\n', t, 'b')
867
868
        self.assertRaises(NoSuchFile, t.copy, 'c', 'd')
869
        os.mkdir('c')
870
        # What should the assert be if you try to copy a
871
        # file over a directory?
872
        #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
873
        t.put_bytes('d', 'text in d\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
874
        t.copy('d', 'b')
875
        self.check_transport_contents('text in d\n', t, 'b')
876
877
        # TODO: test copy_multi
878
879
    def test_connection_error(self):
1910.7.17 by Andrew Bennetts
Various cosmetic changes.
880
        """ConnectionError is raised when connection is impossible.
881
        
882
        The error may be raised from either the constructor or the first
883
        operation on the transport.
884
        """
1530.1.9 by Robert Collins
Test bogus urls with http in the new infrastructure.
885
        try:
886
            url = self._server.get_bogus_url()
887
        except NotImplementedError:
888
            raise TestSkipped("Transport %s has no bogus URL support." %
889
                              self._server.__class__)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
890
        try:
1711.2.42 by John Arbash Meinel
enable bogus_url support for SFTP tests
891
            t = bzrlib.transport.get_transport(url)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
892
            t.get('.bzr/branch')
893
        except (ConnectionError, NoSuchFile), e:
894
            pass
895
        except (Exception), e:
1786.1.27 by John Arbash Meinel
Fix up the http transports so that tests pass with the new configuration.
896
            self.fail('Wrong exception thrown (%s.%s): %s' 
897
                        % (e.__class__.__module__, e.__class__.__name__, e))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
898
        else:
1707.3.11 by John Arbash Meinel
fixing more tests.
899
            self.fail('Did not get the expected ConnectionError or NoSuchFile.')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
900
901
    def test_stat(self):
902
        # TODO: Test stat, just try once, and if it throws, stop testing
903
        from stat import S_ISDIR, S_ISREG
904
905
        t = self.get_transport()
906
907
        try:
908
            st = t.stat('.')
909
        except TransportNotPossible, e:
910
            # This transport cannot stat
911
            return
912
913
        paths = ['a', 'b/', 'b/c', 'b/d/', 'b/d/e']
914
        sizes = [14, 0, 16, 0, 18] 
1551.2.39 by abentley
Fix line endings in tests
915
        self.build_tree(paths, transport=t, line_endings='binary')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
916
917
        for path, size in zip(paths, sizes):
918
            st = t.stat(path)
919
            if path.endswith('/'):
920
                self.failUnless(S_ISDIR(st.st_mode))
921
                # directory sizes are meaningless
922
            else:
923
                self.failUnless(S_ISREG(st.st_mode))
924
                self.assertEqual(size, st.st_size)
925
926
        remote_stats = list(t.stat_multi(paths))
927
        remote_iter_stats = list(t.stat_multi(iter(paths)))
928
929
        self.assertRaises(NoSuchFile, t.stat, 'q')
930
        self.assertRaises(NoSuchFile, t.stat, 'b/a')
931
932
        self.assertListRaises(NoSuchFile, t.stat_multi, ['a', 'c', 'd'])
933
        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.
934
        self.build_tree(['subdir/', 'subdir/file'], transport=t)
935
        subdir = t.clone('subdir')
936
        subdir.stat('./file')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
937
        subdir.stat('.')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
938
939
    def test_list_dir(self):
940
        # TODO: Test list_dir, just try once, and if it throws, stop testing
941
        t = self.get_transport()
942
        
943
        if not t.listable():
944
            self.assertRaises(TransportNotPossible, t.list_dir, '.')
945
            return
946
947
        def sorted_list(d):
948
            l = list(t.list_dir(d))
949
            l.sort()
950
            return l
951
952
        # SftpServer creates control files in the working directory
953
        # so lets move down a directory to avoid those.
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
954
        if not t.is_readonly():
955
            t.mkdir('wd')
956
        else:
957
            os.mkdir('wd')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
958
        t = t.clone('wd')
959
1910.7.1 by Andrew Bennetts
Make sure list_dir always returns url-escaped names.
960
        self.assertEqual([], sorted_list('.'))
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
961
        # c2 is precisely one letter longer than c here to test that
962
        # suffixing is not confused.
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
963
        # a%25b checks that quoting is done consistently across transports
964
        tree_names = ['a', 'a%25b', 'b', 'c/', 'c/d', 'c/e', 'c2/']
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
965
        if not t.is_readonly():
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
966
            self.build_tree(tree_names, transport=t)
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
967
        else:
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
968
            self.build_tree(['wd/' + name for name in tree_names])
1530.1.3 by Robert Collins
transport implementations now tested consistently.
969
1959.2.1 by John Arbash Meinel
David Allouche: Make transports return escaped paths
970
        self.assertEqual(
1959.2.3 by John Arbash Meinel
Remove some unicode string notations
971
            ['a', 'a%2525b', 'b', 'c', 'c2'], sorted_list('.'))
1910.7.1 by Andrew Bennetts
Make sure list_dir always returns url-escaped names.
972
        self.assertEqual(['d', 'e'], sorted_list('c'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
973
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
974
        if not t.is_readonly():
975
            t.delete('c/d')
976
            t.delete('b')
977
        else:
978
            os.unlink('wd/c/d')
979
            os.unlink('wd/b')
980
            
1959.2.3 by John Arbash Meinel
Remove some unicode string notations
981
        self.assertEqual(['a', 'a%2525b', 'c', 'c2'], sorted_list('.'))
1910.7.1 by Andrew Bennetts
Make sure list_dir always returns url-escaped names.
982
        self.assertEqual(['e'], sorted_list('c'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
983
1662.1.12 by Martin Pool
Translate unknown sftp errors to PathError, no NoSuchFile
984
        self.assertListRaises(PathError, t.list_dir, 'q')
985
        self.assertListRaises(PathError, t.list_dir, 'c/f')
986
        self.assertListRaises(PathError, t.list_dir, 'a')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
987
1910.7.1 by Andrew Bennetts
Make sure list_dir always returns url-escaped names.
988
    def test_list_dir_result_is_url_escaped(self):
989
        t = self.get_transport()
990
        if not t.listable():
991
            raise TestSkipped("transport not listable")
992
993
        if not t.is_readonly():
994
            self.build_tree(['a/', 'a/%'], transport=t)
995
        else:
996
            self.build_tree(['a/', 'a/%'])
997
        
1910.7.2 by Andrew Bennetts
Also assert that list_dir returns plain str objects.
998
        names = list(t.list_dir('a'))
999
        self.assertEqual(['%25'], names)
1000
        self.assertIsInstance(names[0], str)
1910.7.1 by Andrew Bennetts
Make sure list_dir always returns url-escaped names.
1001
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1002
    def test_clone(self):
1003
        # TODO: Test that clone moves up and down the filesystem
1004
        t1 = self.get_transport()
1005
1006
        self.build_tree(['a', 'b/', 'b/c'], transport=t1)
1007
1008
        self.failUnless(t1.has('a'))
1009
        self.failUnless(t1.has('b/c'))
1010
        self.failIf(t1.has('c'))
1011
1012
        t2 = t1.clone('b')
1013
        self.assertEqual(t1.base + 'b/', t2.base)
1014
1015
        self.failUnless(t2.has('c'))
1016
        self.failIf(t2.has('a'))
1017
1018
        t3 = t2.clone('..')
1019
        self.failUnless(t3.has('a'))
1020
        self.failIf(t3.has('c'))
1021
1022
        self.failIf(t1.has('b/d'))
1023
        self.failIf(t2.has('d'))
1024
        self.failIf(t3.has('b/d'))
1025
1026
        if t1.is_readonly():
1027
            open('b/d', 'wb').write('newfile\n')
1028
        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
1029
            t2.put_bytes('d', 'newfile\n')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1030
1031
        self.failUnless(t1.has('b/d'))
1032
        self.failUnless(t2.has('d'))
1033
        self.failUnless(t3.has('b/d'))
1034
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
1035
    def test_clone_to_root(self):
1036
        orig_transport = self.get_transport()
1037
        # Repeatedly go up to a parent directory until we're at the root
1038
        # directory of this transport
1039
        root_transport = orig_transport
1040
        while root_transport.clone("..").base != root_transport.base:
1041
            root_transport = root_transport.clone("..")
1042
1043
        # Cloning to "/" should take us to exactly the same location.
1044
        self.assertEqual(root_transport.base, orig_transport.clone("/").base)
1045
1910.15.5 by Andrew Bennetts
Transport behaviour at the root of the URL is now defined and tested.
1046
        # At the root, the URL must still end with / as its a directory
1047
        self.assertEqual(root_transport.base[-1], '/')
1048
1049
    def test_clone_from_root(self):
1050
        """At the root, cloning to a simple dir should just do string append."""
1051
        orig_transport = self.get_transport()
1052
        root_transport = orig_transport.clone('/')
1053
        self.assertEqual(root_transport.base + '.bzr/',
1054
            root_transport.clone('.bzr').base)
1055
1910.15.1 by Andrew Bennetts
More tests for abspath and clone behaviour
1056
    def test_base_url(self):
1057
        t = self.get_transport()
1058
        self.assertEqual('/', t.base[-1])
1059
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1060
    def test_relpath(self):
1061
        t = self.get_transport()
1062
        self.assertEqual('', t.relpath(t.base))
1063
        # base ends with /
1064
        self.assertEqual('', t.relpath(t.base[:-1]))
1065
        # subdirs which dont exist should still give relpaths.
1066
        self.assertEqual('foo', t.relpath(t.base + 'foo'))
1067
        # trailing slash should be the same.
1068
        self.assertEqual('foo', t.relpath(t.base + 'foo/'))
1069
1636.1.1 by Robert Collins
Fix calling relpath() and abspath() on transports at their root.
1070
    def test_relpath_at_root(self):
1071
        t = self.get_transport()
1072
        # clone all the way to the top
1073
        new_transport = t.clone('..')
1074
        while new_transport.base != t.base:
1075
            t = new_transport
1076
            new_transport = t.clone('..')
1077
        # we must be able to get a relpath below the root
1078
        self.assertEqual('', t.relpath(t.base))
1079
        # and a deeper one should work too
1080
        self.assertEqual('foo/bar', t.relpath(t.base + 'foo/bar'))
1081
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1082
    def test_abspath(self):
1083
        # smoke test for abspath. Corner cases for backends like unix fs's
1084
        # that have aliasing problems like symlinks should go in backend
1085
        # specific test cases.
1086
        transport = self.get_transport()
1540.3.24 by Martin Pool
Add new protocol 'http+pycurl' that always uses PyCurl.
1087
        
1088
        # disabled because some transports might normalize urls in generating
1089
        # the abspath - eg http+pycurl-> just http -- mbp 20060308 
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', '')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1239
        transport.put('lock', StringIO())
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