From: Tomek Mrugalski Date: Fri, 25 May 2012 19:32:28 +0000 (+0200) Subject: [1503] DHCPv4 Python tests now don't block when nothing is printed on stderr X-Git-Tag: trac2351_base~226^2~63^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b35d3159e812712e47d59db80ae0115e58cd5c82;p=thirdparty%2Fkea.git [1503] DHCPv4 Python tests now don't block when nothing is printed on stderr --- diff --git a/src/bin/dhcp4/tests/dhcp4_test.py b/src/bin/dhcp4/tests/dhcp4_test.py index 3f75e6929f..a686eda92d 100644 --- a/src/bin/dhcp4/tests/dhcp4_test.py +++ b/src/bin/dhcp4/tests/dhcp4_test.py @@ -23,6 +23,7 @@ import socket from isc.net.addr import IPAddr import time import isc +import fcntl class TestDhcpv4Daemon(unittest.TestCase): def setUp(self): @@ -34,7 +35,7 @@ class TestDhcpv4Daemon(unittest.TestCase): def tearDown(self): pass - def runDhcp4(self, params): + def runDhcp4(self, params, wait=1): """ This method runs dhcp4 and returns a touple: (returncode, stdout, stderr) """ @@ -62,34 +63,55 @@ class TestDhcpv4Daemon(unittest.TestCase): pi = ProcessInfo('Test Process', params) pi.spawn() - time.sleep(1) + time.sleep(wait) os.dup2(self.stdout_old, sys.stdout.fileno()) + os.dup2(self.stderr_old, sys.stderr.fileno()) self.assertNotEqual(pi.process, None) self.assertTrue(type(pi.pid) is int) + # Set non-blocking read on pipes. Process may not print anything + # on specific output and the we would hang without this. + fd = self.stdout_pipes[0] + fl = fcntl.fcntl(fd, fcntl.F_GETFL) + fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) + + fd = self.stderr_pipes[0] + fl = fcntl.fcntl(fd, fcntl.F_GETFL) + fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) + # There's potential problem if b10-dhcp4 prints out more # than 4k of text - output = os.read(self.stdout_pipes[0], 4096) - error = os.read(self.stderr_pipes[0], 4096) + try: + output = os.read(self.stdout_pipes[0], 4096) + except OSError: + print("No data available from stdout") + output = "" + # read can return None. Make sure we have a string if (output is None): output = "" + + try: + error = os.read(self.stderr_pipes[0], 4096) + except OSError: + print("No data available on stderr") + error = "" + + # read can return None. Make sure we have a string if (error is None): error = "" + try: if (not pi.process.poll()): # let's be nice at first... - pi.process.send_signal(signal.SIGTERM) - - # give the process time to die out gracefully - time.sleep(1) - if (pi.process.returncode == None): - # If the suspect does not cooperate, use a bigger hammer. - os.kill(pi.pid, signal.SIGKILL) + pi.process.terminate() except OSError: print("Ignoring failed kill attempt. Process is dead already.") + # call this to get returncode, process should be dead by now + rc = pi.process.wait() + # Clean up our stdout/stderr munging. os.dup2(self.stdout_old, sys.stdout.fileno()) os.close(self.stdout_pipes[0]) @@ -98,9 +120,9 @@ class TestDhcpv4Daemon(unittest.TestCase): os.close(self.stderr_pipes[0]) print ("Process finished, return code=%d, stdout=%d bytes, stderr=%d bytes" - % (pi.process.returncode, len(output), len(error)) ) + % (rc, len(output), len(error)) ) - return (pi.process.returncode, output, error) + return (rc, output, error) def test_alive(self): print("Note: Purpose of some of the tests is to check if DHCPv4 server can be started,")