Show More
@@ -216,6 +216,22 b' def parselistfiles(files, listtype, warn' | |||||
216 | f.close() |
|
216 | f.close() | |
217 | return entries |
|
217 | return entries | |
218 |
|
218 | |||
|
219 | def parsettestcases(path): | |||
|
220 | """read a .t test file, return a set of test case names | |||
|
221 | ||||
|
222 | If path does not exist, return an empty set. | |||
|
223 | """ | |||
|
224 | cases = set() | |||
|
225 | try: | |||
|
226 | with open(path, 'rb') as f: | |||
|
227 | for l in f: | |||
|
228 | if l.startswith(b'#testcases '): | |||
|
229 | cases.update(l[11:].split()) | |||
|
230 | except IOError as ex: | |||
|
231 | if ex.errno != errno.ENOENT: | |||
|
232 | raise | |||
|
233 | return cases | |||
|
234 | ||||
219 | def getparser(): |
|
235 | def getparser(): | |
220 | """Obtain the OptionParser used by the CLI.""" |
|
236 | """Obtain the OptionParser used by the CLI.""" | |
221 | parser = optparse.OptionParser("%prog [options] [tests]") |
|
237 | parser = optparse.OptionParser("%prog [options] [tests]") | |
@@ -587,6 +603,7 b' class Test(unittest.TestCase):' | |||||
587 | self.bname = os.path.basename(path) |
|
603 | self.bname = os.path.basename(path) | |
588 | self.name = _strpath(self.bname) |
|
604 | self.name = _strpath(self.bname) | |
589 | self._testdir = os.path.dirname(path) |
|
605 | self._testdir = os.path.dirname(path) | |
|
606 | self._tmpname = os.path.basename(path) | |||
590 | self.errpath = os.path.join(self._testdir, b'%s.err' % self.bname) |
|
607 | self.errpath = os.path.join(self._testdir, b'%s.err' % self.bname) | |
591 |
|
608 | |||
592 | self._threadtmp = tmpdir |
|
609 | self._threadtmp = tmpdir | |
@@ -646,7 +663,7 b' class Test(unittest.TestCase):' | |||||
646 | if e.errno != errno.EEXIST: |
|
663 | if e.errno != errno.EEXIST: | |
647 | raise |
|
664 | raise | |
648 |
|
665 | |||
649 |
name = |
|
666 | name = self._tmpname | |
650 | self._testtmp = os.path.join(self._threadtmp, name) |
|
667 | self._testtmp = os.path.join(self._threadtmp, name) | |
651 | os.mkdir(self._testtmp) |
|
668 | os.mkdir(self._testtmp) | |
652 |
|
669 | |||
@@ -1055,6 +1072,19 b' class TTest(Test):' | |||||
1055 | ESCAPEMAP = dict((bchr(i), br'\x%02x' % i) for i in range(256)) |
|
1072 | ESCAPEMAP = dict((bchr(i), br'\x%02x' % i) for i in range(256)) | |
1056 | ESCAPEMAP.update({b'\\': b'\\\\', b'\r': br'\r'}) |
|
1073 | ESCAPEMAP.update({b'\\': b'\\\\', b'\r': br'\r'}) | |
1057 |
|
1074 | |||
|
1075 | def __init__(self, path, *args, **kwds): | |||
|
1076 | # accept an extra "case" parameter | |||
|
1077 | case = None | |||
|
1078 | if 'case' in kwds: | |||
|
1079 | case = kwds.pop('case') | |||
|
1080 | self._case = case | |||
|
1081 | self._allcases = parsettestcases(path) | |||
|
1082 | super(TTest, self).__init__(path, *args, **kwds) | |||
|
1083 | if case: | |||
|
1084 | self.name = '%s (case %s)' % (self.name, _strpath(case)) | |||
|
1085 | self.errpath = b'%s.%s.err' % (self.errpath[:-4], case) | |||
|
1086 | self._tmpname += b'-%s' % case | |||
|
1087 | ||||
1058 | @property |
|
1088 | @property | |
1059 | def refpath(self): |
|
1089 | def refpath(self): | |
1060 | return os.path.join(self._testdir, self.bname) |
|
1090 | return os.path.join(self._testdir, self.bname) | |
@@ -1110,6 +1140,20 b' class TTest(Test):' | |||||
1110 | self._timeout = self._slowtimeout |
|
1140 | self._timeout = self._slowtimeout | |
1111 | return True, None |
|
1141 | return True, None | |
1112 |
|
1142 | |||
|
1143 | def _iftest(self, args): | |||
|
1144 | # implements "#if" | |||
|
1145 | reqs = [] | |||
|
1146 | for arg in args: | |||
|
1147 | if arg.startswith(b'no-') and arg[3:] in self._allcases: | |||
|
1148 | if arg[3:] == self._case: | |||
|
1149 | return False | |||
|
1150 | elif arg in self._allcases: | |||
|
1151 | if arg != self._case: | |||
|
1152 | return False | |||
|
1153 | else: | |||
|
1154 | reqs.append(arg) | |||
|
1155 | return self._hghave(reqs)[0] | |||
|
1156 | ||||
1113 | def _parsetest(self, lines): |
|
1157 | def _parsetest(self, lines): | |
1114 | # We generate a shell script which outputs unique markers to line |
|
1158 | # We generate a shell script which outputs unique markers to line | |
1115 | # up script results with our source. These markers include input |
|
1159 | # up script results with our source. These markers include input | |
@@ -1167,7 +1211,7 b' class TTest(Test):' | |||||
1167 | after.setdefault(pos, []).append(' !!! invalid #if\n') |
|
1211 | after.setdefault(pos, []).append(' !!! invalid #if\n') | |
1168 | if skipping is not None: |
|
1212 | if skipping is not None: | |
1169 | after.setdefault(pos, []).append(' !!! nested #if\n') |
|
1213 | after.setdefault(pos, []).append(' !!! nested #if\n') | |
1170 |
skipping = not self._ |
|
1214 | skipping = not self._iftest(lsplit[1:]) | |
1171 | after.setdefault(pos, []).append(l) |
|
1215 | after.setdefault(pos, []).append(l) | |
1172 | elif l.startswith(b'#else'): |
|
1216 | elif l.startswith(b'#else'): | |
1173 | if skipping is None: |
|
1217 | if skipping is None: | |
@@ -2263,14 +2307,29 b' class TestRunner(object):' | |||||
2263 | else: |
|
2307 | else: | |
2264 | args = os.listdir(b'.') |
|
2308 | args = os.listdir(b'.') | |
2265 |
|
2309 | |||
2266 | return [{'path': t} for t in args |
|
2310 | tests = [] | |
2267 | if os.path.basename(t).startswith(b'test-') |
|
2311 | for t in args: | |
2268 | and (t.endswith(b'.py') or t.endswith(b'.t'))] |
|
2312 | if not (os.path.basename(t).startswith(b'test-') | |
|
2313 | and (t.endswith(b'.py') or t.endswith(b'.t'))): | |||
|
2314 | continue | |||
|
2315 | if t.endswith(b'.t'): | |||
|
2316 | # .t file may contain multiple test cases | |||
|
2317 | cases = sorted(parsettestcases(t)) | |||
|
2318 | if cases: | |||
|
2319 | tests += [{'path': t, 'case': c} for c in sorted(cases)] | |||
|
2320 | else: | |||
|
2321 | tests.append({'path': t}) | |||
|
2322 | else: | |||
|
2323 | tests.append({'path': t}) | |||
|
2324 | return tests | |||
2269 |
|
2325 | |||
2270 | def _runtests(self, testdescs): |
|
2326 | def _runtests(self, testdescs): | |
2271 | def _reloadtest(test, i): |
|
2327 | def _reloadtest(test, i): | |
2272 | # convert a test back to its description dict |
|
2328 | # convert a test back to its description dict | |
2273 | desc = {'path': test.path} |
|
2329 | desc = {'path': test.path} | |
|
2330 | case = getattr(test, '_case', None) | |||
|
2331 | if case: | |||
|
2332 | desc['case'] = case | |||
2274 | return self._gettest(desc, i) |
|
2333 | return self._gettest(desc, i) | |
2275 |
|
2334 | |||
2276 | try: |
|
2335 | try: | |
@@ -2286,7 +2345,12 b' class TestRunner(object):' | |||||
2286 | if self.options.restart: |
|
2345 | if self.options.restart: | |
2287 | orig = list(testdescs) |
|
2346 | orig = list(testdescs) | |
2288 | while testdescs: |
|
2347 | while testdescs: | |
2289 |
|
|
2348 | desc = testdescs[0] | |
|
2349 | if 'case' in desc: | |||
|
2350 | errpath = b'%s.%s.err' % (desc['path'], desc['case']) | |||
|
2351 | else: | |||
|
2352 | errpath = b'%s.err' % desc['path'] | |||
|
2353 | if os.path.exists(errpath): | |||
2290 | break |
|
2354 | break | |
2291 | testdescs.pop(0) |
|
2355 | testdescs.pop(0) | |
2292 | if not testdescs: |
|
2356 | if not testdescs: | |
@@ -2369,6 +2433,9 b' class TestRunner(object):' | |||||
2369 | refpath = os.path.join(self._testdir, path) |
|
2433 | refpath = os.path.join(self._testdir, path) | |
2370 | tmpdir = os.path.join(self._hgtmp, b'child%d' % count) |
|
2434 | tmpdir = os.path.join(self._hgtmp, b'child%d' % count) | |
2371 |
|
2435 | |||
|
2436 | # extra keyword parameters. 'case' is used by .t tests | |||
|
2437 | kwds = dict((k, testdesc[k]) for k in ['case'] if k in testdesc) | |||
|
2438 | ||||
2372 | t = testcls(refpath, tmpdir, |
|
2439 | t = testcls(refpath, tmpdir, | |
2373 | keeptmpdir=self.options.keep_tmpdir, |
|
2440 | keeptmpdir=self.options.keep_tmpdir, | |
2374 | debug=self.options.debug, |
|
2441 | debug=self.options.debug, | |
@@ -2379,7 +2446,7 b' class TestRunner(object):' | |||||
2379 | shell=self.options.shell, |
|
2446 | shell=self.options.shell, | |
2380 | hgcommand=self._hgcommand, |
|
2447 | hgcommand=self._hgcommand, | |
2381 | usechg=bool(self.options.with_chg or self.options.chg), |
|
2448 | usechg=bool(self.options.with_chg or self.options.chg), | |
2382 | useipv6=useipv6) |
|
2449 | useipv6=useipv6, **kwds) | |
2383 | t.should_reload = True |
|
2450 | t.should_reload = True | |
2384 | return t |
|
2451 | return t | |
2385 |
|
2452 |
@@ -900,3 +900,78 b' support for bisecting failed tests autom' | |||||
900 | # Ran 1 tests, 0 skipped, 0 warned, 1 failed. |
|
900 | # Ran 1 tests, 0 skipped, 0 warned, 1 failed. | |
901 | python hash seed: * (glob) |
|
901 | python hash seed: * (glob) | |
902 | [1] |
|
902 | [1] | |
|
903 | ||||
|
904 | $ cd .. | |||
|
905 | ||||
|
906 | Test cases in .t files | |||
|
907 | ====================== | |||
|
908 | $ mkdir cases | |||
|
909 | $ cd cases | |||
|
910 | $ cat > test-cases-abc.t <<'EOF' | |||
|
911 | > #testcases A B C | |||
|
912 | > $ V=B | |||
|
913 | > #if A | |||
|
914 | > $ V=A | |||
|
915 | > #endif | |||
|
916 | > #if C | |||
|
917 | > $ V=C | |||
|
918 | > #endif | |||
|
919 | > $ echo $V | sed 's/A/C/' | |||
|
920 | > C | |||
|
921 | > #if C | |||
|
922 | > $ [ $V = C ] | |||
|
923 | > #endif | |||
|
924 | > #if A | |||
|
925 | > $ [ $V = C ] | |||
|
926 | > [1] | |||
|
927 | > #endif | |||
|
928 | > #if no-C | |||
|
929 | > $ [ $V = C ] | |||
|
930 | > [1] | |||
|
931 | > #endif | |||
|
932 | > $ [ $V = D ] | |||
|
933 | > [1] | |||
|
934 | > EOF | |||
|
935 | $ rt | |||
|
936 | . | |||
|
937 | --- $TESTTMP/anothertests/cases/test-cases-abc.t | |||
|
938 | +++ $TESTTMP/anothertests/cases/test-cases-abc.t.B.err | |||
|
939 | @@ -7,7 +7,7 @@ | |||
|
940 | $ V=C | |||
|
941 | #endif | |||
|
942 | $ echo $V | sed 's/A/C/' | |||
|
943 | - C | |||
|
944 | + B | |||
|
945 | #if C | |||
|
946 | $ [ $V = C ] | |||
|
947 | #endif | |||
|
948 | ||||
|
949 | ERROR: test-cases-abc.t (case B) output changed | |||
|
950 | !. | |||
|
951 | Failed test-cases-abc.t (case B): output changed | |||
|
952 | # Ran 3 tests, 0 skipped, 0 warned, 1 failed. | |||
|
953 | python hash seed: * (glob) | |||
|
954 | [1] | |||
|
955 | ||||
|
956 | --restart works | |||
|
957 | ||||
|
958 | $ rt --restart | |||
|
959 | ||||
|
960 | --- $TESTTMP/anothertests/cases/test-cases-abc.t | |||
|
961 | +++ $TESTTMP/anothertests/cases/test-cases-abc.t.B.err | |||
|
962 | @@ -7,7 +7,7 @@ | |||
|
963 | $ V=C | |||
|
964 | #endif | |||
|
965 | $ echo $V | sed 's/A/C/' | |||
|
966 | - C | |||
|
967 | + B | |||
|
968 | #if C | |||
|
969 | $ [ $V = C ] | |||
|
970 | #endif | |||
|
971 | ||||
|
972 | ERROR: test-cases-abc.t (case B) output changed | |||
|
973 | !. | |||
|
974 | Failed test-cases-abc.t (case B): output changed | |||
|
975 | # Ran 2 tests, 0 skipped, 0 warned, 1 failed. | |||
|
976 | python hash seed: * (glob) | |||
|
977 | [1] |
General Comments 0
You need to be logged in to leave comments.
Login now