# COPYING file in the root directory) and Apache 2.0 License
# (found in the LICENSE.Apache file in the root directory).
-'''Filter for error messages in test output:
+"""Filter for error messages in test output:
- Receives merged stdout/stderr from test on stdin
- Finds patterns of known error messages for test name (first argument)
- Prints those error messages to stdout
-'''
+"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-from __future__ import unicode_literals
+from __future__ import absolute_import, division, print_function, unicode_literals
import re
import sys
class ErrorParserBase(object):
def parse_error(self, line):
- '''Parses a line of test output. If it contains an error, returns a
+ """Parses a line of test output. If it contains an error, returns a
formatted message describing the error; otherwise, returns None.
Subclasses must override this method.
- '''
+ """
raise NotImplementedError
class GTestErrorParser(ErrorParserBase):
- '''A parser that remembers the last test that began running so it can print
+ """A parser that remembers the last test that began running so it can print
that test's name upon detecting failure.
- '''
- _GTEST_NAME_PATTERN = re.compile(r'\[ RUN \] (\S+)$')
+ """
+
+ _GTEST_NAME_PATTERN = re.compile(r"\[ RUN \] (\S+)$")
# format: '<filename or "unknown file">:<line #>: Failure'
- _GTEST_FAIL_PATTERN = re.compile(r'(unknown file|\S+:\d+): Failure$')
+ _GTEST_FAIL_PATTERN = re.compile(r"(unknown file|\S+:\d+): Failure$")
def __init__(self):
- self._last_gtest_name = 'Unknown test'
+ self._last_gtest_name = "Unknown test"
def parse_error(self, line):
gtest_name_match = self._GTEST_NAME_PATTERN.match(line)
return None
gtest_fail_match = self._GTEST_FAIL_PATTERN.match(line)
if gtest_fail_match:
- return '%s failed: %s' % (
- self._last_gtest_name, gtest_fail_match.group(1))
+ return "%s failed: %s" % (self._last_gtest_name, gtest_fail_match.group(1))
return None
class MatchErrorParser(ErrorParserBase):
- '''A simple parser that returns the whole line if it matches the pattern.
- '''
+ """A simple parser that returns the whole line if it matches the pattern."""
+
def __init__(self, pattern):
self._pattern = re.compile(pattern)
# format (link error):
# '<filename>:<line #>: error: <error msg>'
# The below regex catches both
- super(CompilerErrorParser, self).__init__(r'\S+:\d+: error:')
+ super(CompilerErrorParser, self).__init__(r"\S+:\d+: error:")
class ScanBuildErrorParser(MatchErrorParser):
def __init__(self):
- super(ScanBuildErrorParser, self).__init__(
- r'scan-build: \d+ bugs found.$')
+ super(ScanBuildErrorParser, self).__init__(r"scan-build: \d+ bugs found.$")
class DbCrashErrorParser(MatchErrorParser):
def __init__(self):
- super(DbCrashErrorParser, self).__init__(r'\*\*\*.*\^$|TEST FAILED.')
+ super(DbCrashErrorParser, self).__init__(r"\*\*\*.*\^$|TEST FAILED.")
class WriteStressErrorParser(MatchErrorParser):
def __init__(self):
super(WriteStressErrorParser, self).__init__(
- r'ERROR: write_stress died with exitcode=\d+')
+ r"ERROR: write_stress died with exitcode=\d+"
+ )
class AsanErrorParser(MatchErrorParser):
def __init__(self):
- super(AsanErrorParser, self).__init__(
- r'==\d+==ERROR: AddressSanitizer:')
+ super(AsanErrorParser, self).__init__(r"==\d+==ERROR: AddressSanitizer:")
class UbsanErrorParser(MatchErrorParser):
def __init__(self):
# format: '<filename>:<line #>:<column #>: runtime error: <error msg>'
- super(UbsanErrorParser, self).__init__(r'\S+:\d+:\d+: runtime error:')
+ super(UbsanErrorParser, self).__init__(r"\S+:\d+:\d+: runtime error:")
class ValgrindErrorParser(MatchErrorParser):
def __init__(self):
# just grab the summary, valgrind doesn't clearly distinguish errors
# from other log messages.
- super(ValgrindErrorParser, self).__init__(r'==\d+== ERROR SUMMARY:')
+ super(ValgrindErrorParser, self).__init__(r"==\d+== ERROR SUMMARY:")
class CompatErrorParser(MatchErrorParser):
def __init__(self):
- super(CompatErrorParser, self).__init__(r'==== .*[Ee]rror.* ====$')
+ super(CompatErrorParser, self).__init__(r"==== .*[Ee]rror.* ====$")
class TsanErrorParser(MatchErrorParser):
def __init__(self):
- super(TsanErrorParser, self).__init__(r'WARNING: ThreadSanitizer:')
+ super(TsanErrorParser, self).__init__(r"WARNING: ThreadSanitizer:")
_TEST_NAME_TO_PARSERS = {
- 'punit': [CompilerErrorParser, GTestErrorParser],
- 'unit': [CompilerErrorParser, GTestErrorParser],
- 'release': [CompilerErrorParser, GTestErrorParser],
- 'unit_481': [CompilerErrorParser, GTestErrorParser],
- 'release_481': [CompilerErrorParser, GTestErrorParser],
- 'clang_unit': [CompilerErrorParser, GTestErrorParser],
- 'clang_release': [CompilerErrorParser, GTestErrorParser],
- 'clang_analyze': [CompilerErrorParser, ScanBuildErrorParser],
- 'code_cov': [CompilerErrorParser, GTestErrorParser],
- 'unity': [CompilerErrorParser, GTestErrorParser],
- 'lite': [CompilerErrorParser],
- 'lite_test': [CompilerErrorParser, GTestErrorParser],
- 'stress_crash': [CompilerErrorParser, DbCrashErrorParser],
- 'stress_crash_with_atomic_flush': [CompilerErrorParser, DbCrashErrorParser],
- 'stress_crash_with_txn': [CompilerErrorParser, DbCrashErrorParser],
- 'write_stress': [CompilerErrorParser, WriteStressErrorParser],
- 'asan': [CompilerErrorParser, GTestErrorParser, AsanErrorParser],
- 'asan_crash': [CompilerErrorParser, AsanErrorParser, DbCrashErrorParser],
- 'asan_crash_with_atomic_flush': [CompilerErrorParser, AsanErrorParser, DbCrashErrorParser],
- 'asan_crash_with_txn': [CompilerErrorParser, AsanErrorParser, DbCrashErrorParser],
- 'ubsan': [CompilerErrorParser, GTestErrorParser, UbsanErrorParser],
- 'ubsan_crash': [CompilerErrorParser, UbsanErrorParser, DbCrashErrorParser],
- 'ubsan_crash_with_atomic_flush': [CompilerErrorParser, UbsanErrorParser, DbCrashErrorParser],
- 'ubsan_crash_with_txn': [CompilerErrorParser, UbsanErrorParser, DbCrashErrorParser],
- 'valgrind': [CompilerErrorParser, GTestErrorParser, ValgrindErrorParser],
- 'tsan': [CompilerErrorParser, GTestErrorParser, TsanErrorParser],
- 'format_compatible': [CompilerErrorParser, CompatErrorParser],
- 'run_format_compatible': [CompilerErrorParser, CompatErrorParser],
- 'no_compression': [CompilerErrorParser, GTestErrorParser],
- 'run_no_compression': [CompilerErrorParser, GTestErrorParser],
- 'regression': [CompilerErrorParser],
- 'run_regression': [CompilerErrorParser],
+ "punit": [CompilerErrorParser, GTestErrorParser],
+ "unit": [CompilerErrorParser, GTestErrorParser],
+ "release": [CompilerErrorParser, GTestErrorParser],
+ "unit_481": [CompilerErrorParser, GTestErrorParser],
+ "release_481": [CompilerErrorParser, GTestErrorParser],
+ "clang_unit": [CompilerErrorParser, GTestErrorParser],
+ "clang_release": [CompilerErrorParser, GTestErrorParser],
+ "clang_analyze": [CompilerErrorParser, ScanBuildErrorParser],
+ "code_cov": [CompilerErrorParser, GTestErrorParser],
+ "unity": [CompilerErrorParser, GTestErrorParser],
+ "lite": [CompilerErrorParser],
+ "lite_test": [CompilerErrorParser, GTestErrorParser],
+ "stress_crash": [CompilerErrorParser, DbCrashErrorParser],
+ "stress_crash_with_atomic_flush": [CompilerErrorParser, DbCrashErrorParser],
+ "stress_crash_with_txn": [CompilerErrorParser, DbCrashErrorParser],
+ "write_stress": [CompilerErrorParser, WriteStressErrorParser],
+ "asan": [CompilerErrorParser, GTestErrorParser, AsanErrorParser],
+ "asan_crash": [CompilerErrorParser, AsanErrorParser, DbCrashErrorParser],
+ "asan_crash_with_atomic_flush": [
+ CompilerErrorParser,
+ AsanErrorParser,
+ DbCrashErrorParser,
+ ],
+ "asan_crash_with_txn": [CompilerErrorParser, AsanErrorParser, DbCrashErrorParser],
+ "ubsan": [CompilerErrorParser, GTestErrorParser, UbsanErrorParser],
+ "ubsan_crash": [CompilerErrorParser, UbsanErrorParser, DbCrashErrorParser],
+ "ubsan_crash_with_atomic_flush": [
+ CompilerErrorParser,
+ UbsanErrorParser,
+ DbCrashErrorParser,
+ ],
+ "ubsan_crash_with_txn": [CompilerErrorParser, UbsanErrorParser, DbCrashErrorParser],
+ "valgrind": [CompilerErrorParser, GTestErrorParser, ValgrindErrorParser],
+ "tsan": [CompilerErrorParser, GTestErrorParser, TsanErrorParser],
+ "format_compatible": [CompilerErrorParser, CompatErrorParser],
+ "run_format_compatible": [CompilerErrorParser, CompatErrorParser],
+ "no_compression": [CompilerErrorParser, GTestErrorParser],
+ "run_no_compression": [CompilerErrorParser, GTestErrorParser],
+ "regression": [CompilerErrorParser],
+ "run_regression": [CompilerErrorParser],
}
def main():
if len(sys.argv) != 2:
- return 'Usage: %s <test name>' % sys.argv[0]
+ return "Usage: %s <test name>" % sys.argv[0]
test_name = sys.argv[1]
if test_name not in _TEST_NAME_TO_PARSERS:
- return 'Unknown test name: %s' % test_name
+ return "Unknown test name: %s" % test_name
error_parsers = []
for parser_cls in _TEST_NAME_TO_PARSERS[test_name]:
print(error_msg)
-if __name__ == '__main__':
+if __name__ == "__main__":
sys.exit(main())