# Copyright (C) 2014 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from common.immutables import ImmutableDict from common.testing import ToUnicode from file_format.c1visualizer.parser import ParseC1visualizerStream from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass from file_format.checker.parser import ParseCheckerStream, ParseCheckerAssertion from file_format.checker.struct import CheckerFile, TestCase, TestAssertion from match.file import MatchTestCase, MatchFailedException from match.line import MatchLines import io import unittest CheckerException = SystemExit class MatchLines_Test(unittest.TestCase): def createTestAssertion(self, checkerString): checkerFile = CheckerFile("<checker-file>") testCase = TestCase(checkerFile, "TestMethod TestPass", 0) return ParseCheckerAssertion(testCase, checkerString, TestAssertion.Variant.InOrder, 0) def tryMatch(self, checkerString, c1String, varState={}): return MatchLines(self.createTestAssertion(checkerString), ToUnicode(c1String), ImmutableDict(varState)) def assertMatches(self, checkerString, c1String, varState={}): self.assertIsNotNone(self.tryMatch(checkerString, c1String, varState)) def assertDoesNotMatch(self, checkerString, c1String, varState={}): self.assertIsNone(self.tryMatch(checkerString, c1String, varState)) def test_TextAndWhitespace(self): self.assertMatches("foo", "foo") self.assertMatches("foo", " foo ") self.assertMatches("foo", "foo bar") self.assertDoesNotMatch("foo", "XfooX") self.assertDoesNotMatch("foo", "zoo") self.assertMatches("foo bar", "foo bar") self.assertMatches("foo bar", "abc foo bar def") self.assertMatches("foo bar", "foo foo bar bar") self.assertMatches("foo bar", "foo X bar") self.assertDoesNotMatch("foo bar", "foo Xbar") def test_Pattern(self): self.assertMatches("foo{{A|B}}bar", "fooAbar") self.assertMatches("foo{{A|B}}bar", "fooBbar") self.assertDoesNotMatch("foo{{A|B}}bar", "fooCbar") def test_VariableReference(self): self.assertMatches("foo<<X>>bar", "foobar", {"X": ""}) self.assertMatches("foo<<X>>bar", "fooAbar", {"X": "A"}) self.assertMatches("foo<<X>>bar", "fooBbar", {"X": "B"}) self.assertDoesNotMatch("foo<<X>>bar", "foobar", {"X": "A"}) self.assertDoesNotMatch("foo<<X>>bar", "foo bar", {"X": "A"}) with self.assertRaises(CheckerException): self.tryMatch("foo<<X>>bar", "foobar", {}) def test_VariableDefinition(self): self.assertMatches("foo<<X:A|B>>bar", "fooAbar") self.assertMatches("foo<<X:A|B>>bar", "fooBbar") self.assertDoesNotMatch("foo<<X:A|B>>bar", "fooCbar") env = self.tryMatch("foo<<X:A.*B>>bar", "fooABbar", {}) self.assertEqual(env, {"X": "AB"}) env = self.tryMatch("foo<<X:A.*B>>bar", "fooAxxBbar", {}) self.assertEqual(env, {"X": "AxxB"}) self.assertMatches("foo<<X:A|B>>bar<<X>>baz", "fooAbarAbaz") self.assertMatches("foo<<X:A|B>>bar<<X>>baz", "fooBbarBbaz") self.assertDoesNotMatch("foo<<X:A|B>>bar<<X>>baz", "fooAbarBbaz") def test_NoVariableRedefinition(self): with self.assertRaises(CheckerException): self.tryMatch("<<X:...>><<X>><<X:...>><<X>>", "foofoobarbar") def test_EnvNotChangedOnPartialMatch(self): env = {"Y": "foo"} self.assertDoesNotMatch("<<X:A>>bar", "Abaz", env) self.assertFalse("X" in env.keys()) def test_VariableContentEscaped(self): self.assertMatches("<<X:..>>foo<<X>>", ".*foo.*") self.assertDoesNotMatch("<<X:..>>foo<<X>>", ".*fooAAAA") class MatchFiles_Test(unittest.TestCase): def assertMatches(self, checkerString, c1String): checkerString = \ """ /// CHECK-START: MyMethod MyPass """ + checkerString c1String = \ """ begin_compilation name "MyMethod" method "MyMethod" date 1234 end_compilation begin_cfg name "MyPass" """ + c1String + \ """ end_cfg """ checkerFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(ToUnicode(checkerString))) c1File = ParseC1visualizerStream("<c1-file>", io.StringIO(ToUnicode(c1String))) assert len(checkerFile.testCases) == 1 assert len(c1File.passes) == 1 MatchTestCase(checkerFile.testCases[0], c1File.passes[0]) def assertDoesNotMatch(self, checkerString, c1String): with self.assertRaises(MatchFailedException): self.assertMatches(checkerString, c1String) def test_Text(self): self.assertMatches("/// CHECK: foo bar", "foo bar") self.assertDoesNotMatch("/// CHECK: foo bar", "abc def") def test_Pattern(self): self.assertMatches("/// CHECK: abc {{de.}}", "abc de#") self.assertDoesNotMatch("/// CHECK: abc {{de.}}", "abc d#f") def test_Variables(self): self.assertMatches( """ /// CHECK: foo<<X:.>>bar /// CHECK: abc<<X>>def """, """ foo0bar abc0def """) self.assertMatches( """ /// CHECK: foo<<X:([0-9]+)>>bar /// CHECK: abc<<X>>def /// CHECK: ### <<X>> ### """, """ foo1234bar abc1234def ### 1234 ### """) self.assertDoesNotMatch( """ /// CHECK: foo<<X:([0-9]+)>>bar /// CHECK: abc<<X>>def """, """ foo1234bar abc1235def """) def test_WholeWordMustMatch(self): self.assertMatches("/// CHECK: b{{.}}r", "abc bar def") self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc Xbar def") self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc barX def") self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc b r def") def test_InOrderAssertions(self): self.assertMatches( """ /// CHECK: foo /// CHECK: bar """, """ foo bar """) self.assertDoesNotMatch( """ /// CHECK: foo /// CHECK: bar """, """ bar foo """) def test_NextLineAssertions(self): self.assertMatches( """ /// CHECK: foo /// CHECK-NEXT: bar /// CHECK-NEXT: abc /// CHECK: def """, """ foo bar abc def """) self.assertMatches( """ /// CHECK: foo /// CHECK-NEXT: bar /// CHECK: def """, """ foo bar abc def """) self.assertDoesNotMatch( """ /// CHECK: foo /// CHECK-NEXT: bar """, """ foo abc bar """) self.assertDoesNotMatch( """ /// CHECK: foo /// CHECK-NEXT: bar """, """ bar foo abc """) def test_DagAssertions(self): self.assertMatches( """ /// CHECK-DAG: foo /// CHECK-DAG: bar """, """ foo bar """) self.assertMatches( """ /// CHECK-DAG: foo /// CHECK-DAG: bar """, """ bar foo """) def test_DagAssertionsScope(self): self.assertMatches( """ /// CHECK: foo /// CHECK-DAG: abc /// CHECK-DAG: def /// CHECK: bar """, """ foo def abc bar """) self.assertDoesNotMatch( """ /// CHECK: foo /// CHECK-DAG: abc /// CHECK-DAG: def /// CHECK: bar """, """ foo abc bar def """) self.assertDoesNotMatch( """ /// CHECK: foo /// CHECK-DAG: abc /// CHECK-DAG: def /// CHECK: bar """, """ foo def bar abc """) def test_NotAssertions(self): self.assertMatches( """ /// CHECK-NOT: foo """, """ abc def """) self.assertDoesNotMatch( """ /// CHECK-NOT: foo """, """ abc foo def """) self.assertDoesNotMatch( """ /// CHECK-NOT: foo /// CHECK-NOT: bar """, """ abc def bar """) def test_NotAssertionsScope(self): self.assertMatches( """ /// CHECK: abc /// CHECK-NOT: foo /// CHECK: def """, """ abc def """) self.assertMatches( """ /// CHECK: abc /// CHECK-NOT: foo /// CHECK: def """, """ abc def foo """) self.assertDoesNotMatch( """ /// CHECK: abc /// CHECK-NOT: foo /// CHECK: def """, """ abc foo def """) def test_LineOnlyMatchesOnce(self): self.assertMatches( """ /// CHECK-DAG: foo /// CHECK-DAG: foo """, """ foo abc foo """) self.assertDoesNotMatch( """ /// CHECK-DAG: foo /// CHECK-DAG: foo """, """ foo abc bar """) def test_EvalAssertions(self): self.assertMatches("/// CHECK-EVAL: True", "foo") self.assertDoesNotMatch("/// CHECK-EVAL: False", "foo") self.assertMatches("/// CHECK-EVAL: 1 + 2 == 3", "foo") self.assertDoesNotMatch("/// CHECK-EVAL: 1 + 2 == 4", "foo") twoVarTestCase = """ /// CHECK-DAG: <<X:\d+>> <<Y:\d+>> /// CHECK-EVAL: <<X>> > <<Y>> """ self.assertMatches(twoVarTestCase, "42 41"); self.assertDoesNotMatch(twoVarTestCase, "42 43")