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, TestStatement, 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].statements), 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].statements), 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 parseStatement(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.statements), 1) 85 return testCase.statements[0] 86 87 def parseExpression(self, string): 88 line = self.parseStatement(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.parseStatement(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.parseStatement("<<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 statementList = caseEntry[1] 201 for statementEntry in statementList: 202 content = statementEntry[0] 203 variant = statementEntry[1] 204 statement = TestStatement(testCase, variant, content, 0) 205 if statement.isEvalContentStatement(): 206 statement.addExpression(TestExpression.createPlainText(content)) 207 elif statement.isPatternMatchContentStatement(): 208 statement.addExpression(TestExpression.createPatternFromPlainText(content)) 209 return testFile 210 211 def assertParsesTo(self, checkerText, expectedData): 212 expectedFile = self.createFile(expectedData) 213 actualFile = self.parse(checkerText) 214 return self.assertEqual(expectedFile, actualFile) 215 216 def parse(self, checkerText): 217 return ParseCheckerStream("<test_file>", "CHECK", io.StringIO(ToUnicode(checkerText))) 218 219 def test_EmptyFile(self): 220 self.assertParsesTo("", []) 221 222 def test_SingleGroup(self): 223 self.assertParsesTo( 224 """ 225 /// CHECK-START: Example Group 226 /// CHECK: foo 227 /// CHECK: bar 228 """, 229 [ ( "Example Group", [ ("foo", TestStatement.Variant.InOrder), 230 ("bar", TestStatement.Variant.InOrder) ] ) ]) 231 232 def test_MultipleGroups(self): 233 self.assertParsesTo( 234 """ 235 /// CHECK-START: Example Group1 236 /// CHECK: foo 237 /// CHECK: bar 238 /// CHECK-START: Example Group2 239 /// CHECK: abc 240 /// CHECK: def 241 """, 242 [ ( "Example Group1", [ ("foo", TestStatement.Variant.InOrder), 243 ("bar", TestStatement.Variant.InOrder) ] ), 244 ( "Example Group2", [ ("abc", TestStatement.Variant.InOrder), 245 ("def", TestStatement.Variant.InOrder) ] ) ]) 246 247 def test_StatementVariants(self): 248 self.assertParsesTo( 249 """ 250 /// CHECK-START: Example Group 251 /// CHECK: foo1 252 /// CHECK: foo2 253 /// CHECK-NEXT: foo3 254 /// CHECK-NEXT: foo4 255 /// CHECK-NOT: bar 256 /// CHECK-DAG: abc 257 /// CHECK-DAG: def 258 /// CHECK-EVAL: x > y 259 /// CHECK-IF: x < y 260 /// CHECK-ELIF: x == y 261 /// CHECK-ELSE: 262 /// CHECK-FI: 263 """, 264 [ ( "Example Group", [ ("foo1", TestStatement.Variant.InOrder), 265 ("foo2", TestStatement.Variant.InOrder), 266 ("foo3", TestStatement.Variant.NextLine), 267 ("foo4", TestStatement.Variant.NextLine), 268 ("bar", TestStatement.Variant.Not), 269 ("abc", TestStatement.Variant.DAG), 270 ("def", TestStatement.Variant.DAG), 271 ("x > y", TestStatement.Variant.Eval), 272 ("x < y", TestStatement.Variant.If), 273 ("x == y", TestStatement.Variant.Elif), 274 (None, TestStatement.Variant.Else), 275 (None, TestStatement.Variant.Fi) ] ) ]) 276 277 def test_NoContentStatements(self): 278 with self.assertRaises(CheckerException): 279 self.parse( 280 """ 281 /// CHECK-START: Example Group 282 /// CHECK-ELSE: foo 283 """) 284 with self.assertRaises(CheckerException): 285 self.parse( 286 """ 287 /// CHECK-START: Example Group 288 /// CHECK-FI: foo 289 """) 290 291class CheckerParser_SuffixTests(unittest.TestCase): 292 293 noarch_block = """ 294 /// CHECK-START: Group 295 /// CHECK: foo 296 /// CHECK-NEXT: bar 297 /// CHECK-NOT: baz 298 /// CHECK-DAG: yoyo 299 /// CHECK-EVAL: x > y 300 /// CHECK-IF: x < y 301 /// CHECK-ELIF: x == y 302 /// CHECK-ELSE: 303 /// CHECK-FI: 304 """ 305 306 arch_block = """ 307 /// CHECK-START-{test_arch}: Group 308 /// CHECK: foo 309 /// CHECK-NEXT: bar 310 /// CHECK-NOT: baz 311 /// CHECK-DAG: yoyo 312 /// CHECK-EVAL: x > y 313 /// CHECK-IF: x < y 314 /// CHECK-ELIF: x == y 315 /// CHECK-ELSE: 316 /// CHECK-FI: 317 """ 318 319 def parse(self, checkerText): 320 return ParseCheckerStream("<test_file>", "CHECK", io.StringIO(ToUnicode(checkerText))) 321 322 def test_NonArchTests(self): 323 for arch in [None] + archs_list: 324 checkerFile = self.parse(self.noarch_block) 325 self.assertEqual(len(checkerFile.testCases), 1) 326 self.assertEqual(len(checkerFile.testCases[0].statements), 9) 327 328 def test_IgnoreNonTargetArch(self): 329 for targetArch in archs_list: 330 for testArch in [a for a in archs_list if a != targetArch]: 331 checkerText = self.arch_block.format(test_arch = testArch) 332 checkerFile = self.parse(checkerText) 333 self.assertEqual(len(checkerFile.testCases), 1) 334 self.assertEqual(len(checkerFile.testCasesForArch(testArch)), 1) 335 self.assertEqual(len(checkerFile.testCasesForArch(targetArch)), 0) 336 337 def test_Arch(self): 338 for arch in archs_list: 339 checkerText = self.arch_block.format(test_arch = arch) 340 checkerFile = self.parse(checkerText) 341 self.assertEqual(len(checkerFile.testCases), 1) 342 self.assertEqual(len(checkerFile.testCasesForArch(arch)), 1) 343 self.assertEqual(len(checkerFile.testCases[0].statements), 9) 344 345 def test_NoDebugAndArch(self): 346 testCase = self.parse(""" 347 /// CHECK-START: Group 348 /// CHECK: foo 349 """).testCases[0] 350 self.assertFalse(testCase.forDebuggable) 351 self.assertEqual(testCase.testArch, None) 352 353 def test_SetDebugNoArch(self): 354 testCase = self.parse(""" 355 /// CHECK-START-DEBUGGABLE: Group 356 /// CHECK: foo 357 """).testCases[0] 358 self.assertTrue(testCase.forDebuggable) 359 self.assertEqual(testCase.testArch, None) 360 361 def test_NoDebugSetArch(self): 362 testCase = self.parse(""" 363 /// CHECK-START-ARM: Group 364 /// CHECK: foo 365 """).testCases[0] 366 self.assertFalse(testCase.forDebuggable) 367 self.assertEqual(testCase.testArch, "ARM") 368 369 def test_SetDebugAndArch(self): 370 testCase = self.parse(""" 371 /// CHECK-START-ARM-DEBUGGABLE: Group 372 /// CHECK: foo 373 """).testCases[0] 374 self.assertTrue(testCase.forDebuggable) 375 self.assertEqual(testCase.testArch, "ARM") 376 377class CheckerParser_EvalTests(unittest.TestCase): 378 def parseTestCase(self, string): 379 checkerText = u"/// CHECK-START: pass\n" + ToUnicode(string) 380 checkerFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(checkerText)) 381 self.assertEqual(len(checkerFile.testCases), 1) 382 return checkerFile.testCases[0] 383 384 def parseExpressions(self, string): 385 testCase = self.parseTestCase("/// CHECK-EVAL: " + string) 386 self.assertEqual(len(testCase.statements), 1) 387 statement = testCase.statements[0] 388 self.assertEqual(statement.variant, TestStatement.Variant.Eval) 389 self.assertEqual(statement.originalText, string) 390 return statement.expressions 391 392 def assertParsesToPlainText(self, text): 393 testCase = self.parseTestCase("/// CHECK-EVAL: " + text) 394 self.assertEqual(len(testCase.statements), 1) 395 statement = testCase.statements[0] 396 self.assertEqual(statement.variant, TestStatement.Variant.Eval) 397 self.assertEqual(statement.originalText, text) 398 self.assertEqual(len(statement.expressions), 1) 399 expression = statement.expressions[0] 400 self.assertEqual(expression.variant, TestExpression.Variant.PlainText) 401 self.assertEqual(expression.text, text) 402 403 def test_PlainText(self): 404 self.assertParsesToPlainText("XYZ") 405 self.assertParsesToPlainText("True") 406 self.assertParsesToPlainText("{{abc}}") 407 self.assertParsesToPlainText("<<ABC:abc>>") 408 self.assertParsesToPlainText("<<ABC=>>") 409 410 def test_VariableReference(self): 411 self.assertEqual(self.parseExpressions("<<ABC>>"), 412 [ TestExpression.createVariableReference("ABC") ]) 413 self.assertEqual(self.parseExpressions("123<<ABC>>"), 414 [ TestExpression.createPlainText("123"), 415 TestExpression.createVariableReference("ABC") ]) 416 self.assertEqual(self.parseExpressions("123 <<ABC>>"), 417 [ TestExpression.createPlainText("123 "), 418 TestExpression.createVariableReference("ABC") ]) 419 self.assertEqual(self.parseExpressions("<<ABC>>XYZ"), 420 [ TestExpression.createVariableReference("ABC"), 421 TestExpression.createPlainText("XYZ") ]) 422 self.assertEqual(self.parseExpressions("<<ABC>> XYZ"), 423 [ TestExpression.createVariableReference("ABC"), 424 TestExpression.createPlainText(" XYZ") ]) 425 self.assertEqual(self.parseExpressions("123<<ABC>>XYZ"), 426 [ TestExpression.createPlainText("123"), 427 TestExpression.createVariableReference("ABC"), 428 TestExpression.createPlainText("XYZ") ]) 429 self.assertEqual(self.parseExpressions("123 <<ABC>> XYZ"), 430 [ TestExpression.createPlainText("123 "), 431 TestExpression.createVariableReference("ABC"), 432 TestExpression.createPlainText(" XYZ") ]) 433