blob: 18152b592c1197ae5e234748f4cfb3ee591a5be7 [file] [log] [blame]
David Brazdil123c5e92015-01-20 09:28:38 +00001#!/usr/bin/env python2
David Brazdilee690a32014-12-01 17:04:16 +00002#
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
David Brazdil2e15cd22014-12-31 17:28:38 +000024# The parent type of exception expected to be thrown by Checker during tests.
25# It must be specific enough to not cover exceptions thrown due to actual flaws
David Brazdil48942de2015-01-07 21:19:50 +000026# in Checker.
David Brazdil2e15cd22014-12-31 17:28:38 +000027CheckerException = SystemExit
28
David Brazdilee690a32014-12-01 17:04:16 +000029
30class TestCheckFile_PrefixExtraction(unittest.TestCase):
31 def __tryParse(self, string):
32 checkFile = checker.CheckFile(None, [])
33 return checkFile._extractLine("CHECK", string)
34
35 def test_InvalidFormat(self):
36 self.assertIsNone(self.__tryParse("CHECK"))
37 self.assertIsNone(self.__tryParse(":CHECK"))
38 self.assertIsNone(self.__tryParse("CHECK:"))
39 self.assertIsNone(self.__tryParse("//CHECK"))
40 self.assertIsNone(self.__tryParse("#CHECK"))
41
42 self.assertIsNotNone(self.__tryParse("//CHECK:foo"))
43 self.assertIsNotNone(self.__tryParse("#CHECK:bar"))
44
45 def test_InvalidLabel(self):
46 self.assertIsNone(self.__tryParse("//ACHECK:foo"))
47 self.assertIsNone(self.__tryParse("#ACHECK:foo"))
48
49 def test_NotFirstOnTheLine(self):
50 self.assertIsNone(self.__tryParse("A// CHECK: foo"))
51 self.assertIsNone(self.__tryParse("A # CHECK: foo"))
52 self.assertIsNone(self.__tryParse("// // CHECK: foo"))
53 self.assertIsNone(self.__tryParse("# # CHECK: foo"))
54
55 def test_WhitespaceAgnostic(self):
56 self.assertIsNotNone(self.__tryParse(" //CHECK: foo"))
57 self.assertIsNotNone(self.__tryParse("// CHECK: foo"))
58 self.assertIsNotNone(self.__tryParse(" //CHECK: foo"))
59 self.assertIsNotNone(self.__tryParse("// CHECK: foo"))
60
61
62class TestCheckLine_Parse(unittest.TestCase):
63 def __getRegex(self, checkLine):
64 return "".join(map(lambda x: "(" + x.pattern + ")", checkLine.lineParts))
65
66 def __tryParse(self, string):
67 return checker.CheckLine(string)
68
69 def __parsesTo(self, string, expected):
70 self.assertEqual(expected, self.__getRegex(self.__tryParse(string)))
71
David Brazdil9a6f20e2014-12-19 11:17:21 +000072 def __tryParseNot(self, string):
David Brazdil2e15cd22014-12-31 17:28:38 +000073 return checker.CheckLine(string, checker.CheckLine.Variant.Not)
David Brazdil9a6f20e2014-12-19 11:17:21 +000074
David Brazdilee690a32014-12-01 17:04:16 +000075 def __parsesPattern(self, string, pattern):
76 line = self.__tryParse(string)
77 self.assertEqual(1, len(line.lineParts))
78 self.assertEqual(checker.CheckElement.Variant.Pattern, line.lineParts[0].variant)
79 self.assertEqual(pattern, line.lineParts[0].pattern)
80
81 def __parsesVarRef(self, string, name):
82 line = self.__tryParse(string)
83 self.assertEqual(1, len(line.lineParts))
84 self.assertEqual(checker.CheckElement.Variant.VarRef, line.lineParts[0].variant)
85 self.assertEqual(name, line.lineParts[0].name)
86
87 def __parsesVarDef(self, string, name, body):
88 line = self.__tryParse(string)
89 self.assertEqual(1, len(line.lineParts))
90 self.assertEqual(checker.CheckElement.Variant.VarDef, line.lineParts[0].variant)
91 self.assertEqual(name, line.lineParts[0].name)
92 self.assertEqual(body, line.lineParts[0].pattern)
93
94 def __doesNotParse(self, string, partType):
95 line = self.__tryParse(string)
96 self.assertEqual(1, len(line.lineParts))
97 self.assertNotEqual(partType, line.lineParts[0].variant)
98
99 # Test that individual parts of the line are recognized
100
101 def test_TextOnly(self):
102 self.__parsesTo("foo", "(foo)")
103 self.__parsesTo(" foo ", "(foo)")
104 self.__parsesTo("f$o^o", "(f\$o\^o)")
105
106 def test_TextWithWhitespace(self):
107 self.__parsesTo("foo bar", "(foo)(\s+)(bar)")
108 self.__parsesTo("foo bar", "(foo)(\s+)(bar)")
109
110 def test_RegexOnly(self):
111 self.__parsesPattern("{{a?b.c}}", "a?b.c")
112
113 def test_VarRefOnly(self):
114 self.__parsesVarRef("[[ABC]]", "ABC")
115
116 def test_VarDefOnly(self):
117 self.__parsesVarDef("[[ABC:a?b.c]]", "ABC", "a?b.c")
118
119 def test_TextWithRegex(self):
120 self.__parsesTo("foo{{abc}}bar", "(foo)(abc)(bar)")
121
122 def test_TextWithVar(self):
123 self.__parsesTo("foo[[ABC:abc]]bar", "(foo)(abc)(bar)")
124
125 def test_PlainWithRegexAndWhitespaces(self):
126 self.__parsesTo("foo {{abc}}bar", "(foo)(\s+)(abc)(bar)")
127 self.__parsesTo("foo{{abc}} bar", "(foo)(abc)(\s+)(bar)")
128 self.__parsesTo("foo {{abc}} bar", "(foo)(\s+)(abc)(\s+)(bar)")
129
130 def test_PlainWithVarAndWhitespaces(self):
131 self.__parsesTo("foo [[ABC:abc]]bar", "(foo)(\s+)(abc)(bar)")
132 self.__parsesTo("foo[[ABC:abc]] bar", "(foo)(abc)(\s+)(bar)")
133 self.__parsesTo("foo [[ABC:abc]] bar", "(foo)(\s+)(abc)(\s+)(bar)")
134
135 def test_AllKinds(self):
136 self.__parsesTo("foo [[ABC:abc]]{{def}}bar", "(foo)(\s+)(abc)(def)(bar)")
137 self.__parsesTo("foo[[ABC:abc]] {{def}}bar", "(foo)(abc)(\s+)(def)(bar)")
138 self.__parsesTo("foo [[ABC:abc]] {{def}} bar", "(foo)(\s+)(abc)(\s+)(def)(\s+)(bar)")
139
140 # Test that variables and patterns are parsed correctly
141
142 def test_ValidPattern(self):
143 self.__parsesPattern("{{abc}}", "abc")
144 self.__parsesPattern("{{a[b]c}}", "a[b]c")
145 self.__parsesPattern("{{(a{bc})}}", "(a{bc})")
146
147 def test_ValidRef(self):
148 self.__parsesVarRef("[[ABC]]", "ABC")
149 self.__parsesVarRef("[[A1BC2]]", "A1BC2")
150
151 def test_ValidDef(self):
152 self.__parsesVarDef("[[ABC:abc]]", "ABC", "abc")
153 self.__parsesVarDef("[[ABC:ab:c]]", "ABC", "ab:c")
154 self.__parsesVarDef("[[ABC:a[b]c]]", "ABC", "a[b]c")
155 self.__parsesVarDef("[[ABC:(a[bc])]]", "ABC", "(a[bc])")
156
157 def test_Empty(self):
158 self.__doesNotParse("{{}}", checker.CheckElement.Variant.Pattern)
159 self.__doesNotParse("[[]]", checker.CheckElement.Variant.VarRef)
160 self.__doesNotParse("[[:]]", checker.CheckElement.Variant.VarDef)
161
162 def test_InvalidVarName(self):
163 self.__doesNotParse("[[0ABC]]", checker.CheckElement.Variant.VarRef)
164 self.__doesNotParse("[[AB=C]]", checker.CheckElement.Variant.VarRef)
165 self.__doesNotParse("[[ABC=]]", checker.CheckElement.Variant.VarRef)
166 self.__doesNotParse("[[0ABC:abc]]", checker.CheckElement.Variant.VarDef)
167 self.__doesNotParse("[[AB=C:abc]]", checker.CheckElement.Variant.VarDef)
168 self.__doesNotParse("[[ABC=:abc]]", checker.CheckElement.Variant.VarDef)
169
170 def test_BodyMatchNotGreedy(self):
171 self.__parsesTo("{{abc}}{{def}}", "(abc)(def)")
172 self.__parsesTo("[[ABC:abc]][[DEF:def]]", "(abc)(def)")
173
David Brazdil9a6f20e2014-12-19 11:17:21 +0000174 def test_NoVarDefsInNotChecks(self):
David Brazdil2e15cd22014-12-31 17:28:38 +0000175 with self.assertRaises(CheckerException):
David Brazdil9a6f20e2014-12-19 11:17:21 +0000176 self.__tryParseNot("[[ABC:abc]]")
David Brazdilee690a32014-12-01 17:04:16 +0000177
178class TestCheckLine_Match(unittest.TestCase):
179 def __matchSingle(self, checkString, outputString, varState={}):
180 checkLine = checker.CheckLine(checkString)
181 newVarState = checkLine.match(outputString, varState)
182 self.assertIsNotNone(newVarState)
183 return newVarState
184
185 def __notMatchSingle(self, checkString, outputString, varState={}):
186 checkLine = checker.CheckLine(checkString)
187 self.assertIsNone(checkLine.match(outputString, varState))
188
189 def test_TextAndWhitespace(self):
190 self.__matchSingle("foo", "foo")
191 self.__matchSingle("foo", "XfooX")
192 self.__matchSingle("foo", "foo bar")
193 self.__notMatchSingle("foo", "zoo")
194
195 self.__matchSingle("foo bar", "foo bar")
196 self.__matchSingle("foo bar", "abc foo bar def")
197 self.__matchSingle("foo bar", "foo foo bar bar")
198 self.__notMatchSingle("foo bar", "foo abc bar")
199
200 def test_Pattern(self):
201 self.__matchSingle("foo{{A|B}}bar", "fooAbar")
202 self.__matchSingle("foo{{A|B}}bar", "fooBbar")
203 self.__notMatchSingle("foo{{A|B}}bar", "fooCbar")
204
205 def test_VariableReference(self):
206 self.__matchSingle("foo[[X]]bar", "foobar", {"X": ""})
207 self.__matchSingle("foo[[X]]bar", "fooAbar", {"X": "A"})
208 self.__matchSingle("foo[[X]]bar", "fooBbar", {"X": "B"})
209 self.__notMatchSingle("foo[[X]]bar", "foobar", {"X": "A"})
210 self.__notMatchSingle("foo[[X]]bar", "foo bar", {"X": "A"})
David Brazdil2e15cd22014-12-31 17:28:38 +0000211 with self.assertRaises(CheckerException):
David Brazdilee690a32014-12-01 17:04:16 +0000212 self.__matchSingle("foo[[X]]bar", "foobar", {})
213
214 def test_VariableDefinition(self):
215 self.__matchSingle("foo[[X:A|B]]bar", "fooAbar")
216 self.__matchSingle("foo[[X:A|B]]bar", "fooBbar")
217 self.__notMatchSingle("foo[[X:A|B]]bar", "fooCbar")
218
219 env = self.__matchSingle("foo[[X:A.*B]]bar", "fooABbar", {})
220 self.assertEqual(env, {"X": "AB"})
221 env = self.__matchSingle("foo[[X:A.*B]]bar", "fooAxxBbar", {})
222 self.assertEqual(env, {"X": "AxxB"})
223
224 self.__matchSingle("foo[[X:A|B]]bar[[X]]baz", "fooAbarAbaz")
225 self.__matchSingle("foo[[X:A|B]]bar[[X]]baz", "fooBbarBbaz")
226 self.__notMatchSingle("foo[[X:A|B]]bar[[X]]baz", "fooAbarBbaz")
227
228 def test_NoVariableRedefinition(self):
David Brazdil2e15cd22014-12-31 17:28:38 +0000229 with self.assertRaises(CheckerException):
David Brazdilee690a32014-12-01 17:04:16 +0000230 self.__matchSingle("[[X:...]][[X]][[X:...]][[X]]", "foofoobarbar")
231
232 def test_EnvNotChangedOnPartialMatch(self):
233 env = {"Y": "foo"}
234 self.__notMatchSingle("[[X:A]]bar", "Abaz", env)
235 self.assertFalse("X" in env.keys())
236
237 def test_VariableContentEscaped(self):
238 self.__matchSingle("[[X:..]]foo[[X]]", ".*foo.*")
239 self.__notMatchSingle("[[X:..]]foo[[X]]", ".*fooAAAA")
240
241
David Brazdil9a6f20e2014-12-19 11:17:21 +0000242CheckVariant = checker.CheckLine.Variant
243
244def prepareSingleCheck(line):
245 if isinstance(line, str):
246 return checker.CheckLine(line)
247 else:
248 return checker.CheckLine(line[0], line[1])
249
250def prepareChecks(lines):
251 if isinstance(lines, str):
252 lines = lines.splitlines()
253 return list(map(lambda line: prepareSingleCheck(line), lines))
254
255
David Brazdilee690a32014-12-01 17:04:16 +0000256class TestCheckGroup_Match(unittest.TestCase):
David Brazdil9a6f20e2014-12-19 11:17:21 +0000257 def __matchMulti(self, checkLines, outputString):
258 checkGroup = checker.CheckGroup("MyGroup", prepareChecks(checkLines))
David Brazdilee690a32014-12-01 17:04:16 +0000259 outputGroup = checker.OutputGroup("MyGroup", outputString.splitlines())
260 return checkGroup.match(outputGroup)
261
262 def __notMatchMulti(self, checkString, outputString):
David Brazdil2e15cd22014-12-31 17:28:38 +0000263 with self.assertRaises(CheckerException):
David Brazdilee690a32014-12-01 17:04:16 +0000264 self.__matchMulti(checkString, outputString)
265
266 def test_TextAndPattern(self):
267 self.__matchMulti("""foo bar
268 abc {{def}}""",
269 """foo bar
270 abc def""");
271 self.__matchMulti("""foo bar
272 abc {{de.}}""",
273 """=======
274 foo bar
275 =======
276 abc de#
277 =======""");
278 self.__notMatchMulti("""//XYZ: foo bar
279 //XYZ: abc {{def}}""",
280 """=======
281 foo bar
282 =======
283 abc de#
284 =======""");
285
286 def test_Variables(self):
287 self.__matchMulti("""foo[[X:.]]bar
288 abc[[X]]def""",
289 """foo bar
290 abc def""");
291 self.__matchMulti("""foo[[X:([0-9]+)]]bar
292 abc[[X]]def
293 ### [[X]] ###""",
294 """foo1234bar
295 abc1234def
296 ### 1234 ###""");
297
298 def test_Ordering(self):
David Brazdil9a6f20e2014-12-19 11:17:21 +0000299 self.__matchMulti([("foo", CheckVariant.InOrder),
300 ("bar", CheckVariant.InOrder)],
David Brazdilee690a32014-12-01 17:04:16 +0000301 """foo
302 bar""")
David Brazdil9a6f20e2014-12-19 11:17:21 +0000303 self.__notMatchMulti([("foo", CheckVariant.InOrder),
304 ("bar", CheckVariant.InOrder)],
David Brazdilee690a32014-12-01 17:04:16 +0000305 """bar
306 foo""")
David Brazdil9a6f20e2014-12-19 11:17:21 +0000307 self.__matchMulti([("abc", CheckVariant.DAG),
308 ("def", CheckVariant.DAG)],
309 """abc
310 def""")
311 self.__matchMulti([("abc", CheckVariant.DAG),
312 ("def", CheckVariant.DAG)],
313 """def
314 abc""")
315 self.__matchMulti([("foo", CheckVariant.InOrder),
316 ("abc", CheckVariant.DAG),
317 ("def", CheckVariant.DAG),
318 ("bar", CheckVariant.InOrder)],
319 """foo
320 def
321 abc
322 bar""")
323 self.__notMatchMulti([("foo", CheckVariant.InOrder),
324 ("abc", CheckVariant.DAG),
325 ("def", CheckVariant.DAG),
326 ("bar", CheckVariant.InOrder)],
327 """foo
328 abc
329 bar""")
330 self.__notMatchMulti([("foo", CheckVariant.InOrder),
331 ("abc", CheckVariant.DAG),
332 ("def", CheckVariant.DAG),
333 ("bar", CheckVariant.InOrder)],
334 """foo
335 def
336 bar""")
337
338 def test_NotAssertions(self):
339 self.__matchMulti([("foo", CheckVariant.Not)],
340 """abc
341 def""")
342 self.__notMatchMulti([("foo", CheckVariant.Not)],
343 """abc foo
344 def""")
David Brazdil21df8892015-01-08 01:49:53 +0000345 self.__notMatchMulti([("foo", CheckVariant.Not),
346 ("bar", CheckVariant.Not)],
347 """abc
348 def bar""")
David Brazdil9a6f20e2014-12-19 11:17:21 +0000349
350 def test_LineOnlyMatchesOnce(self):
351 self.__matchMulti([("foo", CheckVariant.DAG),
352 ("foo", CheckVariant.DAG)],
353 """foo
354 foo""")
355 self.__notMatchMulti([("foo", CheckVariant.DAG),
356 ("foo", CheckVariant.DAG)],
357 """foo
358 bar""")
David Brazdilee690a32014-12-01 17:04:16 +0000359
360class TestOutputFile_Parse(unittest.TestCase):
361 def __parsesTo(self, string, expected):
David Brazdil123c5e92015-01-20 09:28:38 +0000362 if isinstance(string, str):
363 string = unicode(string)
David Brazdilee690a32014-12-01 17:04:16 +0000364 outputStream = io.StringIO(string)
365 return self.assertEqual(checker.OutputFile(outputStream).groups, expected)
366
367 def test_NoInput(self):
368 self.__parsesTo(None, [])
369 self.__parsesTo("", [])
370
371 def test_SingleGroup(self):
372 self.__parsesTo("""begin_compilation
373 method "MyMethod"
374 end_compilation
375 begin_cfg
376 name "pass1"
377 foo
378 bar
379 end_cfg""",
380 [ checker.OutputGroup("MyMethod pass1", [ "foo", "bar" ]) ])
381
382 def test_MultipleGroups(self):
383 self.__parsesTo("""begin_compilation
384 name "xyz1"
385 method "MyMethod1"
386 date 1234
387 end_compilation
388 begin_cfg
389 name "pass1"
390 foo
391 bar
392 end_cfg
393 begin_cfg
394 name "pass2"
395 abc
396 def
397 end_cfg""",
398 [ checker.OutputGroup("MyMethod1 pass1", [ "foo", "bar" ]),
399 checker.OutputGroup("MyMethod1 pass2", [ "abc", "def" ]) ])
400
401 self.__parsesTo("""begin_compilation
402 name "xyz1"
403 method "MyMethod1"
404 date 1234
405 end_compilation
406 begin_cfg
407 name "pass1"
408 foo
409 bar
410 end_cfg
411 begin_compilation
412 name "xyz2"
413 method "MyMethod2"
414 date 5678
415 end_compilation
416 begin_cfg
417 name "pass2"
418 abc
419 def
420 end_cfg""",
421 [ checker.OutputGroup("MyMethod1 pass1", [ "foo", "bar" ]),
422 checker.OutputGroup("MyMethod2 pass2", [ "abc", "def" ]) ])
423
424class TestCheckFile_Parse(unittest.TestCase):
425 def __parsesTo(self, string, expected):
David Brazdil123c5e92015-01-20 09:28:38 +0000426 if isinstance(string, str):
427 string = unicode(string)
David Brazdilee690a32014-12-01 17:04:16 +0000428 checkStream = io.StringIO(string)
429 return self.assertEqual(checker.CheckFile("CHECK", checkStream).groups, expected)
430
431 def test_NoInput(self):
432 self.__parsesTo(None, [])
433 self.__parsesTo("", [])
434
435 def test_SingleGroup(self):
436 self.__parsesTo("""// CHECK-START: Example Group
437 // CHECK: foo
438 // CHECK: bar""",
David Brazdil9a6f20e2014-12-19 11:17:21 +0000439 [ checker.CheckGroup("Example Group", prepareChecks([ "foo", "bar" ])) ])
David Brazdilee690a32014-12-01 17:04:16 +0000440
441 def test_MultipleGroups(self):
442 self.__parsesTo("""// CHECK-START: Example Group1
443 // CHECK: foo
444 // CHECK: bar
445 // CHECK-START: Example Group2
446 // CHECK: abc
447 // CHECK: def""",
David Brazdil9a6f20e2014-12-19 11:17:21 +0000448 [ checker.CheckGroup("Example Group1", prepareChecks([ "foo", "bar" ])),
449 checker.CheckGroup("Example Group2", prepareChecks([ "abc", "def" ])) ])
450
451 def test_CheckVariants(self):
452 self.__parsesTo("""// CHECK-START: Example Group
453 // CHECK: foo
454 // CHECK-NOT: bar
455 // CHECK-DAG: abc
456 // CHECK-DAG: def""",
457 [ checker.CheckGroup("Example Group",
458 prepareChecks([ ("foo", CheckVariant.InOrder),
459 ("bar", CheckVariant.Not),
460 ("abc", CheckVariant.DAG),
461 ("def", CheckVariant.DAG) ])) ])
David Brazdilee690a32014-12-01 17:04:16 +0000462
463if __name__ == '__main__':
David Brazdil7cca5df2015-01-15 00:40:56 +0000464 checker.Logger.Verbosity = checker.Logger.Level.NoOutput
David Brazdilee690a32014-12-01 17:04:16 +0000465 unittest.main()