12c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil# Copyright (C) 2014 The Android Open Source Project 22c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil# 32c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil# Licensed under the Apache License, Version 2.0 (the "License"); 42c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil# you may not use this file except in compliance with the License. 52c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil# You may obtain a copy of the License at 62c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil# 72c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil# http://www.apache.org/licenses/LICENSE-2.0 82c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil# 92c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil# Unless required by applicable law or agreed to in writing, software 102c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil# distributed under the License is distributed on an "AS IS" BASIS, 112c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 122c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil# See the License for the specific language governing permissions and 132c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil# limitations under the License. 142c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 152c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdilfrom common.logger import Logger 162c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdilfrom common.mixins import EqualityMixin, PrintableMixin 172c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 182c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdilimport re 192c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 202c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdilclass CheckerFile(PrintableMixin): 212c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 222c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def __init__(self, fileName): 232c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.fileName = fileName 242c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.testCases = [] 252c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 262c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def addTestCase(self, new_test_case): 272c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.testCases.append(new_test_case) 282c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 295e2c8d323fbab4db8a71041ff94b6baf3953bca9Alexandre Rames def testCasesForArch(self, targetArch): 305e2c8d323fbab4db8a71041ff94b6baf3953bca9Alexandre Rames return [t for t in self.testCases if t.testArch == targetArch] 315e2c8d323fbab4db8a71041ff94b6baf3953bca9Alexandre Rames 322c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def __eq__(self, other): 332c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return isinstance(other, self.__class__) \ 342c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil and self.testCases == other.testCases 352c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 362c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 372c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdilclass TestCase(PrintableMixin): 382c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 395cc343d7239f9b1faf3ddf592cd5172a1371d276David Brazdil def __init__(self, parent, name, startLineNo, testArch = None, forDebuggable = False): 402c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil assert isinstance(parent, CheckerFile) 412c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 422c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.parent = parent 432c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.name = name 442c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.assertions = [] 452c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.startLineNo = startLineNo 465e2c8d323fbab4db8a71041ff94b6baf3953bca9Alexandre Rames self.testArch = testArch 475cc343d7239f9b1faf3ddf592cd5172a1371d276David Brazdil self.forDebuggable = forDebuggable 482c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 492c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil if not self.name: 50711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil Logger.fail("Test case does not have a name", self.fileName, self.startLineNo) 512c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 522c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.parent.addTestCase(self) 532c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 542c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil @property 552c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def fileName(self): 562c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return self.parent.fileName 572c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 582c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def addAssertion(self, new_assertion): 59711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil if new_assertion.variant == TestAssertion.Variant.NextLine: 60711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil if not self.assertions or \ 61711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil (self.assertions[-1].variant != TestAssertion.Variant.InOrder and \ 62711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil self.assertions[-1].variant != TestAssertion.Variant.NextLine): 63711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil Logger.fail("A next-line assertion can only be placed after an " 64711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil "in-order assertion or another next-line assertion.", 65711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil new_assertion.fileName, new_assertion.lineNo) 662c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.assertions.append(new_assertion) 672c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 682c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def __eq__(self, other): 692c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return isinstance(other, self.__class__) \ 702c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil and self.name == other.name \ 712c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil and self.assertions == other.assertions 722c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 732c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 742c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdilclass TestAssertion(PrintableMixin): 752c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 762c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil class Variant(object): 772c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil """Supported types of assertions.""" 78b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil InOrder, NextLine, DAG, Not, Eval = range(5) 792c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 802c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def __init__(self, parent, variant, originalText, lineNo): 812c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil assert isinstance(parent, TestCase) 822c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 832c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.parent = parent 842c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.variant = variant 852c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.expressions = [] 862c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.lineNo = lineNo 872c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.originalText = originalText 882c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 892c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.parent.addAssertion(self) 902c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 912c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil @property 922c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def fileName(self): 932c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return self.parent.fileName 942c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 952c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def addExpression(self, new_expression): 96b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil assert isinstance(new_expression, TestExpression) 972c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil if self.variant == TestAssertion.Variant.Not: 98b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil if new_expression.variant == TestExpression.Variant.VarDef: 992c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil Logger.fail("CHECK-NOT lines cannot define variables", self.fileName, self.lineNo) 1002c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.expressions.append(new_expression) 1012c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1022c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def toRegex(self): 1032c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil """ Returns a regex pattern for this entire assertion. Only used in tests. """ 1042c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil regex = "" 1052c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil for expression in self.expressions: 106b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil if expression.variant == TestExpression.Variant.Separator: 1072c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil regex = regex + ", " 1082c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil else: 109b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil regex = regex + "(" + expression.text + ")" 1102c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return regex 1112c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1122c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def __eq__(self, other): 1132c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return isinstance(other, self.__class__) \ 1142c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil and self.variant == other.variant \ 1152c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil and self.expressions == other.expressions 1162c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1172c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 118b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdilclass TestExpression(EqualityMixin, PrintableMixin): 1192c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1202c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil class Variant(object): 1212c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil """Supported language constructs.""" 122b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil PlainText, Pattern, VarRef, VarDef, Separator = range(5) 1232c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1242c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil class Regex(object): 1252c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil rName = r"([a-zA-Z][a-zA-Z0-9]*)" 1262c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil rRegex = r"(.+?)" 1272c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil rPatternStartSym = r"(\{\{)" 1282c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil rPatternEndSym = r"(\}\})" 129c2c48ffdd623b4e58b34115d1521b0988a42b217David Brazdil rVariableStartSym = r"(<<)" 130c2c48ffdd623b4e58b34115d1521b0988a42b217David Brazdil rVariableEndSym = r"(>>)" 1312c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil rVariableSeparator = r"(:)" 1328ff495e15074d621371b4e9d46ba399563315819David Brazdil rVariableDefinitionBody = rName + rVariableSeparator + rRegex 1332c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1342c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil regexPattern = rPatternStartSym + rRegex + rPatternEndSym 1352c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil regexVariableReference = rVariableStartSym + rName + rVariableEndSym 1368ff495e15074d621371b4e9d46ba399563315819David Brazdil regexVariableDefinition = rVariableStartSym + rVariableDefinitionBody + rVariableEndSym 1372c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 138b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil def __init__(self, variant, name, text): 1392c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.variant = variant 1402c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.name = name 141b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil self.text = text 1422c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1432c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def __eq__(self, other): 1442c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return isinstance(other, self.__class__) \ 1452c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil and self.variant == other.variant \ 1462c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil and self.name == other.name \ 147b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil and self.text == other.text 1482c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1492c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil @staticmethod 1502c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def createSeparator(): 151b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil return TestExpression(TestExpression.Variant.Separator, None, None) 1522c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1532c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil @staticmethod 154b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil def createPlainText(text): 155b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil return TestExpression(TestExpression.Variant.PlainText, None, text) 156b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil 157b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil @staticmethod 158b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil def createPatternFromPlainText(text): 159b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil return TestExpression(TestExpression.Variant.Pattern, None, re.escape(text)) 1602c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1612c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil @staticmethod 1622c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def createPattern(pattern): 163b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil return TestExpression(TestExpression.Variant.Pattern, None, pattern) 1642c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1652c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil @staticmethod 1662c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def createVariableReference(name): 167b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil assert re.match(TestExpression.Regex.rName, name) 168b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil return TestExpression(TestExpression.Variant.VarRef, name, None) 1692c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1702c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil @staticmethod 1712c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def createVariableDefinition(name, pattern): 172b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil assert re.match(TestExpression.Regex.rName, name) 173b34c35ee8fe1516118d1d172a5e05b263ccbd93dDavid Brazdil return TestExpression(TestExpression.Variant.VarDef, name, pattern) 174