~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,
28
                           )
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
29
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.
30
from bzrlib.transport import (_get_protocol_handlers,
31
                              _get_transport_modules,
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
32
                              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.
33
                              register_lazy_transport,
34
                              _set_protocol_handlers,
35
                              urlescape,
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
45
    def test_urlescape(self):
46
        self.assertEqual('%25', urlescape('%'))
47
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.
48
    def test__get_set_protocol_handlers(self):
49
        handlers = _get_protocol_handlers()
50
        self.assertNotEqual({}, handlers)
51
        try:
52
            _set_protocol_handlers({})
53
            self.assertEqual({}, _get_protocol_handlers())
54
        finally:
55
            _set_protocol_handlers(handlers)
56
57
    def test_get_transport_modules(self):
58
        handlers = _get_protocol_handlers()
59
        class SampleHandler(object):
60
            """I exist, isnt that enough?"""
61
        try:
62
            my_handlers = {}
63
            _set_protocol_handlers(my_handlers)
64
            register_lazy_transport('foo', 'bzrlib.tests.test_transport', 'TestTransport.SampleHandler')
65
            register_lazy_transport('bar', 'bzrlib.tests.test_transport', 'TestTransport.SampleHandler')
66
            self.assertEqual([SampleHandler.__module__],
67
                             _get_transport_modules())
68
        finally:
69
            _set_protocol_handlers(handlers)
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
70
71
    def test_transport_dependency(self):
72
        """Transport with missing dependency causes no error"""
73
        saved_handlers = _get_protocol_handlers()
74
        try:
75
            register_lazy_transport('foo', 'bzrlib.tests.test_transport',
76
                    'BadTransportHandler')
77
            t = get_transport('foo://fooserver/foo')
78
            # because we failed to load the transport
79
            self.assertTrue(isinstance(t, LocalTransport))
80
        finally:
1540.3.10 by Martin Pool
[broken] keep hooking pycurl into test framework
81
            # restore original values
82
            _set_protocol_handlers(saved_handlers)
83
            
84
    def test_transport_fallback(self):
85
        """Transport with missing dependency causes no error"""
86
        saved_handlers = _get_protocol_handlers()
87
        try:
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
88
            _set_protocol_handlers({})
1540.3.10 by Martin Pool
[broken] keep hooking pycurl into test framework
89
            register_lazy_transport('foo', 'bzrlib.tests.test_transport',
90
                    'BackupTransportHandler')
91
            register_lazy_transport('foo', 'bzrlib.tests.test_transport',
92
                    'BadTransportHandler')
93
            t = get_transport('foo://fooserver/foo')
94
            self.assertTrue(isinstance(t, BackupTransportHandler))
95
        finally:
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
96
            _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.
97
            
1540.3.3 by Martin Pool
Review updates of pycurl transport
98
1442.1.44 by Robert Collins
Many transport related tweaks:
99
class TestMemoryTransport(TestCase):
100
101
    def test_get_transport(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
102
        MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
103
104
    def test_clone(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
105
        transport = MemoryTransport()
106
        self.assertTrue(isinstance(transport, MemoryTransport))
1442.1.44 by Robert Collins
Many transport related tweaks:
107
108
    def test_abspath(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
109
        transport = MemoryTransport()
110
        self.assertEqual("memory:/relpath", transport.abspath('relpath'))
1442.1.44 by Robert Collins
Many transport related tweaks:
111
112
    def test_relpath(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
113
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
114
115
    def test_append_and_get(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
116
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
117
        transport.append('path', StringIO('content'))
118
        self.assertEqual(transport.get('path').read(), 'content')
119
        transport.append('path', StringIO('content'))
120
        self.assertEqual(transport.get('path').read(), 'contentcontent')
121
122
    def test_put_and_get(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
123
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
124
        transport.put('path', StringIO('content'))
125
        self.assertEqual(transport.get('path').read(), 'content')
126
        transport.put('path', StringIO('content'))
127
        self.assertEqual(transport.get('path').read(), 'content')
128
129
    def test_append_without_dir_fails(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
130
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
131
        self.assertRaises(NoSuchFile,
132
                          transport.append, 'dir/path', StringIO('content'))
133
134
    def test_put_without_dir_fails(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
135
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
136
        self.assertRaises(NoSuchFile,
137
                          transport.put, 'dir/path', StringIO('content'))
138
139
    def test_get_missing(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
140
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
141
        self.assertRaises(NoSuchFile, transport.get, 'foo')
142
143
    def test_has_missing(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
144
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
145
        self.assertEquals(False, transport.has('foo'))
146
147
    def test_has_present(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
148
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
149
        transport.append('foo', StringIO('content'))
150
        self.assertEquals(True, transport.has('foo'))
151
152
    def test_mkdir(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
153
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
154
        transport.mkdir('dir')
155
        transport.append('dir/path', StringIO('content'))
156
        self.assertEqual(transport.get('dir/path').read(), 'content')
157
158
    def test_mkdir_missing_parent(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
159
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
160
        self.assertRaises(NoSuchFile,
161
                          transport.mkdir, 'dir/dir')
162
163
    def test_mkdir_twice(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
164
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
165
        transport.mkdir('dir')
166
        self.assertRaises(FileExists, transport.mkdir, 'dir')
1530.1.5 by Robert Collins
Reinstate Memory parameter tests.
167
168
    def test_parameters(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
169
        transport = MemoryTransport()
1530.1.5 by Robert Collins
Reinstate Memory parameter tests.
170
        self.assertEqual(True, transport.listable())
171
        self.assertEqual(False, transport.should_cache())
172
        self.assertEqual(False, transport.is_readonly())
1442.1.44 by Robert Collins
Many transport related tweaks:
173
174
    def test_iter_files_recursive(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
175
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
176
        transport.mkdir('dir')
177
        transport.put('dir/foo', StringIO('content'))
178
        transport.put('dir/bar', StringIO('content'))
179
        transport.put('bar', StringIO('content'))
180
        paths = set(transport.iter_files_recursive())
181
        self.assertEqual(set(['dir/foo', 'dir/bar', 'bar']), paths)
182
183
    def test_stat(self):
1540.3.6 by Martin Pool
[merge] update from bzr.dev
184
        transport = MemoryTransport()
1442.1.44 by Robert Collins
Many transport related tweaks:
185
        transport.put('foo', StringIO('content'))
186
        transport.put('bar', StringIO('phowar'))
187
        self.assertEqual(7, transport.stat('foo').st_size)
188
        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
189
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
190
        
191
class ReadonlyDecoratorTransportTest(TestCase):
192
    """Readonly decoration specific tests."""
193
194
    def test_local_parameters(self):
195
        import bzrlib.transport.readonly as readonly
196
        # connect to . in readonly mode
197
        transport = readonly.ReadonlyTransportDecorator('readonly+.')
198
        self.assertEqual(True, transport.listable())
199
        self.assertEqual(False, transport.should_cache())
200
        self.assertEqual(True, transport.is_readonly())
201
202
    def test_http_parameters(self):
203
        import bzrlib.transport.readonly as readonly
204
        from bzrlib.transport.http import HttpServer
205
        # connect to . via http which is not listable
206
        server = HttpServer()
207
        server.setUp()
208
        try:
209
            transport = get_transport('readonly+' + server.get_url())
210
            self.failUnless(isinstance(transport,
211
                                       readonly.ReadonlyTransportDecorator))
212
            self.assertEqual(False, transport.listable())
213
            self.assertEqual(True, transport.should_cache())
214
            self.assertEqual(True, transport.is_readonly())
215
        finally:
216
            server.tearDown()
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
217
218
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
219
class FakeNFSDecoratorTests(TestCaseInTempDir):
220
    """NFS decorator specific tests."""
221
222
    def get_nfs_transport(self, url):
223
        import bzrlib.transport.fakenfs as fakenfs
224
        # connect to url with nfs decoration
225
        return fakenfs.FakeNFSTransportDecorator('fakenfs+' + url)
226
227
    def test_local_parameters(self):
228
        # the listable, should_cache and is_readonly parameters
229
        # are not changed by the fakenfs decorator
230
        transport = self.get_nfs_transport('.')
231
        self.assertEqual(True, transport.listable())
232
        self.assertEqual(False, transport.should_cache())
233
        self.assertEqual(False, transport.is_readonly())
234
235
    def test_http_parameters(self):
236
        # the listable, should_cache and is_readonly parameters
237
        # are not changed by the fakenfs decorator
238
        from bzrlib.transport.http import HttpServer
239
        # connect to . via http which is not listable
240
        server = HttpServer()
241
        server.setUp()
242
        try:
243
            transport = self.get_nfs_transport(server.get_url())
244
            self.assertIsInstance(
245
                transport, bzrlib.transport.fakenfs.FakeNFSTransportDecorator)
246
            self.assertEqual(False, transport.listable())
247
            self.assertEqual(True, transport.should_cache())
248
            self.assertEqual(True, transport.is_readonly())
249
        finally:
250
            server.tearDown()
251
252
    def test_fakenfs_server_default(self):
253
        # a FakeNFSServer() should bring up a local relpath server for itself
254
        import bzrlib.transport.fakenfs as fakenfs
255
        server = fakenfs.FakeNFSServer()
256
        server.setUp()
257
        try:
258
            # the server should be a relpath localhost server
259
            self.assertEqual(server.get_url(), 'fakenfs+.')
260
            # and we should be able to get a transport for it
261
            transport = get_transport(server.get_url())
262
            # which must be a FakeNFSTransportDecorator instance.
263
            self.assertIsInstance(
264
                transport, fakenfs.FakeNFSTransportDecorator)
265
        finally:
266
            server.tearDown()
267
268
    def test_fakenfs_rename_semantics(self):
269
        # a FakeNFS transport must mangle the way rename errors occur to
270
        # look like NFS problems.
271
        transport = self.get_nfs_transport('.')
272
        self.build_tree(['from/', 'from/foo', 'to/', 'to/bar'],
273
                        transport=transport)
274
        self.assertRaises(bzrlib.errors.ResourceBusy,
275
                          transport.rename, 'from', 'to')
276
277
1540.3.8 by Martin Pool
Some support for falling back between transport implementations.
278
class BadTransportHandler(Transport):
279
    def __init__(self, base_url):
280
        raise DependencyNotPresent('some_lib', 'testing missing dependency')
281
282
283
class BackupTransportHandler(Transport):
284
    """Test transport that works as a backup for the BadTransportHandler"""
1540.3.10 by Martin Pool
[broken] keep hooking pycurl into test framework
285
    pass