tests/run-tests.py
changeset 24508 fbe2fb71a6e6
parent 24507 a0668a587c04
child 24509 27092bb70293
equal deleted inserted replaced
24507:a0668a587c04 24508:fbe2fb71a6e6
    73 # subprocess._cleanup can race with any Popen.wait or Popen.poll on py24
    73 # subprocess._cleanup can race with any Popen.wait or Popen.poll on py24
    74 # http://bugs.python.org/issue1731717 for details. We shouldn't be producing
    74 # http://bugs.python.org/issue1731717 for details. We shouldn't be producing
    75 # zombies but it's pretty harmless even if we do.
    75 # zombies but it's pretty harmless even if we do.
    76 if sys.version_info < (2, 5):
    76 if sys.version_info < (2, 5):
    77     subprocess._cleanup = lambda: None
    77     subprocess._cleanup = lambda: None
       
    78 
       
    79 wifexited = getattr(os, "WIFEXITED", lambda x: False)
    78 
    80 
    79 closefds = os.name == 'posix'
    81 closefds = os.name == 'posix'
    80 def Popen4(cmd, wd, timeout, env=None):
    82 def Popen4(cmd, wd, timeout, env=None):
    81     processlock.acquire()
    83     processlock.acquire()
    82     p = subprocess.Popen(cmd, shell=True, bufsize=-1, cwd=wd, env=env,
    84     p = subprocess.Popen(cmd, shell=True, bufsize=-1, cwd=wd, env=env,
   718     def fail(self, msg):
   720     def fail(self, msg):
   719         # unittest differentiates between errored and failed.
   721         # unittest differentiates between errored and failed.
   720         # Failed is denoted by AssertionError (by default at least).
   722         # Failed is denoted by AssertionError (by default at least).
   721         raise AssertionError(msg)
   723         raise AssertionError(msg)
   722 
   724 
       
   725     def _runcommand(self, cmd, wd, replacements, env, debug=False,
       
   726                     timeout=None):
       
   727         """Run command in a sub-process, capturing the output (stdout and
       
   728         stderr).
       
   729 
       
   730         Return a tuple (exitcode, output). output is None in debug mode.
       
   731         """
       
   732         if debug:
       
   733             proc = subprocess.Popen(cmd, shell=True, cwd=wd, env=env)
       
   734             ret = proc.wait()
       
   735             return (ret, None)
       
   736 
       
   737         proc = Popen4(cmd, wd, timeout, env)
       
   738         def cleanup():
       
   739             terminate(proc)
       
   740             ret = proc.wait()
       
   741             if ret == 0:
       
   742                 ret = signal.SIGTERM << 8
       
   743             killdaemons(env['DAEMON_PIDS'])
       
   744             return ret
       
   745 
       
   746         output = ''
       
   747         proc.tochild.close()
       
   748 
       
   749         try:
       
   750             output = proc.fromchild.read()
       
   751         except KeyboardInterrupt:
       
   752             vlog('# Handling keyboard interrupt')
       
   753             cleanup()
       
   754             raise
       
   755 
       
   756         ret = proc.wait()
       
   757         if wifexited(ret):
       
   758             ret = os.WEXITSTATUS(ret)
       
   759 
       
   760         if proc.timeout:
       
   761             ret = 'timeout'
       
   762 
       
   763         if ret:
       
   764             killdaemons(env['DAEMON_PIDS'])
       
   765 
       
   766         for s, r in replacements:
       
   767             output = re.sub(s, r, output)
       
   768         return ret, output.splitlines(True)
       
   769 
   723 class PythonTest(Test):
   770 class PythonTest(Test):
   724     """A Python-based test."""
   771     """A Python-based test."""
   725 
   772 
   726     @property
   773     @property
   727     def refpath(self):
   774     def refpath(self):
   731         py3kswitch = self._py3kwarnings and ' -3' or ''
   778         py3kswitch = self._py3kwarnings and ' -3' or ''
   732         cmd = '%s%s "%s"' % (PYTHON, py3kswitch, self.path)
   779         cmd = '%s%s "%s"' % (PYTHON, py3kswitch, self.path)
   733         vlog("# Running", cmd)
   780         vlog("# Running", cmd)
   734         if os.name == 'nt':
   781         if os.name == 'nt':
   735             replacements.append((r'\r\n', '\n'))
   782             replacements.append((r'\r\n', '\n'))
   736         result = run(cmd, self._testtmp, replacements, env,
   783         result = self._runcommand(cmd, self._testtmp, replacements, env,
   737                    debug=self._debug, timeout=self._timeout)
   784                                   debug=self._debug, timeout=self._timeout)
   738         if self._aborted:
   785         if self._aborted:
   739             raise KeyboardInterrupt()
   786             raise KeyboardInterrupt()
   740 
   787 
   741         return result
   788         return result
   742 
   789 
   779         f.close()
   826         f.close()
   780 
   827 
   781         cmd = '%s "%s"' % (self._shell, fname)
   828         cmd = '%s "%s"' % (self._shell, fname)
   782         vlog("# Running", cmd)
   829         vlog("# Running", cmd)
   783 
   830 
   784         exitcode, output = run(cmd, self._testtmp, replacements, env,
   831         exitcode, output = self._runcommand(cmd, self._testtmp, replacements,
   785                                debug=self._debug, timeout=self._timeout)
   832                                             env, debug=self._debug,
       
   833                                             timeout=self._timeout)
   786 
   834 
   787         if self._aborted:
   835         if self._aborted:
   788             raise KeyboardInterrupt()
   836             raise KeyboardInterrupt()
   789 
   837 
   790         # Do not merge output if skipped. Return hghave message instead.
   838         # Do not merge output if skipped. Return hghave message instead.
  1073 
  1121 
  1074     @staticmethod
  1122     @staticmethod
  1075     def _stringescape(s):
  1123     def _stringescape(s):
  1076         return TTest.ESCAPESUB(TTest._escapef, s)
  1124         return TTest.ESCAPESUB(TTest._escapef, s)
  1077 
  1125 
  1078 
       
  1079 wifexited = getattr(os, "WIFEXITED", lambda x: False)
       
  1080 def run(cmd, wd, replacements, env, debug=False, timeout=None):
       
  1081     """Run command in a sub-process, capturing the output (stdout and stderr).
       
  1082     Return a tuple (exitcode, output).  output is None in debug mode."""
       
  1083     if debug:
       
  1084         proc = subprocess.Popen(cmd, shell=True, cwd=wd, env=env)
       
  1085         ret = proc.wait()
       
  1086         return (ret, None)
       
  1087 
       
  1088     proc = Popen4(cmd, wd, timeout, env)
       
  1089     def cleanup():
       
  1090         terminate(proc)
       
  1091         ret = proc.wait()
       
  1092         if ret == 0:
       
  1093             ret = signal.SIGTERM << 8
       
  1094         killdaemons(env['DAEMON_PIDS'])
       
  1095         return ret
       
  1096 
       
  1097     output = ''
       
  1098     proc.tochild.close()
       
  1099 
       
  1100     try:
       
  1101         output = proc.fromchild.read()
       
  1102     except KeyboardInterrupt:
       
  1103         vlog('# Handling keyboard interrupt')
       
  1104         cleanup()
       
  1105         raise
       
  1106 
       
  1107     ret = proc.wait()
       
  1108     if wifexited(ret):
       
  1109         ret = os.WEXITSTATUS(ret)
       
  1110 
       
  1111     if proc.timeout:
       
  1112         ret = 'timeout'
       
  1113 
       
  1114     if ret:
       
  1115         killdaemons(env['DAEMON_PIDS'])
       
  1116 
       
  1117     for s, r in replacements:
       
  1118         output = re.sub(s, r, output)
       
  1119     return ret, output.splitlines(True)
       
  1120 
       
  1121 iolock = threading.RLock()
  1126 iolock = threading.RLock()
  1122 
  1127 
  1123 class SkipTest(Exception):
  1128 class SkipTest(Exception):
  1124     """Raised to indicate that a test is to be skipped."""
  1129     """Raised to indicate that a test is to be skipped."""
  1125 
  1130