From: David Brazdil Date: Wed, 2 Mar 2016 16:09:46 +0000 (+0000) Subject: Improve Checker error messages X-Git-Tag: android-x86-7.1-r1~340^2~3^2^2~16^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=0f73bda41a849734587a8df6428402beb65c2bc0;p=android-x86%2Fart.git Improve Checker error messages Now prints the offending Checker line and variable values. Change-Id: Id4395083de6ddddbd69f66cb7ba38c943146799a --- diff --git a/tools/checker/common/logger.py b/tools/checker/common/logger.py index 28bb458da..f13eaf614 100644 --- a/tools/checker/common/logger.py +++ b/tools/checker/common/logger.py @@ -13,6 +13,7 @@ # limitations under the License. from __future__ import print_function +import collections import sys class Logger(object): @@ -21,7 +22,7 @@ class Logger(object): NoOutput, Error, Info = range(3) class Color(object): - Default, Blue, Gray, Purple, Red = range(5) + Default, Blue, Gray, Purple, Red, Green = range(6) @staticmethod def terminalCode(color, out=sys.stdout): @@ -35,6 +36,8 @@ class Logger(object): return '\033[95m' elif color == Logger.Color.Red: return '\033[91m' + elif color == Logger.Color.Green: + return '\033[32m' else: return '\033[0m' @@ -52,19 +55,34 @@ class Logger(object): out.flush() @staticmethod - def fail(msg, file=None, line=-1): - location = "" - if file: - location += file + ":" - if line > 0: - location += str(line) + ":" - if location: - location += " " - - Logger.log(location, Logger.Level.Error, color=Logger.Color.Gray, newLine=False, out=sys.stderr) + def fail(msg, file=None, line=-1, lineText=None, variables=None): Logger.log("error: ", Logger.Level.Error, color=Logger.Color.Red, newLine=False, out=sys.stderr) Logger.log(msg, Logger.Level.Error, out=sys.stderr) - sys.exit(msg) + + if lineText: + loc = "" + if file: + loc += file + ":" + if line > 0: + loc += str(line) + ":" + if loc: + loc += " " + Logger.log(loc, Logger.Level.Error, color=Logger.Color.Gray, newLine=False, out=sys.stderr) + Logger.log(lineText, Logger.Level.Error, out=sys.stderr) + + if variables: + longestName = 0 + for var in variables: + longestName = max(longestName, len(var)) + + for var in collections.OrderedDict(sorted(variables.items())): + padding = ' ' * (longestName - len(var)) + Logger.log(var, Logger.Level.Error, color=Logger.Color.Green, newLine=False, out=sys.stderr) + Logger.log(padding, Logger.Level.Error, newLine=False, out=sys.stderr) + Logger.log(" = ", Logger.Level.Error, newLine=False, out=sys.stderr) + Logger.log(variables[var], Logger.Level.Error, out=sys.stderr) + + sys.exit(1) @staticmethod def startTest(name): @@ -76,6 +94,6 @@ class Logger(object): Logger.log("PASS", color=Logger.Color.Blue) @staticmethod - def testFailed(msg, file=None, line=-1): + def testFailed(msg, assertion, variables): Logger.log("FAIL", color=Logger.Color.Red) - Logger.fail(msg, file, line) + Logger.fail(msg, assertion.fileName, assertion.lineNo, assertion.originalText, variables) diff --git a/tools/checker/match/file.py b/tools/checker/match/file.py index 3ded07482..6ff19d519 100644 --- a/tools/checker/match/file.py +++ b/tools/checker/match/file.py @@ -23,9 +23,10 @@ MatchScope = namedtuple("MatchScope", ["start", "end"]) MatchInfo = namedtuple("MatchInfo", ["scope", "variables"]) class MatchFailedException(Exception): - def __init__(self, assertion, lineNo): + def __init__(self, assertion, lineNo, variables): self.assertion = assertion self.lineNo = lineNo + self.variables = variables def splitIntoGroups(assertions): """ Breaks up a list of assertions, grouping instructions which should be @@ -58,7 +59,7 @@ def findMatchingLine(assertion, c1Pass, scope, variables, excludeLines=[]): newVariables = MatchLines(assertion, c1Pass.body[i], variables) if newVariables is not None: return MatchInfo(MatchScope(i, i), newVariables) - raise MatchFailedException(assertion, scope.start) + raise MatchFailedException(assertion, scope.start, variables) def matchDagGroup(assertions, c1Pass, scope, variables): """ Attempts to find matching `c1Pass` lines for a group of DAG assertions. @@ -92,12 +93,12 @@ def testNotGroup(assertions, c1Pass, scope, variables): for assertion in assertions: assert assertion.variant == TestAssertion.Variant.Not if MatchLines(assertion, line, variables) is not None: - raise MatchFailedException(assertion, i) + raise MatchFailedException(assertion, i, variables) def testEvalGroup(assertions, scope, variables): for assertion in assertions: if not EvaluateLine(assertion, variables): - raise MatchFailedException(assertion, scope.start) + raise MatchFailedException(assertion, scope.start, variables) def MatchTestCase(testCase, c1Pass): """ Runs a test case against a C1visualizer graph dump. @@ -181,8 +182,8 @@ def MatchFiles(checkerFile, c1File, targetArch, debuggableMode): except MatchFailedException as e: lineNo = c1Pass.startLineNo + e.lineNo if e.assertion.variant == TestAssertion.Variant.Not: - Logger.testFailed("NOT assertion matched line {}".format(lineNo), - e.assertion.fileName, e.assertion.lineNo) + msg = "NOT assertion matched line {}" else: - Logger.testFailed("Assertion could not be matched starting from line {}".format(lineNo), - e.assertion.fileName, e.assertion.lineNo) + msg = "Assertion could not be matched starting from line {}" + msg = msg.format(lineNo) + Logger.testFailed(msg, e.assertion, e.variables) diff --git a/tools/checker/match/line.py b/tools/checker/match/line.py index 08f001f66..ed48a5329 100644 --- a/tools/checker/match/line.py +++ b/tools/checker/match/line.py @@ -35,15 +35,13 @@ def getVariable(name, variables, pos): if name in variables: return variables[name] else: - Logger.testFailed("Missing definition of variable \"{}\"".format(name), - pos.fileName, pos.lineNo) + Logger.testFailed("Missing definition of variable \"{}\"".format(name), pos, variables) def setVariable(name, value, variables, pos): if name not in variables: return variables.copyWith(name, value) else: - Logger.testFailed("Multiple definitions of variable \"{}\"".format(name), - pos.fileName, pos.lineNo) + Logger.testFailed("Multiple definitions of variable \"{}\"".format(name), pos, variables) def matchWords(checkerWord, stringWord, variables, pos): """ Attempts to match a list of TestExpressions against a string.