Now prints the offending Checker line and variable values.
Change-Id: Id4395083de6ddddbd69f66cb7ba38c943146799a
# limitations under the License.
from __future__ import print_function
+import collections
import sys
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):
return '\033[95m'
elif color == Logger.Color.Red:
return '\033[91m'
+ elif color == Logger.Color.Green:
+ return '\033[32m'
else:
return '\033[0m'
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):
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)
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
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.
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.
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)
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.