]> granicus.if.org Git - python/commitdiff
Michael fixed the race conditions and removed the sleeps.
authorGuido van Rossum <guido@python.org>
Tue, 18 Jun 2002 18:35:13 +0000 (18:35 +0000)
committerGuido van Rossum <guido@python.org>
Tue, 18 Jun 2002 18:35:13 +0000 (18:35 +0000)
This is his SF patch 569697.  I renamed main() to test_main() again so
that this is run as part of the standard test suite.

Lib/test/test_socket.py

index b4540a4a35d89b845a135fc21dcd625ae7172514..a2d10ef1fec5f5dee96708df6d0492dca1f92730 100644 (file)
@@ -37,6 +37,42 @@ class SocketUDPTest(unittest.TestCase):
         self.serv = None
 
 class ThreadableTest:
+    """Threadable Test class
+
+    The ThreadableTest class makes it easy to create a threaded
+    client/server pair from an existing unit test. To create a
+    new threaded class from an existing unit test, use multiple
+    inheritance:
+
+        class NewClass (OldClass, ThreadableTest):
+            pass
+
+    This class defines two new fixture functions with obvious
+    purposes for overriding:
+
+        clientSetUp ()
+        clientTearDown ()
+
+    Any new test functions within the class must then define
+    tests in pairs, where the test name is preceeded with a
+    '_' to indicate the client portion of the test. Ex:
+
+        def testFoo(self):
+            # Server portion
+
+        def _testFoo(self):
+            # Client portion
+
+    Any exceptions raised by the clients during their tests
+    are caught and transferred to the main thread to alert
+    the testing framework.
+
+    Note, the server setup function cannot call any blocking
+    functions that rely on the client thread during setup,
+    unless serverExplicityReady() is called just before
+    the blocking call (such as in setting up a client/server
+    connection and performing the accept() in setUp().
+    """
 
     def __init__(self):
         # Swap the true setup function
@@ -45,8 +81,16 @@ class ThreadableTest:
         self.setUp = self._setUp
         self.tearDown = self._tearDown
 
+    def serverExplicitReady(self):
+        """This method allows the server to explicitly indicate that
+        it wants the client thread to proceed. This is useful if the
+        server is about to execute a blocking routine that is
+        dependent upon the client thread during its setup routine."""
+        self.server_ready.set()
+
     def _setUp(self):
-        self.ready = threading.Event()
+        self.server_ready = threading.Event()
+        self.client_ready = threading.Event()
         self.done = threading.Event()
         self.queue = Queue.Queue(1)
 
@@ -59,7 +103,9 @@ class ThreadableTest:
             self.clientRun, (test_method,))
 
         self.__setUp()
-        self.ready.wait()
+        if not self.server_ready.isSet():
+            self.server_ready.set()
+        self.client_ready.wait()
 
     def _tearDown(self):
         self.__tearDown()
@@ -70,7 +116,8 @@ class ThreadableTest:
             self.fail(msg)
 
     def clientRun(self, test_func):
-        self.ready.set()
+        self.server_ready.wait()
+        self.client_ready.set()
         self.clientSetUp()
         if not callable(test_func):
             raise TypeError, "test_func must be a callable function"
@@ -117,6 +164,9 @@ class SocketConnectedTest(ThreadedTCPSocketTest):
 
     def setUp(self):
         ThreadedTCPSocketTest.setUp(self)
+        # Indicate explicitly we're ready for the client thread to
+        # proceed and then perform the blocking call to accept
+        self.serverExplicitReady()
         conn, addr = self.serv.accept()
         self.cli_conn = conn
 
@@ -369,7 +419,6 @@ class BasicUDPTest(ThreadedUDPSocketTest):
         self.assertEqual(msg, MSG)
 
     def _testRecvFrom(self):
-        time.sleep(1) # Give server a chance to set up
         self.cli.sendto(MSG, 0, (HOST, PORT))
 
 class NonBlockingTCPTests(ThreadedTCPSocketTest):
@@ -407,12 +456,10 @@ class NonBlockingTCPTests(ThreadedTCPSocketTest):
             self.fail("Error trying to do accept after select.")
 
     def _testAccept(self):
-        time.sleep(1)
         self.cli.connect((HOST, PORT))
 
     def testConnect(self):
         """Testing non-blocking connect."""
-        time.sleep(1)
         conn, addr = self.serv.accept()
 
     def _testConnect(self):
@@ -438,7 +485,6 @@ class NonBlockingTCPTests(ThreadedTCPSocketTest):
 
     def _testRecv(self):
         self.cli.connect((HOST, PORT))
-        time.sleep(1)
         self.cli.send(MSG)
 
 class FileObjectClassTestCase(SocketConnectedTest):
@@ -498,7 +544,7 @@ class FileObjectClassTestCase(SocketConnectedTest):
         self.cli_file.write(MSG)
         self.cli_file.flush()
 
-def main():
+def test_main():
     suite = unittest.TestSuite()
     suite.addTest(unittest.makeSuite(GeneralModuleTests))
     suite.addTest(unittest.makeSuite(BasicTCPTest))
@@ -508,4 +554,4 @@ def main():
     test_support.run_suite(suite)
 
 if __name__ == "__main__":
-    main()
+    test_main()