/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
1553.5.10 by Martin Pool
New DirectoryNotEmpty exception, and raise this from local and memory
28
from bzrlib.errors import (DirectoryNotEmpty, NoSuchFile, FileExists,
1185.85.84 by John Arbash Meinel
[merge] bzr.dev 1573, lots of updates
29
                           LockError, PathError,
1185.85.76 by John Arbash Meinel
Adding an InvalidURL so transports can report they expect utf-8 quoted paths. Updated tests
30
                           TransportNotPossible, ConnectionError,
31
                           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
32
from bzrlib.osutils import getcwd
1530.1.9 by Robert Collins
Test bogus urls with http in the new infrastructure.
33
from bzrlib.tests import TestCaseInTempDir, TestSkipped
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
34
from bzrlib.tests.test_transport import TestTransportImplementation
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
35
from bzrlib.transport import memory
1530.1.3 by Robert Collins
transport implementations now tested consistently.
36
import bzrlib.transport
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
37
import bzrlib.urlutils as urlutils
1530.1.3 by Robert Collins
transport implementations now tested consistently.
38
39
40
def _append(fn, txt):
41
    """Append the given text (file-like object) to the supplied filename."""
42
    f = open(fn, 'ab')
1530.1.21 by Robert Collins
Review feedback fixes.
43
    try:
44
        f.write(txt.read())
45
    finally:
46
        f.close()
1530.1.3 by Robert Collins
transport implementations now tested consistently.
47
48
1871.1.2 by Robert Collins
Reduce code duplication in transport-parameterised tests.
49
class TransportTests(TestTransportImplementation):
50
1530.1.3 by Robert Collins
transport implementations now tested consistently.
51
    def check_transport_contents(self, content, transport, relpath):
52
        """Check that transport.get(relpath).read() == content."""
1530.1.21 by Robert Collins
Review feedback fixes.
53
        self.assertEqualDiff(content, transport.get(relpath).read())
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
54
1530.1.3 by Robert Collins
transport implementations now tested consistently.
55
    def assertListRaises(self, excClass, func, *args, **kwargs):
1530.1.21 by Robert Collins
Review feedback fixes.
56
        """Fail unless excClass is raised when the iterator from func is used.
57
        
58
        Many transport functions can return generators this makes sure
1530.1.3 by Robert Collins
transport implementations now tested consistently.
59
        to wrap them in a list() call to make sure the whole generator
60
        is run, and that the proper exception is raised.
61
        """
62
        try:
63
            list(func(*args, **kwargs))
64
        except excClass:
65
            return
66
        else:
67
            if hasattr(excClass,'__name__'): excName = excClass.__name__
68
            else: excName = str(excClass)
69
            raise self.failureException, "%s not raised" % excName
70
71
    def test_has(self):
72
        t = self.get_transport()
73
74
        files = ['a', 'b', 'e', 'g', '%']
75
        self.build_tree(files, transport=t)
76
        self.assertEqual(True, t.has('a'))
77
        self.assertEqual(False, t.has('c'))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
78
        self.assertEqual(True, t.has(urlutils.escape('%')))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
79
        self.assertEqual(list(t.has_multi(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])),
80
                [True, True, False, False, True, False, True, False])
81
        self.assertEqual(True, t.has_any(['a', 'b', 'c']))
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
82
        self.assertEqual(False, t.has_any(['c', 'd', 'f', urlutils.escape('%%')]))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
83
        self.assertEqual(list(t.has_multi(iter(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']))),
84
                [True, True, False, False, True, False, True, False])
85
        self.assertEqual(False, t.has_any(['c', 'c', 'c']))
86
        self.assertEqual(True, t.has_any(['b', 'b', 'b']))
87
88
    def test_get(self):
89
        t = self.get_transport()
90
91
        files = ['a', 'b', 'e', 'g']
92
        contents = ['contents of a\n',
93
                    'contents of b\n',
94
                    'contents of e\n',
95
                    'contents of g\n',
96
                    ]
1551.2.39 by abentley
Fix line endings in tests
97
        self.build_tree(files, transport=t, line_endings='binary')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
98
        self.check_transport_contents('contents of a\n', t, 'a')
99
        content_f = t.get_multi(files)
100
        for content, f in zip(contents, content_f):
101
            self.assertEqual(content, f.read())
102
103
        content_f = t.get_multi(iter(files))
104
        for content, f in zip(contents, content_f):
105
            self.assertEqual(content, f.read())
106
107
        self.assertRaises(NoSuchFile, t.get, 'c')
108
        self.assertListRaises(NoSuchFile, t.get_multi, ['a', 'b', 'c'])
109
        self.assertListRaises(NoSuchFile, t.get_multi, iter(['a', 'b', 'c']))
110
111
    def test_put(self):
112
        t = self.get_transport()
113
114
        if t.is_readonly():
115
            self.assertRaises(TransportNotPossible,
116
                    t.put, 'a', 'some text for a\n')
117
            return
118
119
        t.put('a', StringIO('some text for a\n'))
120
        self.failUnless(t.has('a'))
121
        self.check_transport_contents('some text for a\n', t, 'a')
122
        # Make sure 'has' is updated
123
        self.assertEqual(list(t.has_multi(['a', 'b', 'c', 'd', 'e'])),
124
                [True, False, False, False, False])
125
        # Put also replaces contents
126
        self.assertEqual(t.put_multi([('a', StringIO('new\ncontents for\na\n')),
127
                                      ('d', StringIO('contents\nfor d\n'))]),
128
                         2)
129
        self.assertEqual(list(t.has_multi(['a', 'b', 'c', 'd', 'e'])),
130
                [True, False, False, True, False])
131
        self.check_transport_contents('new\ncontents for\na\n', t, 'a')
132
        self.check_transport_contents('contents\nfor d\n', t, 'd')
133
134
        self.assertEqual(
135
            t.put_multi(iter([('a', StringIO('diff\ncontents for\na\n')),
136
                              ('d', StringIO('another contents\nfor d\n'))])),
137
                        2)
138
        self.check_transport_contents('diff\ncontents for\na\n', t, 'a')
139
        self.check_transport_contents('another contents\nfor d\n', t, 'd')
140
141
        self.assertRaises(NoSuchFile,
142
                          t.put, 'path/doesnt/exist/c', 'contents')
143
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
144
    def test_put_permissions(self):
145
        t = self.get_transport()
146
147
        if t.is_readonly():
148
            return
1711.4.32 by John Arbash Meinel
Skip permission tests on win32 no modebits
149
        if not t._can_roundtrip_unix_modebits():
150
            # Can't roundtrip, so no need to run this test
151
            return
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
152
        t.put('mode644', StringIO('test text\n'), mode=0644)
1530.1.21 by Robert Collins
Review feedback fixes.
153
        self.assertTransportMode(t, 'mode644', 0644)
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
154
        t.put('mode666', StringIO('test text\n'), mode=0666)
1530.1.21 by Robert Collins
Review feedback fixes.
155
        self.assertTransportMode(t, 'mode666', 0666)
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
156
        t.put('mode600', StringIO('test text\n'), mode=0600)
1530.1.21 by Robert Collins
Review feedback fixes.
157
        self.assertTransportMode(t, 'mode600', 0600)
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
158
        # Yes, you can put a file such that it becomes readonly
159
        t.put('mode400', StringIO('test text\n'), mode=0400)
1530.1.21 by Robert Collins
Review feedback fixes.
160
        self.assertTransportMode(t, 'mode400', 0400)
1530.1.15 by Robert Collins
Move put mode tests into test_transport_implementation.
161
        t.put_multi([('mmode644', StringIO('text\n'))], mode=0644)
1530.1.21 by Robert Collins
Review feedback fixes.
162
        self.assertTransportMode(t, 'mmode644', 0644)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
163
        
1530.1.3 by Robert Collins
transport implementations now tested consistently.
164
    def test_mkdir(self):
165
        t = self.get_transport()
166
167
        if t.is_readonly():
168
            # cannot mkdir on readonly transports. We're not testing for 
169
            # cache coherency because cache behaviour is not currently
170
            # defined for the transport interface.
171
            self.assertRaises(TransportNotPossible, t.mkdir, '.')
172
            self.assertRaises(TransportNotPossible, t.mkdir, 'new_dir')
173
            self.assertRaises(TransportNotPossible, t.mkdir_multi, ['new_dir'])
174
            self.assertRaises(TransportNotPossible, t.mkdir, 'path/doesnt/exist')
175
            return
176
        # Test mkdir
177
        t.mkdir('dir_a')
178
        self.assertEqual(t.has('dir_a'), True)
179
        self.assertEqual(t.has('dir_b'), False)
180
181
        t.mkdir('dir_b')
182
        self.assertEqual(t.has('dir_b'), True)
183
184
        t.mkdir_multi(['dir_c', 'dir_d'])
185
186
        t.mkdir_multi(iter(['dir_e', 'dir_f']))
187
        self.assertEqual(list(t.has_multi(
188
            ['dir_a', 'dir_b', 'dir_c', 'dir_q',
189
             'dir_d', 'dir_e', 'dir_f', 'dir_b'])),
190
            [True, True, True, False,
191
             True, True, True, True])
192
193
        # we were testing that a local mkdir followed by a transport
194
        # mkdir failed thusly, but given that we * in one process * do not
195
        # concurrently fiddle with disk dirs and then use transport to do 
196
        # things, the win here seems marginal compared to the constraint on
197
        # the interface. RBC 20051227
198
        t.mkdir('dir_g')
199
        self.assertRaises(FileExists, t.mkdir, 'dir_g')
200
201
        # Test get/put in sub-directories
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.
202
        self.assertEqual(2, 
1530.1.3 by Robert Collins
transport implementations now tested consistently.
203
            t.put_multi([('dir_a/a', StringIO('contents of dir_a/a')),
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.
204
                         ('dir_b/b', StringIO('contents of dir_b/b'))]))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
205
        self.check_transport_contents('contents of dir_a/a', t, 'dir_a/a')
206
        self.check_transport_contents('contents of dir_b/b', t, 'dir_b/b')
207
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
208
        # mkdir of a dir with an absent parent
209
        self.assertRaises(NoSuchFile, t.mkdir, 'missing/dir')
210
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
211
    def test_mkdir_permissions(self):
212
        t = self.get_transport()
213
        if t.is_readonly():
214
            return
1608.2.7 by Martin Pool
Rename supports_unix_modebits to _can_roundtrip_unix_modebits for clarity
215
        if not t._can_roundtrip_unix_modebits():
1608.2.5 by Martin Pool
Add Transport.supports_unix_modebits, so tests can
216
            # no sense testing on this transport
217
            return
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
218
        # Test mkdir with a mode
219
        t.mkdir('dmode755', mode=0755)
1530.1.21 by Robert Collins
Review feedback fixes.
220
        self.assertTransportMode(t, 'dmode755', 0755)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
221
        t.mkdir('dmode555', mode=0555)
1530.1.21 by Robert Collins
Review feedback fixes.
222
        self.assertTransportMode(t, 'dmode555', 0555)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
223
        t.mkdir('dmode777', mode=0777)
1530.1.21 by Robert Collins
Review feedback fixes.
224
        self.assertTransportMode(t, 'dmode777', 0777)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
225
        t.mkdir('dmode700', mode=0700)
1530.1.21 by Robert Collins
Review feedback fixes.
226
        self.assertTransportMode(t, 'dmode700', 0700)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
227
        # TODO: jam 20051215 test mkdir_multi with a mode
228
        t.mkdir_multi(['mdmode755'], mode=0755)
1530.1.21 by Robert Collins
Review feedback fixes.
229
        self.assertTransportMode(t, 'mdmode755', 0755)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
230
1530.1.3 by Robert Collins
transport implementations now tested consistently.
231
    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.
232
        # FIXME: test:   same server to same server (partly done)
233
        # same protocol two servers
234
        # and    different protocols (done for now except for MemoryTransport.
235
        # - RBC 20060122
1530.1.3 by Robert Collins
transport implementations now tested consistently.
236
        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.
237
238
        def simple_copy_files(transport_from, transport_to):
239
            files = ['a', 'b', 'c', 'd']
240
            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.
241
            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.
242
            for f in files:
243
                self.check_transport_contents(transport_to.get(f).read(),
244
                                              transport_from, f)
245
1530.1.3 by Robert Collins
transport implementations now tested consistently.
246
        t = self.get_transport()
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
247
        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.
248
        simple_copy_files(t, temp_transport)
249
        if not t.is_readonly():
250
            t.mkdir('copy_to_simple')
251
            t2 = t.clone('copy_to_simple')
252
            simple_copy_files(t, t2)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
253
254
255
        # Test that copying into a missing directory raises
256
        # NoSuchFile
257
        if t.is_readonly():
1530.1.21 by Robert Collins
Review feedback fixes.
258
            self.build_tree(['e/', 'e/f'])
1530.1.3 by Robert Collins
transport implementations now tested consistently.
259
        else:
260
            t.mkdir('e')
261
            t.put('e/f', StringIO('contents of e'))
262
        self.assertRaises(NoSuchFile, t.copy_to, ['e/f'], temp_transport)
263
        temp_transport.mkdir('e')
264
        t.copy_to(['e/f'], temp_transport)
265
266
        del temp_transport
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
267
        temp_transport = MemoryTransport('memory:///')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
268
269
        files = ['a', 'b', 'c', 'd']
270
        t.copy_to(iter(files), temp_transport)
271
        for f in files:
272
            self.check_transport_contents(temp_transport.get(f).read(),
273
                                          t, f)
274
        del temp_transport
275
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
276
        for mode in (0666, 0644, 0600, 0400):
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
277
            temp_transport = MemoryTransport("memory:///")
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
278
            t.copy_to(files, temp_transport, mode=mode)
279
            for f in files:
1530.1.21 by Robert Collins
Review feedback fixes.
280
                self.assertTransportMode(temp_transport, f, mode)
1530.1.16 by Robert Collins
Move mkdir and copy_to permissions tests to test_transport_impleentation.
281
1530.1.3 by Robert Collins
transport implementations now tested consistently.
282
    def test_append(self):
283
        t = self.get_transport()
284
285
        if t.is_readonly():
286
            open('a', 'wb').write('diff\ncontents for\na\n')
287
            open('b', 'wb').write('contents\nfor b\n')
288
        else:
289
            t.put_multi([
290
                    ('a', StringIO('diff\ncontents for\na\n')),
291
                    ('b', StringIO('contents\nfor b\n'))
292
                    ])
293
294
        if t.is_readonly():
295
            self.assertRaises(TransportNotPossible,
296
                    t.append, 'a', 'add\nsome\nmore\ncontents\n')
297
            _append('a', StringIO('add\nsome\nmore\ncontents\n'))
298
        else:
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.
299
            self.assertEqual(20,
300
                t.append('a', StringIO('add\nsome\nmore\ncontents\n')))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
301
302
        self.check_transport_contents(
303
            'diff\ncontents for\na\nadd\nsome\nmore\ncontents\n',
304
            t, 'a')
305
306
        if t.is_readonly():
307
            self.assertRaises(TransportNotPossible,
308
                    t.append_multi,
309
                        [('a', 'and\nthen\nsome\nmore\n'),
310
                         ('b', 'some\nmore\nfor\nb\n')])
311
            _append('a', StringIO('and\nthen\nsome\nmore\n'))
312
            _append('b', StringIO('some\nmore\nfor\nb\n'))
313
        else:
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.
314
            self.assertEqual((43, 15), 
315
                t.append_multi([('a', StringIO('and\nthen\nsome\nmore\n')),
316
                                ('b', StringIO('some\nmore\nfor\nb\n'))]))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
317
        self.check_transport_contents(
318
            'diff\ncontents for\na\n'
319
            'add\nsome\nmore\ncontents\n'
320
            'and\nthen\nsome\nmore\n',
321
            t, 'a')
322
        self.check_transport_contents(
323
                'contents\nfor b\n'
324
                'some\nmore\nfor\nb\n',
325
                t, 'b')
326
327
        if t.is_readonly():
328
            _append('a', StringIO('a little bit more\n'))
329
            _append('b', StringIO('from an iterator\n'))
330
        else:
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.
331
            self.assertEqual((62, 31),
332
                t.append_multi(iter([('a', StringIO('a little bit more\n')),
333
                                     ('b', StringIO('from an iterator\n'))])))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
334
        self.check_transport_contents(
335
            'diff\ncontents for\na\n'
336
            'add\nsome\nmore\ncontents\n'
337
            'and\nthen\nsome\nmore\n'
338
            'a little bit more\n',
339
            t, 'a')
340
        self.check_transport_contents(
341
                'contents\nfor b\n'
342
                'some\nmore\nfor\nb\n'
343
                'from an iterator\n',
344
                t, 'b')
345
346
        if t.is_readonly():
347
            _append('c', StringIO('some text\nfor a missing file\n'))
348
            _append('a', StringIO('some text in a\n'))
349
            _append('d', StringIO('missing file r\n'))
350
        else:
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.
351
            self.assertEqual(0,
352
                t.append('c', StringIO('some text\nfor a missing file\n')))
353
            self.assertEqual((80, 0),
354
                t.append_multi([('a', StringIO('some text in a\n')),
355
                                ('d', StringIO('missing file r\n'))]))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
356
        self.check_transport_contents(
357
            'diff\ncontents for\na\n'
358
            'add\nsome\nmore\ncontents\n'
359
            'and\nthen\nsome\nmore\n'
360
            'a little bit more\n'
361
            'some text in a\n',
362
            t, 'a')
363
        self.check_transport_contents('some text\nfor a missing file\n',
364
                                      t, 'c')
365
        self.check_transport_contents('missing file r\n', t, 'd')
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
366
        
367
        # a file with no parent should fail..
368
        if not t.is_readonly():
369
            self.assertRaises(NoSuchFile,
370
                              t.append, 'missing/path', 
371
                              StringIO('content'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
372
373
    def test_append_file(self):
374
        t = self.get_transport()
375
376
        contents = [
377
            ('f1', StringIO('this is a string\nand some more stuff\n')),
378
            ('f2', StringIO('here is some text\nand a bit more\n')),
379
            ('f3', StringIO('some text for the\nthird file created\n')),
380
            ('f4', StringIO('this is a string\nand some more stuff\n')),
381
            ('f5', StringIO('here is some text\nand a bit more\n')),
382
            ('f6', StringIO('some text for the\nthird file created\n'))
383
        ]
384
        
385
        if t.is_readonly():
386
            for f, val in contents:
387
                open(f, 'wb').write(val.read())
388
        else:
389
            t.put_multi(contents)
390
391
        a1 = StringIO('appending to\none\n')
392
        if t.is_readonly():
393
            _append('f1', a1)
394
        else:
395
            t.append('f1', a1)
396
397
        del a1
398
399
        self.check_transport_contents(
400
                'this is a string\nand some more stuff\n'
401
                'appending to\none\n',
402
                t, 'f1')
403
404
        a2 = StringIO('adding more\ntext to two\n')
405
        a3 = StringIO('some garbage\nto put in three\n')
406
407
        if t.is_readonly():
408
            _append('f2', a2)
409
            _append('f3', a3)
410
        else:
411
            t.append_multi([('f2', a2), ('f3', a3)])
412
413
        del a2, a3
414
415
        self.check_transport_contents(
416
                'here is some text\nand a bit more\n'
417
                'adding more\ntext to two\n',
418
                t, 'f2')
419
        self.check_transport_contents( 
420
                'some text for the\nthird file created\n'
421
                'some garbage\nto put in three\n',
422
                t, 'f3')
423
424
        # Test that an actual file object can be used with put
425
        a4 = t.get('f1')
426
        if t.is_readonly():
427
            _append('f4', a4)
428
        else:
429
            t.append('f4', a4)
430
431
        del a4
432
433
        self.check_transport_contents(
434
                'this is a string\nand some more stuff\n'
435
                'this is a string\nand some more stuff\n'
436
                'appending to\none\n',
437
                t, 'f4')
438
439
        a5 = t.get('f2')
440
        a6 = t.get('f3')
441
        if t.is_readonly():
442
            _append('f5', a5)
443
            _append('f6', a6)
444
        else:
445
            t.append_multi([('f5', a5), ('f6', a6)])
446
447
        del a5, a6
448
449
        self.check_transport_contents(
450
                'here is some text\nand a bit more\n'
451
                'here is some text\nand a bit more\n'
452
                'adding more\ntext to two\n',
453
                t, 'f5')
454
        self.check_transport_contents(
455
                'some text for the\nthird file created\n'
456
                'some text for the\nthird file created\n'
457
                'some garbage\nto put in three\n',
458
                t, 'f6')
459
460
        a5 = t.get('f2')
461
        a6 = t.get('f2')
462
        a7 = t.get('f3')
463
        if t.is_readonly():
464
            _append('c', a5)
465
            _append('a', a6)
466
            _append('d', a7)
467
        else:
468
            t.append('c', a5)
469
            t.append_multi([('a', a6), ('d', a7)])
470
        del a5, a6, a7
471
        self.check_transport_contents(t.get('f2').read(), t, 'c')
472
        self.check_transport_contents(t.get('f3').read(), t, 'd')
473
1666.1.6 by Robert Collins
Make knit the default format.
474
    def test_append_mode(self):
475
        # check append accepts a mode
476
        t = self.get_transport()
477
        if t.is_readonly():
478
            return
479
        t.append('f', StringIO('f'), mode=None)
480
        
1530.1.3 by Robert Collins
transport implementations now tested consistently.
481
    def test_delete(self):
482
        # TODO: Test Transport.delete
483
        t = self.get_transport()
484
485
        # Not much to do with a readonly transport
486
        if t.is_readonly():
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
487
            self.assertRaises(TransportNotPossible, t.delete, 'missing')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
488
            return
489
490
        t.put('a', StringIO('a little bit of text\n'))
491
        self.failUnless(t.has('a'))
492
        t.delete('a')
493
        self.failIf(t.has('a'))
494
495
        self.assertRaises(NoSuchFile, t.delete, 'a')
496
497
        t.put('a', StringIO('a text\n'))
498
        t.put('b', StringIO('b text\n'))
499
        t.put('c', StringIO('c text\n'))
500
        self.assertEqual([True, True, True],
501
                list(t.has_multi(['a', 'b', 'c'])))
502
        t.delete_multi(['a', 'c'])
503
        self.assertEqual([False, True, False],
504
                list(t.has_multi(['a', 'b', 'c'])))
505
        self.failIf(t.has('a'))
506
        self.failUnless(t.has('b'))
507
        self.failIf(t.has('c'))
508
509
        self.assertRaises(NoSuchFile,
510
                t.delete_multi, ['a', 'b', 'c'])
511
512
        self.assertRaises(NoSuchFile,
513
                t.delete_multi, iter(['a', 'b', 'c']))
514
515
        t.put('a', StringIO('another a text\n'))
516
        t.put('c', StringIO('another c text\n'))
517
        t.delete_multi(iter(['a', 'b', 'c']))
518
519
        # We should have deleted everything
520
        # SftpServer creates control files in the
521
        # working directory, so we can just do a
522
        # plain "listdir".
523
        # self.assertEqual([], os.listdir('.'))
524
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
525
    def test_rmdir(self):
526
        t = self.get_transport()
527
        # Not much to do with a readonly transport
528
        if t.is_readonly():
529
            self.assertRaises(TransportNotPossible, t.rmdir, 'missing')
530
            return
531
        t.mkdir('adir')
532
        t.mkdir('adir/bdir')
533
        t.rmdir('adir/bdir')
534
        self.assertRaises(NoSuchFile, t.stat, 'adir/bdir')
535
        t.rmdir('adir')
536
        self.assertRaises(NoSuchFile, t.stat, 'adir')
537
1553.5.10 by Martin Pool
New DirectoryNotEmpty exception, and raise this from local and memory
538
    def test_rmdir_not_empty(self):
539
        """Deleting a non-empty directory raises an exception
540
        
541
        sftp (and possibly others) don't give us a specific "directory not
542
        empty" exception -- we can just see that the operation failed.
543
        """
544
        t = self.get_transport()
545
        if t.is_readonly():
546
            return
547
        t.mkdir('adir')
548
        t.mkdir('adir/bdir')
549
        self.assertRaises(PathError, t.rmdir, 'adir')
550
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
551
    def test_rename_dir_succeeds(self):
552
        t = self.get_transport()
553
        if t.is_readonly():
554
            raise TestSkipped("transport is readonly")
555
        t.mkdir('adir')
556
        t.mkdir('adir/asubdir')
557
        t.rename('adir', 'bdir')
558
        self.assertTrue(t.has('bdir/asubdir'))
559
        self.assertFalse(t.has('adir'))
560
561
    def test_rename_dir_nonempty(self):
562
        """Attempting to replace a nonemtpy directory should fail"""
563
        t = self.get_transport()
564
        if t.is_readonly():
565
            raise TestSkipped("transport is readonly")
566
        t.mkdir('adir')
567
        t.mkdir('adir/asubdir')
568
        t.mkdir('bdir')
569
        t.mkdir('bdir/bsubdir')
570
        self.assertRaises(PathError, t.rename, 'bdir', 'adir')
571
        # nothing was changed so it should still be as before
572
        self.assertTrue(t.has('bdir/bsubdir'))
573
        self.assertFalse(t.has('adir/bdir'))
574
        self.assertFalse(t.has('adir/bsubdir'))
575
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
576
    def test_delete_tree(self):
577
        t = self.get_transport()
578
579
        # Not much to do with a readonly transport
580
        if t.is_readonly():
581
            self.assertRaises(TransportNotPossible, t.delete_tree, 'missing')
582
            return
583
584
        # and does it like listing ?
585
        t.mkdir('adir')
586
        try:
587
            t.delete_tree('adir')
588
        except TransportNotPossible:
589
            # ok, this transport does not support delete_tree
590
            return
591
        
592
        # did it delete that trivial case?
593
        self.assertRaises(NoSuchFile, t.stat, 'adir')
594
595
        self.build_tree(['adir/',
596
                         'adir/file', 
597
                         'adir/subdir/', 
598
                         'adir/subdir/file', 
599
                         'adir/subdir2/',
600
                         'adir/subdir2/file',
601
                         ], transport=t)
602
603
        t.delete_tree('adir')
604
        # adir should be gone now.
605
        self.assertRaises(NoSuchFile, t.stat, 'adir')
606
1530.1.3 by Robert Collins
transport implementations now tested consistently.
607
    def test_move(self):
608
        t = self.get_transport()
609
610
        if t.is_readonly():
611
            return
612
613
        # TODO: I would like to use os.listdir() to
614
        # make sure there are no extra files, but SftpServer
615
        # creates control files in the working directory
616
        # perhaps all of this could be done in a subdirectory
617
618
        t.put('a', StringIO('a first file\n'))
619
        self.assertEquals([True, False], list(t.has_multi(['a', 'b'])))
620
621
        t.move('a', 'b')
622
        self.failUnless(t.has('b'))
623
        self.failIf(t.has('a'))
624
625
        self.check_transport_contents('a first file\n', t, 'b')
626
        self.assertEquals([False, True], list(t.has_multi(['a', 'b'])))
627
628
        # Overwrite a file
629
        t.put('c', StringIO('c this file\n'))
630
        t.move('c', 'b')
631
        self.failIf(t.has('c'))
632
        self.check_transport_contents('c this file\n', t, 'b')
633
634
        # TODO: Try to write a test for atomicity
635
        # TODO: Test moving into a non-existant subdirectory
636
        # TODO: Test Transport.move_multi
637
638
    def test_copy(self):
639
        t = self.get_transport()
640
641
        if t.is_readonly():
642
            return
643
644
        t.put('a', StringIO('a file\n'))
645
        t.copy('a', 'b')
646
        self.check_transport_contents('a file\n', t, 'b')
647
648
        self.assertRaises(NoSuchFile, t.copy, 'c', 'd')
649
        os.mkdir('c')
650
        # What should the assert be if you try to copy a
651
        # file over a directory?
652
        #self.assertRaises(Something, t.copy, 'a', 'c')
653
        t.put('d', StringIO('text in d\n'))
654
        t.copy('d', 'b')
655
        self.check_transport_contents('text in d\n', t, 'b')
656
657
        # TODO: test copy_multi
658
659
    def test_connection_error(self):
660
        """ConnectionError is raised when connection is impossible"""
1530.1.9 by Robert Collins
Test bogus urls with http in the new infrastructure.
661
        try:
662
            url = self._server.get_bogus_url()
663
        except NotImplementedError:
664
            raise TestSkipped("Transport %s has no bogus URL support." %
665
                              self._server.__class__)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
666
        try:
1711.2.42 by John Arbash Meinel
enable bogus_url support for SFTP tests
667
            t = bzrlib.transport.get_transport(url)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
668
            t.get('.bzr/branch')
669
        except (ConnectionError, NoSuchFile), e:
670
            pass
671
        except (Exception), e:
1786.1.27 by John Arbash Meinel
Fix up the http transports so that tests pass with the new configuration.
672
            self.fail('Wrong exception thrown (%s.%s): %s' 
673
                        % (e.__class__.__module__, e.__class__.__name__, e))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
674
        else:
1707.3.11 by John Arbash Meinel
fixing more tests.
675
            self.fail('Did not get the expected ConnectionError or NoSuchFile.')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
676
677
    def test_stat(self):
678
        # TODO: Test stat, just try once, and if it throws, stop testing
679
        from stat import S_ISDIR, S_ISREG
680
681
        t = self.get_transport()
682
683
        try:
684
            st = t.stat('.')
685
        except TransportNotPossible, e:
686
            # This transport cannot stat
687
            return
688
689
        paths = ['a', 'b/', 'b/c', 'b/d/', 'b/d/e']
690
        sizes = [14, 0, 16, 0, 18] 
1551.2.39 by abentley
Fix line endings in tests
691
        self.build_tree(paths, transport=t, line_endings='binary')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
692
693
        for path, size in zip(paths, sizes):
694
            st = t.stat(path)
695
            if path.endswith('/'):
696
                self.failUnless(S_ISDIR(st.st_mode))
697
                # directory sizes are meaningless
698
            else:
699
                self.failUnless(S_ISREG(st.st_mode))
700
                self.assertEqual(size, st.st_size)
701
702
        remote_stats = list(t.stat_multi(paths))
703
        remote_iter_stats = list(t.stat_multi(iter(paths)))
704
705
        self.assertRaises(NoSuchFile, t.stat, 'q')
706
        self.assertRaises(NoSuchFile, t.stat, 'b/a')
707
708
        self.assertListRaises(NoSuchFile, t.stat_multi, ['a', 'c', 'd'])
709
        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.
710
        self.build_tree(['subdir/', 'subdir/file'], transport=t)
711
        subdir = t.clone('subdir')
712
        subdir.stat('./file')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
713
        subdir.stat('.')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
714
715
    def test_list_dir(self):
716
        # TODO: Test list_dir, just try once, and if it throws, stop testing
717
        t = self.get_transport()
718
        
719
        if not t.listable():
720
            self.assertRaises(TransportNotPossible, t.list_dir, '.')
721
            return
722
723
        def sorted_list(d):
724
            l = list(t.list_dir(d))
725
            l.sort()
726
            return l
727
728
        # SftpServer creates control files in the working directory
729
        # so lets move down a directory to avoid those.
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
730
        if not t.is_readonly():
731
            t.mkdir('wd')
732
        else:
733
            os.mkdir('wd')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
734
        t = t.clone('wd')
735
736
        self.assertEqual([], sorted_list(u'.'))
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
737
        # c2 is precisely one letter longer than c here to test that
738
        # suffixing is not confused.
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
739
        if not t.is_readonly():
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
740
            self.build_tree(['a', 'b', 'c/', 'c/d', 'c/e', 'c2/'], transport=t)
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
741
        else:
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
742
            self.build_tree(['wd/a', 'wd/b', 'wd/c/', 'wd/c/d', 'wd/c/e', 'wd/c2/'])
1530.1.3 by Robert Collins
transport implementations now tested consistently.
743
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
744
        self.assertEqual([u'a', u'b', u'c', u'c2'], sorted_list(u'.'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
745
        self.assertEqual([u'd', u'e'], sorted_list(u'c'))
746
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
747
        if not t.is_readonly():
748
            t.delete('c/d')
749
            t.delete('b')
750
        else:
751
            os.unlink('wd/c/d')
752
            os.unlink('wd/b')
753
            
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
754
        self.assertEqual([u'a', u'c', u'c2'], sorted_list('.'))
1530.1.3 by Robert Collins
transport implementations now tested consistently.
755
        self.assertEqual([u'e'], sorted_list(u'c'))
756
1662.1.12 by Martin Pool
Translate unknown sftp errors to PathError, no NoSuchFile
757
        self.assertListRaises(PathError, t.list_dir, 'q')
758
        self.assertListRaises(PathError, t.list_dir, 'c/f')
759
        self.assertListRaises(PathError, t.list_dir, 'a')
1530.1.3 by Robert Collins
transport implementations now tested consistently.
760
761
    def test_clone(self):
762
        # TODO: Test that clone moves up and down the filesystem
763
        t1 = self.get_transport()
764
765
        self.build_tree(['a', 'b/', 'b/c'], transport=t1)
766
767
        self.failUnless(t1.has('a'))
768
        self.failUnless(t1.has('b/c'))
769
        self.failIf(t1.has('c'))
770
771
        t2 = t1.clone('b')
772
        self.assertEqual(t1.base + 'b/', t2.base)
773
774
        self.failUnless(t2.has('c'))
775
        self.failIf(t2.has('a'))
776
777
        t3 = t2.clone('..')
778
        self.failUnless(t3.has('a'))
779
        self.failIf(t3.has('c'))
780
781
        self.failIf(t1.has('b/d'))
782
        self.failIf(t2.has('d'))
783
        self.failIf(t3.has('b/d'))
784
785
        if t1.is_readonly():
786
            open('b/d', 'wb').write('newfile\n')
787
        else:
788
            t2.put('d', StringIO('newfile\n'))
789
790
        self.failUnless(t1.has('b/d'))
791
        self.failUnless(t2.has('d'))
792
        self.failUnless(t3.has('b/d'))
793
794
    def test_relpath(self):
795
        t = self.get_transport()
796
        self.assertEqual('', t.relpath(t.base))
797
        # base ends with /
798
        self.assertEqual('', t.relpath(t.base[:-1]))
799
        # subdirs which dont exist should still give relpaths.
800
        self.assertEqual('foo', t.relpath(t.base + 'foo'))
801
        # trailing slash should be the same.
802
        self.assertEqual('foo', t.relpath(t.base + 'foo/'))
803
1636.1.1 by Robert Collins
Fix calling relpath() and abspath() on transports at their root.
804
    def test_relpath_at_root(self):
805
        t = self.get_transport()
806
        # clone all the way to the top
807
        new_transport = t.clone('..')
808
        while new_transport.base != t.base:
809
            t = new_transport
810
            new_transport = t.clone('..')
811
        # we must be able to get a relpath below the root
812
        self.assertEqual('', t.relpath(t.base))
813
        # and a deeper one should work too
814
        self.assertEqual('foo/bar', t.relpath(t.base + 'foo/bar'))
815
1530.1.3 by Robert Collins
transport implementations now tested consistently.
816
    def test_abspath(self):
817
        # smoke test for abspath. Corner cases for backends like unix fs's
818
        # that have aliasing problems like symlinks should go in backend
819
        # specific test cases.
820
        transport = self.get_transport()
1540.3.24 by Martin Pool
Add new protocol 'http+pycurl' that always uses PyCurl.
821
        
822
        # disabled because some transports might normalize urls in generating
823
        # the abspath - eg http+pycurl-> just http -- mbp 20060308 
1530.1.3 by Robert Collins
transport implementations now tested consistently.
824
        self.assertEqual(transport.base + 'relpath',
825
                         transport.abspath('relpath'))
826
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
827
    def test_local_abspath(self):
828
        transport = self.get_transport()
829
        try:
830
            p = transport.local_abspath('.')
831
        except TransportNotPossible:
832
            pass # This is not a local transport
833
        else:
834
            self.assertEqual(getcwd(), p)
835
1636.1.1 by Robert Collins
Fix calling relpath() and abspath() on transports at their root.
836
    def test_abspath_at_root(self):
837
        t = self.get_transport()
838
        # clone all the way to the top
839
        new_transport = t.clone('..')
840
        while new_transport.base != t.base:
841
            t = new_transport
842
            new_transport = t.clone('..')
843
        # we must be able to get a abspath of the root when we ask for
844
        # t.abspath('..') - this due to our choice that clone('..')
845
        # should return the root from the root, combined with the desire that
846
        # the url from clone('..') and from abspath('..') should be the same.
847
        self.assertEqual(t.base, t.abspath('..'))
848
        # '' should give us the root
849
        self.assertEqual(t.base, t.abspath(''))
850
        # and a path should append to the url
851
        self.assertEqual(t.base + 'foo', t.abspath('foo'))
852
1530.1.3 by Robert Collins
transport implementations now tested consistently.
853
    def test_iter_files_recursive(self):
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
854
        transport = self.get_transport()
855
        if not transport.listable():
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
856
            self.assertRaises(TransportNotPossible,
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
857
                              transport.iter_files_recursive)
858
            return
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
859
        self.build_tree(['isolated/',
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
860
                         'isolated/dir/',
861
                         'isolated/dir/foo',
862
                         'isolated/dir/bar',
863
                         'isolated/bar'],
864
                        transport=transport)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
865
        paths = set(transport.iter_files_recursive())
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
866
        # nb the directories are not converted
867
        self.assertEqual(paths,
868
                    set(['isolated/dir/foo',
869
                         'isolated/dir/bar',
870
                         'isolated/bar']))
871
        sub_transport = transport.clone('isolated')
872
        paths = set(sub_transport.iter_files_recursive())
1530.1.3 by Robert Collins
transport implementations now tested consistently.
873
        self.assertEqual(set(['dir/foo', 'dir/bar', 'bar']), paths)
1185.85.76 by John Arbash Meinel
Adding an InvalidURL so transports can report they expect utf-8 quoted paths. Updated tests
874
875
    def test_unicode_paths(self):
1685.1.57 by Martin Pool
[broken] Skip unicode blackbox tests if not supported by filesystem
876
        """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
877
        t = self.get_transport()
878
1711.7.36 by John Arbash Meinel
Use different filenames to avoid path collisions on win32 w/ FAT32
879
        # With FAT32 and certain encodings on win32
880
        # '\xe5' and '\xe4' actually map to the same file
881
        # adding a suffix kicks in the 'preserving but insensitive'
882
        # route, and maintains the right files
883
        files = [u'\xe5.1', # a w/ circle iso-8859-1
884
                 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
885
                 u'\u017d', # Z with umlat iso-8859-2
886
                 u'\u062c', # Arabic j
887
                 u'\u0410', # Russian A
888
                 u'\u65e5', # Kanji person
889
                ]
890
1685.1.72 by Wouter van Heyst
StubSFTPServer should use bytestreams rather than unicode
891
        try:
1711.4.13 by John Arbash Meinel
Use line_endings='binary' for win32
892
            self.build_tree(files, transport=t, line_endings='binary')
1685.1.72 by Wouter van Heyst
StubSFTPServer should use bytestreams rather than unicode
893
        except UnicodeError:
894
            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
895
896
        # A plain unicode string is not a valid url
897
        for fname in files:
898
            self.assertRaises(InvalidURL, t.get, fname)
899
900
        for fname in files:
901
            fname_utf8 = fname.encode('utf-8')
902
            contents = 'contents of %s\n' % (fname_utf8,)
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
903
            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
904
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
905
    def test_connect_twice_is_same_content(self):
906
        # check that our server (whatever it is) is accessable reliably
907
        # via get_transport and multiple connections share content.
908
        transport = self.get_transport()
909
        if transport.is_readonly():
910
            return
911
        transport.put('foo', StringIO('bar'))
912
        transport2 = self.get_transport()
913
        self.check_transport_contents('bar', transport2, 'foo')
914
        # its base should be usable.
915
        transport2 = bzrlib.transport.get_transport(transport.base)
916
        self.check_transport_contents('bar', transport2, 'foo')
917
918
        # now opening at a relative url should give use a sane result:
919
        transport.mkdir('newdir')
920
        transport2 = bzrlib.transport.get_transport(transport.base + "newdir")
921
        transport2 = transport2.clone('..')
922
        self.check_transport_contents('bar', transport2, 'foo')
923
924
    def test_lock_write(self):
925
        transport = self.get_transport()
926
        if transport.is_readonly():
927
            self.assertRaises(TransportNotPossible, transport.lock_write, 'foo')
928
            return
929
        transport.put('lock', StringIO())
930
        lock = transport.lock_write('lock')
931
        # TODO make this consistent on all platforms:
932
        # self.assertRaises(LockError, transport.lock_write, 'lock')
933
        lock.unlock()
934
935
    def test_lock_read(self):
936
        transport = self.get_transport()
937
        if transport.is_readonly():
938
            file('lock', 'w').close()
939
        else:
940
            transport.put('lock', StringIO())
941
        lock = transport.lock_read('lock')
942
        # TODO make this consistent on all platforms:
943
        # self.assertRaises(LockError, transport.lock_read, 'lock')
944
        lock.unlock()
1185.85.80 by John Arbash Meinel
[merge] jam-integration 1527, including branch-formats, help text, misc bug fixes.
945
1594.2.5 by Robert Collins
Readv patch from Johan Rydberg giving knits partial download support.
946
    def test_readv(self):
947
        transport = self.get_transport()
948
        if transport.is_readonly():
949
            file('a', 'w').write('0123456789')
950
        else:
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
951
            transport.put('a', StringIO('0123456789'))
1185.85.76 by John Arbash Meinel
Adding an InvalidURL so transports can report they expect utf-8 quoted paths. Updated tests
952
1594.2.17 by Robert Collins
Better readv coalescing, now with test, and progress during knit index reading.
953
        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.
954
        self.assertEqual(d[0], (0, '0'))
1594.2.17 by Robert Collins
Better readv coalescing, now with test, and progress during knit index reading.
955
        self.assertEqual(d[1], (1, '1'))
956
        self.assertEqual(d[2], (3, '34'))
957
        self.assertEqual(d[3], (9, '9'))
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
958
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
959
    def test_readv_out_of_order(self):
960
        transport = self.get_transport()
961
        if transport.is_readonly():
962
            file('a', 'w').write('0123456789')
963
        else:
964
            transport.put('a', StringIO('01234567890'))
965
966
        d = list(transport.readv('a', ((1, 1), (9, 1), (0, 1), (3, 2))))
967
        self.assertEqual(d[0], (1, '1'))
968
        self.assertEqual(d[1], (9, '9'))
969
        self.assertEqual(d[2], (0, '0'))
970
        self.assertEqual(d[3], (3, '34'))