aboutsummaryrefslogtreecommitdiffstats
path: root/testing/parser.py
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2020-02-16 15:41:16 +0100
committerChristian Tismer <tismer@stackless.com>2020-02-20 16:44:13 +0100
commitd4ad80f7c09393438c7f330ee6bb85f34e4c6413 (patch)
tree894824ba81f341793fd802178c7f1ce2138e9df9 /testing/parser.py
parent5b868dae533e37b13be7890840191263a2caaa23 (diff)
testrunner: Fix disrupted lines in the error log
Windows inserts extra newlines into the error log when certain errors occur like "Exit code 0xc0000409\n***Exception:" and that newline caused the parser match to fail. Note that this is the normal stdout. CMake does not use stderr. It makes no sense to fix the pipe structure of the script. Instead, the only fix needed was recognition of line breaks in the error log. You can see this also in the failure listing The following tests FAILED: 1 - pysidetest_constructor_properties_test (Exit code 0xc0000409 ) The following improvements were done: - add an extra pass that checks for broken lines in the error log - add ad extra plausibility check or consecutive test numbers - improve the output, program structure and add some documentation When there should still an unforeseen bug occurs, it will be recognized by the plausi-check and the test repetitions are immediately cancelled. We could also fix the output not to contain the line breaks, but that breaks the principle of keeping the original output and needs discussion by the developers. Fixes: PYSIDE-1229 Change-Id: Ib71f3361e78eb59f3469da172c74c719e9f08706 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'testing/parser.py')
-rw-r--r--testing/parser.py116
1 files changed, 76 insertions, 40 deletions
diff --git a/testing/parser.py b/testing/parser.py
index 035aab091..1d5c34680 100644
--- a/testing/parser.py
+++ b/testing/parser.py
@@ -44,6 +44,15 @@ import re
from collections import namedtuple
from .helper import StringIO
+"""
+testing/parser.py
+
+Parse test output lines from ctest and build TestResult objects.
+
+TestParser.iter_blacklist adds info from the blacklist while iterating
+over the test results.
+"""
+
_EXAMPLE = """
Example output:
@@ -62,39 +71,42 @@ Note the field "mod_name". I had split this before, but it is necessary
to use the combination as the key, because the test names are not unique.
"""
-# validation of our pattern:
+_TEST_PAT_PRE = r"""
+ ^ # start
+ \s* # any whitespace ==: WS
+ ([0-9]+)/([0-9]+) # ip1 "/" n
+ \s+ # some WS
+ Test # "Test"
+ \s+ # some WS
+ \# # sharp symbol "#"
+ ([0-9]+) # sharp
+ : # colon symbol ':'
+ """
+_TEST_PAT = _TEST_PAT_PRE + r"""
+ \s+ # some WS
+ ([\w-]+) # mod_name
+ .*? # whatever (non greedy)
+ ( #
+ (Passed) # either "Passed", None
+ | #
+ \*\*\*(\w+.*?) # or None, "Something"
+ ) # code
+ \s+ # some WS
+ ([0-9]+\.[0-9]+) # tim
+ \s+ # some WS
+ sec # "sec"
+ \s* # any WS
+ $ # end
+ """
-_TEST_PAT = r"""
- ^ # start
- \s* # any whitespace ==: WS
- ([0-9]+)/([0-9]+) # ip1 "/" n
- \s+ # some WS
- Test # "Test"
- \s+ # some WS
- \# # sharp symbol "#"
- ([0-9]+) # sharp
- : # colon symbol ':'
- \s+ # some WS
- ([\w-]+) # mod_name
- .*? # whatever (non greedy)
- ( #
- (Passed) # either "Passed", None
- | #
- \*\*\*(\w+.*?) # or None, "Something"
- ) # code
- \s+ # some WS
- ([0-9]+\.[0-9]+) # tim
- \s+ # some WS
- sec # "sec"
- \s* # any WS
- $ # end
- """
+# validation of our pattern:
assert re.match(_TEST_PAT, _EXAMPLE.splitlines()[5], re.VERBOSE)
assert len(re.match(_TEST_PAT, _EXAMPLE.splitlines()[5], re.VERBOSE).groups()) == 8
assert len(re.match(_TEST_PAT, _EXAMPLE.splitlines()[7], re.VERBOSE).groups()) == 8
-TestResult = namedtuple("TestResult", ["idx", "mod_name", "passed",
- "code", "time"])
+TestResult = namedtuple("TestResult", "idx n sharp mod_name passed "
+ "code time fatal rich_result".split())
+
def _parse_tests(test_log):
"""
Create a TestResult object for every entry.
@@ -107,6 +119,15 @@ def _parse_tests(test_log):
lines = f.readlines()
else:
lines = []
+
+ # PYSIDE-1229: Fix disrupted lines like "Exit code 0xc0000409\n***Exception:"
+ pat = _TEST_PAT_PRE
+ for idx, line in enumerate(lines[:-1]):
+ match = re.match(pat, line, re.VERBOSE)
+ if match and line.split()[-1] != "sec":
+ # don't change the number of lines
+ lines[idx : idx + 2] = [line.rstrip() + lines[idx + 1], ""]
+
pat = _TEST_PAT
for line in lines:
match = re.match(pat, line, re.VERBOSE)
@@ -114,29 +135,41 @@ def _parse_tests(test_log):
idx, n, sharp, mod_name, much_stuff, code1, code2, tim = tup = match.groups()
# either code1 or code2 is None
code = code1 or code2
- idx, n, code, tim = int(idx), int(n), code.lower(), float(tim)
- res = TestResult(idx, mod_name, code == "passed", code, tim)
- result.append(res)
+ idx, n, sharp, code, tim = int(idx), int(n), int(sharp), code.lower(), float(tim)
+ item = TestResult(idx, n, sharp, mod_name, code == "passed", code, tim, False, None)
+ result.append(item)
+
+ # PYSIDE-1229: Be sure that the numbering of the tests is consecutive
+ for idx, item in enumerate(result):
+ # testing fatal error:
+ # Use "if idx + 1 != item.idx or idx == 42:"
+ if idx + 1 != item.idx:
+ # The numbering is disrupted. Provoke an error in this line!
+ passed = False
+ code += ", but lines are disrupted!"
+ result[idx] = item._replace(passed=False,
+ code=item.code + ", but lines are disrupted!",
+ fatal=True)
+ break
return result
class TestParser(object):
def __init__(self, test_log):
- self._result = _parse_tests(test_log)
+ self._results = _parse_tests(test_log)
@property
- def result(self):
- return self._result
+ def results(self):
+ return self._results
def __len__(self):
- return len(self._result)
+ return len(self._results)
def iter_blacklist(self, blacklist):
bl = blacklist
- for line in self._result:
- mod_name = line.mod_name
- passed = line.passed
- match = bl.find_matching_line(line)
+ for item in self.results:
+ passed = item.passed
+ match = bl.find_matching_line(item)
if not passed:
if match:
res = "BFAIL"
@@ -147,4 +180,7 @@ class TestParser(object):
res = "BPASS"
else:
res = "PASS"
- yield mod_name, res
+ if item.fatal:
+ # PYSIDE-1229: Stop the testing completely when a fatal error exists
+ res = "FATAL"
+ yield item._replace(rich_result=res)