blob: f69f9e3f2bb7db6657a14ff670338ccdaa7b286a [file] [log] [blame]
David Brazdilee690a32014-12-01 17:04:16 +00001#!/usr/bin/env python3
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
17# This is a test file which exercises all feautres supported by the domain-
18# specific markup language implemented by Checker.
19
20import checker
21import io
22import unittest
23
24
25class TestCheckFile_PrefixExtraction(unittest.TestCase):
26 def __tryParse(self, string):
27 checkFile = checker.CheckFile(None, [])
28 return checkFile._extractLine("CHECK", string)
29
30 def test_InvalidFormat(self):
31 self.assertIsNone(self.__tryParse("CHECK"))
32 self.assertIsNone(self.__tryParse(":CHECK"))
33 self.assertIsNone(self.__tryParse("CHECK:"))
34 self.assertIsNone(self.__tryParse("//CHECK"))
35 self.assertIsNone(self.__tryParse("#CHECK"))
36
37 self.assertIsNotNone(self.__tryParse("//CHECK:foo"))
38 self.assertIsNotNone(self.__tryParse("#CHECK:bar"))
39
40 def test_InvalidLabel(self):
41 self.assertIsNone(self.__tryParse("//ACHECK:foo"))
42 self.assertIsNone(self.__tryParse("#ACHECK:foo"))
43
44 def test_NotFirstOnTheLine(self):
45 self.assertIsNone(self.__tryParse("A// CHECK: foo"))
46 self.assertIsNone(self.__tryParse("A # CHECK: foo"))
47 self.assertIsNone(self.__tryParse("// // CHECK: foo"))
48 self.assertIsNone(self.__tryParse("# # CHECK: foo"))
49
50 def test_WhitespaceAgnostic(self):
51 self.assertIsNotNone(self.__tryParse(" //CHECK: foo"))
52 self.assertIsNotNone(self.__tryParse("// CHECK: foo"))
53 self.assertIsNotNone(self.__tryParse(" //CHECK: foo"))
54 self.assertIsNotNone(self.__tryParse("// CHECK: foo"))
55
56
57class TestCheckLine_Parse(unittest.TestCase):
58 def __getRegex(self, checkLine):
59 return "".join(map(lambda x: "(" + x.pattern + ")", checkLine.lineParts))
60
61 def __tryParse(self, string):
62 return checker.CheckLine(string)
63
64 def __parsesTo(self, string, expected):
65 self.assertEqual(expected, self.__getRegex(self.__tryParse(string)))
66
67 def __parsesPattern(self, string, pattern):
68 line = self.__tryParse(string)
69 self.assertEqual(1, len(line.lineParts))
70 self.assertEqual(checker.CheckElement.Variant.Pattern, line.lineParts[0].variant)
71 self.assertEqual(pattern, line.lineParts[0].pattern)
72
73 def __parsesVarRef(self, string, name):
74 line = self.__tryParse(string)
75 self.assertEqual(1, len(line.lineParts))
76 self.assertEqual(checker.CheckElement.Variant.VarRef, line.lineParts[0].variant)
77 self.assertEqual(name, line.lineParts[0].name)
78
79 def __parsesVarDef(self, string, name, body):
80 line = self.__tryParse(string)
81 self.assertEqual(1, len(line.lineParts))
82 self.assertEqual(checker.CheckElement.Variant.VarDef, line.lineParts[0].variant)
83 self.assertEqual(name, line.lineParts[0].name)
84 self.assertEqual(body, line.lineParts[0].pattern)
85
86 def __doesNotParse(self, string, partType):
87 line = self.__tryParse(string)
88 self.assertEqual(1, len(line.lineParts))
89 self.assertNotEqual(partType, line.lineParts[0].variant)
90
91 # Test that individual parts of the line are recognized
92
93 def test_TextOnly(self):
94 self.__parsesTo("foo", "(foo)")
95 self.__parsesTo(" foo ", "(foo)")
96 self.__parsesTo("f$o^o", "(f\$o\^o)")
97
98 def test_TextWithWhitespace(self):
99 self.__parsesTo("foo bar", "(foo)(\s+)(bar)")
100 self.__parsesTo("foo bar", "(foo)(\s+)(bar)")
101
102 def test_RegexOnly(self):
103 self.__parsesPattern("{{a?b.c}}", "a?b.c")
104
105 def test_VarRefOnly(self):
106 self.__parsesVarRef("[[ABC]]", "ABC")
107
108 def test_VarDefOnly(self):
109 self.__parsesVarDef("[[ABC:a?b.c]]", "ABC", "a?b.c")
110
111 def test_TextWithRegex(self):
112 self.__parsesTo("foo{{abc}}bar", "(foo)(abc)(bar)")
113
114 def test_TextWithVar(self):
115 self.__parsesTo("foo[[ABC:abc]]bar", "(foo)(abc)(bar)")
116
117 def test_PlainWithRegexAndWhitespaces(self):
118 self.__parsesTo("foo {{abc}}bar", "(foo)(\s+)(abc)(bar)")
119 self.__parsesTo("foo{{abc}} bar", "(foo)(abc)(\s+)(bar)")
120 self.__parsesTo("foo {{abc}} bar", "(foo)(\s+)(abc)(\s+)(bar)")
121
122 def test_PlainWithVarAndWhitespaces(self):
123 self.__parsesTo("foo [[ABC:abc]]bar", "(foo)(\s+)(abc)(bar)")
124 self.__parsesTo("foo[[ABC:abc]] bar", "(foo)(abc)(\s+)(bar)")
125 self.__parsesTo("foo [[ABC:abc]] bar", "(foo)(\s+)(abc)(\s+)(bar)")
126
127 def test_AllKinds(self):
128 self.__parsesTo("foo [[ABC:abc]]{{def}}bar", "(foo)(\s+)(abc)(def)(bar)")
129 self.__parsesTo("foo[[ABC:abc]] {{def}}bar", "(foo)(abc)(\s+)(def)(bar)")
130 self.__parsesTo("foo [[ABC:abc]] {{def}} bar", "(foo)(\s+)(abc)(\s+)(def)(\s+)(bar)")
131
132 # Test that variables and patterns are parsed correctly
133
134 def test_ValidPattern(self):
135 self.__parsesPattern("{{abc}}", "abc")
136 self.__parsesPattern("{{a[b]c}}", "a[b]c")
137 self.__parsesPattern("{{(a{bc})}}", "(a{bc})")
138
139 def test_ValidRef(self):
140 self.__parsesVarRef("[[ABC]]", "ABC")
141 self.__parsesVarRef("[[A1BC2]]", "A1BC2")
142
143 def test_ValidDef(self):
144 self.__parsesVarDef("[[ABC:abc]]", "ABC", "abc")
145 self.__parsesVarDef("[[ABC:ab:c]]", "ABC", "ab:c")
146 self.__parsesVarDef("[[ABC:a[b]c]]", "ABC", "a[b]c")
147 self.__parsesVarDef("[[ABC:(a[bc])]]", "ABC", "(a[bc])")
148
149 def test_Empty(self):
150 self.__doesNotParse("{{}}", checker.CheckElement.Variant.Pattern)
151 self.__doesNotParse("[[]]", checker.CheckElement.Variant.VarRef)
152 self.__doesNotParse("[[:]]", checker.CheckElement.Variant.VarDef)
153
154 def test_InvalidVarName(self):
155 self.__doesNotParse("[[0ABC]]", checker.CheckElement.Variant.VarRef)
156 self.__doesNotParse("[[AB=C]]", checker.CheckElement.Variant.VarRef)
157 self.__doesNotParse("[[ABC=]]", checker.CheckElement.Variant.VarRef)
158 self.__doesNotParse("[[0ABC:abc]]", checker.CheckElement.Variant.VarDef)
159 self.__doesNotParse("[[AB=C:abc]]", checker.CheckElement.Variant.VarDef)
160 self.__doesNotParse("[[ABC=:abc]]", checker.CheckElement.Variant.VarDef)
161
162 def test_BodyMatchNotGreedy(self):
163 self.__parsesTo("{{abc}}{{def}}", "(abc)(def)")
164 self.__parsesTo("[[ABC:abc]][[DEF:def]]", "(abc)(def)")
165
166
167class TestCheckLine_Match(unittest.TestCase):
168 def __matchSingle(self, checkString, outputString, varState={}):
169 checkLine = checker.CheckLine(checkString)
170 newVarState = checkLine.match(outputString, varState)
171 self.assertIsNotNone(newVarState)
172 return newVarState
173
174 def __notMatchSingle(self, checkString, outputString, varState={}):
175 checkLine = checker.CheckLine(checkString)
176 self.assertIsNone(checkLine.match(outputString, varState))
177
178 def test_TextAndWhitespace(self):
179 self.__matchSingle("foo", "foo")
180 self.__matchSingle("foo", "XfooX")
181 self.__matchSingle("foo", "foo bar")
182 self.__notMatchSingle("foo", "zoo")
183
184 self.__matchSingle("foo bar", "foo bar")
185 self.__matchSingle("foo bar", "abc foo bar def")
186 self.__matchSingle("foo bar", "foo foo bar bar")
187 self.__notMatchSingle("foo bar", "foo abc bar")
188
189 def test_Pattern(self):
190 self.__matchSingle("foo{{A|B}}bar", "fooAbar")
191 self.__matchSingle("foo{{A|B}}bar", "fooBbar")
192 self.__notMatchSingle("foo{{A|B}}bar", "fooCbar")
193
194 def test_VariableReference(self):
195 self.__matchSingle("foo[[X]]bar", "foobar", {"X": ""})
196 self.__matchSingle("foo[[X]]bar", "fooAbar", {"X": "A"})
197 self.__matchSingle("foo[[X]]bar", "fooBbar", {"X": "B"})
198 self.__notMatchSingle("foo[[X]]bar", "foobar", {"X": "A"})
199 self.__notMatchSingle("foo[[X]]bar", "foo bar", {"X": "A"})
200 with self.assertRaises(Exception):
201 self.__matchSingle("foo[[X]]bar", "foobar", {})
202
203 def test_VariableDefinition(self):
204 self.__matchSingle("foo[[X:A|B]]bar", "fooAbar")
205 self.__matchSingle("foo[[X:A|B]]bar", "fooBbar")
206 self.__notMatchSingle("foo[[X:A|B]]bar", "fooCbar")
207
208 env = self.__matchSingle("foo[[X:A.*B]]bar", "fooABbar", {})
209 self.assertEqual(env, {"X": "AB"})
210 env = self.__matchSingle("foo[[X:A.*B]]bar", "fooAxxBbar", {})
211 self.assertEqual(env, {"X": "AxxB"})
212
213 self.__matchSingle("foo[[X:A|B]]bar[[X]]baz", "fooAbarAbaz")
214 self.__matchSingle("foo[[X:A|B]]bar[[X]]baz", "fooBbarBbaz")
215 self.__notMatchSingle("foo[[X:A|B]]bar[[X]]baz", "fooAbarBbaz")
216
217 def test_NoVariableRedefinition(self):
218 with self.assertRaises(Exception):
219 self.__matchSingle("[[X:...]][[X]][[X:...]][[X]]", "foofoobarbar")
220
221 def test_EnvNotChangedOnPartialMatch(self):
222 env = {"Y": "foo"}
223 self.__notMatchSingle("[[X:A]]bar", "Abaz", env)
224 self.assertFalse("X" in env.keys())
225
226 def test_VariableContentEscaped(self):
227 self.__matchSingle("[[X:..]]foo[[X]]", ".*foo.*")
228 self.__notMatchSingle("[[X:..]]foo[[X]]", ".*fooAAAA")
229
230
231class TestCheckGroup_Match(unittest.TestCase):
232 def __matchMulti(self, checkString, outputString):
233 checkGroup = checker.CheckGroup.parse("MyGroup", checkString.splitlines())
234 outputGroup = checker.OutputGroup("MyGroup", outputString.splitlines())
235 return checkGroup.match(outputGroup)
236
237 def __notMatchMulti(self, checkString, outputString):
238 with self.assertRaises(Exception):
239 self.__matchMulti(checkString, outputString)
240
241 def test_TextAndPattern(self):
242 self.__matchMulti("""foo bar
243 abc {{def}}""",
244 """foo bar
245 abc def""");
246 self.__matchMulti("""foo bar
247 abc {{de.}}""",
248 """=======
249 foo bar
250 =======
251 abc de#
252 =======""");
253 self.__notMatchMulti("""//XYZ: foo bar
254 //XYZ: abc {{def}}""",
255 """=======
256 foo bar
257 =======
258 abc de#
259 =======""");
260
261 def test_Variables(self):
262 self.__matchMulti("""foo[[X:.]]bar
263 abc[[X]]def""",
264 """foo bar
265 abc def""");
266 self.__matchMulti("""foo[[X:([0-9]+)]]bar
267 abc[[X]]def
268 ### [[X]] ###""",
269 """foo1234bar
270 abc1234def
271 ### 1234 ###""");
272
273 def test_Ordering(self):
274 self.__matchMulti("""foo
275 bar""",
276 """foo
277 bar""")
278 self.__notMatchMulti("""foo
279 bar""",
280 """bar
281 foo""")
282
283class TestOutputFile_Parse(unittest.TestCase):
284 def __parsesTo(self, string, expected):
285 outputStream = io.StringIO(string)
286 return self.assertEqual(checker.OutputFile(outputStream).groups, expected)
287
288 def test_NoInput(self):
289 self.__parsesTo(None, [])
290 self.__parsesTo("", [])
291
292 def test_SingleGroup(self):
293 self.__parsesTo("""begin_compilation
294 method "MyMethod"
295 end_compilation
296 begin_cfg
297 name "pass1"
298 foo
299 bar
300 end_cfg""",
301 [ checker.OutputGroup("MyMethod pass1", [ "foo", "bar" ]) ])
302
303 def test_MultipleGroups(self):
304 self.__parsesTo("""begin_compilation
305 name "xyz1"
306 method "MyMethod1"
307 date 1234
308 end_compilation
309 begin_cfg
310 name "pass1"
311 foo
312 bar
313 end_cfg
314 begin_cfg
315 name "pass2"
316 abc
317 def
318 end_cfg""",
319 [ checker.OutputGroup("MyMethod1 pass1", [ "foo", "bar" ]),
320 checker.OutputGroup("MyMethod1 pass2", [ "abc", "def" ]) ])
321
322 self.__parsesTo("""begin_compilation
323 name "xyz1"
324 method "MyMethod1"
325 date 1234
326 end_compilation
327 begin_cfg
328 name "pass1"
329 foo
330 bar
331 end_cfg
332 begin_compilation
333 name "xyz2"
334 method "MyMethod2"
335 date 5678
336 end_compilation
337 begin_cfg
338 name "pass2"
339 abc
340 def
341 end_cfg""",
342 [ checker.OutputGroup("MyMethod1 pass1", [ "foo", "bar" ]),
343 checker.OutputGroup("MyMethod2 pass2", [ "abc", "def" ]) ])
344
345class TestCheckFile_Parse(unittest.TestCase):
346 def __parsesTo(self, string, expected):
347 checkStream = io.StringIO(string)
348 return self.assertEqual(checker.CheckFile("CHECK", checkStream).groups, expected)
349
350 def test_NoInput(self):
351 self.__parsesTo(None, [])
352 self.__parsesTo("", [])
353
354 def test_SingleGroup(self):
355 self.__parsesTo("""// CHECK-START: Example Group
356 // CHECK: foo
357 // CHECK: bar""",
358 [ checker.CheckGroup.parse("Example Group", [ "foo", "bar" ]) ])
359
360 def test_MultipleGroups(self):
361 self.__parsesTo("""// CHECK-START: Example Group1
362 // CHECK: foo
363 // CHECK: bar
364 // CHECK-START: Example Group2
365 // CHECK: abc
366 // CHECK: def""",
367 [ checker.CheckGroup.parse("Example Group1", [ "foo", "bar" ]),
368 checker.CheckGroup.parse("Example Group2", [ "abc", "def" ]) ])
369
370if __name__ == '__main__':
371 unittest.main()