/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5557.1.7 by John Arbash Meinel
Merge in the bzr.dev 5582
1
# Copyright (C) 2010, 2011 Canonical Ltd
5017.3.1 by Vincent Ladeuil
Create a tests.test_server.TestServer class out of transport.Server (while retaining the later for some special non-tests usages).
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
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
17
import errno
5247.1.1 by Vincent Ladeuil
Merge previous attempt into current trunk
18
import socket
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
19
import SocketServer
5247.2.2 by Vincent Ladeuil
Implement a thread that can re-raise exceptions.
20
import sys
21
import threading
6175.1.1 by John Arbash Meinel
Close the request when we don't process it.
22
import traceback
5247.1.1 by Vincent Ladeuil
Merge previous attempt into current trunk
23
24
5017.3.1 by Vincent Ladeuil
Create a tests.test_server.TestServer class out of transport.Server (while retaining the later for some special non-tests usages).
25
from bzrlib import (
5652.1.6 by Vincent Ladeuil
thread is already a python module, avoid confusion and use cethread instead.
26
    cethread,
6175.1.5 by John Arbash Meinel
Suppress ConnectionTimeout as a server-side exception.
27
    errors,
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
28
    osutils,
5017.3.1 by Vincent Ladeuil
Create a tests.test_server.TestServer class out of transport.Server (while retaining the later for some special non-tests usages).
29
    transport,
5017.3.15 by Vincent Ladeuil
Fix missing import.
30
    urlutils,
5017.3.1 by Vincent Ladeuil
Create a tests.test_server.TestServer class out of transport.Server (while retaining the later for some special non-tests usages).
31
    )
5017.3.19 by Vincent Ladeuil
Move TestingPathFilteringServer to bzrlib.tests.test_server
32
from bzrlib.transport import (
5017.3.20 by Vincent Ladeuil
Move TestingChrootServer to bzrlib.tests.test_server
33
    chroot,
5017.3.19 by Vincent Ladeuil
Move TestingPathFilteringServer to bzrlib.tests.test_server
34
    pathfilter,
35
    )
5247.3.36 by Vincent Ladeuil
Start refactoring the smart server to control which thread it runs in.
36
from bzrlib.smart import (
37
    medium,
38
    server,
39
    )
5017.3.1 by Vincent Ladeuil
Create a tests.test_server.TestServer class out of transport.Server (while retaining the later for some special non-tests usages).
40
41
5247.5.17 by Vincent Ladeuil
Add some basic debug tracing controlled by -Ethreads.
42
def debug_threads():
43
    # FIXME: There is a dependency loop between bzrlib.tests and
44
    # bzrlib.tests.test_server that needs to be fixed. In the mean time
45
    # defining this function is enough for our needs. -- vila 20100611
46
    from bzrlib import tests
47
    return 'threads' in tests.selftest_debug_flags
48
49
5017.3.1 by Vincent Ladeuil
Create a tests.test_server.TestServer class out of transport.Server (while retaining the later for some special non-tests usages).
50
class TestServer(transport.Server):
51
    """A Transport Server dedicated to tests.
52
53
    The TestServer interface provides a server for a given transport. We use
54
    these servers as loopback testing tools. For any given transport the
55
    Servers it provides must either allow writing, or serve the contents
56
    of os.getcwdu() at the time start_server is called.
57
58
    Note that these are real servers - they must implement all the things
59
    that we want bzr transports to take advantage of.
60
    """
61
62
    def get_url(self):
63
        """Return a url for this server.
64
65
        If the transport does not represent a disk directory (i.e. it is
66
        a database like svn, or a memory only transport, it should return
67
        a connection to a newly established resource for this Server.
68
        Otherwise it should return a url that will provide access to the path
69
        that was os.getcwdu() when start_server() was called.
70
71
        Subsequent calls will return the same resource.
72
        """
73
        raise NotImplementedError
74
75
    def get_bogus_url(self):
76
        """Return a url for this protocol, that will fail to connect.
77
78
        This may raise NotImplementedError to indicate that this server cannot
79
        provide bogus urls.
80
        """
81
        raise NotImplementedError
82
83
5017.3.6 by Vincent Ladeuil
Fix some fallouts of moving test servers around.
84
class LocalURLServer(TestServer):
5017.3.3 by Vincent Ladeuil
Move LocalURLServer to bzrlib.tests.test_server
85
    """A pretend server for local transports, using file:// urls.
86
87
    Of course no actual server is required to access the local filesystem, so
88
    this just exists to tell the test code how to get to it.
89
    """
90
91
    def start_server(self):
92
        pass
93
94
    def get_url(self):
95
        """See Transport.Server.get_url."""
96
        return urlutils.local_path_to_url('')
97
98
5017.3.6 by Vincent Ladeuil
Fix some fallouts of moving test servers around.
99
class DecoratorServer(TestServer):
5017.3.2 by Vincent Ladeuil
Move DecoratorServer to test_server.py
100
    """Server for the TransportDecorator for testing with.
101
102
    To use this when subclassing TransportDecorator, override override the
103
    get_decorator_class method.
104
    """
105
106
    def start_server(self, server=None):
107
        """See bzrlib.transport.Server.start_server.
108
109
        :server: decorate the urls given by server. If not provided a
110
        LocalServer is created.
111
        """
112
        if server is not None:
113
            self._made_server = False
114
            self._server = server
115
        else:
116
            self._made_server = True
117
            self._server = LocalURLServer()
118
            self._server.start_server()
119
120
    def stop_server(self):
121
        if self._made_server:
122
            self._server.stop_server()
123
124
    def get_decorator_class(self):
125
        """Return the class of the decorators we should be constructing."""
126
        raise NotImplementedError(self.get_decorator_class)
127
128
    def get_url_prefix(self):
129
        """What URL prefix does this decorator produce?"""
130
        return self.get_decorator_class()._get_url_prefix()
131
132
    def get_bogus_url(self):
133
        """See bzrlib.transport.Server.get_bogus_url."""
134
        return self.get_url_prefix() + self._server.get_bogus_url()
135
136
    def get_url(self):
137
        """See bzrlib.transport.Server.get_url."""
138
        return self.get_url_prefix() + self._server.get_url()
139
140
5017.3.8 by Vincent Ladeuil
Move BrokenRenameServer to bzrlib.tests.test_server
141
class BrokenRenameServer(DecoratorServer):
142
    """Server for the BrokenRenameTransportDecorator for testing with."""
143
144
    def get_decorator_class(self):
145
        from bzrlib.transport import brokenrename
146
        return brokenrename.BrokenRenameTransportDecorator
147
148
5017.3.7 by Vincent Ladeuil
Move FakeNFSServer to bzrlib.tests.test_server
149
class FakeNFSServer(DecoratorServer):
150
    """Server for the FakeNFSTransportDecorator for testing with."""
151
152
    def get_decorator_class(self):
153
        from bzrlib.transport import fakenfs
154
        return fakenfs.FakeNFSTransportDecorator
155
156
5017.3.9 by Vincent Ladeuil
Move FakeVFATServer to bzrlib.tests.test_server
157
class FakeVFATServer(DecoratorServer):
158
    """A server that suggests connections through FakeVFATTransportDecorator
159
160
    For use in testing.
161
    """
162
163
    def get_decorator_class(self):
164
        from bzrlib.transport import fakevfat
5017.3.14 by Vincent Ladeuil
Fix some missing prefixes.
165
        return fakevfat.FakeVFATTransportDecorator
5017.3.9 by Vincent Ladeuil
Move FakeVFATServer to bzrlib.tests.test_server
166
167
5017.3.11 by Vincent Ladeuil
Move LogDecoratorServer to bzrlib.tests.test_server
168
class LogDecoratorServer(DecoratorServer):
169
    """Server for testing."""
170
171
    def get_decorator_class(self):
172
        from bzrlib.transport import log
173
        return log.TransportLogDecorator
174
175
5017.3.12 by Vincent Ladeuil
Move NoSmartTransportServer to bzrlib.tests.test_server
176
class NoSmartTransportServer(DecoratorServer):
177
    """Server for the NoSmartTransportDecorator for testing with."""
178
179
    def get_decorator_class(self):
180
        from bzrlib.transport import nosmart
5017.3.14 by Vincent Ladeuil
Fix some missing prefixes.
181
        return nosmart.NoSmartTransportDecorator
5017.3.12 by Vincent Ladeuil
Move NoSmartTransportServer to bzrlib.tests.test_server
182
183
5017.3.5 by Vincent Ladeuil
Move ReadonlyServer to bzrlib.tests.readonly
184
class ReadonlyServer(DecoratorServer):
185
    """Server for the ReadonlyTransportDecorator for testing with."""
186
187
    def get_decorator_class(self):
188
        from bzrlib.transport import readonly
189
        return readonly.ReadonlyTransportDecorator
190
191
5017.3.10 by Vincent Ladeuil
Move TraceServer to bzrlib.tests.test_server
192
class TraceServer(DecoratorServer):
193
    """Server for the TransportTraceDecorator for testing with."""
194
195
    def get_decorator_class(self):
196
        from bzrlib.transport import trace
5017.3.14 by Vincent Ladeuil
Fix some missing prefixes.
197
        return trace.TransportTraceDecorator
5017.3.10 by Vincent Ladeuil
Move TraceServer to bzrlib.tests.test_server
198
199
5017.3.13 by Vincent Ladeuil
Move UnlistableServer to bzrlib.tests.test_server
200
class UnlistableServer(DecoratorServer):
201
    """Server for the UnlistableTransportDecorator for testing with."""
202
203
    def get_decorator_class(self):
204
        from bzrlib.transport import unlistable
205
        return unlistable.UnlistableTransportDecorator
206
207
5017.3.19 by Vincent Ladeuil
Move TestingPathFilteringServer to bzrlib.tests.test_server
208
class TestingPathFilteringServer(pathfilter.PathFilteringServer):
209
210
    def __init__(self):
5017.3.20 by Vincent Ladeuil
Move TestingChrootServer to bzrlib.tests.test_server
211
        """TestingPathFilteringServer is not usable until start_server
212
        is called."""
5017.3.19 by Vincent Ladeuil
Move TestingPathFilteringServer to bzrlib.tests.test_server
213
214
    def start_server(self, backing_server=None):
215
        """Setup the Chroot on backing_server."""
216
        if backing_server is not None:
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
217
            self.backing_transport = transport.get_transport_from_url(
5017.3.19 by Vincent Ladeuil
Move TestingPathFilteringServer to bzrlib.tests.test_server
218
                backing_server.get_url())
219
        else:
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
220
            self.backing_transport = transport.get_transport_from_path('.')
5017.3.19 by Vincent Ladeuil
Move TestingPathFilteringServer to bzrlib.tests.test_server
221
        self.backing_transport.clone('added-by-filter').ensure_base()
222
        self.filter_func = lambda x: 'added-by-filter/' + x
223
        super(TestingPathFilteringServer, self).start_server()
224
5017.3.20 by Vincent Ladeuil
Move TestingChrootServer to bzrlib.tests.test_server
225
    def get_bogus_url(self):
226
        raise NotImplementedError
227
228
229
class TestingChrootServer(chroot.ChrootServer):
230
231
    def __init__(self):
232
        """TestingChrootServer is not usable until start_server is called."""
233
        super(TestingChrootServer, self).__init__(None)
234
235
    def start_server(self, backing_server=None):
236
        """Setup the Chroot on backing_server."""
237
        if backing_server is not None:
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
238
            self.backing_transport = transport.get_transport_from_url(
5017.3.20 by Vincent Ladeuil
Move TestingChrootServer to bzrlib.tests.test_server
239
                backing_server.get_url())
240
        else:
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
241
            self.backing_transport = transport.get_transport_from_path('.')
5017.3.20 by Vincent Ladeuil
Move TestingChrootServer to bzrlib.tests.test_server
242
        super(TestingChrootServer, self).start_server()
243
244
    def get_bogus_url(self):
245
        raise NotImplementedError
246
5017.3.19 by Vincent Ladeuil
Move TestingPathFilteringServer to bzrlib.tests.test_server
247
5652.1.6 by Vincent Ladeuil
thread is already a python module, avoid confusion and use cethread instead.
248
class TestThread(cethread.CatchingExceptionThread):
5247.2.2 by Vincent Ladeuil
Implement a thread that can re-raise exceptions.
249
5560.1.2 by Vincent Ladeuil
Oops, remove debug value.
250
    def join(self, timeout=5):
5652.1.1 by Vincent Ladeuil
Split ThreadWithException out of the tests hierarchy.
251
        """Overrides to use a default timeout.
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
252
253
        The default timeout is set to 5 and should expire only when a thread
254
        serving a client connection is hung.
5247.2.3 by Vincent Ladeuil
join(timeout=0) is useful to check for an exception without stopping the thread.
255
        """
5652.1.1 by Vincent Ladeuil
Split ThreadWithException out of the tests hierarchy.
256
        super(TestThread, self).join(timeout)
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
257
        if timeout and self.isAlive():
258
            # The timeout expired without joining the thread, the thread is
259
            # therefore stucked and that's a failure as far as the test is
260
            # concerned. We used to hang here.
5247.2.37 by Vincent Ladeuil
Don't make leaking tests fail on hung threads, there are only a few left.
261
262
            # FIXME: we need to kill the thread, but as far as the test is
263
            # concerned, raising an assertion is too strong. On most of the
264
            # platforms, this doesn't occur, so just mentioning the problem is
265
            # enough for now -- vila 2010824
266
            sys.stderr.write('thread %s hung\n' % (self.name,))
267
            #raise AssertionError('thread %s hung' % (self.name,))
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
268
5247.2.2 by Vincent Ladeuil
Implement a thread that can re-raise exceptions.
269
6133.4.32 by John Arbash Meinel
Don't use server.socket.close() go through the server._close() abstraction.
270
class TestingTCPServerMixin(object):
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
271
    """Mixin to support running SocketServer.TCPServer in a thread.
272
273
    Tests are connecting from the main thread, the server has to be run in a
274
    separate thread.
275
    """
276
5247.5.32 by Vincent Ladeuil
Fix the sibling_class hack, we now know that we need only two methods
277
    def __init__(self):
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
278
        self.started = threading.Event()
5247.5.31 by Vincent Ladeuil
Use a boolean for server.serving, a threading.Event() is not needed here.
279
        self.serving = None
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
280
        self.stopped = threading.Event()
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
281
        # We collect the resources used by the clients so we can release them
282
        # when shutting down
283
        self.clients = []
5247.5.4 by Vincent Ladeuil
Implement an execption handling mechanism that can be injected in ThreadWithException.
284
        self.ignored_exceptions = None
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
285
5247.3.11 by Vincent Ladeuil
Start implementing the threading variants.
286
    def server_bind(self):
5247.5.32 by Vincent Ladeuil
Fix the sibling_class hack, we now know that we need only two methods
287
        self.socket.bind(self.server_address)
288
        self.server_address = self.socket.getsockname()
5247.3.11 by Vincent Ladeuil
Start implementing the threading variants.
289
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
290
    def serve(self):
5247.5.31 by Vincent Ladeuil
Use a boolean for server.serving, a threading.Event() is not needed here.
291
        self.serving = True
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
292
        self.stopped.clear()
293
        # We are listening and ready to accept connections
294
        self.started.set()
5247.5.9 by Vincent Ladeuil
Use a better sync for test_exception_swallowed_while_serving test.
295
        try:
5247.5.31 by Vincent Ladeuil
Use a boolean for server.serving, a threading.Event() is not needed here.
296
            while self.serving:
5247.5.9 by Vincent Ladeuil
Use a better sync for test_exception_swallowed_while_serving test.
297
                # Really a connection but the python framework is generic and
298
                # call them requests
299
                self.handle_request()
300
            # Let's close the listening socket
301
            self.server_close()
302
        finally:
303
            self.stopped.set()
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
304
5247.5.10 by Vincent Ladeuil
Fix broken test.
305
    def handle_request(self):
306
        """Handle one request.
307
308
        The python version swallows some socket exceptions and we don't use
309
        timeout, so we override it to better control the server behavior.
310
        """
311
        request, client_address = self.get_request()
312
        if self.verify_request(request, client_address):
313
            try:
314
                self.process_request(request, client_address)
315
            except:
316
                self.handle_error(request, client_address)
6175.1.1 by John Arbash Meinel
Close the request when we don't process it.
317
        else:
318
            self.close_request(request)
5247.5.10 by Vincent Ladeuil
Fix broken test.
319
5247.5.32 by Vincent Ladeuil
Fix the sibling_class hack, we now know that we need only two methods
320
    def get_request(self):
321
        return self.socket.accept()
322
5247.3.9 by Vincent Ladeuil
Ensure a simple dialog can occur between a client and a server.
323
    def verify_request(self, request, client_address):
324
        """Verify the request.
325
326
        Return True if we should proceed with this request, False if we should
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
327
        not even touch a single byte in the socket ! This is useful when we
328
        stop the server with a dummy last connection.
5247.3.9 by Vincent Ladeuil
Ensure a simple dialog can occur between a client and a server.
329
        """
5247.5.31 by Vincent Ladeuil
Use a boolean for server.serving, a threading.Event() is not needed here.
330
        return self.serving
5247.3.9 by Vincent Ladeuil
Ensure a simple dialog can occur between a client and a server.
331
5247.3.10 by Vincent Ladeuil
Test errors during server life.
332
    def handle_error(self, request, client_address):
333
        # Stop serving and re-raise the last exception seen
5247.5.31 by Vincent Ladeuil
Use a boolean for server.serving, a threading.Event() is not needed here.
334
        self.serving = False
5247.6.8 by Vincent Ladeuil
Explain why we left some code commented: useful in rare debug cases.
335
        # The following can be used for debugging purposes, it will display the
336
        # exception and the traceback just when it occurs instead of waiting
337
        # for the thread to be joined.
338
        # SocketServer.BaseServer.handle_error(self, request, client_address)
6175.1.6 by John Arbash Meinel
Separate the comments, for vila.
339
6175.1.1 by John Arbash Meinel
Close the request when we don't process it.
340
        # We call close_request manually, because we are going to raise an
341
        # exception. The SocketServer implementation calls:
342
        #   handle_error(...)
343
        #   close_request(...)
344
        # But because we raise the exception, close_request will never be
345
        # triggered. This helps client not block waiting for a response when
346
        # the server gets an exception.
347
        self.close_request(request)
5247.3.10 by Vincent Ladeuil
Test errors during server life.
348
        raise
349
5247.5.7 by Vincent Ladeuil
Factor out socket exception handling during server shutdown.
350
    def ignored_exceptions_during_shutdown(self, e):
351
        if sys.platform == 'win32':
5247.2.40 by Vincent Ladeuil
Catch EPIPE during test server shutdown.
352
            accepted_errnos = [errno.EBADF,
353
                               errno.EPIPE,
354
                               errno.WSAEBADF,
355
                               errno.WSAECONNRESET,
356
                               errno.WSAENOTCONN,
357
                               errno.WSAESHUTDOWN,
358
                               ]
5247.5.7 by Vincent Ladeuil
Factor out socket exception handling during server shutdown.
359
        else:
5247.2.40 by Vincent Ladeuil
Catch EPIPE during test server shutdown.
360
            accepted_errnos = [errno.EBADF,
361
                               errno.ECONNRESET,
362
                               errno.ENOTCONN,
363
                               errno.EPIPE,
364
                               ]
5247.5.7 by Vincent Ladeuil
Factor out socket exception handling during server shutdown.
365
        if isinstance(e, socket.error) and e[0] in accepted_errnos:
366
            return True
367
        return False
368
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
369
    # The following methods are called by the main thread
370
371
    def stop_client_connections(self):
372
        while self.clients:
373
            c = self.clients.pop()
374
            self.shutdown_client(c)
375
5247.5.9 by Vincent Ladeuil
Use a better sync for test_exception_swallowed_while_serving test.
376
    def shutdown_socket(self, sock):
377
        """Properly shutdown a socket.
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
378
379
        This should be called only when no other thread is trying to use the
380
        socket.
381
        """
382
        try:
383
            sock.shutdown(socket.SHUT_RDWR)
384
            sock.close()
5247.5.7 by Vincent Ladeuil
Factor out socket exception handling during server shutdown.
385
        except Exception, e:
386
            if self.ignored_exceptions(e):
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
387
                pass
388
            else:
389
                raise
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
390
5247.5.4 by Vincent Ladeuil
Implement an execption handling mechanism that can be injected in ThreadWithException.
391
    # The following methods are called by the main thread
392
393
    def set_ignored_exceptions(self, thread, ignored_exceptions):
394
        self.ignored_exceptions = ignored_exceptions
395
        thread.set_ignored_exceptions(self.ignored_exceptions)
396
397
    def _pending_exception(self, thread):
398
        """Raise server uncaught exception.
399
400
        Daughter classes can override this if they use daughter threads.
401
        """
402
        thread.pending_exception()
403
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
404
405
class TestingTCPServer(TestingTCPServerMixin, SocketServer.TCPServer):
406
407
    def __init__(self, server_address, request_handler_class):
5247.5.32 by Vincent Ladeuil
Fix the sibling_class hack, we now know that we need only two methods
408
        TestingTCPServerMixin.__init__(self)
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
409
        SocketServer.TCPServer.__init__(self, server_address,
410
                                        request_handler_class)
411
412
    def get_request(self):
413
        """Get the request and client address from the socket."""
5247.5.32 by Vincent Ladeuil
Fix the sibling_class hack, we now know that we need only two methods
414
        sock, addr = TestingTCPServerMixin.get_request(self)
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
415
        self.clients.append((sock, addr))
416
        return sock, addr
417
418
    # The following methods are called by the main thread
419
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
420
    def shutdown_client(self, client):
421
        sock, addr = client
5247.5.9 by Vincent Ladeuil
Use a better sync for test_exception_swallowed_while_serving test.
422
        self.shutdown_socket(sock)
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
423
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
424
5247.3.11 by Vincent Ladeuil
Start implementing the threading variants.
425
class TestingThreadingTCPServer(TestingTCPServerMixin,
426
                                SocketServer.ThreadingTCPServer):
427
428
    def __init__(self, server_address, request_handler_class):
5247.5.32 by Vincent Ladeuil
Fix the sibling_class hack, we now know that we need only two methods
429
        TestingTCPServerMixin.__init__(self)
430
        SocketServer.ThreadingTCPServer.__init__(self, server_address,
431
                                                 request_handler_class)
5247.3.11 by Vincent Ladeuil
Start implementing the threading variants.
432
6175.1.1 by John Arbash Meinel
Close the request when we don't process it.
433
    def get_request(self):
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
434
        """Get the request and client address from the socket."""
5247.5.32 by Vincent Ladeuil
Fix the sibling_class hack, we now know that we need only two methods
435
        sock, addr = TestingTCPServerMixin.get_request(self)
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
436
        # The thread is not create yet, it will be updated in process_request
437
        self.clients.append((sock, addr, None))
438
        return sock, addr
439
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
440
    def process_request_thread(self, started, stopped, request, client_address):
441
        started.set()
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
442
        SocketServer.ThreadingTCPServer.process_request_thread(
443
            self, request, client_address)
444
        self.close_request(request)
445
        stopped.set()
446
447
    def process_request(self, request, client_address):
448
        """Start a new thread to process the request."""
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
449
        started = threading.Event()
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
450
        stopped = threading.Event()
5652.1.1 by Vincent Ladeuil
Split ThreadWithException out of the tests hierarchy.
451
        t = TestThread(
5652.1.2 by Vincent Ladeuil
Use clearer names.
452
            sync_event=stopped,
5247.5.17 by Vincent Ladeuil
Add some basic debug tracing controlled by -Ethreads.
453
            name='%s -> %s' % (client_address, self.server_address),
6175.1.1 by John Arbash Meinel
Close the request when we don't process it.
454
            target=self.process_request_thread,
455
            args=(started, stopped, request, client_address))
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
456
        # Update the client description
6133.4.18 by John Arbash Meinel
Revert debugging changes to test_server.py
457
        self.clients.pop()
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
458
        self.clients.append((request, client_address, t))
5560.1.5 by Vincent Ladeuil
Fix spelling mistake.
459
        # Propagate the exception handler since we must use the same one as
5560.1.1 by Vincent Ladeuil
Catch the bogus ssl exception for closed sockets.
460
        # TestingTCPServer for connections running in their own threads.
6133.4.18 by John Arbash Meinel
Revert debugging changes to test_server.py
461
        t.set_ignored_exceptions(self.ignored_exceptions)
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
462
        t.start()
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
463
        started.wait()
5247.5.17 by Vincent Ladeuil
Add some basic debug tracing controlled by -Ethreads.
464
        if debug_threads():
5247.5.29 by Vincent Ladeuil
Fixed as per jam's review.
465
            sys.stderr.write('Client thread %s started\n' % (t.name,))
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
466
        # If an exception occured during the thread start, it will get raised.
467
        t.pending_exception()
468
469
    # The following methods are called by the main thread
470
471
    def shutdown_client(self, client):
5247.5.2 by Vincent Ladeuil
Cosmetic change.
472
        sock, addr, connection_thread = client
5247.5.9 by Vincent Ladeuil
Use a better sync for test_exception_swallowed_while_serving test.
473
        self.shutdown_socket(sock)
5247.5.2 by Vincent Ladeuil
Cosmetic change.
474
        if connection_thread is not None:
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
475
            # The thread has been created only if the request is processed but
476
            # after the connection is inited. This could happen during server
477
            # shutdown. If an exception occurred in the thread it will be
478
            # re-raised
5247.5.17 by Vincent Ladeuil
Add some basic debug tracing controlled by -Ethreads.
479
            if debug_threads():
5247.5.29 by Vincent Ladeuil
Fixed as per jam's review.
480
                sys.stderr.write('Client thread %s will be joined\n'
481
                                 % (connection_thread.name,))
5247.5.2 by Vincent Ladeuil
Cosmetic change.
482
            connection_thread.join()
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
483
5247.5.4 by Vincent Ladeuil
Implement an execption handling mechanism that can be injected in ThreadWithException.
484
    def set_ignored_exceptions(self, thread, ignored_exceptions):
485
        TestingTCPServerMixin.set_ignored_exceptions(self, thread,
486
                                                     ignored_exceptions)
487
        for sock, addr, connection_thread in self.clients:
488
            if connection_thread is not None:
489
                connection_thread.set_ignored_exceptions(
490
                    self.ignored_exceptions)
491
5247.5.3 by Vincent Ladeuil
Fix exception raising only once for a given ThreadWithException.
492
    def _pending_exception(self, thread):
493
        for sock, addr, connection_thread in self.clients:
494
            if connection_thread is not None:
495
                connection_thread.pending_exception()
5247.5.4 by Vincent Ladeuil
Implement an execption handling mechanism that can be injected in ThreadWithException.
496
        TestingTCPServerMixin._pending_exception(self, thread)
5247.5.3 by Vincent Ladeuil
Fix exception raising only once for a given ThreadWithException.
497
5247.3.11 by Vincent Ladeuil
Start implementing the threading variants.
498
5247.3.14 by Vincent Ladeuil
Use a proper load_tests.
499
class TestingTCPServerInAThread(transport.Server):
5247.3.11 by Vincent Ladeuil
Start implementing the threading variants.
500
    """A server in a thread that re-raise thread exceptions."""
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
501
502
    def __init__(self, server_address, server_class, request_handler_class):
503
        self.server_class = server_class
504
        self.request_handler_class = request_handler_class
5247.3.15 by Vincent Ladeuil
All http tests passing, https failing.
505
        self.host, self.port = server_address
5247.3.10 by Vincent Ladeuil
Test errors during server life.
506
        self.server = None
5247.5.4 by Vincent Ladeuil
Implement an execption handling mechanism that can be injected in ThreadWithException.
507
        self._server_thread = None
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
508
5247.3.14 by Vincent Ladeuil
Use a proper load_tests.
509
    def __repr__(self):
5247.3.15 by Vincent Ladeuil
All http tests passing, https failing.
510
        return "%s(%s:%s)" % (self.__class__.__name__, self.host, self.port)
5247.3.14 by Vincent Ladeuil
Use a proper load_tests.
511
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
512
    def create_server(self):
5247.3.15 by Vincent Ladeuil
All http tests passing, https failing.
513
        return self.server_class((self.host, self.port),
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
514
                                 self.request_handler_class)
515
516
    def start_server(self):
517
        self.server = self.create_server()
5652.1.1 by Vincent Ladeuil
Split ThreadWithException out of the tests hierarchy.
518
        self._server_thread = TestThread(
5652.1.2 by Vincent Ladeuil
Use clearer names.
519
            sync_event=self.server.started,
5247.5.17 by Vincent Ladeuil
Add some basic debug tracing controlled by -Ethreads.
520
            target=self.run_server)
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
521
        self._server_thread.start()
522
        # Wait for the server thread to start (i.e release the lock)
523
        self.server.started.wait()
524
        # Get the real address, especially the port
5247.3.15 by Vincent Ladeuil
All http tests passing, https failing.
525
        self.host, self.port = self.server.server_address
5247.5.18 by Vincent Ladeuil
Compatibility with python 2.5 and 2.4 for ThreadWithException.name.
526
        self._server_thread.name = self.server.server_address
527
        if debug_threads():
5247.5.29 by Vincent Ladeuil
Fixed as per jam's review.
528
            sys.stderr.write('Server thread %s started\n'
529
                             % (self._server_thread.name,))
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
530
        # If an exception occured during the server start, it will get raised,
531
        # otherwise, the server is blocked on its accept() call.
532
        self._server_thread.pending_exception()
5247.3.10 by Vincent Ladeuil
Test errors during server life.
533
        # From now on, we'll use a different event to ensure the server can set
534
        # its exception
5652.1.2 by Vincent Ladeuil
Use clearer names.
535
        self._server_thread.set_sync_event(self.server.stopped)
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
536
537
    def run_server(self):
538
        self.server.serve()
539
540
    def stop_server(self):
541
        if self.server is None:
542
            return
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
543
        try:
544
            # The server has been started successfully, shut it down now.  As
5247.5.10 by Vincent Ladeuil
Fix broken test.
545
            # soon as we stop serving, no more connection are accepted except
546
            # one to get out of the blocking listen.
5247.5.7 by Vincent Ladeuil
Factor out socket exception handling during server shutdown.
547
            self.set_ignored_exceptions(
548
                self.server.ignored_exceptions_during_shutdown)
5247.5.31 by Vincent Ladeuil
Use a boolean for server.serving, a threading.Event() is not needed here.
549
            self.server.serving = False
5247.5.17 by Vincent Ladeuil
Add some basic debug tracing controlled by -Ethreads.
550
            if debug_threads():
5247.5.29 by Vincent Ladeuil
Fixed as per jam's review.
551
                sys.stderr.write('Server thread %s will be joined\n'
552
                                 % (self._server_thread.name,))
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
553
            # The server is listening for a last connection, let's give it:
554
            last_conn = None
555
            try:
5247.3.15 by Vincent Ladeuil
All http tests passing, https failing.
556
                last_conn = osutils.connect_socket((self.host, self.port))
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
557
            except socket.error, e:
558
                # But ignore connection errors as the point is to unblock the
559
                # server thread, it may happen that it's not blocked or even
560
                # not started.
6133.4.18 by John Arbash Meinel
Revert debugging changes to test_server.py
561
                pass
562
            # We start shutting down the clients while the server itself is
563
            # shutting down.
564
            self.server.stop_client_connections()
565
            # Now we wait for the thread running self.server.serve() to finish
566
            self.server.stopped.wait()
6133.4.8 by John Arbash Meinel
Refactor a bit. Use a common _wait_for_descriptor code.
567
            if last_conn is not None:
568
                # Close the last connection without trying to use it. The
569
                # server will not process a single byte on that socket to avoid
570
                # complications (SSL starts with a handshake for example).
571
                last_conn.close()
5247.3.10 by Vincent Ladeuil
Test errors during server life.
572
            # Check for any exception that could have occurred in the server
573
            # thread
5247.5.9 by Vincent Ladeuil
Use a better sync for test_exception_swallowed_while_serving test.
574
            try:
575
                self._server_thread.join()
576
            except Exception, e:
577
                if self.server.ignored_exceptions(e):
578
                    pass
579
                else:
580
                    raise
5247.3.10 by Vincent Ladeuil
Test errors during server life.
581
        finally:
5247.3.13 by Vincent Ladeuil
Really test against a threading server and properly shutdown socket and threads.
582
            # Make sure we can be called twice safely, note that this means
583
            # that we will raise a single exception even if several occurred in
584
            # the various threads involved.
5247.3.10 by Vincent Ladeuil
Test errors during server life.
585
            self.server = None
5247.3.8 by Vincent Ladeuil
Start implementing a TCP server running in its own thread (using
586
5247.5.4 by Vincent Ladeuil
Implement an execption handling mechanism that can be injected in ThreadWithException.
587
    def set_ignored_exceptions(self, ignored_exceptions):
588
        """Install an exception handler for the server."""
589
        self.server.set_ignored_exceptions(self._server_thread,
590
                                           ignored_exceptions)
591
5247.5.3 by Vincent Ladeuil
Fix exception raising only once for a given ThreadWithException.
592
    def pending_exception(self):
593
        """Raise uncaught exception in the server."""
594
        self.server._pending_exception(self._server_thread)
595
5247.3.12 by Vincent Ladeuil
Spawn a thread for each connection from a client.
596
5247.3.38 by Vincent Ladeuil
Fix the last remaining failures.
597
class TestingSmartConnectionHandler(SocketServer.BaseRequestHandler,
598
                                    medium.SmartServerSocketStreamMedium):
5247.3.37 by Vincent Ladeuil
Use TestingTCPServerInAThread for smart test servers, only 4 test failures remaining.
599
600
    def __init__(self, request, client_address, server):
601
        medium.SmartServerSocketStreamMedium.__init__(
602
            self, request, server.backing_transport,
6133.4.26 by John Arbash Meinel
get rid of the default timeout parameters.
603
            server.root_client_path,
604
            timeout=_DEFAULT_TESTING_CLIENT_TIMEOUT)
5247.3.37 by Vincent Ladeuil
Use TestingTCPServerInAThread for smart test servers, only 4 test failures remaining.
605
        request.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
606
        SocketServer.BaseRequestHandler.__init__(self, request, client_address,
607
                                                 server)
608
609
    def handle(self):
6175.1.5 by John Arbash Meinel
Suppress ConnectionTimeout as a server-side exception.
610
        try:
611
            while not self.finished:
612
                server_protocol = self._build_protocol()
613
                self._serve_one_request(server_protocol)
614
        except errors.ConnectionTimeout:
615
            # idle connections aren't considered a failure of the server
616
            return
5247.3.37 by Vincent Ladeuil
Use TestingTCPServerInAThread for smart test servers, only 4 test failures remaining.
617
618
6133.4.23 by John Arbash Meinel
Setup the TestingSmartServer to set a default client timeout,
619
_DEFAULT_TESTING_CLIENT_TIMEOUT = 4.0
620
5247.3.37 by Vincent Ladeuil
Use TestingTCPServerInAThread for smart test servers, only 4 test failures remaining.
621
class TestingSmartServer(TestingThreadingTCPServer, server.SmartTCPServer):
622
623
    def __init__(self, server_address, request_handler_class,
624
                 backing_transport, root_client_path):
625
        TestingThreadingTCPServer.__init__(self, server_address,
626
                                           request_handler_class)
627
        server.SmartTCPServer.__init__(self, backing_transport,
6133.4.23 by John Arbash Meinel
Setup the TestingSmartServer to set a default client timeout,
628
            root_client_path, client_timeout=_DEFAULT_TESTING_CLIENT_TIMEOUT)
629
5247.3.38 by Vincent Ladeuil
Fix the last remaining failures.
630
    def serve(self):
631
        self.run_server_started_hooks()
632
        try:
633
            TestingThreadingTCPServer.serve(self)
634
        finally:
635
            self.run_server_stopped_hooks()
5247.3.37 by Vincent Ladeuil
Use TestingTCPServerInAThread for smart test servers, only 4 test failures remaining.
636
637
    def get_url(self):
638
        """Return the url of the server"""
639
        return "bzr://%s:%d/" % self.server_address
640
641
642
class SmartTCPServer_for_testing(TestingTCPServerInAThread):
5017.3.18 by Vincent Ladeuil
Move SmartTCPServer_for_testing and friends to bzrlib.tests.test_server
643
    """Server suitable for use by transport tests.
644
645
    This server is backed by the process's cwd.
646
    """
647
    def __init__(self, thread_name_suffix=''):
648
        self.client_path_extra = None
649
        self.thread_name_suffix = thread_name_suffix
5247.3.37 by Vincent Ladeuil
Use TestingTCPServerInAThread for smart test servers, only 4 test failures remaining.
650
        self.host = '127.0.0.1'
651
        self.port = 0
652
        super(SmartTCPServer_for_testing, self).__init__(
653
                (self.host, self.port),
654
                TestingSmartServer,
5247.3.38 by Vincent Ladeuil
Fix the last remaining failures.
655
                TestingSmartConnectionHandler)
5247.3.37 by Vincent Ladeuil
Use TestingTCPServerInAThread for smart test servers, only 4 test failures remaining.
656
657
    def create_server(self):
658
        return self.server_class((self.host, self.port),
659
                                 self.request_handler_class,
660
                                 self.backing_transport,
661
                                 self.root_client_path)
662
5017.3.18 by Vincent Ladeuil
Move SmartTCPServer_for_testing and friends to bzrlib.tests.test_server
663
664
    def start_server(self, backing_transport_server=None,
5247.3.37 by Vincent Ladeuil
Use TestingTCPServerInAThread for smart test servers, only 4 test failures remaining.
665
                     client_path_extra='/extra/'):
5017.3.18 by Vincent Ladeuil
Move SmartTCPServer_for_testing and friends to bzrlib.tests.test_server
666
        """Set up server for testing.
667
668
        :param backing_transport_server: backing server to use.  If not
669
            specified, a LocalURLServer at the current working directory will
670
            be used.
671
        :param client_path_extra: a path segment starting with '/' to append to
672
            the root URL for this server.  For instance, a value of '/foo/bar/'
673
            will mean the root of the backing transport will be published at a
674
            URL like `bzr://127.0.0.1:nnnn/foo/bar/`, rather than
675
            `bzr://127.0.0.1:nnnn/`.  Default value is `extra`, so that tests
676
            by default will fail unless they do the necessary path translation.
677
        """
678
        if not client_path_extra.startswith('/'):
679
            raise ValueError(client_path_extra)
5247.3.37 by Vincent Ladeuil
Use TestingTCPServerInAThread for smart test servers, only 4 test failures remaining.
680
        self.root_client_path = self.client_path_extra = client_path_extra
5017.3.18 by Vincent Ladeuil
Move SmartTCPServer_for_testing and friends to bzrlib.tests.test_server
681
        from bzrlib.transport.chroot import ChrootServer
682
        if backing_transport_server is None:
683
            backing_transport_server = LocalURLServer()
684
        self.chroot_server = ChrootServer(
685
            self.get_backing_transport(backing_transport_server))
686
        self.chroot_server.start_server()
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
687
        self.backing_transport = transport.get_transport_from_url(
5017.3.18 by Vincent Ladeuil
Move SmartTCPServer_for_testing and friends to bzrlib.tests.test_server
688
            self.chroot_server.get_url())
5247.3.37 by Vincent Ladeuil
Use TestingTCPServerInAThread for smart test servers, only 4 test failures remaining.
689
        super(SmartTCPServer_for_testing, self).start_server()
690
5247.3.38 by Vincent Ladeuil
Fix the last remaining failures.
691
    def stop_server(self):
5247.3.40 by Vincent Ladeuil
Make sure the chroot server is shut down too.
692
        try:
693
            super(SmartTCPServer_for_testing, self).stop_server()
694
        finally:
695
            self.chroot_server.stop_server()
5247.3.38 by Vincent Ladeuil
Fix the last remaining failures.
696
5247.3.37 by Vincent Ladeuil
Use TestingTCPServerInAThread for smart test servers, only 4 test failures remaining.
697
    def get_backing_transport(self, backing_transport_server):
698
        """Get a backing transport from a server we are decorating."""
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
699
        return transport.get_transport_from_url(
700
            backing_transport_server.get_url())
5017.3.18 by Vincent Ladeuil
Move SmartTCPServer_for_testing and friends to bzrlib.tests.test_server
701
702
    def get_url(self):
5247.3.37 by Vincent Ladeuil
Use TestingTCPServerInAThread for smart test servers, only 4 test failures remaining.
703
        url = self.server.get_url()
5017.3.18 by Vincent Ladeuil
Move SmartTCPServer_for_testing and friends to bzrlib.tests.test_server
704
        return url[:-1] + self.client_path_extra
705
706
    def get_bogus_url(self):
707
        """Return a URL which will fail to connect"""
708
        return 'bzr://127.0.0.1:1/'
709
710
711
class ReadonlySmartTCPServer_for_testing(SmartTCPServer_for_testing):
712
    """Get a readonly server for testing."""
713
714
    def get_backing_transport(self, backing_transport_server):
715
        """Get a backing transport from a server we are decorating."""
716
        url = 'readonly+' + backing_transport_server.get_url()
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
717
        return transport.get_transport_from_url(url)
5017.3.18 by Vincent Ladeuil
Move SmartTCPServer_for_testing and friends to bzrlib.tests.test_server
718
719
720
class SmartTCPServer_for_testing_v2_only(SmartTCPServer_for_testing):
721
    """A variation of SmartTCPServer_for_testing that limits the client to
722
    using RPCs in protocol v2 (i.e. bzr <= 1.5).
723
    """
724
725
    def get_url(self):
726
        url = super(SmartTCPServer_for_testing_v2_only, self).get_url()
727
        url = 'bzr-v2://' + url[len('bzr://'):]
728
        return url
729
730
731
class ReadonlySmartTCPServer_for_testing_v2_only(
732
    SmartTCPServer_for_testing_v2_only):
733
    """Get a readonly server for testing."""
734
735
    def get_backing_transport(self, backing_transport_server):
736
        """Get a backing transport from a server we are decorating."""
737
        url = 'readonly+' + backing_transport_server.get_url()
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
738
        return transport.get_transport_from_url(url)