~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/http_server.py

  • Committer: Vincent Ladeuil
  • Date: 2007-12-17 10:16:17 UTC
  • mto: (3146.3.1 179368) (3156.2.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 3158.
  • Revision ID: v.ladeuil+lp@free.fr-20071217101617-zsszx3y00yj25dd2
Rework http test servers classes. Both 1.0 and 1.1 passing tests (1.1 forced manually).

* bzrlib/tests/http_server.py:
(TestingHTTPServerWrapper): Introduce a wrapper to allow different
subclasses for servers while keeping the common parts in a single
place.
(TestingHTTPServer): The 1.0 server.
(TestingThreadingHTTPServer): The 1.1 server.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
import re
24
24
import SimpleHTTPServer
25
25
import socket
 
26
import SocketServer
26
27
import sys
27
28
import threading
28
29
import time
268
269
            return path
269
270
 
270
271
 
271
 
class TestingHTTPServer(BaseHTTPServer.HTTPServer):
272
 
 
273
 
    def __init__(self, server_address, request_handler_class,
274
 
                 test_case_server):
275
 
        BaseHTTPServer.HTTPServer.__init__(self, server_address,
276
 
                                           request_handler_class)
 
272
class TestingHTTPServerWrapper(object):
 
273
    """Isolate the wrapper itself to make the server use transparent.
 
274
 
 
275
    Daughter classes can override any method and/or directly call the _server
 
276
    methods.
 
277
    """
 
278
 
 
279
    def __init__(self, server_class, test_case_server,
 
280
                 server_address, request_handler_class):
 
281
        self._server = server_class(server_address, request_handler_class)
277
282
        # test_case_server can be used to communicate between the
278
283
        # tests and the server (or the request handler and the
279
284
        # server), allowing dynamic behaviors to be defined from
280
285
        # the tests cases.
281
 
        self.test_case_server = test_case_server
 
286
        self._server.test_case_server = test_case_server
 
287
 
 
288
    def __getattr__(self, name):
 
289
        return getattr(self._server, name)
 
290
 
 
291
    def server_bind(self):
 
292
        """Override server_bind to store the server name."""
 
293
        self._server.server_bind()
 
294
        host, port = self._server.socket.getsockname()[:2]
 
295
        self._server.server_name = socket.getfqdn(host)
 
296
        self._server.server_port = port
282
297
 
283
298
    def server_close(self):
284
 
        """Called to clean-up the server.
285
 
 
286
 
        Since the server may be in a blocking read, we shutdown the socket
287
 
        before closing it.
288
 
        """
289
 
        self.socket.shutdown(socket.SHUT_RDWR)
290
 
        BaseHTTPServer.HTTPServer.server_close(self)
 
299
         """Called to clean-up the server.
 
300
 
 
301
         Since the server may be (surely is, even) in a blocking listen, we
 
302
         shutdown its socket before closing it.
 
303
         """
 
304
         # Note that is this executed as part of the implicit tear down in the
 
305
         # main thread while the server runs in its own thread. The clean way
 
306
         # to tear down the server will be to instruct him to stop accepting
 
307
         # connections and wait for the current connection to end naturally. To
 
308
         # end the connection naturally, the http transports should close their
 
309
         # socket when they do not need to talk to the server anymore.  We
 
310
         # don't want to impose such a constraint on the http transports (and
 
311
         # we can't anyway ;). So we must tear down here, from the main thread,
 
312
         # when the test have ended.  Note that since the server is in a
 
313
         # blocking operation and since python use select internally, shutting
 
314
         # down the socket is reliable and relatively clean.
 
315
         self._server.socket.shutdown(socket.SHUT_RDWR)
 
316
         # Let the server properly close the socket
 
317
         self._server.server_close()
 
318
 
 
319
class TestingHTTPServer(TestingHTTPServerWrapper):
 
320
 
 
321
    def __init__(self, server_address, request_handler_class, test_case_server):
 
322
        super(TestingHTTPServer, self).__init__(
 
323
            SocketServer.TCPServer, test_case_server,
 
324
            server_address, request_handler_class)
 
325
 
 
326
 
 
327
class TestingThreadingHTTPServer(TestingHTTPServerWrapper):
 
328
    """A threading HTTP test server for HTTP 1.1.
 
329
 
 
330
    Since tests can initiate several concurrent connections to the same http
 
331
    server, we need an independent connection for each of them. We achieve that
 
332
    by spawning a new thread for each connection.
 
333
    """
 
334
 
 
335
    def __init__(self, server_address, request_handler_class, test_case_server):
 
336
        super(TestingThreadingHTTPServer, self).__init__(
 
337
            SocketServer.ThreadingTCPServer, test_case_server,
 
338
            server_address, request_handler_class)
 
339
        # Decides how threads will act upon termination of the main
 
340
        # process. This is prophylactic as we should not leave the threads
 
341
        # lying around.
 
342
        self._server.daemon_threads = True
291
343
 
292
344
 
293
345
class HttpServer(transport.Server):
315
367
 
316
368
    def _get_httpd(self):
317
369
        if self._httpd is None:
318
 
            self._httpd = TestingHTTPServer((self.host, self.port),
319
 
                                            self.request_handler,
320
 
                                            self)
 
370
            self._httpd = TestingHTTPServer(
 
371
                (self.host, self.port), self.request_handler, self)
321
372
            host, self.port = self._httpd.socket.getsockname()
322
373
        return self._httpd
323
374