1 # Copyright (C) 2014 The Android Open Source Project 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 15 from common.immutables import ImmutableDict 16 from common.testing import ToUnicode 17 from file_format.c1visualizer.parser import ParseC1visualizerStream 18 from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass 19 from file_format.checker.parser import ParseCheckerStream, ParseCheckerAssertion 20 from file_format.checker.struct import CheckerFile, TestCase, TestAssertion 21 from match.file import MatchTestCase, MatchFailedException 22 from match.line import MatchLines 23 24 import io 25 import unittest 26 27 CheckerException = SystemExit 28 29 class MatchLines_Test(unittest.TestCase): 30 31 def createTestAssertion(self, checkerString): 32 checkerFile = CheckerFile("<checker-file>") 33 testCase = TestCase(checkerFile, "TestMethod TestPass", 0) 34 return ParseCheckerAssertion(testCase, checkerString, TestAssertion.Variant.InOrder, 0) 35 36 def tryMatch(self, checkerString, c1String, varState={}): 37 return MatchLines(self.createTestAssertion(checkerString), 38 ToUnicode(c1String), 39 ImmutableDict(varState)) 40 41 def assertMatches(self, checkerString, c1String, varState={}): 42 self.assertIsNotNone(self.tryMatch(checkerString, c1String, varState)) 43 44 def assertDoesNotMatch(self, checkerString, c1String, varState={}): 45 self.assertIsNone(self.tryMatch(checkerString, c1String, varState)) 46 47 def test_TextAndWhitespace(self): 48 self.assertMatches("foo", "foo") 49 self.assertMatches("foo", " foo ") 50 self.assertMatches("foo", "foo bar") 51 self.assertDoesNotMatch("foo", "XfooX") 52 self.assertDoesNotMatch("foo", "zoo") 53 54 self.assertMatches("foo bar", "foo bar") 55 self.assertMatches("foo bar", "abc foo bar def") 56 self.assertMatches("foo bar", "foo foo bar bar") 57 58 self.assertMatches("foo bar", "foo X bar") 59 self.assertDoesNotMatch("foo bar", "foo Xbar") 60 61 def test_Pattern(self): 62 self.assertMatches("foo{{A|B}}bar", "fooAbar") 63 self.assertMatches("foo{{A|B}}bar", "fooBbar") 64 self.assertDoesNotMatch("foo{{A|B}}bar", "fooCbar") 65 66 def test_VariableReference(self): 67 self.assertMatches("foo<<X>>bar", "foobar", {"X": ""}) 68 self.assertMatches("foo<<X>>bar", "fooAbar", {"X": "A"}) 69 self.assertMatches("foo<<X>>bar", "fooBbar", {"X": "B"}) 70 self.assertDoesNotMatch("foo<<X>>bar", "foobar", {"X": "A"}) 71 self.assertDoesNotMatch("foo<<X>>bar", "foo bar", {"X": "A"}) 72 with self.assertRaises(CheckerException): 73 self.tryMatch("foo<<X>>bar", "foobar", {}) 74 75 def test_VariableDefinition(self): 76 self.assertMatches("foo<<X:A|B>>bar", "fooAbar") 77 self.assertMatches("foo<<X:A|B>>bar", "fooBbar") 78 self.assertDoesNotMatch("foo<<X:A|B>>bar", "fooCbar") 79 80 env = self.tryMatch("foo<<X:A.*B>>bar", "fooABbar", {}) 81 self.assertEqual(env, {"X": "AB"}) 82 env = self.tryMatch("foo<<X:A.*B>>bar", "fooAxxBbar", {}) 83 self.assertEqual(env, {"X": "AxxB"}) 84 85 self.assertMatches("foo<<X:A|B>>bar<<X>>baz", "fooAbarAbaz") 86 self.assertMatches("foo<<X:A|B>>bar<<X>>baz", "fooBbarBbaz") 87 self.assertDoesNotMatch("foo<<X:A|B>>bar<<X>>baz", "fooAbarBbaz") 88 89 def test_NoVariableRedefinition(self): 90 with self.assertRaises(CheckerException): 91 self.tryMatch("<<X:...>><<X>><<X:...>><<X>>", "foofoobarbar") 92 93 def test_EnvNotChangedOnPartialMatch(self): 94 env = {"Y": "foo"} 95 self.assertDoesNotMatch("<<X:A>>bar", "Abaz", env) 96 self.assertFalse("X" in env.keys()) 97 98 def test_VariableContentEscaped(self): 99 self.assertMatches("<<X:..>>foo<<X>>", ".*foo.*") 100 self.assertDoesNotMatch("<<X:..>>foo<<X>>", ".*fooAAAA") 101 102 103 class MatchFiles_Test(unittest.TestCase): 104 105 def assertMatches(self, checkerString, c1String): 106 checkerString = \ 107 """ 108 /// CHECK-START: MyMethod MyPass 109 """ + checkerString 110 c1String = \ 111 """ 112 begin_compilation 113 name "MyMethod" 114 method "MyMethod" 115 date 1234 116 end_compilation 117 begin_cfg 118 name "MyPass" 119 """ + c1String + \ 120 """ 121 end_cfg 122 """ 123 checkerFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(ToUnicode(checkerString))) 124 c1File = ParseC1visualizerStream("<c1-file>", io.StringIO(ToUnicode(c1String))) 125 assert len(checkerFile.testCases) == 1 126 assert len(c1File.passes) == 1 127 MatchTestCase(checkerFile.testCases[0], c1File.passes[0]) 128 129 def assertDoesNotMatch(self, checkerString, c1String): 130 with self.assertRaises(MatchFailedException): 131 self.assertMatches(checkerString, c1String) 132 133 def test_Text(self): 134 self.assertMatches("/// CHECK: foo bar", "foo bar") 135 self.assertDoesNotMatch("/// CHECK: foo bar", "abc def") 136 137 def test_Pattern(self): 138 self.assertMatches("/// CHECK: abc {{de.}}", "abc de#") 139 self.assertDoesNotMatch("/// CHECK: abc {{de.}}", "abc d#f") 140 141 def test_Variables(self): 142 self.assertMatches( 143 """ 144 /// CHECK: foo<<X:.>>bar 145 /// CHECK: abc<<X>>def 146 """, 147 """ 148 foo0bar 149 abc0def 150 """) 151 self.assertMatches( 152 """ 153 /// CHECK: foo<<X:([0-9]+)>>bar 154 /// CHECK: abc<<X>>def 155 /// CHECK: ### <<X>> ### 156 """, 157 """ 158 foo1234bar 159 abc1234def 160 ### 1234 ### 161 """) 162 self.assertDoesNotMatch( 163 """ 164 /// CHECK: foo<<X:([0-9]+)>>bar 165 /// CHECK: abc<<X>>def 166 """, 167 """ 168 foo1234bar 169 abc1235def 170 """) 171 172 def test_WholeWordMustMatch(self): 173 self.assertMatches("/// CHECK: b{{.}}r", "abc bar def") 174 self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc Xbar def") 175 self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc barX def") 176 self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc b r def") 177 178 def test_InOrderAssertions(self): 179 self.assertMatches( 180 """ 181 /// CHECK: foo 182 /// CHECK: bar 183 """, 184 """ 185 foo 186 bar 187 """) 188 self.assertDoesNotMatch( 189 """ 190 /// CHECK: foo 191 /// CHECK: bar 192 """, 193 """ 194 bar 195 foo 196 """) 197 198 def test_NextLineAssertions(self): 199 self.assertMatches( 200 """ 201 /// CHECK: foo 202 /// CHECK-NEXT: bar 203 /// CHECK-NEXT: abc 204 /// CHECK: def 205 """, 206 """ 207 foo 208 bar 209 abc 210 def 211 """) 212 self.assertMatches( 213 """ 214 /// CHECK: foo 215 /// CHECK-NEXT: bar 216 /// CHECK: def 217 """, 218 """ 219 foo 220 bar 221 abc 222 def 223 """) 224 self.assertDoesNotMatch( 225 """ 226 /// CHECK: foo 227 /// CHECK-NEXT: bar 228 """, 229 """ 230 foo 231 abc 232 bar 233 """) 234 235 self.assertDoesNotMatch( 236 """ 237 /// CHECK: foo 238 /// CHECK-NEXT: bar 239 """, 240 """ 241 bar 242 foo 243 abc 244 """) 245 246 def test_DagAssertions(self): 247 self.assertMatches( 248 """ 249 /// CHECK-DAG: foo 250 /// CHECK-DAG: bar 251 """, 252 """ 253 foo 254 bar 255 """) 256 self.assertMatches( 257 """ 258 /// CHECK-DAG: foo 259 /// CHECK-DAG: bar 260 """, 261 """ 262 bar 263 foo 264 """) 265 266 def test_DagAssertionsScope(self): 267 self.assertMatches( 268 """ 269 /// CHECK: foo 270 /// CHECK-DAG: abc 271 /// CHECK-DAG: def 272 /// CHECK: bar 273 """, 274 """ 275 foo 276 def 277 abc 278 bar 279 """) 280 self.assertDoesNotMatch( 281 """ 282 /// CHECK: foo 283 /// CHECK-DAG: abc 284 /// CHECK-DAG: def 285 /// CHECK: bar 286 """, 287 """ 288 foo 289 abc 290 bar 291 def 292 """) 293 self.assertDoesNotMatch( 294 """ 295 /// CHECK: foo 296 /// CHECK-DAG: abc 297 /// CHECK-DAG: def 298 /// CHECK: bar 299 """, 300 """ 301 foo 302 def 303 bar 304 abc 305 """) 306 307 def test_NotAssertions(self): 308 self.assertMatches( 309 """ 310 /// CHECK-NOT: foo 311 """, 312 """ 313 abc 314 def 315 """) 316 self.assertDoesNotMatch( 317 """ 318 /// CHECK-NOT: foo 319 """, 320 """ 321 abc foo 322 def 323 """) 324 self.assertDoesNotMatch( 325 """ 326 /// CHECK-NOT: foo 327 /// CHECK-NOT: bar 328 """, 329 """ 330 abc 331 def bar 332 """) 333 334 def test_NotAssertionsScope(self): 335 self.assertMatches( 336 """ 337 /// CHECK: abc 338 /// CHECK-NOT: foo 339 /// CHECK: def 340 """, 341 """ 342 abc 343 def 344 """) 345 self.assertMatches( 346 """ 347 /// CHECK: abc 348 /// CHECK-NOT: foo 349 /// CHECK: def 350 """, 351 """ 352 abc 353 def 354 foo 355 """) 356 self.assertDoesNotMatch( 357 """ 358 /// CHECK: abc 359 /// CHECK-NOT: foo 360 /// CHECK: def 361 """, 362 """ 363 abc 364 foo 365 def 366 """) 367 368 def test_LineOnlyMatchesOnce(self): 369 self.assertMatches( 370 """ 371 /// CHECK-DAG: foo 372 /// CHECK-DAG: foo 373 """, 374 """ 375 foo 376 abc 377 foo 378 """) 379 self.assertDoesNotMatch( 380 """ 381 /// CHECK-DAG: foo 382 /// CHECK-DAG: foo 383 """, 384 """ 385 foo 386 abc 387 bar 388 """) 389 390 def test_EvalAssertions(self): 391 self.assertMatches("/// CHECK-EVAL: True", "foo") 392 self.assertDoesNotMatch("/// CHECK-EVAL: False", "foo") 393 394 self.assertMatches("/// CHECK-EVAL: 1 + 2 == 3", "foo") 395 self.assertDoesNotMatch("/// CHECK-EVAL: 1 + 2 == 4", "foo") 396 397 twoVarTestCase = """ 398 /// CHECK-DAG: <<X:\d+>> <<Y:\d+>> 399 /// CHECK-EVAL: <<X>> > <<Y>> 400 """ 401 self.assertMatches(twoVarTestCase, "42 41"); 402 self.assertDoesNotMatch(twoVarTestCase, "42 43") 403