Bug 1215756 - Fix mozprocess unit tests failures. r=ahal

This now check process status based on pids, not anymore
on an arbitrary string given in the command line.

Some cleanup in there, including removing code duplicate.
This commit is contained in:
Julien Pagès 2015-10-21 10:57:58 -04:00
parent 1dd29cc1ee
commit eae5e47702
8 changed files with 40 additions and 258 deletions

View File

@ -6,23 +6,6 @@ import psutil
here = os.path.dirname(os.path.abspath(__file__))
def check_for_process(processName):
"""
Use to determine if process of the given name is still running.
Returns:
detected -- True if process is detected to exist, False otherwise
output -- if process exists, stdout of the process, [] otherwise
"""
name = os.path.basename(processName)
process = [p.pid for p in psutil.process_iter()
if p.name() == name]
if process:
return True, process
return False, []
class ProcTest(unittest.TestCase):
@classmethod
@ -30,24 +13,24 @@ class ProcTest(unittest.TestCase):
cls.proclaunch = os.path.join(here, "proclaunch.py")
cls.python = sys.executable
def determine_status(self,
detected=False,
output='',
returncode=0,
didtimeout=False,
isalive=False,
expectedfail=()):
def determine_status(self, proc, isalive=False, expectedfail=()):
"""
Use to determine if the situation has failed.
Parameters:
detected -- value from check_for_process to determine if the process is detected
output -- string of data from detected process, can be ''
returncode -- return code from process, defaults to 0
didtimeout -- True if process timed out, defaults to False
proc -- the processhandler instance
isalive -- Use True to indicate we pass if the process exists; however, by default
the test will pass if the process does not exist (isalive == False)
expectedfail -- Defaults to [], used to indicate a list of fields that are expected to fail
"""
returncode = proc.proc.returncode
didtimeout = proc.didTimeout
detected = psutil.pid_exists(proc.pid)
output = ''
# ProcessHandler has output when store_output is set to True in the constructor
# (this is the default)
if getattr(proc, 'output'):
output = proc.output
if 'returncode' in expectedfail:
self.assertTrue(returncode, "Detected an unexpected return code of: %s" % returncode)
elif isalive:

View File

@ -8,6 +8,7 @@ import os
import subprocess
import sys
import unittest
import proctest
from mozprocess import processhandler
here = os.path.dirname(os.path.abspath(__file__))
@ -49,45 +50,8 @@ def make_proclaunch(aDir):
raise AssertionError("proclaunch executable '%s' does not exist (sys.platform=%s)" % (exepath, sys.platform))
return exepath
def check_for_process(processName):
"""
Use to determine if process of the given name is still running.
Returns:
detected -- True if process is detected to exist, False otherwise
output -- if process exists, stdout of the process, '' otherwise
"""
# TODO: replace with
# https://github.com/mozilla/mozbase/blob/master/mozprocess/mozprocess/pid.py
# which should be augmented from talos
# see https://bugzilla.mozilla.org/show_bug.cgi?id=705864
output = ''
if sys.platform == "win32":
# On windows we use tasklist
p1 = subprocess.Popen(["tasklist"], stdout=subprocess.PIPE)
output = p1.communicate()[0]
detected = False
for line in output.splitlines():
if processName in line:
detected = True
break
else:
p1 = subprocess.Popen(["ps", "-ef"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["grep", processName], stdin=p1.stdout, stdout=subprocess.PIPE)
p1.stdout.close()
output = p2.communicate()[0]
detected = False
for line in output.splitlines():
if "grep %s" % processName in line:
continue
elif processName in line and not 'defunct' in line:
detected = True
break
return detected, output
class ProcTest(unittest.TestCase):
class ProcTest(proctest.ProcTest):
# whether to remove created files on exit
cleanup = os.environ.get('CLEANUP', 'true').lower() in ('1', 'true')
@ -128,11 +92,7 @@ class ProcTest(unittest.TestCase):
p.run()
p.wait()
detected, output = check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout)
self.determine_status(p)
def test_commandline_no_args(self):
"""Command line is reported correctly when no arguments are specified"""
@ -185,11 +145,7 @@ class ProcTest(unittest.TestCase):
p.run()
p.wait()
detected, output = check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout)
self.determine_status(p)
def test_process_timeout(self):
""" Process is started, runs but we time out waiting on it
@ -200,13 +156,7 @@ class ProcTest(unittest.TestCase):
p.run(timeout=10)
p.wait()
detected, output = check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout,
False,
['returncode', 'didtimeout'])
self.determine_status(p, False, ['returncode', 'didtimeout'])
def test_process_timeout_no_kill(self):
""" Process is started, runs but we time out waiting on it
@ -224,13 +174,7 @@ class ProcTest(unittest.TestCase):
p.wait()
self.assertTrue(p.didTimeout)
detected, output = check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout,
False,
['returncode', 'didtimeout'])
self.determine_status(p, False, ['returncode', 'didtimeout'])
def test_process_waittimeout(self):
"""
@ -244,13 +188,7 @@ class ProcTest(unittest.TestCase):
p.run()
p.wait(timeout=5)
detected, output = check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout,
True,
())
self.determine_status(p, True, ())
def test_process_waitnotimeout(self):
""" Process is started, runs to completion before our wait times out
@ -261,11 +199,7 @@ class ProcTest(unittest.TestCase):
p.run(timeout=30)
p.wait()
detected, output = check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout)
self.determine_status(p)
def test_process_kill(self):
"""Process is started, we kill it"""
@ -275,11 +209,7 @@ class ProcTest(unittest.TestCase):
p.run()
p.kill()
detected, output = check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout)
self.determine_status(p)
def test_process_output_twice(self):
"""
@ -293,46 +223,8 @@ class ProcTest(unittest.TestCase):
p.processOutput(timeout=5)
p.wait()
detected, output = check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout,
False,
())
self.determine_status(p, False, ())
def determine_status(self,
detected=False,
output='',
returncode=0,
didtimeout=False,
isalive=False,
expectedfail=()):
"""
Use to determine if the situation has failed.
Parameters:
detected -- value from check_for_process to determine if the process is detected
output -- string of data from detected process, can be ''
returncode -- return code from process, defaults to 0
didtimeout -- True if process timed out, defaults to False
isalive -- Use True to indicate we pass if the process exists; however, by default
the test will pass if the process does not exist (isalive == False)
expectedfail -- Defaults to [], used to indicate a list of fields that are expected to fail
"""
if 'returncode' in expectedfail:
self.assertTrue(returncode, "Detected an unexpected return code of: %s" % returncode)
elif not isalive:
self.assertTrue(returncode == 0, "Detected non-zero return code of: %d" % returncode)
if 'didtimeout' in expectedfail:
self.assertTrue(didtimeout, "Detected that process didn't time out")
else:
self.assertTrue(not didtimeout, "Detected that process timed out")
if isalive:
self.assertTrue(detected, "Detected process is not running, process output: %s" % output)
else:
self.assertTrue(not detected, "Detected process is still running, process output: %s" % output)
if __name__ == '__main__':
unittest.main()

View File

@ -26,12 +26,7 @@ class ProcTestKill(proctest.ProcTest):
p.run()
p.kill()
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout,
expectedfail=('returncode',))
self.determine_status(p, expectedfail=('returncode',))
def test_process_kill_deep(self):
"""Process is started, we kill it, we use a deep process tree"""
@ -41,12 +36,7 @@ class ProcTestKill(proctest.ProcTest):
p.run()
p.kill()
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout,
expectedfail=('returncode',))
self.determine_status(p, expectedfail=('returncode',))
def test_process_kill_deep_wait(self):
"""Process is started, we use a deep process tree, we let it spawn
@ -59,12 +49,7 @@ class ProcTestKill(proctest.ProcTest):
time.sleep(3)
p.kill()
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout,
expectedfail=('returncode',))
self.determine_status(p, expectedfail=('returncode',))
def test_process_kill_broad(self):
"""Process is started, we kill it, we use a broad process tree"""
@ -74,12 +59,7 @@ class ProcTestKill(proctest.ProcTest):
p.run()
p.kill()
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout,
expectedfail=('returncode',))
self.determine_status(p, expectedfail=('returncode',))
@unittest.skipUnless(processhandler.isPosix, "posix only")
def test_process_kill_with_sigterm(self):

View File

@ -25,12 +25,7 @@ class ProcTestKill(proctest.ProcTest):
time.sleep(3)
p.kill()
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout,
expectedfail=('returncode',))
self.determine_status(p, expectedfail=('returncode',))
if __name__ == '__main__':
unittest.main()

View File

@ -22,13 +22,7 @@ class ProcTestMisc(proctest.ProcTest):
p.processOutput(timeout=5)
p.wait()
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout,
False,
())
self.determine_status(p, False, ())
if __name__ == '__main__':
unittest.main()

View File

@ -22,13 +22,7 @@ class ProcTestOutput(proctest.ProcTest):
p.processOutput(timeout=5)
p.wait()
detected, output = proctest.check_for_process("procnonewline.py")
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout,
False,
())
self.determine_status(p, False, ())
def test_stream_process_output(self):
"""
@ -56,13 +50,7 @@ class ProcTestOutput(proctest.ProcTest):
self.assertFalse(buf.closed)
buf.close()
detected, output = proctest.check_for_process("proccountfive.py")
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout,
False,
())
self.determine_status(p, False, ())
if __name__ == '__main__':
unittest.main()

View File

@ -34,12 +34,7 @@ class ProcTestPoll(proctest.ProcTest):
self.assertEqual(returncode, None)
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
returncode,
p.didTimeout,
True)
self.determine_status(p, True)
p.kill()
def test_poll_after_kill(self):
@ -55,11 +50,7 @@ class ProcTestPoll(proctest.ProcTest):
self.assertLess(returncode, 0)
self.assertEqual(returncode, p.poll())
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
returncode,
p.didTimeout)
self.determine_status(p)
def test_poll_after_kill_no_process_group(self):
"""Process (no group) is killed, and poll() is called"""
@ -76,11 +67,7 @@ class ProcTestPoll(proctest.ProcTest):
self.assertLess(returncode, 0)
self.assertEqual(returncode, p.poll())
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
returncode,
p.didTimeout)
self.determine_status(p)
def test_poll_after_double_kill(self):
"""Process is killed twice, and poll() is called"""
@ -96,11 +83,7 @@ class ProcTestPoll(proctest.ProcTest):
self.assertLess(returncode, 0)
self.assertEqual(returncode, p.poll())
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
returncode,
p.didTimeout)
self.determine_status(p)
def test_poll_after_external_kill(self):
"""Process is killed externally, and poll() is called"""
@ -116,11 +99,7 @@ class ProcTestPoll(proctest.ProcTest):
self.assertEqual(returncode, -signal.SIGTERM)
self.assertEqual(returncode, p.poll())
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
returncode,
p.didTimeout)
self.determine_status(p)
if __name__ == '__main__':

View File

@ -19,11 +19,7 @@ class ProcTestWait(proctest.ProcTest):
p.run()
p.wait()
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout)
self.determine_status(p)
def test_wait(self):
"""Process is started runs to completion while we wait indefinitely"""
@ -34,11 +30,7 @@ class ProcTestWait(proctest.ProcTest):
p.run()
p.wait()
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout)
self.determine_status(p)
def test_timeout(self):
@ -50,18 +42,11 @@ class ProcTestWait(proctest.ProcTest):
p.run(timeout=10)
p.wait()
detected, output = proctest.check_for_process(self.proclaunch)
if mozinfo.isUnix:
# process was killed, so returncode should be negative
self.assertLess(p.proc.returncode, 0)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout,
False,
['returncode', 'didtimeout'])
self.determine_status(p, False, ['returncode', 'didtimeout'])
def test_waittimeout(self):
"""
@ -75,13 +60,7 @@ class ProcTestWait(proctest.ProcTest):
p.run()
p.wait(timeout=5)
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout,
True,
())
self.determine_status(p, True, ())
def test_waitnotimeout(self):
""" Process is started, runs to completion before our wait times out
@ -92,11 +71,7 @@ class ProcTestWait(proctest.ProcTest):
p.run(timeout=30)
p.wait()
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
p.proc.returncode,
p.didTimeout)
self.determine_status(p)
def test_wait_twice_after_kill(self):
"""Bug 968718: Process is started and stopped. wait() twice afterward."""
@ -108,11 +83,7 @@ class ProcTestWait(proctest.ProcTest):
returncode1 = p.wait()
returncode2 = p.wait()
detected, output = proctest.check_for_process(self.proclaunch)
self.determine_status(detected,
output,
returncode2,
p.didTimeout)
self.determine_status(p)
self.assertLess(returncode2, 0,
'Negative returncode expected, got "%s"' % returncode2)