tests/run-tests.py
changeset 1342 64c56144ce88
parent 1341 c559280de767
child 1343 958582800276
equal deleted inserted replaced
1333:90d2e5021063 1342:64c56144ce88
   774     if exitcode == SKIPPED_STATUS or output is None:
   774     if exitcode == SKIPPED_STATUS or output is None:
   775         return exitcode, output
   775         return exitcode, output
   776 
   776 
   777     # Merge the script output back into a unified test
   777     # Merge the script output back into a unified test
   778 
   778 
       
   779     warnonly = True
   779     pos = -1
   780     pos = -1
   780     postout = []
   781     postout = []
   781     ret = 0
       
   782     for l in output:
   782     for l in output:
   783         lout, lcmd = l, None
   783         lout, lcmd = l, None
   784         if salt in l:
   784         if salt in l:
   785             lout, lcmd = l.split(salt, 1)
   785             lout, lcmd = l.split(salt, 1)
   786 
   786 
   795 
   795 
   796             r = linematch(el, lout)
   796             r = linematch(el, lout)
   797             if isinstance(r, str):
   797             if isinstance(r, str):
   798                 if r == '+glob':
   798                 if r == '+glob':
   799                     lout = el[:-1] + ' (glob)\n'
   799                     lout = el[:-1] + ' (glob)\n'
   800                     r = False
   800                     r = 0 # warn only
   801                 elif r == '-glob':
   801                 elif r == '-glob':
   802                     log('\ninfo, unnecessary glob in %s (after line %d):'
   802                     lout = ''.join(el.rsplit(' (glob)', 1))
   803                         ' %s (glob)\n' % (test, pos, el[:-1]))
   803                     r = 0 # warn only
   804                     r = True # pass on unnecessary glob
       
   805                 else:
   804                 else:
   806                     log('\ninfo, unknown linematch result: %r\n' % r)
   805                     log('\ninfo, unknown linematch result: %r\n' % r)
   807                     r = False
   806                     r = False
   808             if r:
   807             if r:
   809                 postout.append("  " + el)
   808                 postout.append("  " + el)
   810             else:
   809             else:
   811                 if needescape(lout):
   810                 if needescape(lout):
   812                     lout = stringescape(lout.rstrip('\n')) + " (esc)\n"
   811                     lout = stringescape(lout.rstrip('\n')) + " (esc)\n"
   813                 postout.append("  " + lout) # let diff deal with it
   812                 postout.append("  " + lout) # let diff deal with it
       
   813                 if r != 0: # != warn only
       
   814                     warnonly = False
   814 
   815 
   815         if lcmd:
   816         if lcmd:
   816             # add on last return code
   817             # add on last return code
   817             ret = int(lcmd.split()[1])
   818             ret = int(lcmd.split()[1])
   818             if ret != 0:
   819             if ret != 0:
   823             pos = int(lcmd.split()[0])
   824             pos = int(lcmd.split()[0])
   824 
   825 
   825     if pos in after:
   826     if pos in after:
   826         postout += after.pop(pos)
   827         postout += after.pop(pos)
   827 
   828 
       
   829     if warnonly and exitcode == 0:
       
   830         exitcode = False
   828     return exitcode, postout
   831     return exitcode, postout
   829 
   832 
   830 wifexited = getattr(os, "WIFEXITED", lambda x: False)
   833 wifexited = getattr(os, "WIFEXITED", lambda x: False)
   831 def run(cmd, wd, options, replacements, env):
   834 def run(cmd, wd, options, replacements, env):
   832     """Run command in a sub-process, capturing the output (stdout and stderr).
   835     """Run command in a sub-process, capturing the output (stdout and stderr).
   880         if options.verbose:
   883         if options.verbose:
   881             log("\nSkipping %s: %s" % (testpath, msg))
   884             log("\nSkipping %s: %s" % (testpath, msg))
   882         return 's', test, msg
   885         return 's', test, msg
   883 
   886 
   884     def fail(msg, ret):
   887     def fail(msg, ret):
       
   888         warned = ret is False
   885         if not options.nodiff:
   889         if not options.nodiff:
   886             log("\nERROR: %s %s" % (testpath, msg))
   890             log("\n%s: %s %s" % (warned and 'Warning' or 'ERROR', test, msg))
   887         if (not ret and options.interactive
   891         if (not ret and options.interactive
   888             and os.path.exists(testpath + ".err")):
   892             and os.path.exists(testpath + ".err")):
   889             iolock.acquire()
   893             iolock.acquire()
   890             print "Accept this change? [n] ",
   894             print "Accept this change? [n] ",
   891             answer = sys.stdin.readline().strip()
   895             answer = sys.stdin.readline().strip()
   894                 if test.endswith(".t"):
   898                 if test.endswith(".t"):
   895                     rename(testpath + ".err", testpath)
   899                     rename(testpath + ".err", testpath)
   896                 else:
   900                 else:
   897                     rename(testpath + ".err", testpath + ".out")
   901                     rename(testpath + ".err", testpath + ".out")
   898                 return '.', test, ''
   902                 return '.', test, ''
   899         return '!', test, msg
   903         return warned and '~' or '!', test, msg
   900 
   904 
   901     def success():
   905     def success():
   902         return '.', test, ''
   906         return '.', test, ''
   903 
   907 
   904     def ignore(msg):
   908     def ignore(msg):
  1073     if os.path.abspath(actualhg) != os.path.abspath(expecthg):
  1077     if os.path.abspath(actualhg) != os.path.abspath(expecthg):
  1074         sys.stderr.write('warning: %s with unexpected mercurial lib: %s\n'
  1078         sys.stderr.write('warning: %s with unexpected mercurial lib: %s\n'
  1075                          '         (expected %s)\n'
  1079                          '         (expected %s)\n'
  1076                          % (verb, actualhg, expecthg))
  1080                          % (verb, actualhg, expecthg))
  1077 
  1081 
  1078 results = {'.':[], '!':[], 's':[], 'i':[]}
  1082 results = {'.':[], '!':[], '~': [], 's':[], 'i':[]}
  1079 times = []
  1083 times = []
  1080 iolock = threading.Lock()
  1084 iolock = threading.Lock()
  1081 abort = False
  1085 abort = False
  1082 
  1086 
  1083 def scheduletests(options, tests):
  1087 def scheduletests(options, tests):
  1137                 tests = orig
  1141                 tests = orig
  1138 
  1142 
  1139         scheduletests(options, tests)
  1143         scheduletests(options, tests)
  1140 
  1144 
  1141         failed = len(results['!'])
  1145         failed = len(results['!'])
  1142         tested = len(results['.']) + failed
  1146         warned = len(results['~'])
       
  1147         tested = len(results['.']) + failed + warned
  1143         skipped = len(results['s'])
  1148         skipped = len(results['s'])
  1144         ignored = len(results['i'])
  1149         ignored = len(results['i'])
  1145 
  1150 
  1146         print
  1151         print
  1147         if not options.noskips:
  1152         if not options.noskips:
  1148             for s in results['s']:
  1153             for s in results['s']:
  1149                 print "Skipped %s: %s" % s
  1154                 print "Skipped %s: %s" % s
       
  1155         for s in results['~']:
       
  1156             print "Warned %s: %s" % s
  1150         for s in results['!']:
  1157         for s in results['!']:
  1151             print "Failed %s: %s" % s
  1158             print "Failed %s: %s" % s
  1152         _checkhglib("Tested")
  1159         _checkhglib("Tested")
  1153         print "# Ran %d tests, %d skipped, %d failed." % (
  1160         print "# Ran %d tests, %d skipped, %d warned, %d failed." % (
  1154             tested, skipped + ignored, failed)
  1161             tested, skipped + ignored, warned, failed)
  1155         if results['!']:
  1162         if results['!']:
  1156             print 'python hash seed:', os.environ['PYTHONHASHSEED']
  1163             print 'python hash seed:', os.environ['PYTHONHASHSEED']
  1157         if options.time:
  1164         if options.time:
  1158             outputtimes(options)
  1165             outputtimes(options)
  1159 
  1166 
  1162     except KeyboardInterrupt:
  1169     except KeyboardInterrupt:
  1163         failed = True
  1170         failed = True
  1164         print "\ninterrupted!"
  1171         print "\ninterrupted!"
  1165 
  1172 
  1166     if failed:
  1173     if failed:
  1167         sys.exit(1)
  1174         return 1
       
  1175     if warned:
       
  1176         return 80
  1168 
  1177 
  1169 testtypes = [('.py', pytest, '.out'),
  1178 testtypes = [('.py', pytest, '.out'),
  1170              ('.t', tsttest, '')]
  1179              ('.t', tsttest, '')]
  1171 
  1180 
  1172 def main():
  1181 def main():
  1253     path = [BINDIR] + os.environ["PATH"].split(os.pathsep)
  1262     path = [BINDIR] + os.environ["PATH"].split(os.pathsep)
  1254     os.environ["PATH"] = os.pathsep.join(path)
  1263     os.environ["PATH"] = os.pathsep.join(path)
  1255 
  1264 
  1256     # Include TESTDIR in PYTHONPATH so that out-of-tree extensions
  1265     # Include TESTDIR in PYTHONPATH so that out-of-tree extensions
  1257     # can run .../tests/run-tests.py test-foo where test-foo
  1266     # can run .../tests/run-tests.py test-foo where test-foo
  1258     # adds an extension to HGRC
  1267     # adds an extension to HGRC. Also include run-test.py directory to import
  1259     pypath = [PYTHONDIR, TESTDIR]
  1268     # modules like heredoctest.
       
  1269     pypath = [PYTHONDIR, TESTDIR, os.path.abspath(os.path.dirname(__file__))]
  1260     # We have to augment PYTHONPATH, rather than simply replacing
  1270     # We have to augment PYTHONPATH, rather than simply replacing
  1261     # it, in case external libraries are only available via current
  1271     # it, in case external libraries are only available via current
  1262     # PYTHONPATH.  (In particular, the Subversion bindings on OS X
  1272     # PYTHONPATH.  (In particular, the Subversion bindings on OS X
  1263     # are in /opt/subversion.)
  1273     # are in /opt/subversion.)
  1264     oldpypath = os.environ.get(IMPL_PATH)
  1274     oldpypath = os.environ.get(IMPL_PATH)
  1272     vlog("# Using HGTMP", HGTMP)
  1282     vlog("# Using HGTMP", HGTMP)
  1273     vlog("# Using PATH", os.environ["PATH"])
  1283     vlog("# Using PATH", os.environ["PATH"])
  1274     vlog("# Using", IMPL_PATH, os.environ[IMPL_PATH])
  1284     vlog("# Using", IMPL_PATH, os.environ[IMPL_PATH])
  1275 
  1285 
  1276     try:
  1286     try:
  1277         runtests(options, tests)
  1287         sys.exit(runtests(options, tests) or 0)
  1278     finally:
  1288     finally:
  1279         time.sleep(.1)
  1289         time.sleep(.1)
  1280         cleanup(options)
  1290         cleanup(options)
  1281 
  1291 
  1282 if __name__ == '__main__':
  1292 if __name__ == '__main__':