testing/mozbase/mozprocess/tests/test_mozprocess.py

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 #!/usr/bin/env python
     3 # This Source Code Form is subject to the terms of the Mozilla Public
     4 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
     5 # You can obtain one at http://mozilla.org/MPL/2.0/.
     7 import optparse
     8 import os
     9 import subprocess
    10 import sys
    11 import unittest
    12 from mozprocess import processhandler
    13 from time import sleep
    15 here = os.path.dirname(os.path.abspath(__file__))
    17 def make_proclaunch(aDir):
    18     """
    19         Makes the proclaunch executable.
    20         Params:
    21             aDir - the directory in which to issue the make commands
    22         Returns:
    23             the path to the proclaunch executable that is generated
    24     """
    26     if sys.platform == "win32":
    27         exepath = os.path.join(aDir, "proclaunch.exe")
    28     else:
    29         exepath = os.path.join(aDir, "proclaunch")
    31     # remove the launcher, if it already exists
    32     # otherwise, if the make fails you may not notice
    33     if os.path.exists(exepath):
    34         os.remove(exepath)
    36     # Ideally make should take care of both calls through recursion, but since it doesn't,
    37     # on windows anyway (to file?), let's just call out both targets explicitly.
    38     for command in [["make", "-C", "iniparser"],
    39                     ["make"]]:
    40         process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=aDir)
    41         stdout, stderr = process.communicate()
    42         if process.returncode:
    43             # SomethingBadHappen; print all the things
    44             print "%s: exit %d" % (command, process.returncode)
    45             print "stdout:\n%s" % stdout
    46             print "stderr:\n%s" % stderr
    47             raise subprocess.CalledProcessError(process.returncode, command, stdout)
    49     # ensure the launcher now exists
    50     if not os.path.exists(exepath):
    51         raise AssertionError("proclaunch executable '%s' does not exist (sys.platform=%s)" % (exepath, sys.platform))
    52     return exepath
    54 def check_for_process(processName):
    55     """
    56         Use to determine if process of the given name is still running.
    58         Returns:
    59         detected -- True if process is detected to exist, False otherwise
    60         output -- if process exists, stdout of the process, '' otherwise
    61     """
    62     # TODO: replace with
    63     # https://github.com/mozilla/mozbase/blob/master/mozprocess/mozprocess/pid.py
    64     # which should be augmented from talos
    65     # see https://bugzilla.mozilla.org/show_bug.cgi?id=705864
    66     output = ''
    67     if sys.platform == "win32":
    68         # On windows we use tasklist
    69         p1 = subprocess.Popen(["tasklist"], stdout=subprocess.PIPE)
    70         output = p1.communicate()[0]
    71         detected = False
    72         for line in output.splitlines():
    73             if processName in line:
    74                 detected = True
    75                 break
    76     else:
    77         p1 = subprocess.Popen(["ps", "-ef"], stdout=subprocess.PIPE)
    78         p2 = subprocess.Popen(["grep", processName], stdin=p1.stdout, stdout=subprocess.PIPE)
    79         p1.stdout.close()
    80         output = p2.communicate()[0]
    81         detected = False
    82         for line in output.splitlines():
    83             if "grep %s" % processName in line:
    84                 continue
    85             elif processName in line and not 'defunct' in line:
    86                 detected = True
    87                 break
    89     return detected, output
    92 class ProcTest(unittest.TestCase):
    94     # whether to remove created files on exit
    95     cleanup = os.environ.get('CLEANUP', 'true').lower() in ('1', 'true')
    97     @classmethod
    98     def setUpClass(cls):
    99         cls.proclaunch = make_proclaunch(here)
   101     @classmethod
   102     def tearDownClass(cls):
   103         del cls.proclaunch
   104         if not cls.cleanup:
   105             return
   106         files = [('proclaunch',),
   107                  ('proclaunch.exe',),
   108                  ('iniparser', 'dictionary.o'),
   109                  ('iniparser', 'iniparser.lib'),
   110                  ('iniparser', 'iniparser.o'),
   111                  ('iniparser', 'libiniparser.a'),
   112                  ('iniparser', 'libiniparser.so.0'),
   113                  ]
   114         files = [os.path.join(here, *path) for path in files]
   115         errors = []
   116         for path in files:
   117             if os.path.exists(path):
   118                 try:
   119                     os.remove(path)
   120                 except OSError as e:
   121                     errors.append(str(e))
   122         if errors:
   123             raise OSError("Error(s) encountered tearing down %s.%s:\n%s" % (cls.__module__, cls.__name__, '\n'.join(errors)))
   125     def test_process_normal_finish(self):
   126         """Process is started, runs to completion while we wait for it"""
   128         p = processhandler.ProcessHandler([self.proclaunch, "process_normal_finish.ini"],
   129                                           cwd=here)
   130         p.run()
   131         p.wait()
   133         detected, output = check_for_process(self.proclaunch)
   134         self.determine_status(detected,
   135                               output,
   136                               p.proc.returncode,
   137                               p.didTimeout)
   139     def test_commandline_no_args(self):
   140         """Command line is reported correctly when no arguments are specified"""
   141         p = processhandler.ProcessHandler(self.proclaunch, cwd=here)
   142         self.assertEqual(p.commandline, self.proclaunch)
   144     def test_commandline_overspecified(self):
   145         """Command line raises an exception when the arguments are specified ambiguously"""
   146         err = None
   147         try:
   148             p = processhandler.ProcessHandler([self.proclaunch, "process_normal_finish.ini"],
   149                                               args=["1", "2", "3"],
   150                                               cwd=here)
   151         except TypeError, e:
   152             err = e
   154         self.assertTrue(err)
   156     def test_commandline_from_list(self):
   157         """Command line is reported correctly when command and arguments are specified in a list"""
   158         p = processhandler.ProcessHandler([self.proclaunch, "process_normal_finish.ini"],
   159                                           cwd=here)
   160         self.assertEqual(p.commandline, self.proclaunch + ' process_normal_finish.ini')
   162     def test_commandline_over_specified(self):
   163         """Command line raises an exception when the arguments are specified ambiguously"""
   164         err = None
   165         try:
   166             p = processhandler.ProcessHandler([self.proclaunch, "process_normal_finish.ini"],
   167                                               args=["1", "2", "3"],
   168                                               cwd=here)
   169         except TypeError, e:
   170             err = e
   172         self.assertTrue(err)
   174     def test_commandline_from_args(self):
   175         """Command line is reported correctly when arguments are specified in a dedicated list"""
   176         p = processhandler.ProcessHandler(self.proclaunch,
   177                                           args=["1", "2", "3"],
   178                                           cwd=here)
   179         self.assertEqual(p.commandline, self.proclaunch + ' 1 2 3')
   181     def test_process_wait(self):
   182         """Process is started runs to completion while we wait indefinitely"""
   184         p = processhandler.ProcessHandler([self.proclaunch,
   185                                           "process_waittimeout_10s.ini"],
   186                                           cwd=here)
   187         p.run()
   188         p.wait()
   190         detected, output = check_for_process(self.proclaunch)
   191         self.determine_status(detected,
   192                               output,
   193                               p.proc.returncode,
   194                               p.didTimeout)
   196     def test_process_timeout(self):
   197         """ Process is started, runs but we time out waiting on it
   198             to complete
   199         """
   200         p = processhandler.ProcessHandler([self.proclaunch, "process_waittimeout.ini"],
   201                                           cwd=here)
   202         p.run(timeout=10)
   203         p.wait()
   205         detected, output = check_for_process(self.proclaunch)
   206         self.determine_status(detected,
   207                               output,
   208                               p.proc.returncode,
   209                               p.didTimeout,
   210                               False,
   211                               ['returncode', 'didtimeout'])
   213     def test_process_timeout_no_kill(self):
   214         """ Process is started, runs but we time out waiting on it
   215             to complete. Process should not be killed.
   216         """
   217         p = None
   218         def timeout_handler():
   219             self.assertEqual(p.proc.poll(), None)
   220             p.kill()
   221         p = processhandler.ProcessHandler([self.proclaunch, "process_waittimeout.ini"],
   222                                           cwd=here,
   223                                           onTimeout=(timeout_handler,),
   224                                           kill_on_timeout=False)
   225         p.run(timeout=1)
   226         p.wait()
   227         self.assertTrue(p.didTimeout)
   229         detected, output = check_for_process(self.proclaunch)
   230         self.determine_status(detected,
   231                               output,
   232                               p.proc.returncode,
   233                               p.didTimeout,
   234                               False,
   235                               ['returncode', 'didtimeout'])
   237     def test_process_waittimeout(self):
   238         """
   239         Process is started, then wait is called and times out.
   240         Process is still running and didn't timeout
   241         """
   242         p = processhandler.ProcessHandler([self.proclaunch,
   243                                           "process_waittimeout_10s.ini"],
   244                                           cwd=here)
   246         p.run()
   247         p.wait(timeout=5)
   249         detected, output = check_for_process(self.proclaunch)
   250         self.determine_status(detected,
   251                               output,
   252                               p.proc.returncode,
   253                               p.didTimeout,
   254                               True,
   255                               ())
   257     def test_process_waitnotimeout(self):
   258         """ Process is started, runs to completion before our wait times out
   259         """
   260         p = processhandler.ProcessHandler([self.proclaunch,
   261                                           "process_waittimeout_10s.ini"],
   262                                           cwd=here)
   263         p.run(timeout=30)
   264         p.wait()
   266         detected, output = check_for_process(self.proclaunch)
   267         self.determine_status(detected,
   268                               output,
   269                               p.proc.returncode,
   270                               p.didTimeout)
   272     def test_process_kill(self):
   273         """Process is started, we kill it"""
   275         p = processhandler.ProcessHandler([self.proclaunch, "process_normal_finish.ini"],
   276                                           cwd=here)
   277         p.run()
   278         p.kill()
   280         detected, output = check_for_process(self.proclaunch)
   281         self.determine_status(detected,
   282                               output,
   283                               p.proc.returncode,
   284                               p.didTimeout)
   286     def test_process_output_twice(self):
   287         """
   288         Process is started, then processOutput is called a second time explicitly
   289         """
   290         p = processhandler.ProcessHandler([self.proclaunch,
   291                                           "process_waittimeout_10s.ini"],
   292                                           cwd=here)
   294         p.run()
   295         p.processOutput(timeout=5)
   296         p.wait()
   298         detected, output = check_for_process(self.proclaunch)
   299         self.determine_status(detected,
   300                               output,
   301                               p.proc.returncode,
   302                               p.didTimeout,
   303                               False,
   304                               ())
   306     def determine_status(self,
   307                          detected=False,
   308                          output='',
   309                          returncode=0,
   310                          didtimeout=False,
   311                          isalive=False,
   312                          expectedfail=()):
   313         """
   314         Use to determine if the situation has failed.
   315         Parameters:
   316             detected -- value from check_for_process to determine if the process is detected
   317             output -- string of data from detected process, can be ''
   318             returncode -- return code from process, defaults to 0
   319             didtimeout -- True if process timed out, defaults to False
   320             isalive -- Use True to indicate we pass if the process exists; however, by default
   321                        the test will pass if the process does not exist (isalive == False)
   322             expectedfail -- Defaults to [], used to indicate a list of fields that are expected to fail
   323         """
   324         if 'returncode' in expectedfail:
   325             self.assertTrue(returncode, "Detected an unexpected return code of: %s" % returncode)
   326         elif not isalive:
   327             self.assertTrue(returncode == 0, "Detected non-zero return code of: %d" % returncode)
   329         if 'didtimeout' in expectedfail:
   330             self.assertTrue(didtimeout, "Detected that process didn't time out")
   331         else:
   332             self.assertTrue(not didtimeout, "Detected that process timed out")
   334         if isalive:
   335             self.assertTrue(detected, "Detected process is not running, process output: %s" % output)
   336         else:
   337             self.assertTrue(not detected, "Detected process is still running, process output: %s" % output)
   339 if __name__ == '__main__':
   340     unittest.main()

mercurial