| #!/usr/bin/env python |
| |
| # This Source Code Form is subject to the terms of the Mozilla Public |
| # License, v. 2.0. If a copy of the MPL was not distributed with this file, |
| # You can obtain one at http://mozilla.org/MPL/2.0/. |
| |
| import os |
| import subprocess |
| import sys |
| import unittest |
| import proctest |
| from mozprocess import processhandler |
| |
| here = os.path.dirname(os.path.abspath(__file__)) |
| |
| def make_proclaunch(aDir): |
| """ |
| Makes the proclaunch executable. |
| Params: |
| aDir - the directory in which to issue the make commands |
| Returns: |
| the path to the proclaunch executable that is generated |
| """ |
| |
| if sys.platform == "win32": |
| exepath = os.path.join(aDir, "proclaunch.exe") |
| else: |
| exepath = os.path.join(aDir, "proclaunch") |
| |
| # remove the launcher, if it already exists |
| # otherwise, if the make fails you may not notice |
| if os.path.exists(exepath): |
| os.remove(exepath) |
| |
| # Ideally make should take care of both calls through recursion, but since it doesn't, |
| # on windows anyway (to file?), let's just call out both targets explicitly. |
| for command in [["make", "-C", "iniparser"], |
| ["make"]]: |
| process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=aDir) |
| stdout, stderr = process.communicate() |
| if process.returncode: |
| # SomethingBadHappen; print all the things |
| print "%s: exit %d" % (command, process.returncode) |
| print "stdout:\n%s" % stdout |
| print "stderr:\n%s" % stderr |
| raise subprocess.CalledProcessError(process.returncode, command, stdout) |
| |
| # ensure the launcher now exists |
| if not os.path.exists(exepath): |
| raise AssertionError("proclaunch executable '%s' does not exist (sys.platform=%s)" % (exepath, sys.platform)) |
| return exepath |
| |
| |
| class ProcTest(proctest.ProcTest): |
| |
| # whether to remove created files on exit |
| cleanup = os.environ.get('CLEANUP', 'true').lower() in ('1', 'true') |
| |
| @classmethod |
| def setUpClass(cls): |
| cls.proclaunch = make_proclaunch(here) |
| |
| @classmethod |
| def tearDownClass(cls): |
| del cls.proclaunch |
| if not cls.cleanup: |
| return |
| files = [('proclaunch',), |
| ('proclaunch.exe',), |
| ('iniparser', 'dictionary.o'), |
| ('iniparser', 'iniparser.lib'), |
| ('iniparser', 'iniparser.o'), |
| ('iniparser', 'libiniparser.a'), |
| ('iniparser', 'libiniparser.so.0'), |
| ] |
| files = [os.path.join(here, *path) for path in files] |
| errors = [] |
| for path in files: |
| if os.path.exists(path): |
| try: |
| os.remove(path) |
| except OSError as e: |
| errors.append(str(e)) |
| if errors: |
| raise OSError("Error(s) encountered tearing down %s.%s:\n%s" % (cls.__module__, cls.__name__, '\n'.join(errors))) |
| |
| def test_process_normal_finish(self): |
| """Process is started, runs to completion while we wait for it""" |
| |
| p = processhandler.ProcessHandler([self.proclaunch, "process_normal_finish.ini"], |
| cwd=here) |
| p.run() |
| p.wait() |
| |
| self.determine_status(p) |
| |
| def test_commandline_no_args(self): |
| """Command line is reported correctly when no arguments are specified""" |
| p = processhandler.ProcessHandler(self.proclaunch, cwd=here) |
| self.assertEqual(p.commandline, self.proclaunch) |
| |
| def test_commandline_overspecified(self): |
| """Command line raises an exception when the arguments are specified ambiguously""" |
| err = None |
| try: |
| processhandler.ProcessHandler([self.proclaunch, "process_normal_finish.ini"], |
| args=["1", "2", "3"], |
| cwd=here) |
| except TypeError, e: |
| err = e |
| |
| self.assertTrue(err) |
| |
| def test_commandline_from_list(self): |
| """Command line is reported correctly when command and arguments are specified in a list""" |
| p = processhandler.ProcessHandler([self.proclaunch, "process_normal_finish.ini"], |
| cwd=here) |
| self.assertEqual(p.commandline, self.proclaunch + ' process_normal_finish.ini') |
| |
| def test_commandline_over_specified(self): |
| """Command line raises an exception when the arguments are specified ambiguously""" |
| err = None |
| try: |
| processhandler.ProcessHandler([self.proclaunch, "process_normal_finish.ini"], |
| args=["1", "2", "3"], |
| cwd=here) |
| except TypeError, e: |
| err = e |
| |
| self.assertTrue(err) |
| |
| def test_commandline_from_args(self): |
| """Command line is reported correctly when arguments are specified in a dedicated list""" |
| p = processhandler.ProcessHandler(self.proclaunch, |
| args=["1", "2", "3"], |
| cwd=here) |
| self.assertEqual(p.commandline, self.proclaunch + ' 1 2 3') |
| |
| def test_process_wait(self): |
| """Process is started runs to completion while we wait indefinitely""" |
| |
| p = processhandler.ProcessHandler([self.proclaunch, |
| "process_waittimeout_10s.ini"], |
| cwd=here) |
| p.run() |
| p.wait() |
| |
| self.determine_status(p) |
| |
| def test_process_timeout(self): |
| """ Process is started, runs but we time out waiting on it |
| to complete |
| """ |
| p = processhandler.ProcessHandler([self.proclaunch, "process_waittimeout.ini"], |
| cwd=here) |
| p.run(timeout=10) |
| p.wait() |
| |
| 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 |
| to complete. Process should not be killed. |
| """ |
| p = None |
| def timeout_handler(): |
| self.assertEqual(p.proc.poll(), None) |
| p.kill() |
| p = processhandler.ProcessHandler([self.proclaunch, "process_waittimeout.ini"], |
| cwd=here, |
| onTimeout=(timeout_handler,), |
| kill_on_timeout=False) |
| p.run(timeout=1) |
| p.wait() |
| self.assertTrue(p.didTimeout) |
| |
| self.determine_status(p, False, ['returncode', 'didtimeout']) |
| |
| def test_process_waittimeout(self): |
| """ |
| Process is started, then wait is called and times out. |
| Process is still running and didn't timeout |
| """ |
| p = processhandler.ProcessHandler([self.proclaunch, |
| "process_waittimeout_10s.ini"], |
| cwd=here) |
| |
| p.run() |
| p.wait(timeout=5) |
| |
| self.determine_status(p, True, ()) |
| |
| def test_process_waitnotimeout(self): |
| """ Process is started, runs to completion before our wait times out |
| """ |
| p = processhandler.ProcessHandler([self.proclaunch, |
| "process_waittimeout_10s.ini"], |
| cwd=here) |
| p.run(timeout=30) |
| p.wait() |
| |
| self.determine_status(p) |
| |
| def test_process_kill(self): |
| """Process is started, we kill it""" |
| |
| p = processhandler.ProcessHandler([self.proclaunch, "process_normal_finish.ini"], |
| cwd=here) |
| p.run() |
| p.kill() |
| |
| self.determine_status(p) |
| |
| def test_process_output_twice(self): |
| """ |
| Process is started, then processOutput is called a second time explicitly |
| """ |
| p = processhandler.ProcessHandler([self.proclaunch, |
| "process_waittimeout_10s.ini"], |
| cwd=here) |
| |
| p.run() |
| p.processOutput(timeout=5) |
| p.wait() |
| |
| self.determine_status(p, False, ()) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |