Home | History | Annotate | Download | only in match
      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