1#!/usr/bin/env python2 2# 3# Copyright (C) 2014 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17from common.archs import archs_list 18from common.testing import ToUnicode 19from file_format.checker.parser import ParseCheckerStream 20from file_format.checker.struct import CheckerFile, TestCase, TestAssertion, TestExpression 21 22import io 23import unittest 24 25CheckerException = SystemExit 26 27class CheckerParser_PrefixTest(unittest.TestCase): 28 29 def tryParse(self, string): 30 checkerText = u"/// CHECK-START: pass\n" + ToUnicode(string) 31 return ParseCheckerStream("<test-file>", "CHECK", io.StringIO(checkerText)) 32 33 def assertParses(self, string): 34 checkFile = self.tryParse(string) 35 self.assertEqual(len(checkFile.testCases), 1) 36 self.assertNotEqual(len(checkFile.testCases[0].assertions), 0) 37 38 def assertIgnored(self, string): 39 checkFile = self.tryParse(string) 40 self.assertEqual(len(checkFile.testCases), 1) 41 self.assertEqual(len(checkFile.testCases[0].assertions), 0) 42 43 def assertInvalid(self, string): 44 with self.assertRaises(CheckerException): 45 self.tryParse(string) 46 47 def test_ValidFormat(self): 48 self.assertParses("///CHECK:foo") 49 self.assertParses("##CHECK:bar") 50 51 def test_InvalidFormat(self): 52 self.assertIgnored("CHECK") 53 self.assertIgnored(":CHECK") 54 self.assertIgnored("CHECK:") 55 self.assertIgnored("//CHECK") 56 self.assertIgnored("#CHECK") 57 self.assertInvalid("///CHECK") 58 self.assertInvalid("##CHECK") 59 60 def test_InvalidPrefix(self): 61 self.assertInvalid("///ACHECK:foo") 62 self.assertInvalid("##ACHECK:foo") 63 64 def test_NotFirstOnTheLine(self): 65 self.assertIgnored("A/// CHECK: foo") 66 self.assertIgnored("A # CHECK: foo") 67 self.assertInvalid("/// /// CHECK: foo") 68 self.assertInvalid("## ## CHECK: foo") 69 70 def test_WhitespaceAgnostic(self): 71 self.assertParses(" ///CHECK: foo") 72 self.assertParses("/// CHECK: foo") 73 self.assertParses(" ///CHECK: foo") 74 self.assertParses("/// CHECK: foo") 75 76class CheckerParser_TestExpressionTest(unittest.TestCase): 77 78 def parseAssertion(self, string, variant=""): 79 checkerText = (u"/// CHECK-START: pass\n" + 80 u"/// CHECK" + ToUnicode(variant) + u": " + ToUnicode(string)) 81 checkerFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(checkerText)) 82 self.assertEqual(len(checkerFile.testCases), 1) 83 testCase = checkerFile.testCases[0] 84 self.assertEqual(len(testCase.assertions), 1) 85 return testCase.assertions[0] 86 87 def parseExpression(self, string): 88 line = self.parseAssertion(string) 89 self.assertEqual(1, len(line.expressions)) 90 return line.expressions[0] 91 92 def assertEqualsRegex(self, string, expected): 93 self.assertEqual(expected, self.parseAssertion(string).toRegex()) 94 95 def assertEqualsText(self, string, text): 96 self.assertEqual(self.parseExpression(string), TestExpression.createPatternFromPlainText(text)) 97 98 def assertEqualsPattern(self, string, pattern): 99 self.assertEqual(self.parseExpression(string), TestExpression.createPattern(pattern)) 100 101 def assertEqualsVarRef(self, string, name): 102 self.assertEqual(self.parseExpression(string), TestExpression.createVariableReference(name)) 103 104 def assertEqualsVarDef(self, string, name, pattern): 105 self.assertEqual(self.parseExpression(string), 106 TestExpression.createVariableDefinition(name, pattern)) 107 108 def assertVariantNotEqual(self, string, variant): 109 self.assertNotEqual(variant, self.parseExpression(string).variant) 110 111 # Test that individual parts of the line are recognized 112 113 def test_TextOnly(self): 114 self.assertEqualsText("foo", "foo") 115 self.assertEqualsText(" foo ", "foo") 116 self.assertEqualsRegex("f$o^o", "(f\$o\^o)") 117 118 def test_PatternOnly(self): 119 self.assertEqualsPattern("{{a?b.c}}", "a?b.c") 120 121 def test_VarRefOnly(self): 122 self.assertEqualsVarRef("<<ABC>>", "ABC") 123 124 def test_VarDefOnly(self): 125 self.assertEqualsVarDef("<<ABC:a?b.c>>", "ABC", "a?b.c") 126 127 def test_TextWithWhitespace(self): 128 self.assertEqualsRegex("foo bar", "(foo), (bar)") 129 self.assertEqualsRegex("foo bar", "(foo), (bar)") 130 131 def test_TextWithRegex(self): 132 self.assertEqualsRegex("foo{{abc}}bar", "(foo)(abc)(bar)") 133 134 def test_TextWithVar(self): 135 self.assertEqualsRegex("foo<<ABC:abc>>bar", "(foo)(abc)(bar)") 136 137 def test_PlainWithRegexAndWhitespaces(self): 138 self.assertEqualsRegex("foo {{abc}}bar", "(foo), (abc)(bar)") 139 self.assertEqualsRegex("foo{{abc}} bar", "(foo)(abc), (bar)") 140 self.assertEqualsRegex("foo {{abc}} bar", "(foo), (abc), (bar)") 141 142 def test_PlainWithVarAndWhitespaces(self): 143 self.assertEqualsRegex("foo <<ABC:abc>>bar", "(foo), (abc)(bar)") 144 self.assertEqualsRegex("foo<<ABC:abc>> bar", "(foo)(abc), (bar)") 145 self.assertEqualsRegex("foo <<ABC:abc>> bar", "(foo), (abc), (bar)") 146 147 def test_AllKinds(self): 148 self.assertEqualsRegex("foo <<ABC:abc>>{{def}}bar", "(foo), (abc)(def)(bar)") 149 self.assertEqualsRegex("foo<<ABC:abc>> {{def}}bar", "(foo)(abc), (def)(bar)") 150 self.assertEqualsRegex("foo <<ABC:abc>> {{def}} bar", "(foo), (abc), (def), (bar)") 151 152 # # Test that variables and patterns are parsed correctly 153 154 def test_ValidPattern(self): 155 self.assertEqualsPattern("{{abc}}", "abc") 156 self.assertEqualsPattern("{{a[b]c}}", "a[b]c") 157 self.assertEqualsPattern("{{(a{bc})}}", "(a{bc})") 158 159 def test_ValidRef(self): 160 self.assertEqualsVarRef("<<ABC>>", "ABC") 161 self.assertEqualsVarRef("<<A1BC2>>", "A1BC2") 162 163 def test_ValidDef(self): 164 self.assertEqualsVarDef("<<ABC:abc>>", "ABC", "abc") 165 self.assertEqualsVarDef("<<ABC:ab:c>>", "ABC", "ab:c") 166 self.assertEqualsVarDef("<<ABC:a[b]c>>", "ABC", "a[b]c") 167 self.assertEqualsVarDef("<<ABC:(a[bc])>>", "ABC", "(a[bc])") 168 169 def test_Empty(self): 170 self.assertEqualsText("{{}}", "{{}}") 171 self.assertVariantNotEqual("<<>>", TestExpression.Variant.VarRef) 172 self.assertVariantNotEqual("<<:>>", TestExpression.Variant.VarDef) 173 174 def test_InvalidVarName(self): 175 self.assertVariantNotEqual("<<0ABC>>", TestExpression.Variant.VarRef) 176 self.assertVariantNotEqual("<<AB=C>>", TestExpression.Variant.VarRef) 177 self.assertVariantNotEqual("<<ABC=>>", TestExpression.Variant.VarRef) 178 self.assertVariantNotEqual("<<0ABC:abc>>", TestExpression.Variant.VarDef) 179 self.assertVariantNotEqual("<<AB=C:abc>>", TestExpression.Variant.VarDef) 180 self.assertVariantNotEqual("<<ABC=:abc>>", TestExpression.Variant.VarDef) 181 182 def test_BodyMatchNotGreedy(self): 183 self.assertEqualsRegex("{{abc}}{{def}}", "(abc)(def)") 184 self.assertEqualsRegex("<<ABC:abc>><<DEF:def>>", "(abc)(def)") 185 186 def test_NoVarDefsInNotChecks(self): 187 with self.assertRaises(CheckerException): 188 self.parseAssertion("<<ABC:abc>>", "-NOT") 189 190 191class CheckerParser_FileLayoutTest(unittest.TestCase): 192 193 # Creates an instance of CheckerFile from provided info. 194 # Data format: [ ( <case-name>, [ ( <text>, <assert-variant> ), ... ] ), ... ] 195 def createFile(self, caseList): 196 testFile = CheckerFile("<test_file>") 197 for caseEntry in caseList: 198 caseName = caseEntry[0] 199 testCase = TestCase(testFile, caseName, 0) 200 assertionList = caseEntry[1] 201 for assertionEntry in assertionList: 202 content = assertionEntry[0] 203 variant = assertionEntry[1] 204 assertion = TestAssertion(testCase, variant, content, 0) 205 assertion.addExpression(TestExpression.createPatternFromPlainText(content)) 206 return testFile 207 208 def assertParsesTo(self, checkerText, expectedData): 209 expectedFile = self.createFile(expectedData) 210 actualFile = self.parse(checkerText) 211 return self.assertEqual(expectedFile, actualFile) 212 213 def parse(self, checkerText): 214 return ParseCheckerStream("<test_file>", "CHECK", io.StringIO(ToUnicode(checkerText))) 215 216 def test_EmptyFile(self): 217 self.assertParsesTo("", []) 218 219 def test_SingleGroup(self): 220 self.assertParsesTo( 221 """ 222 /// CHECK-START: Example Group 223 /// CHECK: foo 224 /// CHECK: bar 225 """, 226 [ ( "Example Group", [ ("foo", TestAssertion.Variant.InOrder), 227 ("bar", TestAssertion.Variant.InOrder) ] ) ]) 228 229 def test_MultipleGroups(self): 230 self.assertParsesTo( 231 """ 232 /// CHECK-START: Example Group1 233 /// CHECK: foo 234 /// CHECK: bar 235 /// CHECK-START: Example Group2 236 /// CHECK: abc 237 /// CHECK: def 238 """, 239 [ ( "Example Group1", [ ("foo", TestAssertion.Variant.InOrder), 240 ("bar", TestAssertion.Variant.InOrder) ] ), 241 ( "Example Group2", [ ("abc", TestAssertion.Variant.InOrder), 242 ("def", TestAssertion.Variant.InOrder) ] ) ]) 243 244 def test_AssertionVariants(self): 245 self.assertParsesTo( 246 """ 247 /// CHECK-START: Example Group 248 /// CHECK: foo1 249 /// CHECK: foo2 250 /// CHECK-NEXT: foo3 251 /// CHECK-NEXT: foo4 252 /// CHECK-NOT: bar 253 /// CHECK-DAG: abc 254 /// CHECK-DAG: def 255 """, 256 [ ( "Example Group", [ ("foo1", TestAssertion.Variant.InOrder), 257 ("foo2", TestAssertion.Variant.InOrder), 258 ("foo3", TestAssertion.Variant.NextLine), 259 ("foo4", TestAssertion.Variant.NextLine), 260 ("bar", TestAssertion.Variant.Not), 261 ("abc", TestAssertion.Variant.DAG), 262 ("def", TestAssertion.Variant.DAG) ] ) ]) 263 264 def test_MisplacedNext(self): 265 with self.assertRaises(CheckerException): 266 self.parse( 267 """ 268 /// CHECK-START: Example Group 269 /// CHECK-DAG: foo 270 /// CHECK-NEXT: bar 271 """) 272 with self.assertRaises(CheckerException): 273 self.parse( 274 """ 275 /// CHECK-START: Example Group 276 /// CHECK-NOT: foo 277 /// CHECK-NEXT: bar 278 """) 279 with self.assertRaises(CheckerException): 280 self.parse( 281 """ 282 /// CHECK-START: Example Group 283 /// CHECK-EVAL: foo 284 /// CHECK-NEXT: bar 285 """) 286 with self.assertRaises(CheckerException): 287 self.parse( 288 """ 289 /// CHECK-START: Example Group 290 /// CHECK-NEXT: bar 291 """) 292 293class CheckerParser_SuffixTests(unittest.TestCase): 294 295 noarch_block = """ 296 /// CHECK-START: Group 297 /// CHECK: foo 298 /// CHECK-NEXT: bar 299 /// CHECK-NOT: baz 300 /// CHECK-DAG: yoyo 301 """ 302 303 arch_block = """ 304 /// CHECK-START-{test_arch}: Group 305 /// CHECK: foo 306 /// CHECK-NEXT: bar 307 /// CHECK-NOT: baz 308 /// CHECK-DAG: yoyo 309 """ 310 311 def parse(self, checkerText): 312 return ParseCheckerStream("<test_file>", "CHECK", io.StringIO(ToUnicode(checkerText))) 313 314 def test_NonArchTests(self): 315 for arch in [None] + archs_list: 316 checkerFile = self.parse(self.noarch_block) 317 self.assertEqual(len(checkerFile.testCases), 1) 318 self.assertEqual(len(checkerFile.testCases[0].assertions), 4) 319 320 def test_IgnoreNonTargetArch(self): 321 for targetArch in archs_list: 322 for testArch in [a for a in archs_list if a != targetArch]: 323 checkerText = self.arch_block.format(test_arch = testArch) 324 checkerFile = self.parse(checkerText) 325 self.assertEqual(len(checkerFile.testCases), 1) 326 self.assertEqual(len(checkerFile.testCasesForArch(testArch)), 1) 327 self.assertEqual(len(checkerFile.testCasesForArch(targetArch)), 0) 328 329 def test_Arch(self): 330 for arch in archs_list: 331 checkerText = self.arch_block.format(test_arch = arch) 332 checkerFile = self.parse(checkerText) 333 self.assertEqual(len(checkerFile.testCases), 1) 334 self.assertEqual(len(checkerFile.testCasesForArch(arch)), 1) 335 self.assertEqual(len(checkerFile.testCases[0].assertions), 4) 336 337 def test_NoDebugAndArch(self): 338 testCase = self.parse(""" 339 /// CHECK-START: Group 340 /// CHECK: foo 341 """).testCases[0] 342 self.assertFalse(testCase.forDebuggable) 343 self.assertEqual(testCase.testArch, None) 344 345 def test_SetDebugNoArch(self): 346 testCase = self.parse(""" 347 /// CHECK-START-DEBUGGABLE: Group 348 /// CHECK: foo 349 """).testCases[0] 350 self.assertTrue(testCase.forDebuggable) 351 self.assertEqual(testCase.testArch, None) 352 353 def test_NoDebugSetArch(self): 354 testCase = self.parse(""" 355 /// CHECK-START-ARM: Group 356 /// CHECK: foo 357 """).testCases[0] 358 self.assertFalse(testCase.forDebuggable) 359 self.assertEqual(testCase.testArch, "ARM") 360 361 def test_SetDebugAndArch(self): 362 testCase = self.parse(""" 363 /// CHECK-START-ARM-DEBUGGABLE: Group 364 /// CHECK: foo 365 """).testCases[0] 366 self.assertTrue(testCase.forDebuggable) 367 self.assertEqual(testCase.testArch, "ARM") 368 369class CheckerParser_EvalTests(unittest.TestCase): 370 def parseTestCase(self, string): 371 checkerText = u"/// CHECK-START: pass\n" + ToUnicode(string) 372 checkerFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(checkerText)) 373 self.assertEqual(len(checkerFile.testCases), 1) 374 return checkerFile.testCases[0] 375 376 def parseExpressions(self, string): 377 testCase = self.parseTestCase("/// CHECK-EVAL: " + string) 378 self.assertEqual(len(testCase.assertions), 1) 379 assertion = testCase.assertions[0] 380 self.assertEqual(assertion.variant, TestAssertion.Variant.Eval) 381 self.assertEqual(assertion.originalText, string) 382 return assertion.expressions 383 384 def assertParsesToPlainText(self, text): 385 testCase = self.parseTestCase("/// CHECK-EVAL: " + text) 386 self.assertEqual(len(testCase.assertions), 1) 387 assertion = testCase.assertions[0] 388 self.assertEqual(assertion.variant, TestAssertion.Variant.Eval) 389 self.assertEqual(assertion.originalText, text) 390 self.assertEqual(len(assertion.expressions), 1) 391 expression = assertion.expressions[0] 392 self.assertEqual(expression.variant, TestExpression.Variant.PlainText) 393 self.assertEqual(expression.text, text) 394 395 def test_PlainText(self): 396 self.assertParsesToPlainText("XYZ") 397 self.assertParsesToPlainText("True") 398 self.assertParsesToPlainText("{{abc}}") 399 self.assertParsesToPlainText("<<ABC:abc>>") 400 self.assertParsesToPlainText("<<ABC=>>") 401 402 def test_VariableReference(self): 403 self.assertEqual(self.parseExpressions("<<ABC>>"), 404 [ TestExpression.createVariableReference("ABC") ]) 405 self.assertEqual(self.parseExpressions("123<<ABC>>"), 406 [ TestExpression.createPlainText("123"), 407 TestExpression.createVariableReference("ABC") ]) 408 self.assertEqual(self.parseExpressions("123 <<ABC>>"), 409 [ TestExpression.createPlainText("123 "), 410 TestExpression.createVariableReference("ABC") ]) 411 self.assertEqual(self.parseExpressions("<<ABC>>XYZ"), 412 [ TestExpression.createVariableReference("ABC"), 413 TestExpression.createPlainText("XYZ") ]) 414 self.assertEqual(self.parseExpressions("<<ABC>> XYZ"), 415 [ TestExpression.createVariableReference("ABC"), 416 TestExpression.createPlainText(" XYZ") ]) 417 self.assertEqual(self.parseExpressions("123<<ABC>>XYZ"), 418 [ TestExpression.createPlainText("123"), 419 TestExpression.createVariableReference("ABC"), 420 TestExpression.createPlainText("XYZ") ]) 421 self.assertEqual(self.parseExpressions("123 <<ABC>> XYZ"), 422 [ TestExpression.createPlainText("123 "), 423 TestExpression.createVariableReference("ABC"), 424 TestExpression.createPlainText(" XYZ") ]) 425