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
15from common.immutables               import ImmutableDict
16from common.testing                  import ToUnicode
17from file_format.c1visualizer.parser import ParseC1visualizerStream
18from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass
19from file_format.checker.parser      import ParseCheckerStream, ParseCheckerAssertion
20from file_format.checker.struct      import CheckerFile, TestCase, TestAssertion
21from match.file                      import MatchTestCase, MatchFailedException
22from match.line                      import MatchLines
23
24import io
25import unittest
26
27CheckerException = SystemExit
28
29class 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
103class 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