• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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