173 parser.add_option("--shell", type="string", |
174 parser.add_option("--shell", type="string", |
174 help="shell to use (default: $%s or %s)" % defaults['shell']) |
175 help="shell to use (default: $%s or %s)" % defaults['shell']) |
175 parser.add_option("-t", "--timeout", type="int", |
176 parser.add_option("-t", "--timeout", type="int", |
176 help="kill errant tests after TIMEOUT seconds" |
177 help="kill errant tests after TIMEOUT seconds" |
177 " (default: $%s or %d)" % defaults['timeout']) |
178 " (default: $%s or %d)" % defaults['timeout']) |
|
179 parser.add_option("--time", action="store_true", |
|
180 help="time how long each test takes") |
178 parser.add_option("--tmpdir", type="string", |
181 parser.add_option("--tmpdir", type="string", |
179 help="run tests in the given temporary directory" |
182 help="run tests in the given temporary directory" |
180 " (implies --keep-tmpdir)") |
183 " (implies --keep-tmpdir)") |
181 parser.add_option("-v", "--verbose", action="store_true", |
184 parser.add_option("-v", "--verbose", action="store_true", |
182 help="output verbose messages") |
185 help="output verbose messages") |
261 if options.debug: |
264 if options.debug: |
262 if options.timeout != defaults['timeout']: |
265 if options.timeout != defaults['timeout']: |
263 sys.stderr.write( |
266 sys.stderr.write( |
264 'warning: --timeout option ignored with --debug\n') |
267 'warning: --timeout option ignored with --debug\n') |
265 options.timeout = 0 |
268 options.timeout = 0 |
|
269 if options.time: |
|
270 sys.stderr.write( |
|
271 'warning: --time option ignored with --debug\n') |
|
272 options.time = False |
266 if options.py3k_warnings: |
273 if options.py3k_warnings: |
267 if sys.version_info[:2] < (2, 6) or sys.version_info[:2] >= (3, 0): |
274 if sys.version_info[:2] < (2, 6) or sys.version_info[:2] >= (3, 0): |
268 parser.error('--py3k-warnings can only be used on Python 2.6+') |
275 parser.error('--py3k-warnings can only be used on Python 2.6+') |
269 if options.blacklist: |
276 if options.blacklist: |
270 options.blacklist = parselistfiles(options.blacklist, 'blacklist') |
277 options.blacklist = parselistfiles(options.blacklist, 'blacklist') |
444 rc = os.path.join(TESTDIR, '.coveragerc') |
451 rc = os.path.join(TESTDIR, '.coveragerc') |
445 vlog('# Installing coverage rc to %s' % rc) |
452 vlog('# Installing coverage rc to %s' % rc) |
446 os.environ['COVERAGE_PROCESS_START'] = rc |
453 os.environ['COVERAGE_PROCESS_START'] = rc |
447 fn = os.path.join(INST, '..', '.coverage') |
454 fn = os.path.join(INST, '..', '.coverage') |
448 os.environ['COVERAGE_FILE'] = fn |
455 os.environ['COVERAGE_FILE'] = fn |
|
456 |
|
457 def outputtimes(options): |
|
458 vlog('# Producing time report') |
|
459 times.sort(key=lambda t: (t[1], t[0]), reverse=True) |
|
460 cols = '%7.3f %s' |
|
461 print '\n%-7s %s' % ('Time', 'Test') |
|
462 for test, timetaken in times: |
|
463 print cols % (timetaken, test) |
449 |
464 |
450 def outputcoverage(options): |
465 def outputcoverage(options): |
451 |
466 |
452 vlog('# Producing coverage report') |
467 vlog('# Producing coverage report') |
453 os.chdir(PYTHONDIR) |
468 os.chdir(PYTHONDIR) |
751 '''tristate output: |
766 '''tristate output: |
752 None -> skipped |
767 None -> skipped |
753 True -> passed |
768 True -> passed |
754 False -> failed''' |
769 False -> failed''' |
755 |
770 |
756 global results, resultslock, iolock |
771 global results, iolock |
757 |
772 |
758 testpath = os.path.join(TESTDIR, test) |
773 testpath = os.path.join(TESTDIR, test) |
759 |
|
760 def result(l, e): |
|
761 resultslock.acquire() |
|
762 results[l].append(e) |
|
763 resultslock.release() |
|
764 |
774 |
765 def skip(msg): |
775 def skip(msg): |
766 if not options.verbose: |
776 if not options.verbose: |
767 result('s', (test, msg)) |
777 results['s'].append((test, msg)) |
768 else: |
778 else: |
769 iolock.acquire() |
779 iolock.acquire() |
770 print "\nSkipping %s: %s" % (testpath, msg) |
780 print "\nSkipping %s: %s" % (testpath, msg) |
771 iolock.release() |
781 iolock.release() |
772 return None |
782 return None |
785 if answer.lower() in "y yes".split(): |
795 if answer.lower() in "y yes".split(): |
786 if test.endswith(".t"): |
796 if test.endswith(".t"): |
787 rename(testpath + ".err", testpath) |
797 rename(testpath + ".err", testpath) |
788 else: |
798 else: |
789 rename(testpath + ".err", testpath + ".out") |
799 rename(testpath + ".err", testpath + ".out") |
790 result('p', test) |
800 success(test) |
791 return |
801 return |
792 result('f', (test, msg)) |
802 results['f'].append((test, msg)) |
793 |
803 |
794 def success(): |
804 def success(): |
795 result('p', test) |
805 results['p'].append(test) |
796 |
806 |
797 def ignore(msg): |
807 def ignore(msg): |
798 result('i', (test, msg)) |
808 results['i'].append((test, msg)) |
799 |
809 |
800 if (os.path.basename(test).startswith("test-") and '~' not in test and |
810 if (os.path.basename(test).startswith("test-") and '~' not in test and |
801 ('.' not in test or test.endswith('.py') or |
811 ('.' not in test or test.endswith('.py') or |
802 test.endswith('.bat') or test.endswith('.t'))): |
812 test.endswith('.bat') or test.endswith('.t'))): |
803 if not os.path.exists(test): |
813 if not os.path.exists(test): |
889 for c in testtmp), '$TESTTMP')) |
899 for c in testtmp), '$TESTTMP')) |
890 else: |
900 else: |
891 replacements.append((re.escape(testtmp), '$TESTTMP')) |
901 replacements.append((re.escape(testtmp), '$TESTTMP')) |
892 |
902 |
893 os.mkdir(testtmp) |
903 os.mkdir(testtmp) |
|
904 if options.time: |
|
905 starttime = time.time() |
894 ret, out = runner(testpath, testtmp, options, replacements) |
906 ret, out = runner(testpath, testtmp, options, replacements) |
|
907 if options.time: |
|
908 endtime = time.time() |
|
909 times.append((test, endtime - starttime)) |
895 vlog("# Ret was:", ret) |
910 vlog("# Ret was:", ret) |
896 |
911 |
897 mark = '.' |
912 mark = '.' |
898 |
913 |
899 skipped = (ret == SKIPPED_STATUS) |
914 skipped = (ret == SKIPPED_STATUS) |
1054 childopts = ['--child=%d' % wfd, '--port=%d' % (options.port + j * 3)] |
1069 childopts = ['--child=%d' % wfd, '--port=%d' % (options.port + j * 3)] |
1055 childtmp = os.path.join(HGTMP, 'child%d' % j) |
1070 childtmp = os.path.join(HGTMP, 'child%d' % j) |
1056 childopts += ['--tmpdir', childtmp] |
1071 childopts += ['--tmpdir', childtmp] |
1057 cmdline = [PYTHON, sys.argv[0]] + opts + childopts + job |
1072 cmdline = [PYTHON, sys.argv[0]] + opts + childopts + job |
1058 vlog(' '.join(cmdline)) |
1073 vlog(' '.join(cmdline)) |
1059 fps[os.spawnvp(os.P_NOWAIT, cmdline[0], cmdline)] = os.fdopen(rfd, 'r') |
1074 fps[os.spawnvp(os.P_NOWAIT, cmdline[0], cmdline)] = os.fdopen(rfd, 'rb') |
1060 os.close(wfd) |
1075 os.close(wfd) |
1061 signal.signal(signal.SIGINT, signal.SIG_IGN) |
1076 signal.signal(signal.SIGINT, signal.SIG_IGN) |
1062 failures = 0 |
1077 failures = 0 |
1063 tested, skipped, failed = 0, 0, 0 |
1078 passed, skipped, failed = 0, 0, 0 |
1064 skips = [] |
1079 skips = [] |
1065 fails = [] |
1080 fails = [] |
1066 while fps: |
1081 while fps: |
1067 pid, status = os.wait() |
1082 pid, status = os.wait() |
1068 fp = fps.pop(pid) |
1083 fp = fps.pop(pid) |
1069 l = fp.read().splitlines() |
|
1070 try: |
1084 try: |
1071 test, skip, fail = map(int, l[:3]) |
1085 childresults = pickle.load(fp) |
1072 except ValueError: |
1086 except pickle.UnpicklingError: |
1073 test, skip, fail = 0, 0, 0 |
1087 pass |
1074 split = -fail or len(l) |
1088 else: |
1075 for s in l[3:split]: |
1089 passed += len(childresults['p']) |
1076 skips.append(s.split(" ", 1)) |
1090 skipped += len(childresults['s']) |
1077 for s in l[split:]: |
1091 failed += len(childresults['f']) |
1078 fails.append(s.split(" ", 1)) |
1092 skips.extend(childresults['s']) |
1079 tested += test |
1093 fails.extend(childresults['f']) |
1080 skipped += skip |
1094 if options.time: |
1081 failed += fail |
1095 childtimes = pickle.load(fp) |
|
1096 times.extend(childtimes) |
|
1097 |
1082 vlog('pid %d exited, status %d' % (pid, status)) |
1098 vlog('pid %d exited, status %d' % (pid, status)) |
1083 failures |= status |
1099 failures |= status |
1084 print |
1100 print |
1085 skipped += len(blacklisted) |
1101 skipped += len(blacklisted) |
1086 if not options.noskips: |
1102 if not options.noskips: |
1091 for s in fails: |
1107 for s in fails: |
1092 print "Failed %s: %s" % (s[0], s[1]) |
1108 print "Failed %s: %s" % (s[0], s[1]) |
1093 |
1109 |
1094 _checkhglib("Tested") |
1110 _checkhglib("Tested") |
1095 print "# Ran %d tests, %d skipped, %d failed." % ( |
1111 print "# Ran %d tests, %d skipped, %d failed." % ( |
1096 tested, skipped, failed) |
1112 passed + failed, skipped, failed) |
1097 |
1113 |
|
1114 if options.time: |
|
1115 outputtimes(options) |
1098 if options.anycoverage: |
1116 if options.anycoverage: |
1099 outputcoverage(options) |
1117 outputcoverage(options) |
1100 sys.exit(failures != 0) |
1118 sys.exit(failures != 0) |
1101 |
1119 |
1102 results = dict(p=[], f=[], s=[], i=[]) |
1120 results = dict(p=[], f=[], s=[], i=[]) |
1103 resultslock = threading.Lock() |
1121 times = [] |
1104 iolock = threading.Lock() |
1122 iolock = threading.Lock() |
1105 |
1123 |
1106 def runqueue(options, tests, results): |
1124 def runqueue(options, tests): |
1107 for test in tests: |
1125 for test in tests: |
1108 ret = runone(options, test) |
1126 ret = runone(options, test) |
1109 if options.first and ret is not None and not ret: |
1127 if options.first and ret is not None and not ret: |
1110 break |
1128 break |
1111 |
1129 |
1127 tests.pop(0) |
1145 tests.pop(0) |
1128 if not tests: |
1146 if not tests: |
1129 print "running all tests" |
1147 print "running all tests" |
1130 tests = orig |
1148 tests = orig |
1131 |
1149 |
1132 runqueue(options, tests, results) |
1150 runqueue(options, tests) |
1133 |
1151 |
1134 failed = len(results['f']) |
1152 failed = len(results['f']) |
1135 tested = len(results['p']) + failed |
1153 tested = len(results['p']) + failed |
1136 skipped = len(results['s']) |
1154 skipped = len(results['s']) |
1137 ignored = len(results['i']) |
1155 ignored = len(results['i']) |
1138 |
1156 |
1139 if options.child: |
1157 if options.child: |
1140 fp = os.fdopen(options.child, 'w') |
1158 fp = os.fdopen(options.child, 'wb') |
1141 fp.write('%d\n%d\n%d\n' % (tested, skipped, failed)) |
1159 pickle.dump(results, fp, pickle.HIGHEST_PROTOCOL) |
1142 for s in results['s']: |
1160 if options.time: |
1143 fp.write("%s %s\n" % s) |
1161 pickle.dump(times, fp, pickle.HIGHEST_PROTOCOL) |
1144 for s in results['f']: |
|
1145 fp.write("%s %s\n" % s) |
|
1146 fp.close() |
1162 fp.close() |
1147 else: |
1163 else: |
1148 print |
1164 print |
1149 for s in results['s']: |
1165 for s in results['s']: |
1150 print "Skipped %s: %s" % s |
1166 print "Skipped %s: %s" % s |
1151 for s in results['f']: |
1167 for s in results['f']: |
1152 print "Failed %s: %s" % s |
1168 print "Failed %s: %s" % s |
1153 _checkhglib("Tested") |
1169 _checkhglib("Tested") |
1154 print "# Ran %d tests, %d skipped, %d failed." % ( |
1170 print "# Ran %d tests, %d skipped, %d failed." % ( |
1155 tested, skipped + ignored, failed) |
1171 tested, skipped + ignored, failed) |
|
1172 if options.time: |
|
1173 outputtimes(options) |
1156 |
1174 |
1157 if options.anycoverage: |
1175 if options.anycoverage: |
1158 outputcoverage(options) |
1176 outputcoverage(options) |
1159 except KeyboardInterrupt: |
1177 except KeyboardInterrupt: |
1160 failed = True |
1178 failed = True |