Merge "Revert "ART: Split Checker into smaller files""
diff --git a/test/run-test b/test/run-test
index 239681f..2873a35 100755
--- a/test/run-test
+++ b/test/run-test
@@ -39,7 +39,7 @@
 else
   tmp_dir="${TMPDIR}/$USER/${test_dir}"
 fi
-checker="${progdir}/../tools/checker/checker.py"
+checker="${progdir}/../tools/checker.py"
 
 export JAVA="java"
 export JAVAC="javac -g"
diff --git a/tools/checker.py b/tools/checker.py
new file mode 100755
index 0000000..08ad57b
--- /dev/null
+++ b/tools/checker.py
@@ -0,0 +1,778 @@
+#!/usr/bin/env python2
+#
+# 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.
+
+
+# Checker is a testing tool which compiles a given test file and compares the
+# state of the control-flow graph before and after each optimization pass
+# against a set of assertions specified alongside the tests.
+#
+# Tests are written in Java, turned into DEX and compiled with the Optimizing
+# compiler. "Check lines" are assertions formatted as comments of the Java file.
+# They begin with prefix 'CHECK' followed by a pattern that the engine attempts
+# to match in the compiler-generated output.
+#
+# Assertions are tested in groups which correspond to the individual compiler
+# passes. Each group of check lines therefore must start with a 'CHECK-START'
+# header which specifies the output group it should be tested against. The group
+# name must exactly match one of the groups recognized in the output (they can
+# be listed with the '--list-groups' command-line flag).
+#
+# Matching of check lines is carried out in the order of appearance in the
+# source file. There are three types of check lines:
+#  - CHECK:     Must match an output line which appears in the output group
+#               later than lines matched against any preceeding checks. Output
+#               lines must therefore match the check lines in the same order.
+#               These are referred to as "in-order" checks in the code.
+#  - CHECK-DAG: Must match an output line which appears in the output group
+#               later than lines matched against any preceeding in-order checks.
+#               In other words, the order of output lines does not matter
+#               between consecutive DAG checks.
+#  - CHECK-NOT: Must not match any output line which appears in the output group
+#               later than lines matched against any preceeding checks and
+#               earlier than lines matched against any subsequent checks.
+#               Surrounding non-negative checks (or boundaries of the group)
+#               therefore create a scope within which the assertion is verified.
+#
+# Check-line patterns are treated as plain text rather than regular expressions
+# but are whitespace agnostic.
+#
+# Actual regex patterns can be inserted enclosed in '{{' and '}}' brackets. If
+# curly brackets need to be used inside the body of the regex, they need to be
+# enclosed in round brackets. For example, the pattern '{{foo{2}}}' will parse
+# the invalid regex 'foo{2', but '{{(fo{2})}}' will match 'foo'.
+#
+# Regex patterns can be named and referenced later. A new variable is defined
+# with '[[name:regex]]' and can be referenced with '[[name]]'. Variables are
+# only valid within the scope of the defining group. Within a group they cannot
+# be redefined or used undefined.
+#
+# Example:
+#   The following assertions can be placed in a Java source file:
+#
+#   // CHECK-START: int MyClass.MyMethod() constant_folding (after)
+#   // CHECK:         [[ID:i[0-9]+]] IntConstant {{11|22}}
+#   // CHECK:                        Return [ [[ID]] ]
+#
+#   The engine will attempt to match the check lines against the output of the
+#   group named on the first line. Together they verify that the CFG after
+#   constant folding returns an integer constant with value either 11 or 22.
+#
+
+from __future__ import print_function
+import argparse
+import os
+import re
+import shutil
+import sys
+import tempfile
+
+class Logger(object):
+
+  class Level(object):
+    NoOutput, Error, Info = range(3)
+
+  class Color(object):
+    Default, Blue, Gray, Purple, Red = range(5)
+
+    @staticmethod
+    def terminalCode(color, out=sys.stdout):
+      if not out.isatty():
+        return ''
+      elif color == Logger.Color.Blue:
+        return '\033[94m'
+      elif color == Logger.Color.Gray:
+        return '\033[37m'
+      elif color == Logger.Color.Purple:
+        return '\033[95m'
+      elif color == Logger.Color.Red:
+        return '\033[91m'
+      else:
+        return '\033[0m'
+
+  Verbosity = Level.Info
+
+  @staticmethod
+  def log(text, level=Level.Info, color=Color.Default, newLine=True, out=sys.stdout):
+    if level <= Logger.Verbosity:
+      text = Logger.Color.terminalCode(color, out) + text + \
+             Logger.Color.terminalCode(Logger.Color.Default, out)
+      if newLine:
+        print(text, file=out)
+      else:
+        print(text, end="", file=out)
+      out.flush()
+
+  @staticmethod
+  def fail(msg, file=None, line=-1):
+    location = ""
+    if file:
+      location += file + ":"
+    if line > 0:
+      location += str(line) + ":"
+    if location:
+      location += " "
+
+    Logger.log(location, Logger.Level.Error, color=Logger.Color.Gray, newLine=False, out=sys.stderr)
+    Logger.log("error: ", Logger.Level.Error, color=Logger.Color.Red, newLine=False, out=sys.stderr)
+    Logger.log(msg, Logger.Level.Error, out=sys.stderr)
+    sys.exit(msg)
+
+  @staticmethod
+  def startTest(name):
+    Logger.log("TEST ", color=Logger.Color.Purple, newLine=False)
+    Logger.log(name + "... ", newLine=False)
+
+  @staticmethod
+  def testPassed():
+    Logger.log("PASS", color=Logger.Color.Blue)
+
+  @staticmethod
+  def testFailed(msg, file=None, line=-1):
+    Logger.log("FAIL", color=Logger.Color.Red)
+    Logger.fail(msg, file, line)
+
+class CommonEqualityMixin:
+  """Mixin for class equality as equality of the fields."""
+  def __eq__(self, other):
+    return (isinstance(other, self.__class__)
+           and self.__dict__ == other.__dict__)
+
+  def __ne__(self, other):
+    return not self.__eq__(other)
+
+  def __repr__(self):
+    return "<%s: %s>" % (type(self).__name__, str(self.__dict__))
+
+
+class CheckElement(CommonEqualityMixin):
+  """Single element of the check line."""
+
+  class Variant(object):
+    """Supported language constructs."""
+    Text, Pattern, VarRef, VarDef, Separator = range(5)
+
+  rStartOptional = r"("
+  rEndOptional = r")?"
+
+  rName = r"([a-zA-Z][a-zA-Z0-9]*)"
+  rRegex = r"(.+?)"
+  rPatternStartSym = r"(\{\{)"
+  rPatternEndSym = r"(\}\})"
+  rVariableStartSym = r"(\[\[)"
+  rVariableEndSym = r"(\]\])"
+  rVariableSeparator = r"(:)"
+
+  regexPattern = rPatternStartSym + rRegex + rPatternEndSym
+  regexVariable = rVariableStartSym + \
+                    rName + \
+                    (rStartOptional + rVariableSeparator + rRegex + rEndOptional) + \
+                  rVariableEndSym
+
+  def __init__(self, variant, name, pattern):
+    self.variant = variant
+    self.name = name
+    self.pattern = pattern
+
+  @staticmethod
+  def newSeparator():
+    return CheckElement(CheckElement.Variant.Separator, None, None)
+
+  @staticmethod
+  def parseText(text):
+    return CheckElement(CheckElement.Variant.Text, None, re.escape(text))
+
+  @staticmethod
+  def parsePattern(patternElem):
+    return CheckElement(CheckElement.Variant.Pattern, None, patternElem[2:-2])
+
+  @staticmethod
+  def parseVariable(varElem):
+    colonPos = varElem.find(":")
+    if colonPos == -1:
+      # Variable reference
+      name = varElem[2:-2]
+      return CheckElement(CheckElement.Variant.VarRef, name, None)
+    else:
+      # Variable definition
+      name = varElem[2:colonPos]
+      body = varElem[colonPos+1:-2]
+      return CheckElement(CheckElement.Variant.VarDef, name, body)
+
+class CheckLine(CommonEqualityMixin):
+  """Representation of a single assertion in the check file formed of one or
+     more regex elements. Matching against an output line is successful only
+     if all regex elements can be matched in the given order."""
+
+  class Variant(object):
+    """Supported types of assertions."""
+    InOrder, DAG, Not = range(3)
+
+  def __init__(self, content, variant=Variant.InOrder, fileName=None, lineNo=-1):
+    self.fileName = fileName
+    self.lineNo = lineNo
+    self.content = content.strip()
+
+    self.variant = variant
+    self.lineParts = self.__parse(self.content)
+    if not self.lineParts:
+      Logger.fail("Empty check line", self.fileName, self.lineNo)
+
+    if self.variant == CheckLine.Variant.Not:
+      for elem in self.lineParts:
+        if elem.variant == CheckElement.Variant.VarDef:
+          Logger.fail("CHECK-NOT lines cannot define variables", self.fileName, self.lineNo)
+
+  def __eq__(self, other):
+    return (isinstance(other, self.__class__) and
+            self.variant == other.variant and
+            self.lineParts == other.lineParts)
+
+  # Returns True if the given Match object was at the beginning of the line.
+  def __isMatchAtStart(self, match):
+    return (match is not None) and (match.start() == 0)
+
+  # Takes in a list of Match objects and returns the minimal start point among
+  # them. If there aren't any successful matches it returns the length of
+  # the searched string.
+  def __firstMatch(self, matches, string):
+    starts = map(lambda m: len(string) if m is None else m.start(), matches)
+    return min(starts)
+
+  # This method parses the content of a check line stripped of the initial
+  # comment symbol and the CHECK keyword.
+  def __parse(self, line):
+    lineParts = []
+    # Loop as long as there is something to parse.
+    while line:
+      # Search for the nearest occurrence of the special markers.
+      matchWhitespace = re.search(r"\s+", line)
+      matchPattern = re.search(CheckElement.regexPattern, line)
+      matchVariable = re.search(CheckElement.regexVariable, line)
+
+      # If one of the above was identified at the current position, extract them
+      # from the line, parse them and add to the list of line parts.
+      if self.__isMatchAtStart(matchWhitespace):
+        # A whitespace in the check line creates a new separator of line parts.
+        # This allows for ignored output between the previous and next parts.
+        line = line[matchWhitespace.end():]
+        lineParts.append(CheckElement.newSeparator())
+      elif self.__isMatchAtStart(matchPattern):
+        pattern = line[0:matchPattern.end()]
+        line = line[matchPattern.end():]
+        lineParts.append(CheckElement.parsePattern(pattern))
+      elif self.__isMatchAtStart(matchVariable):
+        var = line[0:matchVariable.end()]
+        line = line[matchVariable.end():]
+        lineParts.append(CheckElement.parseVariable(var))
+      else:
+        # If we're not currently looking at a special marker, this is a plain
+        # text match all the way until the first special marker (or the end
+        # of the line).
+        firstMatch = self.__firstMatch([ matchWhitespace, matchPattern, matchVariable ], line)
+        text = line[0:firstMatch]
+        line = line[firstMatch:]
+        lineParts.append(CheckElement.parseText(text))
+    return lineParts
+
+  # Returns the regex pattern to be matched in the output line. Variable
+  # references are substituted with their current values provided in the
+  # 'varState' argument.
+  # An exception is raised if a referenced variable is undefined.
+  def __generatePattern(self, linePart, varState):
+    if linePart.variant == CheckElement.Variant.VarRef:
+      try:
+        return re.escape(varState[linePart.name])
+      except KeyError:
+        Logger.testFailed("Use of undefined variable \"" + linePart.name + "\"",
+                          self.fileName, self.lineNo)
+    else:
+      return linePart.pattern
+
+  def __isSeparated(self, outputLine, matchStart):
+    return (matchStart == 0) or (outputLine[matchStart - 1:matchStart].isspace())
+
+  # Attempts to match the check line against a line from the output file with
+  # the given initial variable values. It returns the new variable state if
+  # successful and None otherwise.
+  def match(self, outputLine, initialVarState):
+    # Do the full matching on a shadow copy of the variable state. If the
+    # matching fails half-way, we will not need to revert the state.
+    varState = dict(initialVarState)
+
+    matchStart = 0
+    isAfterSeparator = True
+
+    # Now try to parse all of the parts of the check line in the right order.
+    # Variable values are updated on-the-fly, meaning that a variable can
+    # be referenced immediately after its definition.
+    for part in self.lineParts:
+      if part.variant == CheckElement.Variant.Separator:
+        isAfterSeparator = True
+        continue
+
+      # Find the earliest match for this line part.
+      pattern = self.__generatePattern(part, varState)
+      while True:
+        match = re.search(pattern, outputLine[matchStart:])
+        if (match is None) or (not isAfterSeparator and not self.__isMatchAtStart(match)):
+          return None
+        matchEnd = matchStart + match.end()
+        matchStart += match.start()
+
+        # Check if this is a valid match if we expect a whitespace separator
+        # before the matched text. Otherwise loop and look for another match.
+        if not isAfterSeparator or self.__isSeparated(outputLine, matchStart):
+          break
+        else:
+          matchStart += 1
+
+      if part.variant == CheckElement.Variant.VarDef:
+        if part.name in varState:
+          Logger.testFailed("Multiple definitions of variable \"" + part.name + "\"",
+                            self.fileName, self.lineNo)
+        varState[part.name] = outputLine[matchStart:matchEnd]
+
+      matchStart = matchEnd
+      isAfterSeparator = False
+
+    # All parts were successfully matched. Return the new variable state.
+    return varState
+
+
+class CheckGroup(CommonEqualityMixin):
+  """Represents a named collection of check lines which are to be matched
+     against an output group of the same name."""
+
+  def __init__(self, name, lines, fileName=None, lineNo=-1):
+    self.fileName = fileName
+    self.lineNo = lineNo
+
+    if not name:
+      Logger.fail("Check group does not have a name", self.fileName, self.lineNo)
+    if not lines:
+      Logger.fail("Check group does not have a body", self.fileName, self.lineNo)
+
+    self.name = name
+    self.lines = lines
+
+  def __eq__(self, other):
+    return (isinstance(other, self.__class__) and
+            self.name == other.name and
+            self.lines == other.lines)
+
+  def __headAndTail(self, list):
+    return list[0], list[1:]
+
+  # Splits a list of check lines at index 'i' such that lines[i] is the first
+  # element whose variant is not equal to the given parameter.
+  def __splitByVariant(self, lines, variant):
+    i = 0
+    while i < len(lines) and lines[i].variant == variant:
+      i += 1
+    return lines[:i], lines[i:]
+
+  # Extracts the first sequence of check lines which are independent of each
+  # other's match location, i.e. either consecutive DAG lines or a single
+  # InOrder line. Any Not lines preceeding this sequence are also extracted.
+  def __nextIndependentChecks(self, checkLines):
+    notChecks, checkLines = self.__splitByVariant(checkLines, CheckLine.Variant.Not)
+    if not checkLines:
+      return notChecks, [], []
+
+    head, tail = self.__headAndTail(checkLines)
+    if head.variant == CheckLine.Variant.InOrder:
+      return notChecks, [head], tail
+    else:
+      assert head.variant == CheckLine.Variant.DAG
+      independentChecks, checkLines = self.__splitByVariant(checkLines, CheckLine.Variant.DAG)
+      return notChecks, independentChecks, checkLines
+
+  # If successful, returns the line number of the first output line matching the
+  # check line and the updated variable state. Otherwise returns -1 and None,
+  # respectively. The 'lineFilter' parameter can be used to supply a list of
+  # line numbers (counting from 1) which should be skipped.
+  def __findFirstMatch(self, checkLine, outputLines, startLineNo, lineFilter, varState):
+    matchLineNo = startLineNo
+    for outputLine in outputLines:
+      if matchLineNo not in lineFilter:
+        newVarState = checkLine.match(outputLine, varState)
+        if newVarState is not None:
+          return matchLineNo, newVarState
+      matchLineNo += 1
+    return -1, None
+
+  # Matches the given positive check lines against the output in order of
+  # appearance. Variable state is propagated but the scope of the search remains
+  # the same for all checks. Each output line can only be matched once.
+  # If all check lines are matched, the resulting variable state is returned
+  # together with the remaining output. The function also returns output lines
+  # which appear before either of the matched lines so they can be tested
+  # against Not checks.
+  def __matchIndependentChecks(self, checkLines, outputLines, startLineNo, varState):
+    # If no checks are provided, skip over the entire output.
+    if not checkLines:
+      return outputLines, [], startLineNo + len(outputLines), varState
+
+    # Keep track of which lines have been matched.
+    matchedLines = []
+
+    # Find first unused output line which matches each check line.
+    for checkLine in checkLines:
+      matchLineNo, varState = \
+        self.__findFirstMatch(checkLine, outputLines, startLineNo, matchedLines, varState)
+      if varState is None:
+        Logger.testFailed("Could not match check line \"" + checkLine.content + "\" " +
+                          "starting from output line " + str(startLineNo),
+                          self.fileName, checkLine.lineNo)
+      matchedLines.append(matchLineNo)
+
+    # Return new variable state and the output lines which lie outside the
+    # match locations of this independent group.
+    minMatchLineNo = min(matchedLines)
+    maxMatchLineNo = max(matchedLines)
+    preceedingLines = outputLines[:minMatchLineNo - startLineNo]
+    remainingLines = outputLines[maxMatchLineNo - startLineNo + 1:]
+    return preceedingLines, remainingLines, maxMatchLineNo + 1, varState
+
+  # Makes sure that the given check lines do not match any of the given output
+  # lines. Variable state does not change.
+  def __matchNotLines(self, checkLines, outputLines, startLineNo, varState):
+    for checkLine in checkLines:
+      assert checkLine.variant == CheckLine.Variant.Not
+      matchLineNo, matchVarState = \
+        self.__findFirstMatch(checkLine, outputLines, startLineNo, [], varState)
+      if matchVarState is not None:
+        Logger.testFailed("CHECK-NOT line \"" + checkLine.content + "\" matches output line " + \
+                          str(matchLineNo), self.fileName, checkLine.lineNo)
+
+  # Matches the check lines in this group against an output group. It is
+  # responsible for running the checks in the right order and scope, and
+  # for propagating the variable state between the check lines.
+  def match(self, outputGroup):
+    varState = {}
+    checkLines = self.lines
+    outputLines = outputGroup.body
+    startLineNo = outputGroup.lineNo
+
+    while checkLines:
+      # Extract the next sequence of location-independent checks to be matched.
+      notChecks, independentChecks, checkLines = self.__nextIndependentChecks(checkLines)
+
+      # Match the independent checks.
+      notOutput, outputLines, newStartLineNo, newVarState = \
+        self.__matchIndependentChecks(independentChecks, outputLines, startLineNo, varState)
+
+      # Run the Not checks against the output lines which lie between the last
+      # two independent groups or the bounds of the output.
+      self.__matchNotLines(notChecks, notOutput, startLineNo, varState)
+
+      # Update variable state.
+      startLineNo = newStartLineNo
+      varState = newVarState
+
+class OutputGroup(CommonEqualityMixin):
+  """Represents a named part of the test output against which a check group of
+     the same name is to be matched."""
+
+  def __init__(self, name, body, fileName=None, lineNo=-1):
+    if not name:
+      Logger.fail("Output group does not have a name", fileName, lineNo)
+    if not body:
+      Logger.fail("Output group does not have a body", fileName, lineNo)
+
+    self.name = name
+    self.body = body
+    self.lineNo = lineNo
+
+  def __eq__(self, other):
+    return (isinstance(other, self.__class__) and
+            self.name == other.name and
+            self.body == other.body)
+
+
+class FileSplitMixin(object):
+  """Mixin for representing text files which need to be split into smaller
+     chunks before being parsed."""
+
+  def _parseStream(self, stream):
+    lineNo = 0
+    allGroups = []
+    currentGroup = None
+
+    for line in stream:
+      lineNo += 1
+      line = line.strip()
+      if not line:
+        continue
+
+      # Let the child class process the line and return information about it.
+      # The _processLine method can modify the content of the line (or delete it
+      # entirely) and specify whether it starts a new group.
+      processedLine, newGroupName = self._processLine(line, lineNo)
+      if newGroupName is not None:
+        currentGroup = (newGroupName, [], lineNo)
+        allGroups.append(currentGroup)
+      if processedLine is not None:
+        if currentGroup is not None:
+          currentGroup[1].append(processedLine)
+        else:
+          self._exceptionLineOutsideGroup(line, lineNo)
+
+    # Finally, take the generated line groups and let the child class process
+    # each one before storing the final outcome.
+    return list(map(lambda group: self._processGroup(group[0], group[1], group[2]), allGroups))
+
+
+class CheckFile(FileSplitMixin):
+  """Collection of check groups extracted from the input test file."""
+
+  def __init__(self, prefix, checkStream, fileName=None):
+    self.fileName = fileName
+    self.prefix = prefix
+    self.groups = self._parseStream(checkStream)
+
+  # Attempts to parse a check line. The regex searches for a comment symbol
+  # followed by the CHECK keyword, given attribute and a colon at the very
+  # beginning of the line. Whitespaces are ignored.
+  def _extractLine(self, prefix, line):
+    rIgnoreWhitespace = r"\s*"
+    rCommentSymbols = [r"//", r"#"]
+    regexPrefix = rIgnoreWhitespace + \
+                  r"(" + r"|".join(rCommentSymbols) + r")" + \
+                  rIgnoreWhitespace + \
+                  prefix + r":"
+
+    # The 'match' function succeeds only if the pattern is matched at the
+    # beginning of the line.
+    match = re.match(regexPrefix, line)
+    if match is not None:
+      return line[match.end():].strip()
+    else:
+      return None
+
+  # This function is invoked on each line of the check file and returns a pair
+  # which instructs the parser how the line should be handled. If the line is to
+  # be included in the current check group, it is returned in the first value.
+  # If the line starts a new check group, the name of the group is returned in
+  # the second value.
+  def _processLine(self, line, lineNo):
+    # Lines beginning with 'CHECK-START' start a new check group.
+    startLine = self._extractLine(self.prefix + "-START", line)
+    if startLine is not None:
+      return None, startLine
+
+    # Lines starting only with 'CHECK' are matched in order.
+    plainLine = self._extractLine(self.prefix, line)
+    if plainLine is not None:
+      return (plainLine, CheckLine.Variant.InOrder, lineNo), None
+
+    # 'CHECK-DAG' lines are no-order assertions.
+    dagLine = self._extractLine(self.prefix + "-DAG", line)
+    if dagLine is not None:
+      return (dagLine, CheckLine.Variant.DAG, lineNo), None
+
+    # 'CHECK-NOT' lines are no-order negative assertions.
+    notLine = self._extractLine(self.prefix + "-NOT", line)
+    if notLine is not None:
+      return (notLine, CheckLine.Variant.Not, lineNo), None
+
+    # Other lines are ignored.
+    return None, None
+
+  def _exceptionLineOutsideGroup(self, line, lineNo):
+    Logger.fail("Check line not inside a group", self.fileName, lineNo)
+
+  # Constructs a check group from the parser-collected check lines.
+  def _processGroup(self, name, lines, lineNo):
+    checkLines = list(map(lambda line: CheckLine(line[0], line[1], self.fileName, line[2]), lines))
+    return CheckGroup(name, checkLines, self.fileName, lineNo)
+
+  def match(self, outputFile):
+    for checkGroup in self.groups:
+      # TODO: Currently does not handle multiple occurrences of the same group
+      # name, e.g. when a pass is run multiple times. It will always try to
+      # match a check group against the first output group of the same name.
+      outputGroup = outputFile.findGroup(checkGroup.name)
+      if outputGroup is None:
+        Logger.fail("Group \"" + checkGroup.name + "\" not found in the output",
+                    self.fileName, checkGroup.lineNo)
+      Logger.startTest(checkGroup.name)
+      checkGroup.match(outputGroup)
+      Logger.testPassed()
+
+
+class OutputFile(FileSplitMixin):
+  """Representation of the output generated by the test and split into groups
+     within which the checks are performed.
+
+     C1visualizer format is parsed with a state machine which differentiates
+     between the 'compilation' and 'cfg' blocks. The former marks the beginning
+     of a method. It is parsed for the method's name but otherwise ignored. Each
+     subsequent CFG block represents one stage of the compilation pipeline and
+     is parsed into an output group named "<method name> <pass name>".
+     """
+
+  class ParsingState:
+    OutsideBlock, InsideCompilationBlock, StartingCfgBlock, InsideCfgBlock = range(4)
+
+  def __init__(self, outputStream, fileName=None):
+    self.fileName = fileName
+
+    # Initialize the state machine
+    self.lastMethodName = None
+    self.state = OutputFile.ParsingState.OutsideBlock
+    self.groups = self._parseStream(outputStream)
+
+  # This function is invoked on each line of the output file and returns a pair
+  # which instructs the parser how the line should be handled. If the line is to
+  # be included in the current group, it is returned in the first value. If the
+  # line starts a new output group, the name of the group is returned in the
+  # second value.
+  def _processLine(self, line, lineNo):
+    if self.state == OutputFile.ParsingState.StartingCfgBlock:
+      # Previous line started a new 'cfg' block which means that this one must
+      # contain the name of the pass (this is enforced by C1visualizer).
+      if re.match("name\s+\"[^\"]+\"", line):
+        # Extract the pass name, prepend it with the name of the method and
+        # return as the beginning of a new group.
+        self.state = OutputFile.ParsingState.InsideCfgBlock
+        return (None, self.lastMethodName + " " + line.split("\"")[1])
+      else:
+        Logger.fail("Expected output group name", self.fileName, lineNo)
+
+    elif self.state == OutputFile.ParsingState.InsideCfgBlock:
+      if line == "end_cfg":
+        self.state = OutputFile.ParsingState.OutsideBlock
+        return (None, None)
+      else:
+        return (line, None)
+
+    elif self.state == OutputFile.ParsingState.InsideCompilationBlock:
+      # Search for the method's name. Format: method "<name>"
+      if re.match("method\s+\"[^\"]*\"", line):
+        methodName = line.split("\"")[1].strip()
+        if not methodName:
+          Logger.fail("Empty method name in output", self.fileName, lineNo)
+        self.lastMethodName = methodName
+      elif line == "end_compilation":
+        self.state = OutputFile.ParsingState.OutsideBlock
+      return (None, None)
+
+    else:
+      assert self.state == OutputFile.ParsingState.OutsideBlock
+      if line == "begin_cfg":
+        # The line starts a new group but we'll wait until the next line from
+        # which we can extract the name of the pass.
+        if self.lastMethodName is None:
+          Logger.fail("Expected method header", self.fileName, lineNo)
+        self.state = OutputFile.ParsingState.StartingCfgBlock
+        return (None, None)
+      elif line == "begin_compilation":
+        self.state = OutputFile.ParsingState.InsideCompilationBlock
+        return (None, None)
+      else:
+        Logger.fail("Output line not inside a group", self.fileName, lineNo)
+
+  # Constructs an output group from the parser-collected output lines.
+  def _processGroup(self, name, lines, lineNo):
+    return OutputGroup(name, lines, self.fileName, lineNo + 1)
+
+  def findGroup(self, name):
+    for group in self.groups:
+      if group.name == name:
+        return group
+    return None
+
+
+def ParseArguments():
+  parser = argparse.ArgumentParser()
+  parser.add_argument("tested_file",
+                      help="text file the checks should be verified against")
+  parser.add_argument("source_path", nargs="?",
+                      help="path to file/folder with checking annotations")
+  parser.add_argument("--check-prefix", dest="check_prefix", default="CHECK", metavar="PREFIX",
+                      help="prefix of checks in the test files (default: CHECK)")
+  parser.add_argument("--list-groups", dest="list_groups", action="store_true",
+                      help="print a list of all groups found in the tested file")
+  parser.add_argument("--dump-group", dest="dump_group", metavar="GROUP",
+                      help="print the contents of an output group")
+  parser.add_argument("-q", "--quiet", action="store_true",
+                      help="print only errors")
+  return parser.parse_args()
+
+
+def ListGroups(outputFilename):
+  outputFile = OutputFile(open(outputFilename, "r"))
+  for group in outputFile.groups:
+    Logger.log(group.name)
+
+
+def DumpGroup(outputFilename, groupName):
+  outputFile = OutputFile(open(outputFilename, "r"))
+  group = outputFile.findGroup(groupName)
+  if group:
+    lineNo = group.lineNo
+    maxLineNo = lineNo + len(group.body)
+    lenLineNo = len(str(maxLineNo)) + 2
+    for line in group.body:
+      Logger.log((str(lineNo) + ":").ljust(lenLineNo) + line)
+      lineNo += 1
+  else:
+    Logger.fail("Group \"" + groupName + "\" not found in the output")
+
+
+# Returns a list of files to scan for check annotations in the given path. Path
+# to a file is returned as a single-element list, directories are recursively
+# traversed and all '.java' files returned.
+def FindCheckFiles(path):
+  if not path:
+    Logger.fail("No source path provided")
+  elif os.path.isfile(path):
+    return [ path ]
+  elif os.path.isdir(path):
+    foundFiles = []
+    for root, dirs, files in os.walk(path):
+      for file in files:
+        extension = os.path.splitext(file)[1]
+        if extension in [".java", ".smali"]:
+          foundFiles.append(os.path.join(root, file))
+    return foundFiles
+  else:
+    Logger.fail("Source path \"" + path + "\" not found")
+
+
+def RunChecks(checkPrefix, checkPath, outputFilename):
+  outputBaseName = os.path.basename(outputFilename)
+  outputFile = OutputFile(open(outputFilename, "r"), outputBaseName)
+
+  for checkFilename in FindCheckFiles(checkPath):
+    checkBaseName = os.path.basename(checkFilename)
+    checkFile = CheckFile(checkPrefix, open(checkFilename, "r"), checkBaseName)
+    checkFile.match(outputFile)
+
+
+if __name__ == "__main__":
+  args = ParseArguments()
+
+  if args.quiet:
+    Logger.Verbosity = Logger.Level.Error
+
+  if args.list_groups:
+    ListGroups(args.tested_file)
+  elif args.dump_group:
+    DumpGroup(args.tested_file, args.dump_group)
+  else:
+    RunChecks(args.check_prefix, args.source_path, args.tested_file)
diff --git a/tools/checker/README b/tools/checker/README
deleted file mode 100644
index 9b23ae9..0000000
--- a/tools/checker/README
+++ /dev/null
@@ -1,54 +0,0 @@
-Checker is a testing tool which compiles a given test file and compares the
-state of the control-flow graph before and after each optimization pass
-against a set of assertions specified alongside the tests.
-
-Tests are written in Java, turned into DEX and compiled with the Optimizing
-compiler. "Check lines" are assertions formatted as comments of the Java file.
-They begin with prefix 'CHECK' followed by a pattern that the engine attempts
-to match in the compiler-generated output.
-
-Assertions are tested in groups which correspond to the individual compiler
-passes. Each group of check lines therefore must start with a 'CHECK-START'
-header which specifies the output group it should be tested against. The group
-name must exactly match one of the groups recognized in the output (they can
-be listed with the '--list-groups' command-line flag).
-
-Matching of check lines is carried out in the order of appearance in the
-source file. There are three types of check lines:
- - CHECK:     Must match an output line which appears in the output group
-              later than lines matched against any preceeding checks. Output
-              lines must therefore match the check lines in the same order.
-              These are referred to as "in-order" checks in the code.
- - CHECK-DAG: Must match an output line which appears in the output group
-              later than lines matched against any preceeding in-order checks.
-              In other words, the order of output lines does not matter
-              between consecutive DAG checks.
- - CHECK-NOT: Must not match any output line which appears in the output group
-              later than lines matched against any preceeding checks and
-              earlier than lines matched against any subsequent checks.
-              Surrounding non-negative checks (or boundaries of the group)
-              therefore create a scope within which the assertion is verified.
-
-Check-line patterns are treated as plain text rather than regular expressions
-but are whitespace agnostic.
-
-Actual regex patterns can be inserted enclosed in '{{' and '}}' brackets. If
-curly brackets need to be used inside the body of the regex, they need to be
-enclosed in round brackets. For example, the pattern '{{foo{2}}}' will parse
-the invalid regex 'foo{2', but '{{(fo{2})}}' will match 'foo'.
-
-Regex patterns can be named and referenced later. A new variable is defined
-with '[[name:regex]]' and can be referenced with '[[name]]'. Variables are
-only valid within the scope of the defining group. Within a group they cannot
-be redefined or used undefined.
-
-Example:
-  The following assertions can be placed in a Java source file:
-
-  // CHECK-START: int MyClass.MyMethod() constant_folding (after)
-  // CHECK:         [[ID:i\d+]]  IntConstant {{11|22}}
-  // CHECK:                      Return [ [[ID]] ]
-
-  The engine will attempt to match the check lines against the output of the
-  group named on the first line. Together they verify that the CFG after
-  constant folding returns an integer constant with value either 11 or 22.
diff --git a/tools/checker/checker.py b/tools/checker/checker.py
deleted file mode 100755
index d6c3059..0000000
--- a/tools/checker/checker.py
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env python2
-#
-# Copyright (C) 2015 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.
-
-import argparse
-import os
-
-from common.logger                    import Logger
-from file_format.c1visualizer.parser  import ParseC1visualizerStream
-from file_format.checker.parser       import ParseCheckerStream
-from match.file                       import MatchFiles
-
-def ParseArguments():
-  parser = argparse.ArgumentParser()
-  parser.add_argument("tested_file",
-                      help="text file the checks should be verified against")
-  parser.add_argument("source_path", nargs="?",
-                      help="path to file/folder with checking annotations")
-  parser.add_argument("--check-prefix", dest="check_prefix", default="CHECK", metavar="PREFIX",
-                      help="prefix of checks in the test files (default: CHECK)")
-  parser.add_argument("--list-passes", dest="list_passes", action="store_true",
-                      help="print a list of all passes found in the tested file")
-  parser.add_argument("--dump-pass", dest="dump_pass", metavar="PASS",
-                      help="print a compiler pass dump")
-  parser.add_argument("-q", "--quiet", action="store_true",
-                      help="print only errors")
-  return parser.parse_args()
-
-
-def ListPasses(outputFilename):
-  c1File = ParseC1visualizerStream(os.path.basename(outputFilename), open(outputFilename, "r"))
-  for compiler_pass in c1File.passes:
-    Logger.log(compiler_pass.name)
-
-
-def DumpPass(outputFilename, passName):
-  c1File = ParseC1visualizerStream(os.path.basename(outputFilename), open(outputFilename, "r"))
-  compiler_pass = c1File.findPass(passName)
-  if compiler_pass:
-    maxLineNo = compiler_pass.startLineNo + len(compiler_pass.body)
-    lenLineNo = len(str(maxLineNo)) + 2
-    curLineNo = compiler_pass.startLineNo
-    for line in compiler_pass.body:
-      Logger.log((str(curLineNo) + ":").ljust(lenLineNo) + line)
-      curLineNo += 1
-  else:
-    Logger.fail("Pass \"" + passName + "\" not found in the output")
-
-
-def FindCheckerFiles(path):
-  """ Returns a list of files to scan for check annotations in the given path.
-      Path to a file is returned as a single-element list, directories are
-      recursively traversed and all '.java' files returned.
-  """
-  if not path:
-    Logger.fail("No source path provided")
-  elif os.path.isfile(path):
-    return [ path ]
-  elif os.path.isdir(path):
-    foundFiles = []
-    for root, dirs, files in os.walk(path):
-      for file in files:
-        extension = os.path.splitext(file)[1]
-        if extension in [".java", ".smali"]:
-          foundFiles.append(os.path.join(root, file))
-    return foundFiles
-  else:
-    Logger.fail("Source path \"" + path + "\" not found")
-
-
-def RunTests(checkPrefix, checkPath, outputFilename):
-  c1File = ParseC1visualizerStream(os.path.basename(outputFilename), open(outputFilename, "r"))
-  for checkFilename in FindCheckerFiles(checkPath):
-    checkerFile = ParseCheckerStream(os.path.basename(checkFilename),
-                                     checkPrefix,
-                                     open(checkFilename, "r"))
-    MatchFiles(checkerFile, c1File)
-
-
-if __name__ == "__main__":
-  args = ParseArguments()
-
-  if args.quiet:
-    Logger.Verbosity = Logger.Level.Error
-
-  if args.list_passes:
-    ListPasses(args.tested_file)
-  elif args.dump_pass:
-    DumpPass(args.tested_file, args.dump_pass)
-  else:
-    RunTests(args.check_prefix, args.source_path, args.tested_file)
diff --git a/tools/checker/common/__init__.py b/tools/checker/common/__init__.py
deleted file mode 100644
index 33ef6de..0000000
--- a/tools/checker/common/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (C) 2015 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.
diff --git a/tools/checker/common/logger.py b/tools/checker/common/logger.py
deleted file mode 100644
index 6f71f78..0000000
--- a/tools/checker/common/logger.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright (C) 2015 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 __future__ import print_function
-import sys
-
-class Logger(object):
-
-  class Level(object):
-    NoOutput, Error, Info = range(3)
-
-  class Color(object):
-    Default, Blue, Gray, Purple, Red = range(5)
-
-    @staticmethod
-    def terminalCode(color, out=sys.stdout):
-      if not out.isatty():
-        return ''
-      elif color == Logger.Color.Blue:
-        return '\033[94m'
-      elif color == Logger.Color.Gray:
-        return '\033[37m'
-      elif color == Logger.Color.Purple:
-        return '\033[95m'
-      elif color == Logger.Color.Red:
-        return '\033[91m'
-      else:
-        return '\033[0m'
-
-  Verbosity = Level.Info
-
-  @staticmethod
-  def log(text, level=Level.Info, color=Color.Default, newLine=True, out=sys.stdout):
-    if level <= Logger.Verbosity:
-      text = Logger.Color.terminalCode(color, out) + text + \
-             Logger.Color.terminalCode(Logger.Color.Default, out)
-      if newLine:
-        print(text, file=out)
-      else:
-        print(text, end="", file=out)
-      out.flush()
-
-  @staticmethod
-  def fail(msg, file=None, line=-1):
-    location = ""
-    if file:
-      location += file + ":"
-    if line > 0:
-      location += str(line) + ":"
-    if location:
-      location += " "
-
-    Logger.log(location, Logger.Level.Error, color=Logger.Color.Gray, newLine=False, out=sys.stderr)
-    Logger.log("error: ", Logger.Level.Error, color=Logger.Color.Red, newLine=False, out=sys.stderr)
-    Logger.log(msg, Logger.Level.Error, out=sys.stderr)
-    sys.exit(msg)
-
-  @staticmethod
-  def startTest(name):
-    Logger.log("TEST ", color=Logger.Color.Purple, newLine=False)
-    Logger.log(name + "... ", newLine=False)
-
-  @staticmethod
-  def testPassed():
-    Logger.log("PASS", color=Logger.Color.Blue)
-
-  @staticmethod
-  def testFailed(msg, file=None, line=-1):
-    Logger.log("FAIL", color=Logger.Color.Red)
-    Logger.fail(msg, file, line)
diff --git a/tools/checker/common/mixins.py b/tools/checker/common/mixins.py
deleted file mode 100644
index f44e46d..0000000
--- a/tools/checker/common/mixins.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2015 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.
-
-class EqualityMixin:
-  """ Object equality via equality of dictionaries. """
-
-  def __eq__(self, other):
-    return isinstance(other, self.__class__) \
-       and self.__dict__ == other.__dict__
-
-class PrintableMixin:
-  """ Prints object as name-dictionary pair. """
-
-  def __repr__(self):
-    return "<%s: %s>" % (type(self).__name__, str(self.__dict__))
diff --git a/tools/checker/common/testing.py b/tools/checker/common/testing.py
deleted file mode 100644
index 2014afe..0000000
--- a/tools/checker/common/testing.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2015 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.
-
-def ToUnicode(string):
-  """ Converts a string into Unicode.
-
-  This is a delegate function for the built-in `unicode`. It checks if the input
-  is not `None`, because `unicode` turns it into an actual "None" string.
-  """
-  assert string is not None
-  return unicode(string)
diff --git a/tools/checker/file_format/__init__.py b/tools/checker/file_format/__init__.py
deleted file mode 100644
index 33ef6de..0000000
--- a/tools/checker/file_format/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (C) 2015 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.
diff --git a/tools/checker/file_format/c1visualizer/__init__.py b/tools/checker/file_format/c1visualizer/__init__.py
deleted file mode 100644
index 33ef6de..0000000
--- a/tools/checker/file_format/c1visualizer/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (C) 2015 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.
diff --git a/tools/checker/file_format/c1visualizer/parser.py b/tools/checker/file_format/c1visualizer/parser.py
deleted file mode 100644
index f34161b..0000000
--- a/tools/checker/file_format/c1visualizer/parser.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# Copyright (C) 2015 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.logger                   import Logger
-from file_format.common              import SplitStream
-from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass
-
-import re
-
-class C1ParserState:
-  OutsideBlock, InsideCompilationBlock, StartingCfgBlock, InsideCfgBlock = range(4)
-
-  def __init__(self):
-    self.currentState = C1ParserState.OutsideBlock
-    self.lastMethodName = None
-
-def __parseC1Line(line, lineNo, state, fileName):
-  """ This function is invoked on each line of the output file and returns
-      a pair which instructs the parser how the line should be handled. If the
-      line is to be included in the current group, it is returned in the first
-      value. If the line starts a new output group, the name of the group is
-      returned in the second value.
-  """
-  if state.currentState == C1ParserState.StartingCfgBlock:
-    # Previous line started a new 'cfg' block which means that this one must
-    # contain the name of the pass (this is enforced by C1visualizer).
-    if re.match("name\s+\"[^\"]+\"", line):
-      # Extract the pass name, prepend it with the name of the method and
-      # return as the beginning of a new group.
-      state.currentState = C1ParserState.InsideCfgBlock
-      return (None, state.lastMethodName + " " + line.split("\"")[1])
-    else:
-      Logger.fail("Expected output group name", fileName, lineNo)
-
-  elif state.currentState == C1ParserState.InsideCfgBlock:
-    if line == "end_cfg":
-      state.currentState = C1ParserState.OutsideBlock
-      return (None, None)
-    else:
-      return (line, None)
-
-  elif state.currentState == C1ParserState.InsideCompilationBlock:
-    # Search for the method's name. Format: method "<name>"
-    if re.match("method\s+\"[^\"]*\"", line):
-      methodName = line.split("\"")[1].strip()
-      if not methodName:
-        Logger.fail("Empty method name in output", fileName, lineNo)
-      state.lastMethodName = methodName
-    elif line == "end_compilation":
-      state.currentState = C1ParserState.OutsideBlock
-    return (None, None)
-
-  else:
-    assert state.currentState == C1ParserState.OutsideBlock
-    if line == "begin_cfg":
-      # The line starts a new group but we'll wait until the next line from
-      # which we can extract the name of the pass.
-      if state.lastMethodName is None:
-        Logger.fail("Expected method header", fileName, lineNo)
-      state.currentState = C1ParserState.StartingCfgBlock
-      return (None, None)
-    elif line == "begin_compilation":
-      state.currentState = C1ParserState.InsideCompilationBlock
-      return (None, None)
-    else:
-      Logger.fail("C1visualizer line not inside a group", fileName, lineNo)
-
-def ParseC1visualizerStream(fileName, stream):
-  c1File = C1visualizerFile(fileName)
-  state = C1ParserState()
-  fnProcessLine = lambda line, lineNo: __parseC1Line(line, lineNo, state, fileName)
-  fnLineOutsideChunk = lambda line, lineNo: \
-      Logger.fail("C1visualizer line not inside a group", fileName, lineNo)
-  for passName, passLines, startLineNo in SplitStream(stream, fnProcessLine, fnLineOutsideChunk):
-    C1visualizerPass(c1File, passName, passLines, startLineNo + 1)
-  return c1File
diff --git a/tools/checker/file_format/c1visualizer/struct.py b/tools/checker/file_format/c1visualizer/struct.py
deleted file mode 100644
index 0462765..0000000
--- a/tools/checker/file_format/c1visualizer/struct.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright (C) 2015 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.logger import Logger
-from common.mixins import PrintableMixin
-
-class C1visualizerFile(PrintableMixin):
-
-  def __init__(self, fileName):
-    self.fileName = fileName
-    self.passes = []
-
-  def addPass(self, new_pass):
-    self.passes.append(new_pass)
-
-  def findPass(self, name):
-    for entry in self.passes:
-      if entry.name == name:
-        return entry
-    return None
-
-  def __eq__(self, other):
-    return isinstance(other, self.__class__) \
-       and self.passes == other.passes
-
-
-class C1visualizerPass(PrintableMixin):
-
-  def __init__(self, parent, name, body, startLineNo):
-    self.parent = parent
-    self.name = name
-    self.body = body
-    self.startLineNo = startLineNo
-
-    if not self.name:
-      Logger.fail("C1visualizer pass does not have a name", self.fileName, self.startLineNo)
-    if not self.body:
-      Logger.fail("C1visualizer pass does not have a body", self.fileName, self.startLineNo)
-
-    self.parent.addPass(self)
-
-  @property
-  def fileName(self):
-    return self.parent.fileName
-
-  def __eq__(self, other):
-    return isinstance(other, self.__class__) \
-       and self.name == other.name \
-       and self.body == other.body
diff --git a/tools/checker/file_format/c1visualizer/test.py b/tools/checker/file_format/c1visualizer/test.py
deleted file mode 100644
index 812a4cf..0000000
--- a/tools/checker/file_format/c1visualizer/test.py
+++ /dev/null
@@ -1,105 +0,0 @@
-#!/usr/bin/env python2
-#
-# 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.testing                  import ToUnicode
-from file_format.c1visualizer.parser import ParseC1visualizerStream
-from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass
-
-import io
-import unittest
-
-class C1visualizerParser_Test(unittest.TestCase):
-
-  def createFile(self, passList):
-    """ Creates an instance of CheckerFile from provided info.
-
-    Data format: [ ( <case-name>, [ ( <text>, <assert-variant> ), ... ] ), ... ]
-    """
-    c1File = C1visualizerFile("<c1_file>")
-    for passEntry in passList:
-      passName = passEntry[0]
-      passBody = passEntry[1]
-      c1Pass = C1visualizerPass(c1File, passName, passBody, 0)
-    return c1File
-
-  def assertParsesTo(self, c1Text, expectedData):
-    expectedFile = self.createFile(expectedData)
-    actualFile = ParseC1visualizerStream("<c1_file>", io.StringIO(ToUnicode(c1Text)))
-    return self.assertEqual(expectedFile, actualFile)
-
-  def test_EmptyFile(self):
-    self.assertParsesTo("", [])
-
-  def test_SingleGroup(self):
-    self.assertParsesTo(
-      """
-        begin_compilation
-          method "MyMethod"
-        end_compilation
-        begin_cfg
-          name "pass1"
-          foo
-          bar
-        end_cfg
-      """,
-      [ ( "MyMethod pass1", [ "foo", "bar" ] ) ])
-
-  def test_MultipleGroups(self):
-    self.assertParsesTo(
-      """
-        begin_compilation
-          name "xyz1"
-          method "MyMethod1"
-          date 1234
-        end_compilation
-        begin_cfg
-          name "pass1"
-          foo
-          bar
-        end_cfg
-        begin_cfg
-          name "pass2"
-          abc
-          def
-        end_cfg
-      """,
-      [ ( "MyMethod1 pass1", [ "foo", "bar" ] ),
-        ( "MyMethod1 pass2", [ "abc", "def" ] ) ])
-    self.assertParsesTo(
-      """
-        begin_compilation
-          name "xyz1"
-          method "MyMethod1"
-          date 1234
-        end_compilation
-        begin_cfg
-          name "pass1"
-          foo
-          bar
-        end_cfg
-        begin_compilation
-          name "xyz2"
-          method "MyMethod2"
-          date 5678
-        end_compilation
-        begin_cfg
-          name "pass2"
-          abc
-          def
-        end_cfg
-      """,
-      [ ( "MyMethod1 pass1", [ "foo", "bar" ] ),
-        ( "MyMethod2 pass2", [ "abc", "def" ] ) ])
diff --git a/tools/checker/file_format/checker/__init__.py b/tools/checker/file_format/checker/__init__.py
deleted file mode 100644
index 33ef6de..0000000
--- a/tools/checker/file_format/checker/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (C) 2015 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.
diff --git a/tools/checker/file_format/checker/parser.py b/tools/checker/file_format/checker/parser.py
deleted file mode 100644
index 93fa093..0000000
--- a/tools/checker/file_format/checker/parser.py
+++ /dev/null
@@ -1,142 +0,0 @@
-# Copyright (C) 2015 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 file_format.common         import SplitStream
-from file_format.checker.struct import CheckerFile, TestCase, TestAssertion, RegexExpression
-
-import re
-
-def __extractLine(prefix, line):
-  """ Attempts to parse a check line. The regex searches for a comment symbol
-      followed by the CHECK keyword, given attribute and a colon at the very
-      beginning of the line. Whitespaces are ignored.
-  """
-  rIgnoreWhitespace = r"\s*"
-  rCommentSymbols = [r"//", r"#"]
-  regexPrefix = rIgnoreWhitespace + \
-                r"(" + r"|".join(rCommentSymbols) + r")" + \
-                rIgnoreWhitespace + \
-                prefix + r":"
-
-  # The 'match' function succeeds only if the pattern is matched at the
-  # beginning of the line.
-  match = re.match(regexPrefix, line)
-  if match is not None:
-    return line[match.end():].strip()
-  else:
-    return None
-
-def __processLine(line, lineNo, prefix):
-  """ This function is invoked on each line of the check file and returns a pair
-      which instructs the parser how the line should be handled. If the line is
-      to be included in the current check group, it is returned in the first
-      value. If the line starts a new check group, the name of the group is
-      returned in the second value.
-  """
-  # Lines beginning with 'CHECK-START' start a new test case.
-  startLine = __extractLine(prefix + "-START", line)
-  if startLine is not None:
-    return None, startLine
-
-  # Lines starting only with 'CHECK' are matched in order.
-  plainLine = __extractLine(prefix, line)
-  if plainLine is not None:
-    return (plainLine, TestAssertion.Variant.InOrder, lineNo), None
-
-  # 'CHECK-DAG' lines are no-order assertions.
-  dagLine = __extractLine(prefix + "-DAG", line)
-  if dagLine is not None:
-    return (dagLine, TestAssertion.Variant.DAG, lineNo), None
-
-  # 'CHECK-NOT' lines are no-order negative assertions.
-  notLine = __extractLine(prefix + "-NOT", line)
-  if notLine is not None:
-    return (notLine, TestAssertion.Variant.Not, lineNo), None
-
-  # Other lines are ignored.
-  return None, None
-
-def __isMatchAtStart(match):
-  """ Tests if the given Match occurred at the beginning of the line. """
-  return (match is not None) and (match.start() == 0)
-
-def __firstMatch(matches, string):
-  """ Takes in a list of Match objects and returns the minimal start point among
-      them. If there aren't any successful matches it returns the length of
-      the searched string.
-  """
-  starts = map(lambda m: len(string) if m is None else m.start(), matches)
-  return min(starts)
-
-def ParseCheckerAssertion(parent, line, variant, lineNo):
-  """ This method parses the content of a check line stripped of the initial
-      comment symbol and the CHECK keyword.
-  """
-  assertion = TestAssertion(parent, variant, line, lineNo)
-  # Loop as long as there is something to parse.
-  while line:
-    # Search for the nearest occurrence of the special markers.
-    matchWhitespace = re.search(r"\s+", line)
-    matchPattern = re.search(RegexExpression.Regex.regexPattern, line)
-    matchVariableReference = re.search(RegexExpression.Regex.regexVariableReference, line)
-    matchVariableDefinition = re.search(RegexExpression.Regex.regexVariableDefinition, line)
-
-    # If one of the above was identified at the current position, extract them
-    # from the line, parse them and add to the list of line parts.
-    if __isMatchAtStart(matchWhitespace):
-      # A whitespace in the check line creates a new separator of line parts.
-      # This allows for ignored output between the previous and next parts.
-      line = line[matchWhitespace.end():]
-      assertion.addExpression(RegexExpression.createSeparator())
-    elif __isMatchAtStart(matchPattern):
-      pattern = line[0:matchPattern.end()]
-      pattern = pattern[2:-2]
-      line = line[matchPattern.end():]
-      assertion.addExpression(RegexExpression.createPattern(pattern))
-    elif __isMatchAtStart(matchVariableReference):
-      var = line[0:matchVariableReference.end()]
-      line = line[matchVariableReference.end():]
-      name = var[2:-2]
-      assertion.addExpression(RegexExpression.createVariableReference(name))
-    elif __isMatchAtStart(matchVariableDefinition):
-      var = line[0:matchVariableDefinition.end()]
-      line = line[matchVariableDefinition.end():]
-      colonPos = var.find(":")
-      name = var[2:colonPos]
-      body = var[colonPos+1:-2]
-      assertion.addExpression(RegexExpression.createVariableDefinition(name, body))
-    else:
-      # If we're not currently looking at a special marker, this is a plain
-      # text match all the way until the first special marker (or the end
-      # of the line).
-      firstMatch = __firstMatch([ matchWhitespace,
-                                  matchPattern,
-                                  matchVariableReference,
-                                  matchVariableDefinition ],
-                                line)
-      text = line[0:firstMatch]
-      line = line[firstMatch:]
-      assertion.addExpression(RegexExpression.createText(text))
-  return assertion
-
-def ParseCheckerStream(fileName, prefix, stream):
-  checkerFile = CheckerFile(fileName)
-  fnProcessLine = lambda line, lineNo: __processLine(line, lineNo, prefix)
-  fnLineOutsideChunk = lambda line, lineNo: \
-      Logger.fail("C1visualizer line not inside a group", fileName, lineNo)
-  for caseName, caseLines, startLineNo in SplitStream(stream, fnProcessLine, fnLineOutsideChunk):
-    testCase = TestCase(checkerFile, caseName, startLineNo)
-    for caseLine in caseLines:
-      ParseCheckerAssertion(testCase, caseLine[0], caseLine[1], caseLine[2])
-  return checkerFile
diff --git a/tools/checker/file_format/checker/struct.py b/tools/checker/file_format/checker/struct.py
deleted file mode 100644
index d5cdc3b..0000000
--- a/tools/checker/file_format/checker/struct.py
+++ /dev/null
@@ -1,156 +0,0 @@
-# Copyright (C) 2015 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.logger import Logger
-from common.mixins import EqualityMixin, PrintableMixin
-
-import re
-
-class CheckerFile(PrintableMixin):
-
-  def __init__(self, fileName):
-    self.fileName = fileName
-    self.testCases = []
-
-  def addTestCase(self, new_test_case):
-    self.testCases.append(new_test_case)
-
-  def __eq__(self, other):
-    return isinstance(other, self.__class__) \
-       and self.testCases == other.testCases
-
-
-class TestCase(PrintableMixin):
-
-  def __init__(self, parent, name, startLineNo):
-    assert isinstance(parent, CheckerFile)
-
-    self.parent = parent
-    self.name = name
-    self.assertions = []
-    self.startLineNo = startLineNo
-
-    if not self.name:
-      Logger.fail("Test case does not have a name", self.parent.fileName, self.startLineNo)
-
-    self.parent.addTestCase(self)
-
-  @property
-  def fileName(self):
-    return self.parent.fileName
-
-  def addAssertion(self, new_assertion):
-    self.assertions.append(new_assertion)
-
-  def __eq__(self, other):
-    return isinstance(other, self.__class__) \
-       and self.name == other.name \
-       and self.assertions == other.assertions
-
-
-class TestAssertion(PrintableMixin):
-
-  class Variant(object):
-    """Supported types of assertions."""
-    InOrder, DAG, Not = range(3)
-
-  def __init__(self, parent, variant, originalText, lineNo):
-    assert isinstance(parent, TestCase)
-
-    self.parent = parent
-    self.variant = variant
-    self.expressions = []
-    self.lineNo = lineNo
-    self.originalText = originalText
-
-    self.parent.addAssertion(self)
-
-  @property
-  def fileName(self):
-    return self.parent.fileName
-
-  def addExpression(self, new_expression):
-    assert isinstance(new_expression, RegexExpression)
-    if self.variant == TestAssertion.Variant.Not:
-      if new_expression.variant == RegexExpression.Variant.VarDef:
-        Logger.fail("CHECK-NOT lines cannot define variables", self.fileName, self.lineNo)
-    self.expressions.append(new_expression)
-
-  def toRegex(self):
-    """ Returns a regex pattern for this entire assertion. Only used in tests. """
-    regex = ""
-    for expression in self.expressions:
-      if expression.variant == RegexExpression.Variant.Separator:
-        regex = regex + ", "
-      else:
-        regex = regex + "(" + expression.pattern + ")"
-    return regex
-
-  def __eq__(self, other):
-    return isinstance(other, self.__class__) \
-       and self.variant == other.variant \
-       and self.expressions == other.expressions
-
-
-class RegexExpression(EqualityMixin, PrintableMixin):
-
-  class Variant(object):
-    """Supported language constructs."""
-    Text, Pattern, VarRef, VarDef, Separator = range(5)
-
-  class Regex(object):
-    rName = r"([a-zA-Z][a-zA-Z0-9]*)"
-    rRegex = r"(.+?)"
-    rPatternStartSym = r"(\{\{)"
-    rPatternEndSym = r"(\}\})"
-    rVariableStartSym = r"(\[\[)"
-    rVariableEndSym = r"(\]\])"
-    rVariableSeparator = r"(:)"
-
-    regexPattern = rPatternStartSym + rRegex + rPatternEndSym
-    regexVariableReference = rVariableStartSym + rName + rVariableEndSym
-    regexVariableDefinition = rVariableStartSym + rName + rVariableSeparator + rRegex + rVariableEndSym
-
-  def __init__(self, variant, name, pattern):
-    self.variant = variant
-    self.name = name
-    self.pattern = pattern
-
-  def __eq__(self, other):
-    return isinstance(other, self.__class__) \
-       and self.variant == other.variant \
-       and self.name == other.name \
-       and self.pattern == other.pattern
-
-  @staticmethod
-  def createSeparator():
-    return RegexExpression(RegexExpression.Variant.Separator, None, None)
-
-  @staticmethod
-  def createText(text):
-    return RegexExpression(RegexExpression.Variant.Text, None, re.escape(text))
-
-  @staticmethod
-  def createPattern(pattern):
-    return RegexExpression(RegexExpression.Variant.Pattern, None, pattern)
-
-  @staticmethod
-  def createVariableReference(name):
-    assert re.match(RegexExpression.Regex.rName, name)
-    return RegexExpression(RegexExpression.Variant.VarRef, name, None)
-
-  @staticmethod
-  def createVariableDefinition(name, pattern):
-    assert re.match(RegexExpression.Regex.rName, name)
-    return RegexExpression(RegexExpression.Variant.VarDef, name, pattern)
diff --git a/tools/checker/file_format/checker/test.py b/tools/checker/file_format/checker/test.py
deleted file mode 100644
index 167c888..0000000
--- a/tools/checker/file_format/checker/test.py
+++ /dev/null
@@ -1,238 +0,0 @@
-#!/usr/bin/env python2
-#
-# 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.testing             import ToUnicode
-from file_format.checker.parser import ParseCheckerStream
-from file_format.checker.struct import CheckerFile, TestCase, TestAssertion, RegexExpression
-
-import io
-import unittest
-
-CheckerException = SystemExit
-
-class CheckerParser_PrefixTest(unittest.TestCase):
-
-  def tryParse(self, string):
-    checkerText = u"// CHECK-START: pass\n" + ToUnicode(string)
-    checkFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(checkerText))
-    self.assertEqual(len(checkFile.testCases), 1)
-    testCase = checkFile.testCases[0]
-    return len(testCase.assertions) != 0
-
-  def test_InvalidFormat(self):
-    self.assertFalse(self.tryParse("CHECK"))
-    self.assertFalse(self.tryParse(":CHECK"))
-    self.assertFalse(self.tryParse("CHECK:"))
-    self.assertFalse(self.tryParse("//CHECK"))
-    self.assertFalse(self.tryParse("#CHECK"))
-
-    self.assertTrue(self.tryParse("//CHECK:foo"))
-    self.assertTrue(self.tryParse("#CHECK:bar"))
-
-  def test_InvalidLabel(self):
-    self.assertFalse(self.tryParse("//ACHECK:foo"))
-    self.assertFalse(self.tryParse("#ACHECK:foo"))
-
-  def test_NotFirstOnTheLine(self):
-    self.assertFalse(self.tryParse("A// CHECK: foo"))
-    self.assertFalse(self.tryParse("A # CHECK: foo"))
-    self.assertFalse(self.tryParse("// // CHECK: foo"))
-    self.assertFalse(self.tryParse("# # CHECK: foo"))
-
-  def test_WhitespaceAgnostic(self):
-    self.assertTrue(self.tryParse("  //CHECK: foo"))
-    self.assertTrue(self.tryParse("//  CHECK: foo"))
-    self.assertTrue(self.tryParse("    //CHECK: foo"))
-    self.assertTrue(self.tryParse("//    CHECK: foo"))
-
-
-class CheckerParser_RegexExpressionTest(unittest.TestCase):
-
-  def parseAssertion(self, string, variant=""):
-    checkerText = u"// CHECK-START: pass\n// CHECK" + ToUnicode(variant) + u": " + ToUnicode(string)
-    checkerFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(checkerText))
-    self.assertEqual(len(checkerFile.testCases), 1)
-    testCase = checkerFile.testCases[0]
-    self.assertEqual(len(testCase.assertions), 1)
-    return testCase.assertions[0]
-
-  def parseExpression(self, string):
-    line = self.parseAssertion(string)
-    self.assertEqual(1, len(line.expressions))
-    return line.expressions[0]
-
-  def assertEqualsRegex(self, string, expected):
-    self.assertEqual(expected, self.parseAssertion(string).toRegex())
-
-  def assertEqualsText(self, string, text):
-    self.assertEqual(self.parseExpression(string), RegexExpression.createText(text))
-
-  def assertEqualsPattern(self, string, pattern):
-    self.assertEqual(self.parseExpression(string), RegexExpression.createPattern(pattern))
-
-  def assertEqualsVarRef(self, string, name):
-    self.assertEqual(self.parseExpression(string), RegexExpression.createVariableReference(name))
-
-  def assertEqualsVarDef(self, string, name, pattern):
-    self.assertEqual(self.parseExpression(string),
-                     RegexExpression.createVariableDefinition(name, pattern))
-
-  def assertVariantNotEqual(self, string, variant):
-    self.assertNotEqual(variant, self.parseExpression(string).variant)
-
-  # Test that individual parts of the line are recognized
-
-  def test_TextOnly(self):
-    self.assertEqualsText("foo", "foo")
-    self.assertEqualsText("  foo  ", "foo")
-    self.assertEqualsRegex("f$o^o", "(f\$o\^o)")
-
-  def test_PatternOnly(self):
-    self.assertEqualsPattern("{{a?b.c}}", "a?b.c")
-
-  def test_VarRefOnly(self):
-    self.assertEqualsVarRef("[[ABC]]", "ABC")
-
-  def test_VarDefOnly(self):
-    self.assertEqualsVarDef("[[ABC:a?b.c]]", "ABC", "a?b.c")
-
-  def test_TextWithWhitespace(self):
-    self.assertEqualsRegex("foo bar", "(foo), (bar)")
-    self.assertEqualsRegex("foo   bar", "(foo), (bar)")
-
-  def test_TextWithRegex(self):
-    self.assertEqualsRegex("foo{{abc}}bar", "(foo)(abc)(bar)")
-
-  def test_TextWithVar(self):
-    self.assertEqualsRegex("foo[[ABC:abc]]bar", "(foo)(abc)(bar)")
-
-  def test_PlainWithRegexAndWhitespaces(self):
-    self.assertEqualsRegex("foo {{abc}}bar", "(foo), (abc)(bar)")
-    self.assertEqualsRegex("foo{{abc}} bar", "(foo)(abc), (bar)")
-    self.assertEqualsRegex("foo {{abc}} bar", "(foo), (abc), (bar)")
-
-  def test_PlainWithVarAndWhitespaces(self):
-    self.assertEqualsRegex("foo [[ABC:abc]]bar", "(foo), (abc)(bar)")
-    self.assertEqualsRegex("foo[[ABC:abc]] bar", "(foo)(abc), (bar)")
-    self.assertEqualsRegex("foo [[ABC:abc]] bar", "(foo), (abc), (bar)")
-
-  def test_AllKinds(self):
-    self.assertEqualsRegex("foo [[ABC:abc]]{{def}}bar", "(foo), (abc)(def)(bar)")
-    self.assertEqualsRegex("foo[[ABC:abc]] {{def}}bar", "(foo)(abc), (def)(bar)")
-    self.assertEqualsRegex("foo [[ABC:abc]] {{def}} bar", "(foo), (abc), (def), (bar)")
-
-  # # Test that variables and patterns are parsed correctly
-
-  def test_ValidPattern(self):
-    self.assertEqualsPattern("{{abc}}", "abc")
-    self.assertEqualsPattern("{{a[b]c}}", "a[b]c")
-    self.assertEqualsPattern("{{(a{bc})}}", "(a{bc})")
-
-  def test_ValidRef(self):
-    self.assertEqualsVarRef("[[ABC]]", "ABC")
-    self.assertEqualsVarRef("[[A1BC2]]", "A1BC2")
-
-  def test_ValidDef(self):
-    self.assertEqualsVarDef("[[ABC:abc]]", "ABC", "abc")
-    self.assertEqualsVarDef("[[ABC:ab:c]]", "ABC", "ab:c")
-    self.assertEqualsVarDef("[[ABC:a[b]c]]", "ABC", "a[b]c")
-    self.assertEqualsVarDef("[[ABC:(a[bc])]]", "ABC", "(a[bc])")
-
-  def test_Empty(self):
-    self.assertVariantNotEqual("{{}}", RegexExpression.Variant.Pattern)
-    self.assertVariantNotEqual("[[]]", RegexExpression.Variant.VarRef)
-    self.assertVariantNotEqual("[[:]]", RegexExpression.Variant.VarDef)
-
-  def test_InvalidVarName(self):
-    self.assertVariantNotEqual("[[0ABC]]", RegexExpression.Variant.VarRef)
-    self.assertVariantNotEqual("[[AB=C]]", RegexExpression.Variant.VarRef)
-    self.assertVariantNotEqual("[[ABC=]]", RegexExpression.Variant.VarRef)
-    self.assertVariantNotEqual("[[0ABC:abc]]", RegexExpression.Variant.VarDef)
-    self.assertVariantNotEqual("[[AB=C:abc]]", RegexExpression.Variant.VarDef)
-    self.assertVariantNotEqual("[[ABC=:abc]]", RegexExpression.Variant.VarDef)
-
-  def test_BodyMatchNotGreedy(self):
-    self.assertEqualsRegex("{{abc}}{{def}}", "(abc)(def)")
-    self.assertEqualsRegex("[[ABC:abc]][[DEF:def]]", "(abc)(def)")
-
-  def test_NoVarDefsInNotChecks(self):
-    with self.assertRaises(CheckerException):
-      self.parseAssertion("[[ABC:abc]]", "-NOT")
-
-
-class CheckerParser_FileLayoutTest(unittest.TestCase):
-
-  # Creates an instance of CheckerFile from provided info.
-  # Data format: [ ( <case-name>, [ ( <text>, <assert-variant> ), ... ] ), ... ]
-  def createFile(self, caseList):
-    testFile = CheckerFile("<test_file>")
-    for caseEntry in caseList:
-      caseName = caseEntry[0]
-      testCase = TestCase(testFile, caseName, 0)
-      assertionList = caseEntry[1]
-      for assertionEntry in assertionList:
-        content = assertionEntry[0]
-        variant = assertionEntry[1]
-        assertion = TestAssertion(testCase, variant, content, 0)
-        assertion.addExpression(RegexExpression.createText(content))
-    return testFile
-
-  def assertParsesTo(self, checkerText, expectedData):
-    expectedFile = self.createFile(expectedData)
-    actualFile = ParseCheckerStream("<test_file>", "CHECK", io.StringIO(ToUnicode(checkerText)))
-    return self.assertEqual(expectedFile, actualFile)
-
-  def test_EmptyFile(self):
-    self.assertParsesTo("", [])
-
-  def test_SingleGroup(self):
-    self.assertParsesTo(
-      """
-        // CHECK-START: Example Group
-        // CHECK:  foo
-        // CHECK:    bar
-      """,
-      [ ( "Example Group", [ ("foo", TestAssertion.Variant.InOrder),
-                             ("bar", TestAssertion.Variant.InOrder) ] ) ])
-
-  def test_MultipleGroups(self):
-    self.assertParsesTo(
-      """
-        // CHECK-START: Example Group1
-        // CHECK: foo
-        // CHECK: bar
-        // CHECK-START: Example Group2
-        // CHECK: abc
-        // CHECK: def
-      """,
-      [ ( "Example Group1", [ ("foo", TestAssertion.Variant.InOrder),
-                              ("bar", TestAssertion.Variant.InOrder) ] ),
-        ( "Example Group2", [ ("abc", TestAssertion.Variant.InOrder),
-                              ("def", TestAssertion.Variant.InOrder) ] ) ])
-
-  def test_AssertionVariants(self):
-    self.assertParsesTo(
-      """
-        // CHECK-START: Example Group
-        // CHECK:     foo
-        // CHECK-NOT: bar
-        // CHECK-DAG: abc
-        // CHECK-DAG: def
-      """,
-      [ ( "Example Group", [ ("foo", TestAssertion.Variant.InOrder),
-                             ("bar", TestAssertion.Variant.Not),
-                             ("abc", TestAssertion.Variant.DAG),
-                             ("def", TestAssertion.Variant.DAG) ] ) ])
diff --git a/tools/checker/match/__init__.py b/tools/checker/match/__init__.py
deleted file mode 100644
index 33ef6de..0000000
--- a/tools/checker/match/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (C) 2015 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.
diff --git a/tools/checker/match/file.py b/tools/checker/match/file.py
deleted file mode 100644
index d787fe5..0000000
--- a/tools/checker/match/file.py
+++ /dev/null
@@ -1,147 +0,0 @@
-# Copyright (C) 2015 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.logger                    import Logger
-from file_format.c1visualizer.struct  import C1visualizerFile, C1visualizerPass
-from file_format.checker.struct       import CheckerFile, TestCase, TestAssertion
-from match.line                       import MatchLines
-
-def __headAndTail(list):
-  return list[0], list[1:]
-
-def __splitByVariant(lines, variant):
-  """ Splits a list of check lines at index 'i' such that lines[i] is the first
-      element whose variant is not equal to the given parameter.
-  """
-  i = 0
-  while i < len(lines) and lines[i].variant == variant:
-    i += 1
-  return lines[:i], lines[i:]
-
-def __nextIndependentChecks(checkLines):
-  """ Extracts the first sequence of check lines which are independent of each
-      other's match location, i.e. either consecutive DAG lines or a single
-      InOrder line. Any Not lines preceeding this sequence are also extracted.
-  """
-  notChecks, checkLines = __splitByVariant(checkLines, TestAssertion.Variant.Not)
-  if not checkLines:
-    return notChecks, [], []
-
-  head, tail = __headAndTail(checkLines)
-  if head.variant == TestAssertion.Variant.InOrder:
-    return notChecks, [head], tail
-  else:
-    assert head.variant == TestAssertion.Variant.DAG
-    independentChecks, checkLines = __splitByVariant(checkLines, TestAssertion.Variant.DAG)
-    return notChecks, independentChecks, checkLines
-
-def __findFirstMatch(checkLine, outputLines, startLineNo, lineFilter, varState):
-  """ If successful, returns the line number of the first output line matching
-      the check line and the updated variable state. Otherwise returns -1 and
-      None, respectively. The 'lineFilter' parameter can be used to supply a
-      list of line numbers (counting from 1) which should be skipped.
-  """
-  matchLineNo = startLineNo
-  for outputLine in outputLines:
-    if matchLineNo not in lineFilter:
-      newVarState = MatchLines(checkLine, outputLine, varState)
-      if newVarState is not None:
-        return matchLineNo, newVarState
-    matchLineNo += 1
-  return -1, None
-
-def __matchIndependentChecks(checkLines, outputLines, startLineNo, varState):
-  """ Matches the given positive check lines against the output in order of
-      appearance. Variable state is propagated but the scope of the search
-      remains the same for all checks. Each output line can only be matched
-      once. If all check lines are matched, the resulting variable state is
-      returned together with the remaining output. The function also returns
-      output lines which appear before either of the matched lines so they can
-      be tested against Not checks.
-  """
-  # If no checks are provided, skip over the entire output.
-  if not checkLines:
-    return outputLines, [], startLineNo + len(outputLines), varState
-
-  # Keep track of which lines have been matched.
-  matchedLines = []
-
-  # Find first unused output line which matches each check line.
-  for checkLine in checkLines:
-    matchLineNo, varState = \
-      __findFirstMatch(checkLine, outputLines, startLineNo, matchedLines, varState)
-    if varState is None:
-      Logger.testFailed("Could not match check line \"" + checkLine.originalText + "\" " +
-                        "starting from output line " + str(startLineNo),
-                        checkLine.fileName, checkLine.lineNo)
-    matchedLines.append(matchLineNo)
-
-  # Return new variable state and the output lines which lie outside the
-  # match locations of this independent group.
-  minMatchLineNo = min(matchedLines)
-  maxMatchLineNo = max(matchedLines)
-  preceedingLines = outputLines[:minMatchLineNo - startLineNo]
-  remainingLines = outputLines[maxMatchLineNo - startLineNo + 1:]
-  return preceedingLines, remainingLines, maxMatchLineNo + 1, varState
-
-def __matchNotLines(checkLines, outputLines, startLineNo, varState):
-  """ Makes sure that the given check lines do not match any of the given output
-      lines. Variable state does not change.
-  """
-  for checkLine in checkLines:
-    assert checkLine.variant == TestAssertion.Variant.Not
-    matchLineNo, matchVarState = \
-      __findFirstMatch(checkLine, outputLines, startLineNo, [], varState)
-    if matchVarState is not None:
-      Logger.testFailed("CHECK-NOT line \"" + checkLine.originalText + "\" matches output line " + \
-                        str(matchLineNo), checkLine.fileName, checkLine.lineNo)
-
-def __matchGroups(checkGroup, outputGroup):
-  """ Matches the check lines in this group against an output group. It is
-      responsible for running the checks in the right order and scope, and
-      for propagating the variable state between the check lines.
-  """
-  varState = {}
-  checkLines = checkGroup.assertions
-  outputLines = outputGroup.body
-  startLineNo = outputGroup.startLineNo
-
-  while checkLines:
-    # Extract the next sequence of location-independent checks to be matched.
-    notChecks, independentChecks, checkLines = __nextIndependentChecks(checkLines)
-
-    # Match the independent checks.
-    notOutput, outputLines, newStartLineNo, newVarState = \
-      __matchIndependentChecks(independentChecks, outputLines, startLineNo, varState)
-
-    # Run the Not checks against the output lines which lie between the last
-    # two independent groups or the bounds of the output.
-    __matchNotLines(notChecks, notOutput, startLineNo, varState)
-
-    # Update variable state.
-    startLineNo = newStartLineNo
-    varState = newVarState
-
-def MatchFiles(checkerFile, c1File):
-  for testCase in checkerFile.testCases:
-    # TODO: Currently does not handle multiple occurrences of the same group
-    # name, e.g. when a pass is run multiple times. It will always try to
-    # match a check group against the first output group of the same name.
-    c1Pass = c1File.findPass(testCase.name)
-    if c1Pass is None:
-      Logger.fail("Test case \"" + testCase.name + "\" not found in the C1visualizer output",
-                  testCase.fileName, testCase.lineNo)
-    Logger.startTest(testCase.name)
-    __matchGroups(testCase, c1Pass)
-    Logger.testPassed()
diff --git a/tools/checker/match/line.py b/tools/checker/match/line.py
deleted file mode 100644
index eb1ab82..0000000
--- a/tools/checker/match/line.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright (C) 2015 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.logger              import Logger
-from file_format.checker.struct import TestAssertion, RegexExpression
-
-import re
-
-def __isMatchAtStart(match):
-  """ Tests if the given Match occurred at the beginning of the line. """
-  return (match is not None) and (match.start() == 0)
-
-def __generatePattern(checkLine, linePart, varState):
-  """ Returns the regex pattern to be matched in the output line. Variable
-      references are substituted with their current values provided in the
-      'varState' argument.
-
-  An exception is raised if a referenced variable is undefined.
-  """
-  if linePart.variant == RegexExpression.Variant.VarRef:
-    try:
-      return re.escape(varState[linePart.name])
-    except KeyError:
-      Logger.testFailed("Use of undefined variable \"" + linePart.name + "\"",
-                        checkLine.fileName, checkLine.lineNo)
-  else:
-    return linePart.pattern
-
-def __isSeparated(outputLine, matchStart):
-  return (matchStart == 0) or (outputLine[matchStart - 1:matchStart].isspace())
-
-def MatchLines(checkLine, outputLine, initialVarState):
-  """ Attempts to match the check line against a line from the output file with
-      the given initial variable values. It returns the new variable state if
-      successful and None otherwise.
-  """
-  # Do the full matching on a shadow copy of the variable state. If the
-  # matching fails half-way, we will not need to revert the state.
-  varState = dict(initialVarState)
-
-  matchStart = 0
-  isAfterSeparator = True
-
-  # Now try to parse all of the parts of the check line in the right order.
-  # Variable values are updated on-the-fly, meaning that a variable can
-  # be referenced immediately after its definition.
-  for part in checkLine.expressions:
-    if part.variant == RegexExpression.Variant.Separator:
-      isAfterSeparator = True
-      continue
-
-    # Find the earliest match for this line part.
-    pattern = __generatePattern(checkLine, part, varState)
-    while True:
-      match = re.search(pattern, outputLine[matchStart:])
-      if (match is None) or (not isAfterSeparator and not __isMatchAtStart(match)):
-        return None
-      matchEnd = matchStart + match.end()
-      matchStart += match.start()
-
-      # Check if this is a valid match if we expect a whitespace separator
-      # before the matched text. Otherwise loop and look for another match.
-      if not isAfterSeparator or __isSeparated(outputLine, matchStart):
-        break
-      else:
-        matchStart += 1
-
-    if part.variant == RegexExpression.Variant.VarDef:
-      if part.name in varState:
-        Logger.testFailed("Multiple definitions of variable \"" + part.name + "\"",
-                          checkLine.fileName, checkLine.lineNo)
-      varState[part.name] = outputLine[matchStart:matchEnd]
-
-    matchStart = matchEnd
-    isAfterSeparator = False
-
-  # All parts were successfully matched. Return the new variable state.
-  return varState
diff --git a/tools/checker/match/test.py b/tools/checker/match/test.py
deleted file mode 100644
index 976a87f..0000000
--- a/tools/checker/match/test.py
+++ /dev/null
@@ -1,326 +0,0 @@
-# Copyright (C) 2015 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.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, RegexExpression
-from match.file                      import MatchFiles
-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), varState)
-
-  def matches(self, checkerString, c1String, varState={}):
-    return self.tryMatch(checkerString, c1String, varState) is not None
-
-  def test_TextAndWhitespace(self):
-    self.assertTrue(self.matches("foo", "foo"))
-    self.assertTrue(self.matches("foo", "  foo  "))
-    self.assertTrue(self.matches("foo", "foo bar"))
-    self.assertFalse(self.matches("foo", "XfooX"))
-    self.assertFalse(self.matches("foo", "zoo"))
-
-    self.assertTrue(self.matches("foo bar", "foo   bar"))
-    self.assertTrue(self.matches("foo bar", "abc foo bar def"))
-    self.assertTrue(self.matches("foo bar", "foo foo bar bar"))
-
-    self.assertTrue(self.matches("foo bar", "foo X bar"))
-    self.assertFalse(self.matches("foo bar", "foo Xbar"))
-
-  def test_Pattern(self):
-    self.assertTrue(self.matches("foo{{A|B}}bar", "fooAbar"))
-    self.assertTrue(self.matches("foo{{A|B}}bar", "fooBbar"))
-    self.assertFalse(self.matches("foo{{A|B}}bar", "fooCbar"))
-
-  def test_VariableReference(self):
-    self.assertTrue(self.matches("foo[[X]]bar", "foobar", {"X": ""}))
-    self.assertTrue(self.matches("foo[[X]]bar", "fooAbar", {"X": "A"}))
-    self.assertTrue(self.matches("foo[[X]]bar", "fooBbar", {"X": "B"}))
-    self.assertFalse(self.matches("foo[[X]]bar", "foobar", {"X": "A"}))
-    self.assertFalse(self.matches("foo[[X]]bar", "foo bar", {"X": "A"}))
-    with self.assertRaises(CheckerException):
-      self.assertTrue(self.matches("foo[[X]]bar", "foobar", {}))
-
-  def test_VariableDefinition(self):
-    self.assertTrue(self.matches("foo[[X:A|B]]bar", "fooAbar"))
-    self.assertTrue(self.matches("foo[[X:A|B]]bar", "fooBbar"))
-    self.assertFalse(self.matches("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.assertTrue(self.matches("foo[[X:A|B]]bar[[X]]baz", "fooAbarAbaz"))
-    self.assertTrue(self.matches("foo[[X:A|B]]bar[[X]]baz", "fooBbarBbaz"))
-    self.assertFalse(self.matches("foo[[X:A|B]]bar[[X]]baz", "fooAbarBbaz"))
-
-  def test_NoVariableRedefinition(self):
-    with self.assertRaises(CheckerException):
-      self.matches("[[X:...]][[X]][[X:...]][[X]]", "foofoobarbar")
-
-  def test_EnvNotChangedOnPartialMatch(self):
-    env = {"Y": "foo"}
-    self.assertFalse(self.matches("[[X:A]]bar", "Abaz", env))
-    self.assertFalse("X" in env.keys())
-
-  def test_VariableContentEscaped(self):
-    self.assertTrue(self.matches("[[X:..]]foo[[X]]", ".*foo.*"))
-    self.assertFalse(self.matches("[[X:..]]foo[[X]]", ".*fooAAAA"))
-
-
-class MatchFiles_Test(unittest.TestCase):
-
-  def matches(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)))
-    try:
-      MatchFiles(checkerFile, c1File)
-      return True
-    except CheckerException:
-      return False
-
-  def test_Text(self):
-    self.assertTrue(self.matches( "// CHECK: foo bar", "foo bar"))
-    self.assertFalse(self.matches("// CHECK: foo bar", "abc def"))
-
-  def test_Pattern(self):
-    self.assertTrue(self.matches( "// CHECK: abc {{de.}}", "abc de#"))
-    self.assertFalse(self.matches("// CHECK: abc {{de.}}", "abc d#f"))
-
-  def test_Variables(self):
-    self.assertTrue(self.matches(
-    """
-      // CHECK: foo[[X:.]]bar
-      // CHECK: abc[[X]]def
-    """,
-    """
-      foo bar
-      abc def
-    """))
-    self.assertTrue(self.matches(
-    """
-      // CHECK: foo[[X:([0-9]+)]]bar
-      // CHECK: abc[[X]]def
-      // CHECK: ### [[X]] ###
-    """,
-    """
-      foo1234bar
-      abc1234def
-      ### 1234 ###
-    """))
-    self.assertFalse(self.matches(
-    """
-      // CHECK: foo[[X:([0-9]+)]]bar
-      // CHECK: abc[[X]]def
-    """,
-    """
-      foo1234bar
-      abc1235def
-    """))
-
-  def test_InOrderAssertions(self):
-    self.assertTrue(self.matches(
-    """
-      // CHECK: foo
-      // CHECK: bar
-    """,
-    """
-      foo
-      bar
-    """))
-    self.assertFalse(self.matches(
-    """
-      // CHECK: foo
-      // CHECK: bar
-    """,
-    """
-      bar
-      foo
-    """))
-
-  def test_DagAssertions(self):
-    self.assertTrue(self.matches(
-    """
-      // CHECK-DAG: foo
-      // CHECK-DAG: bar
-    """,
-    """
-      foo
-      bar
-    """))
-    self.assertTrue(self.matches(
-    """
-      // CHECK-DAG: foo
-      // CHECK-DAG: bar
-    """,
-    """
-      bar
-      foo
-    """))
-
-  def test_DagAssertionsScope(self):
-    self.assertTrue(self.matches(
-    """
-      // CHECK:     foo
-      // CHECK-DAG: abc
-      // CHECK-DAG: def
-      // CHECK:     bar
-    """,
-    """
-      foo
-      def
-      abc
-      bar
-    """))
-    self.assertFalse(self.matches(
-    """
-      // CHECK:     foo
-      // CHECK-DAG: abc
-      // CHECK-DAG: def
-      // CHECK:     bar
-    """,
-    """
-      foo
-      abc
-      bar
-      def
-    """))
-    self.assertFalse(self.matches(
-    """
-      // CHECK:     foo
-      // CHECK-DAG: abc
-      // CHECK-DAG: def
-      // CHECK:     bar
-    """,
-    """
-      foo
-      def
-      bar
-      abc
-    """))
-
-  def test_NotAssertions(self):
-    self.assertTrue(self.matches(
-    """
-      // CHECK-NOT: foo
-    """,
-    """
-      abc
-      def
-    """))
-    self.assertFalse(self.matches(
-    """
-      // CHECK-NOT: foo
-    """,
-    """
-      abc foo
-      def
-    """))
-    self.assertFalse(self.matches(
-    """
-      // CHECK-NOT: foo
-      // CHECK-NOT: bar
-    """,
-    """
-      abc
-      def bar
-    """))
-
-  def test_NotAssertionsScope(self):
-    self.assertTrue(self.matches(
-    """
-      // CHECK:     abc
-      // CHECK-NOT: foo
-      // CHECK:     def
-    """,
-    """
-      abc
-      def
-    """))
-    self.assertTrue(self.matches(
-    """
-      // CHECK:     abc
-      // CHECK-NOT: foo
-      // CHECK:     def
-    """,
-    """
-      abc
-      def
-      foo
-    """))
-    self.assertFalse(self.matches(
-    """
-      // CHECK:     abc
-      // CHECK-NOT: foo
-      // CHECK:     def
-    """,
-    """
-      abc
-      foo
-      def
-    """))
-
-  def test_LineOnlyMatchesOnce(self):
-    self.assertTrue(self.matches(
-    """
-      // CHECK-DAG: foo
-      // CHECK-DAG: foo
-    """,
-    """
-      foo
-      abc
-      foo
-    """))
-    self.assertFalse(self.matches(
-    """
-      // CHECK-DAG: foo
-      // CHECK-DAG: foo
-    """,
-    """
-      foo
-      abc
-      bar
-    """))
diff --git a/tools/checker/run_unit_tests.py b/tools/checker/run_unit_tests.py
deleted file mode 100755
index 01708db..0000000
--- a/tools/checker/run_unit_tests.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env python2
-#
-# 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.logger                 import Logger
-from file_format.c1visualizer.test import C1visualizerParser_Test
-from file_format.checker.test      import CheckerParser_PrefixTest, \
-                                          CheckerParser_RegexExpressionTest, \
-                                          CheckerParser_FileLayoutTest
-from match.test                    import MatchLines_Test, \
-                                          MatchFiles_Test
-
-import unittest
-
-if __name__ == '__main__':
-  Logger.Verbosity = Logger.Level.NoOutput
-  unittest.main(verbosity=2)
diff --git a/tools/checker_test.py b/tools/checker_test.py
new file mode 100755
index 0000000..667ca90
--- /dev/null
+++ b/tools/checker_test.py
@@ -0,0 +1,474 @@
+#!/usr/bin/env python2
+#
+# 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.
+
+# This is a test file which exercises all feautres supported by the domain-
+# specific markup language implemented by Checker.
+
+import checker
+import io
+import unittest
+
+# The parent type of exception expected to be thrown by Checker during tests.
+# It must be specific enough to not cover exceptions thrown due to actual flaws
+# in Checker.
+CheckerException = SystemExit
+
+
+class TestCheckFile_PrefixExtraction(unittest.TestCase):
+  def __tryParse(self, string):
+    checkFile = checker.CheckFile(None, [])
+    return checkFile._extractLine("CHECK", string)
+
+  def test_InvalidFormat(self):
+    self.assertIsNone(self.__tryParse("CHECK"))
+    self.assertIsNone(self.__tryParse(":CHECK"))
+    self.assertIsNone(self.__tryParse("CHECK:"))
+    self.assertIsNone(self.__tryParse("//CHECK"))
+    self.assertIsNone(self.__tryParse("#CHECK"))
+
+    self.assertIsNotNone(self.__tryParse("//CHECK:foo"))
+    self.assertIsNotNone(self.__tryParse("#CHECK:bar"))
+
+  def test_InvalidLabel(self):
+    self.assertIsNone(self.__tryParse("//ACHECK:foo"))
+    self.assertIsNone(self.__tryParse("#ACHECK:foo"))
+
+  def test_NotFirstOnTheLine(self):
+    self.assertIsNone(self.__tryParse("A// CHECK: foo"))
+    self.assertIsNone(self.__tryParse("A # CHECK: foo"))
+    self.assertIsNone(self.__tryParse("// // CHECK: foo"))
+    self.assertIsNone(self.__tryParse("# # CHECK: foo"))
+
+  def test_WhitespaceAgnostic(self):
+    self.assertIsNotNone(self.__tryParse("  //CHECK: foo"))
+    self.assertIsNotNone(self.__tryParse("//  CHECK: foo"))
+    self.assertIsNotNone(self.__tryParse("    //CHECK: foo"))
+    self.assertIsNotNone(self.__tryParse("//    CHECK: foo"))
+
+
+class TestCheckLine_Parse(unittest.TestCase):
+  def __getPartPattern(self, linePart):
+    if linePart.variant == checker.CheckElement.Variant.Separator:
+      return "\s+"
+    else:
+      return linePart.pattern
+
+  def __getRegex(self, checkLine):
+    return "".join(map(lambda x: "(" + self.__getPartPattern(x) + ")", checkLine.lineParts))
+
+  def __tryParse(self, string):
+    return checker.CheckLine(string)
+
+  def __parsesTo(self, string, expected):
+    self.assertEqual(expected, self.__getRegex(self.__tryParse(string)))
+
+  def __tryParseNot(self, string):
+    return checker.CheckLine(string, checker.CheckLine.Variant.Not)
+
+  def __parsesPattern(self, string, pattern):
+    line = self.__tryParse(string)
+    self.assertEqual(1, len(line.lineParts))
+    self.assertEqual(checker.CheckElement.Variant.Pattern, line.lineParts[0].variant)
+    self.assertEqual(pattern, line.lineParts[0].pattern)
+
+  def __parsesVarRef(self, string, name):
+    line = self.__tryParse(string)
+    self.assertEqual(1, len(line.lineParts))
+    self.assertEqual(checker.CheckElement.Variant.VarRef, line.lineParts[0].variant)
+    self.assertEqual(name, line.lineParts[0].name)
+
+  def __parsesVarDef(self, string, name, body):
+    line = self.__tryParse(string)
+    self.assertEqual(1, len(line.lineParts))
+    self.assertEqual(checker.CheckElement.Variant.VarDef, line.lineParts[0].variant)
+    self.assertEqual(name, line.lineParts[0].name)
+    self.assertEqual(body, line.lineParts[0].pattern)
+
+  def __doesNotParse(self, string, partType):
+    line = self.__tryParse(string)
+    self.assertEqual(1, len(line.lineParts))
+    self.assertNotEqual(partType, line.lineParts[0].variant)
+
+  # Test that individual parts of the line are recognized
+
+  def test_TextOnly(self):
+    self.__parsesTo("foo", "(foo)")
+    self.__parsesTo("  foo  ", "(foo)")
+    self.__parsesTo("f$o^o", "(f\$o\^o)")
+
+  def test_TextWithWhitespace(self):
+    self.__parsesTo("foo bar", "(foo)(\s+)(bar)")
+    self.__parsesTo("foo   bar", "(foo)(\s+)(bar)")
+
+  def test_RegexOnly(self):
+    self.__parsesPattern("{{a?b.c}}", "a?b.c")
+
+  def test_VarRefOnly(self):
+    self.__parsesVarRef("[[ABC]]", "ABC")
+
+  def test_VarDefOnly(self):
+    self.__parsesVarDef("[[ABC:a?b.c]]", "ABC", "a?b.c")
+
+  def test_TextWithRegex(self):
+    self.__parsesTo("foo{{abc}}bar", "(foo)(abc)(bar)")
+
+  def test_TextWithVar(self):
+    self.__parsesTo("foo[[ABC:abc]]bar", "(foo)(abc)(bar)")
+
+  def test_PlainWithRegexAndWhitespaces(self):
+    self.__parsesTo("foo {{abc}}bar", "(foo)(\s+)(abc)(bar)")
+    self.__parsesTo("foo{{abc}} bar", "(foo)(abc)(\s+)(bar)")
+    self.__parsesTo("foo {{abc}} bar", "(foo)(\s+)(abc)(\s+)(bar)")
+
+  def test_PlainWithVarAndWhitespaces(self):
+    self.__parsesTo("foo [[ABC:abc]]bar", "(foo)(\s+)(abc)(bar)")
+    self.__parsesTo("foo[[ABC:abc]] bar", "(foo)(abc)(\s+)(bar)")
+    self.__parsesTo("foo [[ABC:abc]] bar", "(foo)(\s+)(abc)(\s+)(bar)")
+
+  def test_AllKinds(self):
+    self.__parsesTo("foo [[ABC:abc]]{{def}}bar", "(foo)(\s+)(abc)(def)(bar)")
+    self.__parsesTo("foo[[ABC:abc]] {{def}}bar", "(foo)(abc)(\s+)(def)(bar)")
+    self.__parsesTo("foo [[ABC:abc]] {{def}} bar", "(foo)(\s+)(abc)(\s+)(def)(\s+)(bar)")
+
+  # Test that variables and patterns are parsed correctly
+
+  def test_ValidPattern(self):
+    self.__parsesPattern("{{abc}}", "abc")
+    self.__parsesPattern("{{a[b]c}}", "a[b]c")
+    self.__parsesPattern("{{(a{bc})}}", "(a{bc})")
+
+  def test_ValidRef(self):
+    self.__parsesVarRef("[[ABC]]", "ABC")
+    self.__parsesVarRef("[[A1BC2]]", "A1BC2")
+
+  def test_ValidDef(self):
+    self.__parsesVarDef("[[ABC:abc]]", "ABC", "abc")
+    self.__parsesVarDef("[[ABC:ab:c]]", "ABC", "ab:c")
+    self.__parsesVarDef("[[ABC:a[b]c]]", "ABC", "a[b]c")
+    self.__parsesVarDef("[[ABC:(a[bc])]]", "ABC", "(a[bc])")
+
+  def test_Empty(self):
+    self.__doesNotParse("{{}}", checker.CheckElement.Variant.Pattern)
+    self.__doesNotParse("[[]]", checker.CheckElement.Variant.VarRef)
+    self.__doesNotParse("[[:]]", checker.CheckElement.Variant.VarDef)
+
+  def test_InvalidVarName(self):
+    self.__doesNotParse("[[0ABC]]", checker.CheckElement.Variant.VarRef)
+    self.__doesNotParse("[[AB=C]]", checker.CheckElement.Variant.VarRef)
+    self.__doesNotParse("[[ABC=]]", checker.CheckElement.Variant.VarRef)
+    self.__doesNotParse("[[0ABC:abc]]", checker.CheckElement.Variant.VarDef)
+    self.__doesNotParse("[[AB=C:abc]]", checker.CheckElement.Variant.VarDef)
+    self.__doesNotParse("[[ABC=:abc]]", checker.CheckElement.Variant.VarDef)
+
+  def test_BodyMatchNotGreedy(self):
+    self.__parsesTo("{{abc}}{{def}}", "(abc)(def)")
+    self.__parsesTo("[[ABC:abc]][[DEF:def]]", "(abc)(def)")
+
+  def test_NoVarDefsInNotChecks(self):
+    with self.assertRaises(CheckerException):
+      self.__tryParseNot("[[ABC:abc]]")
+
+class TestCheckLine_Match(unittest.TestCase):
+  def __matchSingle(self, checkString, outputString, varState={}):
+    checkLine = checker.CheckLine(checkString)
+    newVarState = checkLine.match(outputString, varState)
+    self.assertIsNotNone(newVarState)
+    return newVarState
+
+  def __notMatchSingle(self, checkString, outputString, varState={}):
+    checkLine = checker.CheckLine(checkString)
+    self.assertIsNone(checkLine.match(outputString, varState))
+
+  def test_TextAndWhitespace(self):
+    self.__matchSingle("foo", "foo")
+    self.__matchSingle("foo", "  foo  ")
+    self.__matchSingle("foo", "foo bar")
+    self.__notMatchSingle("foo", "XfooX")
+    self.__notMatchSingle("foo", "zoo")
+
+    self.__matchSingle("foo bar", "foo   bar")
+    self.__matchSingle("foo bar", "abc foo bar def")
+    self.__matchSingle("foo bar", "foo foo bar bar")
+
+    self.__matchSingle("foo bar", "foo X bar")
+    self.__notMatchSingle("foo bar", "foo Xbar")
+
+  def test_Pattern(self):
+    self.__matchSingle("foo{{A|B}}bar", "fooAbar")
+    self.__matchSingle("foo{{A|B}}bar", "fooBbar")
+    self.__notMatchSingle("foo{{A|B}}bar", "fooCbar")
+
+  def test_VariableReference(self):
+    self.__matchSingle("foo[[X]]bar", "foobar", {"X": ""})
+    self.__matchSingle("foo[[X]]bar", "fooAbar", {"X": "A"})
+    self.__matchSingle("foo[[X]]bar", "fooBbar", {"X": "B"})
+    self.__notMatchSingle("foo[[X]]bar", "foobar", {"X": "A"})
+    self.__notMatchSingle("foo[[X]]bar", "foo bar", {"X": "A"})
+    with self.assertRaises(CheckerException):
+      self.__matchSingle("foo[[X]]bar", "foobar", {})
+
+  def test_VariableDefinition(self):
+    self.__matchSingle("foo[[X:A|B]]bar", "fooAbar")
+    self.__matchSingle("foo[[X:A|B]]bar", "fooBbar")
+    self.__notMatchSingle("foo[[X:A|B]]bar", "fooCbar")
+
+    env = self.__matchSingle("foo[[X:A.*B]]bar", "fooABbar", {})
+    self.assertEqual(env, {"X": "AB"})
+    env = self.__matchSingle("foo[[X:A.*B]]bar", "fooAxxBbar", {})
+    self.assertEqual(env, {"X": "AxxB"})
+
+    self.__matchSingle("foo[[X:A|B]]bar[[X]]baz", "fooAbarAbaz")
+    self.__matchSingle("foo[[X:A|B]]bar[[X]]baz", "fooBbarBbaz")
+    self.__notMatchSingle("foo[[X:A|B]]bar[[X]]baz", "fooAbarBbaz")
+
+  def test_NoVariableRedefinition(self):
+    with self.assertRaises(CheckerException):
+      self.__matchSingle("[[X:...]][[X]][[X:...]][[X]]", "foofoobarbar")
+
+  def test_EnvNotChangedOnPartialMatch(self):
+    env = {"Y": "foo"}
+    self.__notMatchSingle("[[X:A]]bar", "Abaz", env)
+    self.assertFalse("X" in env.keys())
+
+  def test_VariableContentEscaped(self):
+    self.__matchSingle("[[X:..]]foo[[X]]", ".*foo.*")
+    self.__notMatchSingle("[[X:..]]foo[[X]]", ".*fooAAAA")
+
+
+CheckVariant = checker.CheckLine.Variant
+
+def prepareSingleCheck(line):
+  if isinstance(line, str):
+    return checker.CheckLine(line)
+  else:
+    return checker.CheckLine(line[0], line[1])
+
+def prepareChecks(lines):
+  if isinstance(lines, str):
+    lines = lines.splitlines()
+  return list(map(lambda line: prepareSingleCheck(line), lines))
+
+
+class TestCheckGroup_Match(unittest.TestCase):
+  def __matchMulti(self, checkLines, outputString):
+    checkGroup = checker.CheckGroup("MyGroup", prepareChecks(checkLines))
+    outputGroup = checker.OutputGroup("MyGroup", outputString.splitlines())
+    return checkGroup.match(outputGroup)
+
+  def __notMatchMulti(self, checkString, outputString):
+    with self.assertRaises(CheckerException):
+      self.__matchMulti(checkString, outputString)
+
+  def test_TextAndPattern(self):
+    self.__matchMulti("""foo bar
+                         abc {{def}}""",
+                      """foo bar
+                         abc def""");
+    self.__matchMulti("""foo bar
+                         abc {{de.}}""",
+                      """=======
+                         foo bar
+                         =======
+                         abc de#
+                         =======""");
+    self.__notMatchMulti("""//XYZ: foo bar
+                            //XYZ: abc {{def}}""",
+                         """=======
+                            foo bar
+                            =======
+                            abc de#
+                            =======""");
+
+  def test_Variables(self):
+    self.__matchMulti("""foo[[X:.]]bar
+                         abc[[X]]def""",
+                      """foo bar
+                         abc def""");
+    self.__matchMulti("""foo[[X:([0-9]+)]]bar
+                         abc[[X]]def
+                         ### [[X]] ###""",
+                      """foo1234bar
+                         abc1234def
+                         ### 1234 ###""");
+
+  def test_Ordering(self):
+    self.__matchMulti([("foo", CheckVariant.InOrder),
+                       ("bar", CheckVariant.InOrder)],
+                      """foo
+                         bar""")
+    self.__notMatchMulti([("foo", CheckVariant.InOrder),
+                          ("bar", CheckVariant.InOrder)],
+                         """bar
+                            foo""")
+    self.__matchMulti([("abc", CheckVariant.DAG),
+                       ("def", CheckVariant.DAG)],
+                      """abc
+                         def""")
+    self.__matchMulti([("abc", CheckVariant.DAG),
+                       ("def", CheckVariant.DAG)],
+                      """def
+                         abc""")
+    self.__matchMulti([("foo", CheckVariant.InOrder),
+                       ("abc", CheckVariant.DAG),
+                       ("def", CheckVariant.DAG),
+                       ("bar", CheckVariant.InOrder)],
+                      """foo
+                         def
+                         abc
+                         bar""")
+    self.__notMatchMulti([("foo", CheckVariant.InOrder),
+                          ("abc", CheckVariant.DAG),
+                          ("def", CheckVariant.DAG),
+                          ("bar", CheckVariant.InOrder)],
+                         """foo
+                            abc
+                            bar""")
+    self.__notMatchMulti([("foo", CheckVariant.InOrder),
+                          ("abc", CheckVariant.DAG),
+                          ("def", CheckVariant.DAG),
+                          ("bar", CheckVariant.InOrder)],
+                         """foo
+                            def
+                            bar""")
+
+  def test_NotAssertions(self):
+    self.__matchMulti([("foo", CheckVariant.Not)],
+                      """abc
+                         def""")
+    self.__notMatchMulti([("foo", CheckVariant.Not)],
+                         """abc foo
+                            def""")
+    self.__notMatchMulti([("foo", CheckVariant.Not),
+                          ("bar", CheckVariant.Not)],
+                         """abc
+                            def bar""")
+
+  def test_LineOnlyMatchesOnce(self):
+    self.__matchMulti([("foo", CheckVariant.DAG),
+                       ("foo", CheckVariant.DAG)],
+                       """foo
+                          foo""")
+    self.__notMatchMulti([("foo", CheckVariant.DAG),
+                          ("foo", CheckVariant.DAG)],
+                          """foo
+                             bar""")
+
+class TestOutputFile_Parse(unittest.TestCase):
+  def __parsesTo(self, string, expected):
+    if isinstance(string, str):
+      string = unicode(string)
+    outputStream = io.StringIO(string)
+    return self.assertEqual(checker.OutputFile(outputStream).groups, expected)
+
+  def test_NoInput(self):
+    self.__parsesTo(None, [])
+    self.__parsesTo("", [])
+
+  def test_SingleGroup(self):
+    self.__parsesTo("""begin_compilation
+                         method "MyMethod"
+                       end_compilation
+                       begin_cfg
+                         name "pass1"
+                         foo
+                         bar
+                       end_cfg""",
+                    [ checker.OutputGroup("MyMethod pass1", [ "foo", "bar" ]) ])
+
+  def test_MultipleGroups(self):
+    self.__parsesTo("""begin_compilation
+                         name "xyz1"
+                         method "MyMethod1"
+                         date 1234
+                       end_compilation
+                       begin_cfg
+                         name "pass1"
+                         foo
+                         bar
+                       end_cfg
+                       begin_cfg
+                         name "pass2"
+                         abc
+                         def
+                       end_cfg""",
+                    [ checker.OutputGroup("MyMethod1 pass1", [ "foo", "bar" ]),
+                      checker.OutputGroup("MyMethod1 pass2", [ "abc", "def" ]) ])
+
+    self.__parsesTo("""begin_compilation
+                         name "xyz1"
+                         method "MyMethod1"
+                         date 1234
+                       end_compilation
+                       begin_cfg
+                         name "pass1"
+                         foo
+                         bar
+                       end_cfg
+                       begin_compilation
+                         name "xyz2"
+                         method "MyMethod2"
+                         date 5678
+                       end_compilation
+                       begin_cfg
+                         name "pass2"
+                         abc
+                         def
+                       end_cfg""",
+                    [ checker.OutputGroup("MyMethod1 pass1", [ "foo", "bar" ]),
+                      checker.OutputGroup("MyMethod2 pass2", [ "abc", "def" ]) ])
+
+class TestCheckFile_Parse(unittest.TestCase):
+  def __parsesTo(self, string, expected):
+    if isinstance(string, str):
+      string = unicode(string)
+    checkStream = io.StringIO(string)
+    return self.assertEqual(checker.CheckFile("CHECK", checkStream).groups, expected)
+
+  def test_NoInput(self):
+    self.__parsesTo(None, [])
+    self.__parsesTo("", [])
+
+  def test_SingleGroup(self):
+    self.__parsesTo("""// CHECK-START: Example Group
+                       // CHECK:  foo
+                       // CHECK:    bar""",
+                    [ checker.CheckGroup("Example Group", prepareChecks([ "foo", "bar" ])) ])
+
+  def test_MultipleGroups(self):
+    self.__parsesTo("""// CHECK-START: Example Group1
+                       // CHECK: foo
+                       // CHECK: bar
+                       // CHECK-START: Example Group2
+                       // CHECK: abc
+                       // CHECK: def""",
+                    [ checker.CheckGroup("Example Group1", prepareChecks([ "foo", "bar" ])),
+                      checker.CheckGroup("Example Group2", prepareChecks([ "abc", "def" ])) ])
+
+  def test_CheckVariants(self):
+    self.__parsesTo("""// CHECK-START: Example Group
+                       // CHECK:     foo
+                       // CHECK-NOT: bar
+                       // CHECK-DAG: abc
+                       // CHECK-DAG: def""",
+                    [ checker.CheckGroup("Example Group",
+                                         prepareChecks([ ("foo", CheckVariant.InOrder),
+                                                         ("bar", CheckVariant.Not),
+                                                         ("abc", CheckVariant.DAG),
+                                                         ("def", CheckVariant.DAG) ])) ])
+
+if __name__ == '__main__':
+  checker.Logger.Verbosity = checker.Logger.Level.NoOutput
+  unittest.main()