Rev 3115: Select the server depending on the request handler protocol. Add tests. in file:///v/home/vila/src/bzr/bugs/175524/

Vincent Ladeuil v.ladeuil+lp at free.fr
Tue Dec 18 13:53:09 GMT 2007


At file:///v/home/vila/src/bzr/bugs/175524/

------------------------------------------------------------
revno: 3115
revision-id:v.ladeuil+lp at free.fr-20071218135304-rqiekrykivoq8qdm
parent: v.ladeuil+lp at free.fr-20071217101617-zsszx3y00yj25dd2
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: 175524
timestamp: Tue 2007-12-18 14:53:04 +0100
message:
  Select the server depending on the request handler protocol. Add tests.
  
  * bzrlib/tests/test_http.py:
  Fix some more imports.
  (TestHTTPServer): Smoke test for hhtp server.
  
  * bzrlib/tests/http_server.py:
  (HttpServer._get_httpd): Create the server for the protocol
  handled by the request handler.
  (HttpServer._http_start): Catch exceptions that could occur during
  server construction or python will hang.
  (HttpServer.setUp): Report exception if any.
modified:
  bzrlib/tests/http_server.py    httpserver.py-20061012142527-m1yxdj1xazsf8d7s-1
  bzrlib/tests/test_http.py      testhttp.py-20051018020158-b2eef6e867c514d9
-------------- next part --------------
=== modified file 'bzrlib/tests/http_server.py'
--- a/bzrlib/tests/http_server.py	2007-12-17 10:16:17 +0000
+++ b/bzrlib/tests/http_server.py	2007-12-18 13:53:04 +0000
@@ -348,6 +348,11 @@
     Subclasses can provide a specific request handler.
     """
 
+    # The real servers depending on the protocol
+    http_server_class = {'HTTP/1.0': TestingHTTPServer,
+                         'HTTP/1.1': TestingThreadingHTTPServer,
+                         }
+
     # Whether or not we proxy the requests (see
     # TestingHTTPRequestHandler.translate_path).
     proxy_requests = False
@@ -367,20 +372,42 @@
 
     def _get_httpd(self):
         if self._httpd is None:
-            self._httpd = TestingHTTPServer(
-                (self.host, self.port), self.request_handler, self)
+            rhandler = self.request_handler
+            proto_vers = rhandler.protocol_version
+            # Create the appropriate server for the required protocol
+            serv_cls = self.http_server_class.get(proto_vers, None)
+            if serv_cls is None:
+                raise httplib.UnknownProtocol(proto_vers)
+            else:
+                self._httpd = serv_cls((self.host, self.port), rhandler, self)
             host, self.port = self._httpd.socket.getsockname()
         return self._httpd
 
     def _http_start(self):
-        httpd = self._get_httpd()
-        self._http_base_url = '%s://%s:%s/' % (self._url_protocol,
-                                               self.host,
-                                               self.port)
-        self._http_starting.release()
+        """Server thread main entry point. """
+        self._http_running = False
+        try:
+            try:
+                httpd = self._get_httpd()
+                self._http_base_url = '%s://%s:%s/' % (self._url_protocol,
+                                                       self.host, self.port)
+                self._http_running = True
+            except:
+                # Whatever goes wrong, we save the exception for the main
+                # thread. Note that since we are running in a thread, no signal
+                # can be received, so we don't care about KeyboardInterrupt.
+                self._http_exception = sys.exc_info()
+        finally:
+            # Release the lock or the main thread will block and the whole
+            # process will hang.
+            self._http_starting.release()
 
+        # From now on, exceptions are taken care of by the
+        # SocketServer.BaseServer or the request handler.
         while self._http_running:
             try:
+                # Really an HTTP connection but the python framework is generic
+                # and call them requests
                 httpd.handle_request()
             except socket.timeout:
                 pass
@@ -416,15 +443,21 @@
             backing_transport_server
         self._home_dir = os.getcwdu()
         self._local_path_parts = self._home_dir.split(os.path.sep)
+        self._http_base_url = None
+
         self._http_starting = threading.Lock()
         self._http_starting.acquire()
-        self._http_running = True
-        self._http_base_url = None
         self._http_thread = threading.Thread(target=self._http_start)
         self._http_thread.setDaemon(True)
+        self._http_exception = None
         self._http_thread.start()
+
         # Wait for the server thread to start (i.e release the lock)
         self._http_starting.acquire()
+
+        if self._http_exception is not None:
+            exc_class, exc_value, exc_tb = self._http_exception
+            raise exc_class, exc_value, exc_tb
         self._http_starting.release()
         self.logs = []
 

=== modified file 'bzrlib/tests/test_http.py'
--- a/bzrlib/tests/test_http.py	2007-12-11 14:26:18 +0000
+++ b/bzrlib/tests/test_http.py	2007-12-18 13:53:04 +0000
@@ -21,6 +21,7 @@
 # TODO: What about renaming to bzrlib.tests.transport.http ?
 
 from cStringIO import StringIO
+import httplib
 import os
 import select
 import socket
@@ -37,16 +38,12 @@
     urlutils,
     )
 from bzrlib.tests import (
+    http_server,
     TestCase,
     TestUIFactory,
     TestSkipped,
     StringIOWrapper,
     )
-from bzrlib.tests.http_server import (
-    HttpServer,
-    HttpServer_PyCurl,
-    HttpServer_urllib,
-    )
 from bzrlib.tests.http_utils import (
     BadProtocolRequestHandler,
     BadStatusRequestHandler,
@@ -151,6 +148,54 @@
         self.port = None
 
 
+class TestHTTPServer(tests.TestCase):
+    """Test the HTTP servers implementations."""
+
+    def test_invalid_protocol(self):
+        class BogusRequestHandler(http_server.TestingHTTPRequestHandler):
+
+            protocol_version = 'HTTP/0.1'
+
+        server = http_server.HttpServer(BogusRequestHandler)
+        try:
+            self.assertRaises(httplib.UnknownProtocol,server.setUp)
+        except:
+            server.tearDown()
+            self.fail('HTTP Server creation did not raise UnknownProtocol')
+
+    def test_server_start_and_stop(self):
+        server = http_server.HttpServer()
+        server.setUp()
+        self.assertTrue(server._http_running)
+        server.tearDown()
+        self.assertFalse(server._http_running)
+
+    def test_create_http_server_one_zero(self):
+        class RequestHandlerOneZero(http_server.TestingHTTPRequestHandler):
+
+            protocol_version = 'HTTP/1.0'
+
+        server = http_server.HttpServer(RequestHandlerOneZero)
+        server.setUp()
+        try:
+            self.assertIsInstance(server._httpd, http_server.TestingHTTPServer)
+        finally:
+            server.tearDown()
+
+    def test_create_http_server_one_one(self):
+        class RequestHandlerOneOne(http_server.TestingHTTPRequestHandler):
+
+            protocol_version = 'HTTP/1.1'
+
+        server = http_server.HttpServer(RequestHandlerOneOne)
+        server.setUp()
+        try:
+            self.assertIsInstance(server._httpd,
+                                  http_server.TestingThreadingHTTPServer)
+        finally:
+            server.tearDown()
+
+
 class TestWithTransport_pycurl(object):
     """Test case to inherit from if pycurl is present"""
 
@@ -231,7 +276,7 @@
     """Test http urls with urllib"""
 
     _transport = HttpTransport_urllib
-    _server = HttpServer_urllib
+    _server = http_server.HttpServer_urllib
     _qualified_prefix = 'http+urllib'
 
 
@@ -239,7 +284,7 @@
                           tests.TestCase):
     """Test http urls with pycurl"""
 
-    _server = HttpServer_PyCurl
+    _server = http_server.HttpServer_PyCurl
     _qualified_prefix = 'http+pycurl'
 
     # TODO: This should really be moved into another pycurl
@@ -433,7 +478,7 @@
     """Tests exceptions during the connection phase"""
 
     def create_transport_readonly_server(self):
-        return HttpServer(WallRequestHandler)
+        return http_server.HttpServer(WallRequestHandler)
 
     def test_http_has(self):
         server = self.get_readonly_server()
@@ -469,7 +514,7 @@
     """Tests bad status from server."""
 
     def create_transport_readonly_server(self):
-        return HttpServer(BadStatusRequestHandler)
+        return http_server.HttpServer(BadStatusRequestHandler)
 
     def test_http_has(self):
         server = self.get_readonly_server()
@@ -501,7 +546,7 @@
     """
 
     def create_transport_readonly_server(self):
-        return HttpServer(InvalidStatusRequestHandler)
+        return http_server.HttpServer(InvalidStatusRequestHandler)
 
 
 class TestInvalidStatusServer_urllib(TestInvalidStatusServer,
@@ -521,7 +566,7 @@
     """Tests bad protocol from server."""
 
     def create_transport_readonly_server(self):
-        return HttpServer(BadProtocolRequestHandler)
+        return http_server.HttpServer(BadProtocolRequestHandler)
 
     def test_http_has(self):
         server = self.get_readonly_server()
@@ -551,7 +596,7 @@
     """Tests forbidden server"""
 
     def create_transport_readonly_server(self):
-        return HttpServer(ForbiddenRequestHandler)
+        return http_server.HttpServer(ForbiddenRequestHandler)
 
     def test_http_has(self):
         server = self.get_readonly_server()
@@ -688,7 +733,7 @@
     """Test readv against a server which accept only single range requests"""
 
     def create_transport_readonly_server(self):
-        return HttpServer(SingleRangeRequestHandler)
+        return http_server.HttpServer(SingleRangeRequestHandler)
 
 
 class TestSingleRangeRequestServer_urllib(TestSingleRangeRequestServer,
@@ -708,7 +753,7 @@
     """Test readv against a server which only accept single range requests"""
 
     def create_transport_readonly_server(self):
-        return HttpServer(SingleOnlyRangeRequestHandler)
+        return http_server.HttpServer(SingleOnlyRangeRequestHandler)
 
 
 class TestSingleOnlyRangeRequestServer_urllib(TestSingleOnlyRangeRequestServer,
@@ -728,7 +773,7 @@
     """Test readv against a server which do not accept range requests"""
 
     def create_transport_readonly_server(self):
-        return HttpServer(NoRangeRequestHandler)
+        return http_server.HttpServer(NoRangeRequestHandler)
 
 
 class TestNoRangeRequestServer_urllib(TestNoRangeRequestServer,



More information about the bazaar-commits mailing list