tests/run-tests.py
branchstable
changeset 776 1869efbf104d
parent 775 16f4cb2900fe
child 777 cd294ce45931
equal deleted inserted replaced
775:16f4cb2900fe 776:1869efbf104d
    50 import subprocess
    50 import subprocess
    51 import signal
    51 import signal
    52 import sys
    52 import sys
    53 import tempfile
    53 import tempfile
    54 import time
    54 import time
       
    55 import re
    55 
    56 
    56 closefds = os.name == 'posix'
    57 closefds = os.name == 'posix'
    57 def Popen4(cmd, bufsize=-1):
    58 def Popen4(cmd, bufsize=-1):
    58     p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
    59     p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
    59                          close_fds=closefds,
    60                          close_fds=closefds,
   457     # the "cmd /c call" prefix is needed. Grrr
   458     # the "cmd /c call" prefix is needed. Grrr
   458     cmd = 'cmd /c call "%s"' % testpath
   459     cmd = 'cmd /c call "%s"' % testpath
   459     vlog("# Running", cmd)
   460     vlog("# Running", cmd)
   460     return run(cmd, options)
   461     return run(cmd, options)
   461 
   462 
       
   463 def tsttest(test, options):
       
   464     t = open(test)
       
   465     out = []
       
   466     script = []
       
   467     salt = "SALT" + str(time.time())
       
   468 
       
   469     pos = prepos = -1
       
   470     after = {}
       
   471     expected = {}
       
   472     for n, l in enumerate(t):
       
   473         if l.startswith('  $ '): # commands
       
   474             after.setdefault(pos, []).append(l)
       
   475             prepos = pos
       
   476             pos = n
       
   477             script.append('echo %s %s\n' % (salt, n))
       
   478             script.append(l[4:])
       
   479         elif l.startswith('  > '): # continuations
       
   480             after.setdefault(prepos, []).append(l)
       
   481             script.append(l[4:])
       
   482         elif l.startswith('  '): # results
       
   483             # queue up a list of expected results
       
   484             expected.setdefault(pos, []).append(l[2:])
       
   485         else:
       
   486             # non-command/result - queue up for merged output
       
   487             after.setdefault(pos, []).append(l)
       
   488 
       
   489     fd, name = tempfile.mkstemp(suffix='hg-tst')
       
   490 
       
   491     try:
       
   492         for l in script:
       
   493             os.write(fd, l)
       
   494         os.close(fd)
       
   495 
       
   496         cmd = '/bin/sh "%s"' % name
       
   497         vlog("# Running", cmd)
       
   498         exitcode, output = run(cmd, options)
       
   499     finally:
       
   500         os.remove(name)
       
   501 
       
   502     pos = -1
       
   503     postout = []
       
   504     for n, l in enumerate(output):
       
   505         if l.startswith(salt):
       
   506             if pos in after:
       
   507                 postout += after.pop(pos)
       
   508             pos = int(l.split()[1])
       
   509         else:
       
   510             el = None
       
   511             if pos in expected and expected[pos]:
       
   512                 el = expected[pos].pop(0)
       
   513 
       
   514             if el == l: # perfect match (fast)
       
   515                 postout.append("  " + l)
       
   516             elif el and re.match(el, l): # fallback regex match
       
   517                 postout.append("  " + el)
       
   518             else: # mismatch - let diff deal with it
       
   519                 postout.append("  " + l)
       
   520 
       
   521     if pos in after:
       
   522         postout += after.pop(pos)
       
   523 
       
   524     return exitcode, postout
       
   525 
   462 def run(cmd, options):
   526 def run(cmd, options):
   463     """Run command in a sub-process, capturing the output (stdout and stderr).
   527     """Run command in a sub-process, capturing the output (stdout and stderr).
   464     Return a tuple (exitcode, output).  output is None in debug mode."""
   528     Return a tuple (exitcode, output).  output is None in debug mode."""
   465     # TODO: Use subprocess.Popen if we're running on Python 2.4
   529     # TODO: Use subprocess.Popen if we're running on Python 2.4
   466     if options.debug:
   530     if options.debug:
   559     elif lctest.endswith('.bat'):
   623     elif lctest.endswith('.bat'):
   560         # do not run batch scripts on non-windows
   624         # do not run batch scripts on non-windows
   561         if os.name != 'nt':
   625         if os.name != 'nt':
   562             return skip("batch script")
   626             return skip("batch script")
   563         runner = battest
   627         runner = battest
       
   628     elif lctest.endswith('.t'):
       
   629         runner = tsttest
       
   630         ref = testpath
   564     else:
   631     else:
   565         # do not run shell scripts on windows
   632         # do not run shell scripts on windows
   566         if os.name == 'nt':
   633         if os.name == 'nt':
   567             return skip("shell script")
   634             return skip("shell script")
   568         # do not try to run non-executable programs
   635         # do not try to run non-executable programs
   819             elif not ret:
   886             elif not ret:
   820                 if options.interactive:
   887                 if options.interactive:
   821                     print "Accept this change? [n] ",
   888                     print "Accept this change? [n] ",
   822                     answer = sys.stdin.readline().strip()
   889                     answer = sys.stdin.readline().strip()
   823                     if answer.lower() in "y yes".split():
   890                     if answer.lower() in "y yes".split():
   824                         rename(test + ".err", test + ".out")
   891                         if test.endswith(".t"):
       
   892                             rename(test + ".err", test)
       
   893                         else:
       
   894                             rename(test + ".err", test + ".out")
   825                         tested += 1
   895                         tested += 1
   826                         fails.pop()
   896                         fails.pop()
   827                         continue
   897                         continue
   828                 failed += 1
   898                 failed += 1
   829                 if options.first:
   899                 if options.first:
   956 
  1026 
   957     tests = []
  1027     tests = []
   958     for test in args:
  1028     for test in args:
   959         if (test.startswith("test-") and '~' not in test and
  1029         if (test.startswith("test-") and '~' not in test and
   960             ('.' not in test or test.endswith('.py') or
  1030             ('.' not in test or test.endswith('.py') or
   961              test.endswith('.bat'))):
  1031              test.endswith('.bat') or test.endswith('.t'))):
   962             tests.append(test)
  1032             tests.append(test)
   963     if not tests:
  1033     if not tests:
   964         print "# Ran 0 tests, 0 skipped, 0 failed."
  1034         print "# Ran 0 tests, 0 skipped, 0 failed."
   965         return
  1035         return
   966 
  1036