tests/run-tests.py
changeset 14001 9c4da6ab4e5a
parent 14000 636a6f5aa2cd
child 14002 a738c30d4b18
equal deleted inserted replaced
14000:636a6f5aa2cd 14001:9c4da6ab4e5a
    54 import time
    54 import time
    55 import re
    55 import re
    56 import threading
    56 import threading
    57 
    57 
    58 closefds = os.name == 'posix'
    58 closefds = os.name == 'posix'
    59 def Popen4(cmd, bufsize=-1):
    59 def Popen4(cmd, timeout):
    60     p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
    60     p = subprocess.Popen(cmd, shell=True, bufsize=-1,
    61                          close_fds=closefds,
    61                          close_fds=closefds,
    62                          stdin=subprocess.PIPE, stdout=subprocess.PIPE,
    62                          stdin=subprocess.PIPE, stdout=subprocess.PIPE,
    63                          stderr=subprocess.STDOUT)
    63                          stderr=subprocess.STDOUT)
    64     p.fromchild = p.stdout
    64     p.fromchild = p.stdout
    65     p.tochild = p.stdin
    65     p.tochild = p.stdin
    66     p.childerr = p.stderr
    66     p.childerr = p.stderr
       
    67 
       
    68     if timeout:
       
    69         p.timeout = False
       
    70         def t():
       
    71             start = time.time()
       
    72             while time.time() - start < timeout and p.returncode is None:
       
    73                 time.sleep(1)
       
    74             p.timeout = True
       
    75             if p.returncode is None:
       
    76                 try:
       
    77                     p.terminate()
       
    78                 except OSError:
       
    79                     pass
       
    80         threading.Thread(target=t).start()
       
    81 
    67     return p
    82     return p
    68 
    83 
    69 # reserved exit code to skip test (used by hghave)
    84 # reserved exit code to skip test (used by hghave)
    70 SKIPPED_STATUS = 80
    85 SKIPPED_STATUS = 80
    71 SKIPPED_PREFIX = 'skipped: '
    86 SKIPPED_PREFIX = 'skipped: '
   438         adir = os.path.join(TESTDIR, 'annotated')
   453         adir = os.path.join(TESTDIR, 'annotated')
   439         if not os.path.isdir(adir):
   454         if not os.path.isdir(adir):
   440             os.mkdir(adir)
   455             os.mkdir(adir)
   441         covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit)
   456         covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit)
   442 
   457 
   443 class Timeout(Exception):
       
   444     pass
       
   445 
       
   446 def alarmed(signum, frame):
       
   447     raise Timeout
       
   448 
       
   449 def pytest(test, options, replacements):
   458 def pytest(test, options, replacements):
   450     py3kswitch = options.py3k_warnings and ' -3' or ''
   459     py3kswitch = options.py3k_warnings and ' -3' or ''
   451     cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test)
   460     cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test)
   452     vlog("# Running", cmd)
   461     vlog("# Running", cmd)
   453     return run(cmd, options, replacements)
   462     return run(cmd, options, replacements)
   601         output = fromchild.read()
   610         output = fromchild.read()
   602         ret = fromchild.close()
   611         ret = fromchild.close()
   603         if ret is None:
   612         if ret is None:
   604             ret = 0
   613             ret = 0
   605     else:
   614     else:
   606         proc = Popen4(cmd)
   615         proc = Popen4(cmd, options.timeout)
   607         def cleanup():
   616         def cleanup():
   608             os.kill(proc.pid, signal.SIGTERM)
   617             try:
       
   618                 proc.terminate()
       
   619             except OSError:
       
   620                 pass
   609             ret = proc.wait()
   621             ret = proc.wait()
   610             if ret == 0:
   622             if ret == 0:
   611                 ret = signal.SIGTERM << 8
   623                 ret = signal.SIGTERM << 8
   612             killdaemons()
   624             killdaemons()
   613             return ret
   625             return ret
   614 
   626 
       
   627         output = ''
       
   628         proc.tochild.close()
       
   629 
   615         try:
   630         try:
   616             output = ''
       
   617             proc.tochild.close()
       
   618             output = proc.fromchild.read()
   631             output = proc.fromchild.read()
   619             ret = proc.wait()
       
   620             if wifexited(ret):
       
   621                 ret = os.WEXITSTATUS(ret)
       
   622         except Timeout:
       
   623             vlog('# Process %d timed out - killing it' % proc.pid)
       
   624             cleanup()
       
   625             ret = 'timeout'
       
   626             output += ("\n### Abort: timeout after %d seconds.\n"
       
   627                        % options.timeout)
       
   628         except KeyboardInterrupt:
   632         except KeyboardInterrupt:
   629             vlog('# Handling keyboard interrupt')
   633             vlog('# Handling keyboard interrupt')
   630             cleanup()
   634             cleanup()
   631             raise
   635             raise
       
   636 
       
   637         ret = proc.wait()
       
   638         if wifexited(ret):
       
   639             ret = os.WEXITSTATUS(ret)
       
   640 
       
   641         if proc.timeout:
       
   642             ret = 'timeout'
       
   643 
       
   644         if ret:
       
   645             killdaemons()
   632 
   646 
   633     for s, r in replacements:
   647     for s, r in replacements:
   634         output = re.sub(s, r, output)
   648         output = re.sub(s, r, output)
   635     return ret, splitnewlines(output)
   649     return ret, splitnewlines(output)
   636 
   650 
   753         os.path.join(HGTMP, test)
   767         os.path.join(HGTMP, test)
   754 
   768 
   755     os.mkdir(testtmp)
   769     os.mkdir(testtmp)
   756     os.chdir(testtmp)
   770     os.chdir(testtmp)
   757 
   771 
   758     if options.timeout > 0:
       
   759         signal.alarm(options.timeout)
       
   760 
       
   761     ret, out = runner(testpath, options, [
   772     ret, out = runner(testpath, options, [
   762         (re.escape(testtmp), '$TESTTMP'),
   773         (re.escape(testtmp), '$TESTTMP'),
   763         (r':%s\b' % options.port, ':$HGPORT'),
   774         (r':%s\b' % options.port, ':$HGPORT'),
   764         (r':%s\b' % (options.port + 1), ':$HGPORT1'),
   775         (r':%s\b' % (options.port + 1), ':$HGPORT1'),
   765         (r':%s\b' % (options.port + 2), ':$HGPORT2'),
   776         (r':%s\b' % (options.port + 2), ':$HGPORT2'),
   766         ])
   777         ])
   767     vlog("# Ret was:", ret)
   778     vlog("# Ret was:", ret)
   768 
       
   769     if options.timeout > 0:
       
   770         signal.alarm(0)
       
   771 
   779 
   772     mark = '.'
   780     mark = '.'
   773     if ret == 0:
   781     if ret == 0:
   774         success()
   782         success()
   775 
   783 
   805         if failed:
   813         if failed:
   806             fail("hghave failed checking for %s" % failed[-1], ret)
   814             fail("hghave failed checking for %s" % failed[-1], ret)
   807             skipped = False
   815             skipped = False
   808         else:
   816         else:
   809             skip(missing[-1])
   817             skip(missing[-1])
       
   818     elif ret == 'timeout':
       
   819         mark = 't'
       
   820         fail("timed out", ret)
   810     elif out != refout:
   821     elif out != refout:
   811         mark = '!'
   822         mark = '!'
   812         if ret == 'timeout':
   823         if ret:
   813             fail("timed out", ret)
       
   814         elif ret:
       
   815             fail("output changed and returned error code %d" % ret, ret)
   824             fail("output changed and returned error code %d" % ret, ret)
   816         else:
   825         else:
   817             fail("output changed", ret)
   826             fail("output changed", ret)
   818         if ret != 'timeout' and not options.nodiff:
   827         if ret != 'timeout' and not options.nodiff:
   819             if options.view:
   828             if options.view:
   960     try:
   969     try:
   961         if INST:
   970         if INST:
   962             installhg(options)
   971             installhg(options)
   963             _checkhglib("Testing")
   972             _checkhglib("Testing")
   964 
   973 
   965         if options.timeout > 0:
       
   966             try:
       
   967                 signal.signal(signal.SIGALRM, alarmed)
       
   968                 vlog('# Running each test with %d second timeout' %
       
   969                      options.timeout)
       
   970             except AttributeError:
       
   971                 print 'WARNING: cannot run tests with timeouts'
       
   972                 options.timeout = 0
       
   973 
       
   974         if options.restart:
   974         if options.restart:
   975             orig = list(tests)
   975             orig = list(tests)
   976             while tests:
   976             while tests:
   977                 if os.path.exists(tests[0] + ".err"):
   977                 if os.path.exists(tests[0] + ".err"):
   978                     break
   978                     break