~bzr-pqm/bzr/bzr.dev

1540.3.23 by Martin Pool
Allow urls like http+pycurl://host/ to use a particular impl
1
# Copyright (C) 2004, 2005, 2006 by Canonical Ltd
907.1.48 by John Arbash Meinel
Updated LocalTransport by passing it through the transport_test suite, and got it to pass.
2
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.
7
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.
12
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
1185.11.22 by John Arbash Meinel
Major refactoring of testtransport.
18
import os
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
19
import sys
1185.58.4 by John Arbash Meinel
Added permission checking to Branch, and propogated that change into the stores.
20
import stat
1185.11.22 by John Arbash Meinel
Major refactoring of testtransport.
21
from cStringIO import StringIO
1442.1.44 by Robert Collins
Many transport related tweaks:
22
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
23
import bzrlib
1185.50.13 by John Arbash Meinel
Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform.
24
from bzrlib.errors import (NoSuchFile, FileExists,
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
25
                           TransportNotPossible,
26
                           ConnectionError,
27
                           DependencyNotPresent,
1685.1.1 by John Arbash Meinel
[merge] the old bzr-encoding changes, reparenting them on bzr.dev
28
                           InvalidURL,
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
29
                           )
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
30
from bzrlib.tests import TestCase, TestCaseInTempDir
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
31
from bzrlib.transport import (_get_protocol_handlers,
32
                              _get_transport_modules,
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
33
                              get_transport,
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
34
                              register_lazy_transport,
35
                              _set_protocol_handlers,
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
36
                              Transport,
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
37
                              )
1540.3.6 by Martin Pool
[merge] update from bzr.dev
38
from bzrlib.transport.memory import MemoryTransport
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
39
from bzrlib.transport.local import LocalTransport
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
40
41
1185.58.3 by John Arbash Meinel
code cleanup
42
class TestTransport(TestCase):
43
    """Test the non transport-concrete class functionality."""
44
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
45
    def test__get_set_protocol_handlers(self):
46
        handlers = _get_protocol_handlers()
47
        self.assertNotEqual({}, handlers)
48
        try:
49
            _set_protocol_handlers({})
50
            self.assertEqual({}, _get_protocol_handlers())
51
        finally:
52
            _set_protocol_handlers(handlers)
53
54
    def test_get_transport_modules(self):
55
        handlers = _get_protocol_handlers()
56
        class SampleHandler(object):
57
            """I exist, isnt that enough?"""
58
        try:
59
            my_handlers = {}
60
            _set_protocol_handlers(my_handlers)
61
            register_lazy_transport('foo', 'bzrlib.tests.test_transport', 'TestTransport.SampleHandler')
62
            register_lazy_transport('bar', 'bzrlib.tests.test_transport', 'TestTransport.SampleHandler')
63
            self.assertEqual([SampleHandler.__module__],
64
                             _get_transport_modules())
65
        finally:
66
            _set_protocol_handlers(handlers)
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
67
68
    def test_transport_dependency(self):
69
        """Transport with missing dependency causes no error"""
70
        saved_handlers = _get_protocol_handlers()
71
        try:
72
            register_lazy_transport('foo', 'bzrlib.tests.test_transport',
73
                    'BadTransportHandler')
1685.1.32 by John Arbash Meinel
When unable to find an appropriate protocol, we now raise InvalidURL rather than always returning LocalTransport
74
            # TODO: jam 20060427 Now we get InvalidURL because it looks like 
75
            #       a URL but we have no support for it.
76
            #       Is it better to always fall back to LocalTransport?
77
            #       I think this is a better error than a future NoSuchFile
78
            self.assertRaises(InvalidURL, get_transport, 'foo://fooserver/foo')
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
79
        finally:
1540.3.10 by Martin Pool
[broken] keep hooking pycurl into test framework
80
            # restore original values
81
            _set_protocol_handlers(saved_handlers)
82
            
83
    def test_transport_fallback(self):
84
        """Transport with missing dependency causes no error"""
85
        saved_handlers = _get_protocol_handlers()
86
        try:
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
87
            _set_protocol_handlers({})
1540.3.10 by Martin Pool
[broken] keep hooking pycurl into test framework
88
            register_lazy_transport('foo', 'bzrlib.tests.test_transport',
89
                    'BackupTransportHandler')
90
            register_lazy_transport('foo', 'bzrlib.tests.test_transport',
91
                    'BadTransportHandler')
92
            t = get_transport('foo://fooserver/foo')
93
            self.assertTrue(isinstance(t, BackupTransportHandler))
94
        finally:
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
95
            _set_protocol_handlers(saved_handlers)
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
96
            
1540.3.3 by Martin Pool
Review updates of pycurl transport
97
1442.1.44 by Robert Collins
Many transport related tweaks:
98
class TestMemoryTransport(TestCase):
99
100
    def test_get_transport(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
101
        MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
102
103
    def test_clone(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
104
        transport = MemoryTransport()
105
        self.assertTrue(isinstance(transport, MemoryTransport))
1442.1.44 by Robert Collins
Many transport related tweaks:
106
107
    def test_abspath(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
108
        transport = MemoryTransport()
1685.1.42 by John Arbash Meinel
A couple more fixes to make sure memory:/// works correctly.
109
        self.assertEqual("memory:///relpath", transport.abspath('relpath'))
1442.1.44 by Robert Collins
Many transport related tweaks:
110
111
    def test_relpath(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
112
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
113
114
    def test_append_and_get(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
115
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
116
        transport.append('path', StringIO('content'))
117
        self.assertEqual(transport.get('path').read(), 'content')
118
        transport.append('path', StringIO('content'))
119
        self.assertEqual(transport.get('path').read(), 'contentcontent')
120
121
    def test_put_and_get(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
122
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
123
        transport.put('path', StringIO('content'))
124
        self.assertEqual(transport.get('path').read(), 'content')
125
        transport.put('path', StringIO('content'))
126
        self.assertEqual(transport.get('path').read(), 'content')
127
128
    def test_append_without_dir_fails(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
129
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
130
        self.assertRaises(NoSuchFile,
131
                          transport.append, 'dir/path', StringIO('content'))
132
133
    def test_put_without_dir_fails(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
134
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
135
        self.assertRaises(NoSuchFile,
136
                          transport.put, 'dir/path', StringIO('content'))
137
138
    def test_get_missing(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
139
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
140
        self.assertRaises(NoSuchFile, transport.get, 'foo')
141
142
    def test_has_missing(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
143
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
144
        self.assertEquals(False, transport.has('foo'))
145
146
    def test_has_present(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
147
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
148
        transport.append('foo', StringIO('content'))
149
        self.assertEquals(True, transport.has('foo'))
150
151
    def test_mkdir(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
152
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
153
        transport.mkdir('dir')
154
        transport.append('dir/path', StringIO('content'))
155
        self.assertEqual(transport.get('dir/path').read(), 'content')
156
157
    def test_mkdir_missing_parent(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
158
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
159
        self.assertRaises(NoSuchFile,
160
                          transport.mkdir, 'dir/dir')
161
162
    def test_mkdir_twice(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
163
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
164
        transport.mkdir('dir')
165
        self.assertRaises(FileExists, transport.mkdir, 'dir')
1530.1.5 by Robert Collins
Reinstate Memory parameter tests.
166
167
    def test_parameters(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
168
        transport = MemoryTransport()
1530.1.5 by Robert Collins
Reinstate Memory parameter tests.
169
        self.assertEqual(True, transport.listable())
170
        self.assertEqual(False, transport.should_cache())
171
        self.assertEqual(False, transport.is_readonly())
1442.1.44 by Robert Collins
Many transport related tweaks:
172
173
    def test_iter_files_recursive(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
174
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
175
        transport.mkdir('dir')
176
        transport.put('dir/foo', StringIO('content'))
177
        transport.put('dir/bar', StringIO('content'))
178
        transport.put('bar', StringIO('content'))
179
        paths = set(transport.iter_files_recursive())
180
        self.assertEqual(set(['dir/foo', 'dir/bar', 'bar']), paths)
181
182
    def test_stat(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
183
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
184
        transport.put('foo', StringIO('content'))
185
        transport.put('bar', StringIO('phowar'))
186
        self.assertEqual(7, transport.stat('foo').st_size)
187
        self.assertEqual(6, transport.stat('bar').st_size)
1185.35.31 by Aaron Bentley
Throw ConnectionError instead of NoSuchFile except when we get a 404
188
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
189
        
190
class ReadonlyDecoratorTransportTest(TestCase):
191
    """Readonly decoration specific tests."""
192
193
    def test_local_parameters(self):
194
        import bzrlib.transport.readonly as readonly
195
        # connect to . in readonly mode
196
        transport = readonly.ReadonlyTransportDecorator('readonly+.')
197
        self.assertEqual(True, transport.listable())
198
        self.assertEqual(False, transport.should_cache())
199
        self.assertEqual(True, transport.is_readonly())
200
201
    def test_http_parameters(self):
202
        import bzrlib.transport.readonly as readonly
203
        from bzrlib.transport.http import HttpServer
204
        # connect to . via http which is not listable
205
        server = HttpServer()
206
        server.setUp()
207
        try:
208
            transport = get_transport('readonly+' + server.get_url())
209
            self.failUnless(isinstance(transport,
210
                                       readonly.ReadonlyTransportDecorator))
211
            self.assertEqual(False, transport.listable())
212
            self.assertEqual(True, transport.should_cache())
213
            self.assertEqual(True, transport.is_readonly())
214
        finally:
215
            server.tearDown()
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
216
217
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
218
class FakeNFSDecoratorTests(TestCaseInTempDir):
219
    """NFS decorator specific tests."""
220
221
    def get_nfs_transport(self, url):
222
        import bzrlib.transport.fakenfs as fakenfs
223
        # connect to url with nfs decoration
224
        return fakenfs.FakeNFSTransportDecorator('fakenfs+' + url)
225
226
    def test_local_parameters(self):
227
        # the listable, should_cache and is_readonly parameters
228
        # are not changed by the fakenfs decorator
229
        transport = self.get_nfs_transport('.')
230
        self.assertEqual(True, transport.listable())
231
        self.assertEqual(False, transport.should_cache())
232
        self.assertEqual(False, transport.is_readonly())
233
234
    def test_http_parameters(self):
235
        # the listable, should_cache and is_readonly parameters
236
        # are not changed by the fakenfs decorator
237
        from bzrlib.transport.http import HttpServer
238
        # connect to . via http which is not listable
239
        server = HttpServer()
240
        server.setUp()
241
        try:
242
            transport = self.get_nfs_transport(server.get_url())
243
            self.assertIsInstance(
244
                transport, bzrlib.transport.fakenfs.FakeNFSTransportDecorator)
245
            self.assertEqual(False, transport.listable())
246
            self.assertEqual(True, transport.should_cache())
247
            self.assertEqual(True, transport.is_readonly())
248
        finally:
249
            server.tearDown()
250
251
    def test_fakenfs_server_default(self):
252
        # a FakeNFSServer() should bring up a local relpath server for itself
253
        import bzrlib.transport.fakenfs as fakenfs
254
        server = fakenfs.FakeNFSServer()
255
        server.setUp()
256
        try:
257
            # the server should be a relpath localhost server
258
            self.assertEqual(server.get_url(), 'fakenfs+.')
259
            # and we should be able to get a transport for it
260
            transport = get_transport(server.get_url())
261
            # which must be a FakeNFSTransportDecorator instance.
262
            self.assertIsInstance(
263
                transport, fakenfs.FakeNFSTransportDecorator)
264
        finally:
265
            server.tearDown()
266
267
    def test_fakenfs_rename_semantics(self):
268
        # a FakeNFS transport must mangle the way rename errors occur to
269
        # look like NFS problems.
270
        transport = self.get_nfs_transport('.')
271
        self.build_tree(['from/', 'from/foo', 'to/', 'to/bar'],
272
                        transport=transport)
273
        self.assertRaises(bzrlib.errors.ResourceBusy,
274
                          transport.rename, 'from', 'to')
275
276
1608.2.4 by Martin Pool
[broken] Add FakeFVATTransport
277
class FakeVFATDecoratorTests(TestCaseInTempDir):
278
    """Tests for simulation of VFAT restrictions"""
279
280
    def get_vfat_transport(self, url):
281
        """Return vfat-backed transport for test directory"""
282
        from bzrlib.transport.fakevfat import FakeVFATTransportDecorator
283
        return FakeVFATTransportDecorator('vfat+' + url)
284
285
    def test_transport_creation(self):
286
        from bzrlib.transport.fakevfat import FakeVFATTransportDecorator
287
        transport = self.get_vfat_transport('.')
288
        self.assertIsInstance(transport, FakeVFATTransportDecorator)
289
290
    def test_transport_mkdir(self):
291
        transport = self.get_vfat_transport('.')
292
        transport.mkdir('HELLO')
293
        self.assertTrue(transport.has('hello'))
294
        self.assertTrue(transport.has('Hello'))
295
1608.2.11 by Martin Pool
(FakeVFAT) add test for detection of invalid characters
296
    def test_forbidden_chars(self):
297
        transport = self.get_vfat_transport('.')
298
        self.assertRaises(ValueError, transport.has, "<NU>")
299
300
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
301
class BadTransportHandler(Transport):
302
    def __init__(self, base_url):
303
        raise DependencyNotPresent('some_lib', 'testing missing dependency')
304
305
306
class BackupTransportHandler(Transport):
307
    """Test transport that works as a backup for the BadTransportHandler"""
1540.3.10 by Martin Pool
[broken] keep hooking pycurl into test framework
308
    pass