struct.py revision 5e2c8d323fbab4db8a71041ff94b6baf3953bca9
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 395e2c8d323fbab4db8a71041ff94b6baf3953bca9Alexandre Rames def __init__(self, parent, name, startLineNo, testArch = None): 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 472c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 482c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil if not self.name: 49711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil Logger.fail("Test case does not have a name", self.fileName, self.startLineNo) 502c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 512c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.parent.addTestCase(self) 522c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 532c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil @property 542c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def fileName(self): 552c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return self.parent.fileName 562c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 572c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def addAssertion(self, new_assertion): 58711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil if new_assertion.variant == TestAssertion.Variant.NextLine: 59711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil if not self.assertions or \ 60711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil (self.assertions[-1].variant != TestAssertion.Variant.InOrder and \ 61711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil self.assertions[-1].variant != TestAssertion.Variant.NextLine): 62711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil Logger.fail("A next-line assertion can only be placed after an " 63711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil "in-order assertion or another next-line assertion.", 64711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil new_assertion.fileName, new_assertion.lineNo) 652c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.assertions.append(new_assertion) 662c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 672c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def __eq__(self, other): 682c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return isinstance(other, self.__class__) \ 692c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil and self.name == other.name \ 702c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil and self.assertions == other.assertions 712c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 722c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 732c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdilclass TestAssertion(PrintableMixin): 742c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 752c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil class Variant(object): 762c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil """Supported types of assertions.""" 77711411957a433555eda4bcf8d1f05aabf04425e8David Brazdil InOrder, NextLine, DAG, Not = range(4) 782c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 792c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def __init__(self, parent, variant, originalText, lineNo): 802c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil assert isinstance(parent, TestCase) 812c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 822c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.parent = parent 832c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.variant = variant 842c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.expressions = [] 852c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.lineNo = lineNo 862c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.originalText = originalText 872c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 882c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.parent.addAssertion(self) 892c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 902c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil @property 912c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def fileName(self): 922c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return self.parent.fileName 932c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 942c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def addExpression(self, new_expression): 952c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil assert isinstance(new_expression, RegexExpression) 962c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil if self.variant == TestAssertion.Variant.Not: 972c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil if new_expression.variant == RegexExpression.Variant.VarDef: 982c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil Logger.fail("CHECK-NOT lines cannot define variables", self.fileName, self.lineNo) 992c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.expressions.append(new_expression) 1002c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1012c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def toRegex(self): 1022c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil """ Returns a regex pattern for this entire assertion. Only used in tests. """ 1032c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil regex = "" 1042c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil for expression in self.expressions: 1052c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil if expression.variant == RegexExpression.Variant.Separator: 1062c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil regex = regex + ", " 1072c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil else: 1082c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil regex = regex + "(" + expression.pattern + ")" 1092c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return regex 1102c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1112c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def __eq__(self, other): 1122c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return isinstance(other, self.__class__) \ 1132c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil and self.variant == other.variant \ 1142c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil and self.expressions == other.expressions 1152c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1162c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1172c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdilclass RegexExpression(EqualityMixin, PrintableMixin): 1182c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1192c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil class Variant(object): 1202c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil """Supported language constructs.""" 1212c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil Text, Pattern, VarRef, VarDef, Separator = range(5) 1222c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1232c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil class Regex(object): 1242c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil rName = r"([a-zA-Z][a-zA-Z0-9]*)" 1252c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil rRegex = r"(.+?)" 1262c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil rPatternStartSym = r"(\{\{)" 1272c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil rPatternEndSym = r"(\}\})" 128c2c48ffdd623b4e58b34115d1521b0988a42b217David Brazdil rVariableStartSym = r"(<<)" 129c2c48ffdd623b4e58b34115d1521b0988a42b217David Brazdil rVariableEndSym = r"(>>)" 1302c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil rVariableSeparator = r"(:)" 1312c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1322c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil regexPattern = rPatternStartSym + rRegex + rPatternEndSym 1332c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil regexVariableReference = rVariableStartSym + rName + rVariableEndSym 1342c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil regexVariableDefinition = rVariableStartSym + rName + rVariableSeparator + rRegex + rVariableEndSym 1352c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1362c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def __init__(self, variant, name, pattern): 1372c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.variant = variant 1382c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.name = name 1392c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil self.pattern = pattern 1402c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1412c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def __eq__(self, other): 1422c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return isinstance(other, self.__class__) \ 1432c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil and self.variant == other.variant \ 1442c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil and self.name == other.name \ 1452c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil and self.pattern == other.pattern 1462c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1472c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil @staticmethod 1482c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def createSeparator(): 1492c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return RegexExpression(RegexExpression.Variant.Separator, None, None) 1502c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1512c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil @staticmethod 1522c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def createText(text): 1532c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return RegexExpression(RegexExpression.Variant.Text, None, re.escape(text)) 1542c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1552c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil @staticmethod 1562c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def createPattern(pattern): 1572c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return RegexExpression(RegexExpression.Variant.Pattern, None, pattern) 1582c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1592c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil @staticmethod 1602c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def createVariableReference(name): 1612c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil assert re.match(RegexExpression.Regex.rName, name) 1622c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return RegexExpression(RegexExpression.Variant.VarRef, name, None) 1632c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil 1642c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil @staticmethod 1652c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil def createVariableDefinition(name, pattern): 1662c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil assert re.match(RegexExpression.Regex.rName, name) 1672c27f2ccf316aebf96cf365d33d2834a8206444dDavid Brazdil return RegexExpression(RegexExpression.Variant.VarDef, name, pattern) 168