tests/run-tests.py
changeset 920 3881911c17b0
parent 919 1666a4a68262
child 921 abb2a67ce631
equal deleted inserted replaced
917:6f25a5834e14 920:3881911c17b0
    53 import tempfile
    53 import tempfile
    54 import time
    54 import time
    55 import re
    55 import re
    56 import threading
    56 import threading
    57 
    57 
       
    58 processlock = threading.Lock()
       
    59 
    58 closefds = os.name == 'posix'
    60 closefds = os.name == 'posix'
    59 def Popen4(cmd, timeout):
    61 def Popen4(cmd, wd, timeout):
       
    62     processlock.acquire()
       
    63     orig = os.getcwd()
       
    64     os.chdir(wd)
    60     p = subprocess.Popen(cmd, shell=True, bufsize=-1,
    65     p = subprocess.Popen(cmd, shell=True, bufsize=-1,
    61                          close_fds=closefds,
    66                          close_fds=closefds,
    62                          stdin=subprocess.PIPE, stdout=subprocess.PIPE,
    67                          stdin=subprocess.PIPE, stdout=subprocess.PIPE,
    63                          stderr=subprocess.STDOUT)
    68                          stderr=subprocess.STDOUT)
       
    69     os.chdir(orig)
       
    70     processlock.release()
       
    71 
    64     p.fromchild = p.stdout
    72     p.fromchild = p.stdout
    65     p.tochild = p.stdin
    73     p.tochild = p.stdin
    66     p.childerr = p.stderr
    74     p.childerr = p.stderr
    67 
    75 
    68     if timeout:
    76     if timeout:
   201         if options.jobs > 1 or options.child is not None:
   209         if options.jobs > 1 or options.child is not None:
   202             pid = "[%d]" % os.getpid()
   210             pid = "[%d]" % os.getpid()
   203         else:
   211         else:
   204             pid = None
   212             pid = None
   205         def vlog(*msg):
   213         def vlog(*msg):
       
   214             iolock.acquire()
   206             if pid:
   215             if pid:
   207                 print pid,
   216                 print pid,
   208             for m in msg:
   217             for m in msg:
   209                 print m,
   218                 print m,
   210             print
   219             print
   211             sys.stdout.flush()
   220             sys.stdout.flush()
       
   221             iolock.release()
   212     else:
   222     else:
   213         vlog = lambda *msg: None
   223         vlog = lambda *msg: None
   214 
   224 
   215     if options.tmpdir:
   225     if options.tmpdir:
   216         options.tmpdir = os.path.expanduser(options.tmpdir)
   226         options.tmpdir = os.path.expanduser(options.tmpdir)
   453         adir = os.path.join(TESTDIR, 'annotated')
   463         adir = os.path.join(TESTDIR, 'annotated')
   454         if not os.path.isdir(adir):
   464         if not os.path.isdir(adir):
   455             os.mkdir(adir)
   465             os.mkdir(adir)
   456         covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit)
   466         covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit)
   457 
   467 
   458 def pytest(test, options, replacements):
   468 def pytest(test, wd, options, replacements):
   459     py3kswitch = options.py3k_warnings and ' -3' or ''
   469     py3kswitch = options.py3k_warnings and ' -3' or ''
   460     cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test)
   470     cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test)
   461     vlog("# Running", cmd)
   471     vlog("# Running", cmd)
   462     return run(cmd, options, replacements)
   472     return run(cmd, wd, options, replacements)
   463 
   473 
   464 def shtest(test, options, replacements):
   474 def shtest(test, wd, options, replacements):
   465     cmd = '"%s"' % test
   475     cmd = '"%s"' % test
   466     vlog("# Running", cmd)
   476     vlog("# Running", cmd)
   467     return run(cmd, options, replacements)
   477     return run(cmd, wd, options, replacements)
   468 
   478 
   469 needescape = re.compile(r'[\x00-\x08\x0b-\x1f\x7f-\xff]').search
   479 needescape = re.compile(r'[\x00-\x08\x0b-\x1f\x7f-\xff]').search
   470 escapesub = re.compile(r'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub
   480 escapesub = re.compile(r'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub
   471 escapemap = dict((chr(i), r'\x%02x' % i) for i in range(256))
   481 escapemap = dict((chr(i), r'\x%02x' % i) for i in range(256))
   472 escapemap.update({'\\': '\\\\', '\r': r'\r'})
   482 escapemap.update({'\\': '\\\\', '\r': r'\r'})
   473 def escapef(m):
   483 def escapef(m):
   474     return escapemap[m.group(0)]
   484     return escapemap[m.group(0)]
   475 def stringescape(s):
   485 def stringescape(s):
   476     return escapesub(escapef, s)
   486     return escapesub(escapef, s)
   477 
   487 
   478 def tsttest(test, options, replacements):
   488 def tsttest(test, wd, options, replacements):
   479     t = open(test)
   489     t = open(test)
   480     out = []
   490     out = []
   481     script = []
   491     script = []
   482     salt = "SALT" + str(time.time())
   492     salt = "SALT" + str(time.time())
   483 
   493 
   514             os.write(fd, l)
   524             os.write(fd, l)
   515         os.close(fd)
   525         os.close(fd)
   516 
   526 
   517         cmd = '/bin/sh "%s"' % name
   527         cmd = '/bin/sh "%s"' % name
   518         vlog("# Running", cmd)
   528         vlog("# Running", cmd)
   519         exitcode, output = run(cmd, options, replacements)
   529         exitcode, output = run(cmd, wd, options, replacements)
   520         # do not merge output if skipped, return hghave message instead
   530         # do not merge output if skipped, return hghave message instead
   521         # similarly, with --debug, output is None
   531         # similarly, with --debug, output is None
   522         if exitcode == SKIPPED_STATUS or output is None:
   532         if exitcode == SKIPPED_STATUS or output is None:
   523             return exitcode, output
   533             return exitcode, output
   524     finally:
   534     finally:
   593         postout += after.pop(pos)
   603         postout += after.pop(pos)
   594 
   604 
   595     return exitcode, postout
   605     return exitcode, postout
   596 
   606 
   597 wifexited = getattr(os, "WIFEXITED", lambda x: False)
   607 wifexited = getattr(os, "WIFEXITED", lambda x: False)
   598 def run(cmd, options, replacements):
   608 def run(cmd, wd, options, replacements):
   599     """Run command in a sub-process, capturing the output (stdout and stderr).
   609     """Run command in a sub-process, capturing the output (stdout and stderr).
   600     Return a tuple (exitcode, output).  output is None in debug mode."""
   610     Return a tuple (exitcode, output).  output is None in debug mode."""
   601     # TODO: Use subprocess.Popen if we're running on Python 2.4
   611     # TODO: Use subprocess.Popen if we're running on Python 2.4
   602     if options.debug:
   612     if options.debug:
   603         proc = subprocess.Popen(cmd, shell=True)
   613         proc = subprocess.Popen(cmd, shell=True)
   610         output = fromchild.read()
   620         output = fromchild.read()
   611         ret = fromchild.close()
   621         ret = fromchild.close()
   612         if ret is None:
   622         if ret is None:
   613             ret = 0
   623             ret = 0
   614     else:
   624     else:
   615         proc = Popen4(cmd, options.timeout)
   625         proc = Popen4(cmd, wd, options.timeout)
   616         def cleanup():
   626         def cleanup():
   617             try:
   627             try:
   618                 proc.terminate()
   628                 proc.terminate()
   619             except OSError:
   629             except OSError:
   620                 pass
   630                 pass
   771     # Make a tmp subdirectory to work in
   781     # Make a tmp subdirectory to work in
   772     testtmp = os.environ["TESTTMP"] = os.environ["HOME"] = \
   782     testtmp = os.environ["TESTTMP"] = os.environ["HOME"] = \
   773         os.path.join(HGTMP, test)
   783         os.path.join(HGTMP, test)
   774 
   784 
   775     os.mkdir(testtmp)
   785     os.mkdir(testtmp)
   776     os.chdir(testtmp)
   786     ret, out = runner(testpath, testtmp, options, [
   777 
       
   778     ret, out = runner(testpath, options, [
       
   779         (re.escape(testtmp), '$TESTTMP'),
   787         (re.escape(testtmp), '$TESTTMP'),
   780         (r':%s\b' % options.port, ':$HGPORT'),
   788         (r':%s\b' % options.port, ':$HGPORT'),
   781         (r':%s\b' % (options.port + 1), ':$HGPORT1'),
   789         (r':%s\b' % (options.port + 1), ':$HGPORT1'),
   782         (r':%s\b' % (options.port + 2), ':$HGPORT2'),
   790         (r':%s\b' % (options.port + 2), ':$HGPORT2'),
   783         ])
   791         ])
   848         sys.stdout.flush()
   856         sys.stdout.flush()
   849         iolock.release()
   857         iolock.release()
   850 
   858 
   851     killdaemons()
   859     killdaemons()
   852 
   860 
   853     os.chdir(TESTDIR)
       
   854     if not options.keep_tmpdir:
   861     if not options.keep_tmpdir:
   855         shutil.rmtree(testtmp, True)
   862         shutil.rmtree(testtmp, True)
   856     if skipped:
   863     if skipped:
   857         return None
   864         return None
   858     return ret == 0
   865     return ret == 0