← Back to team overview

dulwich-users team mailing list archive

[PATCH 07/33] Make the server thread raise errors in compat tests.

 

From: Dave Borowitz <dborowitz@xxxxxxxxxx>

Errors were previously swallowed by handle_error in TCPServer. This is
sensible behavior for a real server, but was causing silent failures and
false positives in tests.

Still haven't solved the deadlocking issue with failing server compat
tests, but at least the deadlocks are no longer silent.

Change-Id: I3cff75a481d00e7d78473a4ccf710acd17bcb2ef
---
 dulwich/server.py                   |   18 +++++++++++++++++-
 dulwich/tests/compat/test_server.py |    3 ++-
 dulwich/tests/compat/test_web.py    |   11 ++++++++++-
 3 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/dulwich/server.py b/dulwich/server.py
index 780ba51..1c05a16 100644
--- a/dulwich/server.py
+++ b/dulwich/server.py
@@ -754,12 +754,25 @@ class TCPGitServer(SocketServer.TCPServer):
     def _make_handler(self, *args, **kwargs):
         return TCPGitRequestHandler(self.handlers, *args, **kwargs)
 
-    def __init__(self, backend, listen_addr, port=TCP_GIT_PORT, handlers=None):
+    def __init__(self, backend, listen_addr, port=TCP_GIT_PORT, handlers=None,
+                 raise_exceptions=False):
+        """Create a TCP git server.
+
+        :param backend: A Backend object that can open Repos.
+        :param list_addr: The address to listen on.
+        :param port: The port to listen on.
+        :param handlers: An optional dict of service name -> handler class for
+            handling git-upload-pack and git-receive-pack.
+        :param raise_exceptions: If True, exceptions will be raised; otherwise,
+            exceptions will only be logged. Should typically only be True in
+            tests.
+        """
         self.handlers = dict(DEFAULT_HANDLERS)
         if handlers is not None:
             self.handlers.update(handlers)
         self.backend = backend
         logger.info('Listening for TCP connections on %s:%d', listen_addr, port)
+        self._raise_exceptions = raise_exceptions
         SocketServer.TCPServer.__init__(self, (listen_addr, port),
                                         self._make_handler)
 
@@ -770,6 +783,9 @@ class TCPGitServer(SocketServer.TCPServer):
     def handle_error(self, request, client_address):
         logger.exception('Exception happened during processing of request '
                          'from %s', client_address)
+        if self._raise_exceptions:
+            exctype, value, traceback = sys.exc_info()
+            raise exctype, value, traceback
 
 
 def main(argv=sys.argv):
diff --git a/dulwich/tests/compat/test_server.py b/dulwich/tests/compat/test_server.py
index 1fd0eb7..f8abe38 100644
--- a/dulwich/tests/compat/test_server.py
+++ b/dulwich/tests/compat/test_server.py
@@ -81,7 +81,8 @@ class GitServerTestCase(ServerTests, CompatTestCase):
     def _start_server(self, repo):
         backend = DictBackend({'/': repo})
         dul_server = TCPGitServer(backend, 'localhost', 0,
-                                  handlers=self._handlers())
+                                  handlers=self._handlers(),
+                                  raise_exceptions=True)
         self._check_server(dul_server)
         threading.Thread(target=dul_server.serve).start()
         self._server = dul_server
diff --git a/dulwich/tests/compat/test_web.py b/dulwich/tests/compat/test_web.py
index c65eba1..3c25a96 100644
--- a/dulwich/tests/compat/test_web.py
+++ b/dulwich/tests/compat/test_web.py
@@ -24,6 +24,7 @@ warning: these tests should be fairly stable, but when writing/debugging new
     Ctrl-C'ed. On POSIX systems, you can kill the tests with Ctrl-Z, "kill %".
 """
 
+import sys
 import threading
 from wsgiref import simple_server
 
@@ -62,6 +63,14 @@ else:
         serve = ShutdownServerMixIn.serve_forever
 
 
+class TestWSGIServer(WSGIServer):
+    """Subclass of BaseWSGIServer that raises exceptions."""
+
+    def handle_error(self, request, client_address):
+        exctype, value, traceback = sys.exc_info()
+        raise exctype, value, traceback
+
+
 class WebTests(ServerTests):
     """Base tests for web server tests.
 
@@ -75,7 +84,7 @@ class WebTests(ServerTests):
         backend = DictBackend({'/': repo})
         app = self._make_app(backend)
         dul_server = simple_server.make_server(
-          'localhost', 0, app, server_class=WSGIServer,
+          'localhost', 0, app, server_class=TestWSGIServer,
           handler_class=HTTPGitRequestHandler)
         threading.Thread(target=dul_server.serve_forever).start()
         self._server = dul_server
-- 
1.7.3.1



References