~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_server.py

  • Committer: Vincent Ladeuil
  • Date: 2010-02-09 20:33:43 UTC
  • mto: (5029.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 5030.
  • Revision ID: v.ladeuil+lp@free.fr-20100209203343-ktxx7t0xvptvjnt1
Move TestingPathFilteringServer to bzrlib.tests.test_server

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006, 2007, 2008, 2010 Canonical Ltd
 
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
from bzrlib import (
 
18
    transport,
 
19
    urlutils,
 
20
    )
 
21
from bzrlib.transport import (
 
22
    pathfilter,
 
23
    )
 
24
from bzrlib.smart import server
 
25
 
 
26
 
 
27
class TestServer(transport.Server):
 
28
    """A Transport Server dedicated to tests.
 
29
 
 
30
    The TestServer interface provides a server for a given transport. We use
 
31
    these servers as loopback testing tools. For any given transport the
 
32
    Servers it provides must either allow writing, or serve the contents
 
33
    of os.getcwdu() at the time start_server is called.
 
34
 
 
35
    Note that these are real servers - they must implement all the things
 
36
    that we want bzr transports to take advantage of.
 
37
    """
 
38
 
 
39
    def get_url(self):
 
40
        """Return a url for this server.
 
41
 
 
42
        If the transport does not represent a disk directory (i.e. it is
 
43
        a database like svn, or a memory only transport, it should return
 
44
        a connection to a newly established resource for this Server.
 
45
        Otherwise it should return a url that will provide access to the path
 
46
        that was os.getcwdu() when start_server() was called.
 
47
 
 
48
        Subsequent calls will return the same resource.
 
49
        """
 
50
        raise NotImplementedError
 
51
 
 
52
    def get_bogus_url(self):
 
53
        """Return a url for this protocol, that will fail to connect.
 
54
 
 
55
        This may raise NotImplementedError to indicate that this server cannot
 
56
        provide bogus urls.
 
57
        """
 
58
        raise NotImplementedError
 
59
 
 
60
 
 
61
class LocalURLServer(TestServer):
 
62
    """A pretend server for local transports, using file:// urls.
 
63
 
 
64
    Of course no actual server is required to access the local filesystem, so
 
65
    this just exists to tell the test code how to get to it.
 
66
    """
 
67
 
 
68
    def start_server(self):
 
69
        pass
 
70
 
 
71
    def get_url(self):
 
72
        """See Transport.Server.get_url."""
 
73
        return urlutils.local_path_to_url('')
 
74
 
 
75
 
 
76
class MemoryServer(TestServer):
 
77
    """Server for the MemoryTransport for testing with."""
 
78
 
 
79
    def start_server(self):
 
80
        self._dirs = {'/':None}
 
81
        self._files = {}
 
82
        self._locks = {}
 
83
        self._scheme = "memory+%s:///" % id(self)
 
84
        def memory_factory(url):
 
85
            from bzrlib.transport import memory
 
86
            result = memory.MemoryTransport(url)
 
87
            result._dirs = self._dirs
 
88
            result._files = self._files
 
89
            result._locks = self._locks
 
90
            return result
 
91
        self._memory_factory = memory_factory
 
92
        transport.register_transport(self._scheme, self._memory_factory)
 
93
 
 
94
    def stop_server(self):
 
95
        # unregister this server
 
96
        transport.unregister_transport(self._scheme, self._memory_factory)
 
97
 
 
98
    def get_url(self):
 
99
        """See bzrlib.transport.Server.get_url."""
 
100
        return self._scheme
 
101
 
 
102
 
 
103
class DecoratorServer(TestServer):
 
104
    """Server for the TransportDecorator for testing with.
 
105
 
 
106
    To use this when subclassing TransportDecorator, override override the
 
107
    get_decorator_class method.
 
108
    """
 
109
 
 
110
    def start_server(self, server=None):
 
111
        """See bzrlib.transport.Server.start_server.
 
112
 
 
113
        :server: decorate the urls given by server. If not provided a
 
114
        LocalServer is created.
 
115
        """
 
116
        if server is not None:
 
117
            self._made_server = False
 
118
            self._server = server
 
119
        else:
 
120
            self._made_server = True
 
121
            self._server = LocalURLServer()
 
122
            self._server.start_server()
 
123
 
 
124
    def stop_server(self):
 
125
        if self._made_server:
 
126
            self._server.stop_server()
 
127
 
 
128
    def get_decorator_class(self):
 
129
        """Return the class of the decorators we should be constructing."""
 
130
        raise NotImplementedError(self.get_decorator_class)
 
131
 
 
132
    def get_url_prefix(self):
 
133
        """What URL prefix does this decorator produce?"""
 
134
        return self.get_decorator_class()._get_url_prefix()
 
135
 
 
136
    def get_bogus_url(self):
 
137
        """See bzrlib.transport.Server.get_bogus_url."""
 
138
        return self.get_url_prefix() + self._server.get_bogus_url()
 
139
 
 
140
    def get_url(self):
 
141
        """See bzrlib.transport.Server.get_url."""
 
142
        return self.get_url_prefix() + self._server.get_url()
 
143
 
 
144
 
 
145
class BrokenRenameServer(DecoratorServer):
 
146
    """Server for the BrokenRenameTransportDecorator for testing with."""
 
147
 
 
148
    def get_decorator_class(self):
 
149
        from bzrlib.transport import brokenrename
 
150
        return brokenrename.BrokenRenameTransportDecorator
 
151
 
 
152
 
 
153
class FakeNFSServer(DecoratorServer):
 
154
    """Server for the FakeNFSTransportDecorator for testing with."""
 
155
 
 
156
    def get_decorator_class(self):
 
157
        from bzrlib.transport import fakenfs
 
158
        return fakenfs.FakeNFSTransportDecorator
 
159
 
 
160
 
 
161
class FakeVFATServer(DecoratorServer):
 
162
    """A server that suggests connections through FakeVFATTransportDecorator
 
163
 
 
164
    For use in testing.
 
165
    """
 
166
 
 
167
    def get_decorator_class(self):
 
168
        from bzrlib.transport import fakevfat
 
169
        return fakevfat.FakeVFATTransportDecorator
 
170
 
 
171
 
 
172
class LogDecoratorServer(DecoratorServer):
 
173
    """Server for testing."""
 
174
 
 
175
    def get_decorator_class(self):
 
176
        from bzrlib.transport import log
 
177
        return log.TransportLogDecorator
 
178
 
 
179
 
 
180
class NoSmartTransportServer(DecoratorServer):
 
181
    """Server for the NoSmartTransportDecorator for testing with."""
 
182
 
 
183
    def get_decorator_class(self):
 
184
        from bzrlib.transport import nosmart
 
185
        return nosmart.NoSmartTransportDecorator
 
186
 
 
187
 
 
188
class ReadonlyServer(DecoratorServer):
 
189
    """Server for the ReadonlyTransportDecorator for testing with."""
 
190
 
 
191
    def get_decorator_class(self):
 
192
        from bzrlib.transport import readonly
 
193
        return readonly.ReadonlyTransportDecorator
 
194
 
 
195
 
 
196
class TraceServer(DecoratorServer):
 
197
    """Server for the TransportTraceDecorator for testing with."""
 
198
 
 
199
    def get_decorator_class(self):
 
200
        from bzrlib.transport import trace
 
201
        return trace.TransportTraceDecorator
 
202
 
 
203
 
 
204
class UnlistableServer(DecoratorServer):
 
205
    """Server for the UnlistableTransportDecorator for testing with."""
 
206
 
 
207
    def get_decorator_class(self):
 
208
        from bzrlib.transport import unlistable
 
209
        return unlistable.UnlistableTransportDecorator
 
210
 
 
211
 
 
212
class TestingPathFilteringServer(pathfilter.PathFilteringServer):
 
213
 
 
214
    def __init__(self):
 
215
        """TestingChrootServer is not usable until start_server is called."""
 
216
 
 
217
    def start_server(self, backing_server=None):
 
218
        """Setup the Chroot on backing_server."""
 
219
        if backing_server is not None:
 
220
            self.backing_transport = transport.get_transport(
 
221
                backing_server.get_url())
 
222
        else:
 
223
            self.backing_transport = transport.get_transport('.')
 
224
        self.backing_transport.clone('added-by-filter').ensure_base()
 
225
        self.filter_func = lambda x: 'added-by-filter/' + x
 
226
        super(TestingPathFilteringServer, self).start_server()
 
227
 
 
228
 
 
229
class SmartTCPServer_for_testing(server.SmartTCPServer):
 
230
    """Server suitable for use by transport tests.
 
231
 
 
232
    This server is backed by the process's cwd.
 
233
    """
 
234
 
 
235
    def __init__(self, thread_name_suffix=''):
 
236
        super(SmartTCPServer_for_testing, self).__init__(None)
 
237
        self.client_path_extra = None
 
238
        self.thread_name_suffix = thread_name_suffix
 
239
 
 
240
    def get_backing_transport(self, backing_transport_server):
 
241
        """Get a backing transport from a server we are decorating."""
 
242
        return transport.get_transport(backing_transport_server.get_url())
 
243
 
 
244
    def start_server(self, backing_transport_server=None,
 
245
              client_path_extra='/extra/'):
 
246
        """Set up server for testing.
 
247
 
 
248
        :param backing_transport_server: backing server to use.  If not
 
249
            specified, a LocalURLServer at the current working directory will
 
250
            be used.
 
251
        :param client_path_extra: a path segment starting with '/' to append to
 
252
            the root URL for this server.  For instance, a value of '/foo/bar/'
 
253
            will mean the root of the backing transport will be published at a
 
254
            URL like `bzr://127.0.0.1:nnnn/foo/bar/`, rather than
 
255
            `bzr://127.0.0.1:nnnn/`.  Default value is `extra`, so that tests
 
256
            by default will fail unless they do the necessary path translation.
 
257
        """
 
258
        if not client_path_extra.startswith('/'):
 
259
            raise ValueError(client_path_extra)
 
260
        from bzrlib.transport.chroot import ChrootServer
 
261
        if backing_transport_server is None:
 
262
            backing_transport_server = LocalURLServer()
 
263
        self.chroot_server = ChrootServer(
 
264
            self.get_backing_transport(backing_transport_server))
 
265
        self.chroot_server.start_server()
 
266
        self.backing_transport = transport.get_transport(
 
267
            self.chroot_server.get_url())
 
268
        self.root_client_path = self.client_path_extra = client_path_extra
 
269
        self.start_background_thread(self.thread_name_suffix)
 
270
 
 
271
    def stop_server(self):
 
272
        self.stop_background_thread()
 
273
        self.chroot_server.stop_server()
 
274
 
 
275
    def get_url(self):
 
276
        url = super(SmartTCPServer_for_testing, self).get_url()
 
277
        return url[:-1] + self.client_path_extra
 
278
 
 
279
    def get_bogus_url(self):
 
280
        """Return a URL which will fail to connect"""
 
281
        return 'bzr://127.0.0.1:1/'
 
282
 
 
283
 
 
284
class ReadonlySmartTCPServer_for_testing(SmartTCPServer_for_testing):
 
285
    """Get a readonly server for testing."""
 
286
 
 
287
    def get_backing_transport(self, backing_transport_server):
 
288
        """Get a backing transport from a server we are decorating."""
 
289
        url = 'readonly+' + backing_transport_server.get_url()
 
290
        return transport.get_transport(url)
 
291
 
 
292
 
 
293
class SmartTCPServer_for_testing_v2_only(SmartTCPServer_for_testing):
 
294
    """A variation of SmartTCPServer_for_testing that limits the client to
 
295
    using RPCs in protocol v2 (i.e. bzr <= 1.5).
 
296
    """
 
297
 
 
298
    def get_url(self):
 
299
        url = super(SmartTCPServer_for_testing_v2_only, self).get_url()
 
300
        url = 'bzr-v2://' + url[len('bzr://'):]
 
301
        return url
 
302
 
 
303
 
 
304
class ReadonlySmartTCPServer_for_testing_v2_only(
 
305
    SmartTCPServer_for_testing_v2_only):
 
306
    """Get a readonly server for testing."""
 
307
 
 
308
    def get_backing_transport(self, backing_transport_server):
 
309
        """Get a backing transport from a server we are decorating."""
 
310
        url = 'readonly+' + backing_transport_server.get_url()
 
311
        return transport.get_transport(url)
 
312
 
 
313
 
 
314
 
 
315