]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[1927] Harness to run msgq process
authorMichal 'vorner' Vaner <michal.vaner@nic.cz>
Mon, 11 Mar 2013 13:01:56 +0000 (14:01 +0100)
committerMichal 'vorner' Vaner <michal.vaner@nic.cz>
Mon, 11 Mar 2013 13:01:56 +0000 (14:01 +0100)
Provide a test suite to launch and stop msgq from tests as separate
process. It'll be used to test it works correctly, by connecting to it
from the tests.

src/bin/msgq/tests/Makefile.am
src/bin/msgq/tests/msgq_run_test.py [new file with mode: 0644]

index c9ef5d304d60711f75aa07b749e0348e93b2ea71..eca8c9bb75e92be9142b0fb2fa3807f15b6d06f5 100644 (file)
@@ -1,5 +1,5 @@
-PYCOVERAGE_RUN = @PYCOVERAGE_RUN@          
-PYTESTS = msgq_test.py
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
+PYTESTS = msgq_test.py msgq_run_test.py
 EXTRA_DIST = $(PYTESTS)
 
 # If necessary (rare cases), explicitly specify paths to dynamic libraries
@@ -12,7 +12,7 @@ endif
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 if ENABLE_PYTHON_COVERAGE
-       touch $(abs_top_srcdir)/.coverage 
+       touch $(abs_top_srcdir)/.coverage
        rm -f .coverage
        ${LN_S} $(abs_top_srcdir)/.coverage .coverage
 endif
diff --git a/src/bin/msgq/tests/msgq_run_test.py b/src/bin/msgq/tests/msgq_run_test.py
new file mode 100644 (file)
index 0000000..8323ae7
--- /dev/null
@@ -0,0 +1,115 @@
+# Copyright (C) 2013  Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""
+In this test file, we actually start msgq as a process and test it
+as a whole. It may be considered a system test instead of unit test,
+but apart from the terminology, we don't care much. We need to test
+the message queue works as expected, together with the libraries.
+
+In each test, we first start a timeout (because we do some waits
+for messages and if they wouldn't come, the test could block indefinitely).
+The timeout is long, because it is for the case the test fails.
+
+We then start the msgq and wait for the socket file to appear
+(that should indicate it is ready to receive connections). Then the
+actual test starts. After the test, we kill it and remove the test file.
+
+We also register signal handlers for many signals. Even in the case
+the test is interrupted or crashes, we should ensure the message queue
+itself is terminated.
+"""
+
+import unittest
+import os
+import signal
+import sys
+import subprocess
+import time
+
+import isc.log
+
+SOCKET_PATH = os.path.abspath(os.environ['BIND10_TEST_SOCKET_FILE'])
+MSGQ_PATH = os.environ['B10_FROM_BUILD'] + '/src/bin/msgq/run_msgq.sh'
+TIMEOUT = 15 # Some long time (seconds), for single test.
+
+class MsgqRunTest(unittest.TestCase):
+    def setUp(self):
+        """
+        As described above - check the socket file does not exist.
+        Then register signals and timeouts. Finally, launch msgq
+        and wait for it to start.
+        """
+        self.__msgq = None
+        # A precondition check
+        self.assertFalse(os.path.exists(SOCKET_PATH))
+        signal.alarm(TIMEOUT)
+        self.__orig_signals = {}
+        # Register handlers for many signals. Most of them probably
+        # can't happen in python, but we register them anyway just to be
+        # safe.
+        for sig in [signal.SIGHUP, signal.SIGINT, signal.SIGQUIT,
+            signal.SIGILL, signal.SIGTRAP, signal.SIGABRT, signal.SIGBUS,
+            signal.SIGFPE, signal.SIGALRM, signal.SIGTERM]:
+            self.__orig_signals[sig] = signal.signal(sig, self.__signal)
+        # Start msgq
+        self.__msgq = subprocess.Popen([MSGQ_PATH, '-s', SOCKET_PATH],
+                                       close_fds=True)
+        # Wait for it to become ready (up to the alarm-set timeout)
+        while not os.path.exists(SOCKET_PATH):
+            # Just a short wait, so we don't hog CPU, but don't wait too long
+            time.sleep(0.01)
+
+    def tearDown(self):
+        """
+        Perform cleanup after the test.
+        """
+        self.__cleanup()
+
+    def __signal(self, signal, frame):
+        """
+        Called from a signal handler. We perform some cleanup, output
+        a complain and terminate with error.
+        """
+        self.__cleanup()
+        sys.stderr.write("Test terminating from signal " + str(signal) +
+                         " in " + str(frame) + "\n")
+        sys.exit(1)
+
+    def __cleanup(self):
+        """
+        Kill msgq (if running) and restore original signal handlers.
+        """
+        # Remove the socket (as we kill, msgq might not clean up)
+        if self.__msgq:
+            self.__msgq.kill()
+            self.__msgq = None
+        if os.path.exists(SOCKET_PATH):
+            os.unlink(SOCKET_PATH)
+        for sig in self.__orig_signals:
+            signal.signal(sig, self.__orig_signals[sig])
+        # Cancel timeout (so someone else is not hit by it)
+        signal.alarm(0)
+
+    def test_empty_run(self):
+        """
+        Temporary empty test, to see if we can start and stop msgq.
+        Testing the test harness.
+        """
+        pass
+
+if __name__ == '__main__':
+    isc.log.resetUnitTestRootLogger()
+    unittest.main()