#!/usr/bin/python
# Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# suppressions.py

"""Valgrind-style suppressions for heapchecker reports.

Suppressions are defined as follows:

# optional one-line comments anywhere in the suppressions file.
{
  Toolname:Errortype
  Short description of the error.
  fun:function_name
  fun:wildcarded_fun*_name
  # an ellipsis wildcards zero or more functions in a stack.
  ...
  fun:some_other_function_name
}

Note that only a 'fun:' prefix is allowed, i.e. we can't suppress objects and
source files.

If ran from the command line, suppressions.py does a self-test of the
Suppression class.
"""

import re

ELLIPSIS = '...'


class Suppression(object):
  """This class represents a single stack trace suppression.

  Attributes:
    type: A string representing the error type, e.g. Heapcheck:Leak.
    description: A string representing the error description.
  """

  def __init__(self, kind, description, stack):
    """Inits Suppression.

    stack is a list of function names and/or wildcards.

    Args:
      kind:
      description: Same as class attributes.
      stack: A list of strings.
    """
    self.type = kind
    self.description = description
    self._stack = stack
    re_line = ''
    re_bucket = ''
    for line in stack:
      if line == ELLIPSIS:
        re_line += re.escape(re_bucket)
        re_bucket = ''
        re_line += '(.*\n)*'
      else:
        for char in line:
          if char == '*':
            re_line += re.escape(re_bucket)
            re_bucket = ''
            re_line += '.*'
          else:  # there can't be any '\*'s in a stack trace
            re_bucket += char
        re_line += re.escape(re_bucket)
        re_bucket = ''
        re_line += '\n'
    self._re = re.compile(re_line, re.MULTILINE)

  def Match(self, report):
    """Returns bool indicating whether the suppression matches the given report.

    Args:
      report: list of strings (function names).
    Returns:
      True if the suppression is not empty and matches the report.
    """
    if not self._stack:
      return False
    if self._re.match('\n'.join(report) + '\n'):
      return True
    else:
      return False


class SuppressionError(Exception):
  def __init__(self, filename, line, report=''):
    Exception.__init__(self, filename, line, report)
    self._file = filename
    self._line = line
    self._report = report

  def __str__(self):
    return 'Error reading suppressions from "%s" (line %d): %s.' % (
        self._file, self._line, self._report)


def ReadSuppressionsFromFile(filename):
  """Given a file, returns a list of suppressions."""
  input_file = file(filename, 'r')
  result = []
  cur_descr = ''
  cur_type = ''
  cur_stack = []
  nline = 0
  try:
    for line in input_file:
      nline += 1
      line = line.strip()
      if line.startswith('#'):
        continue
      elif line.startswith('{'):
        pass
      elif line.startswith('}'):
        result.append(Suppression(cur_type, cur_descr, cur_stack))
        cur_descr = ''
        cur_type = ''
        cur_stack = []
      elif not cur_descr:
        cur_descr = line
        continue
      elif not cur_type:
        cur_type = line
        continue
      elif line.startswith('fun:'):
        line = line[4:]
        cur_stack.append(line.strip())
      elif line.startswith(ELLIPSIS):
        cur_stack.append(ELLIPSIS)
      else:
        raise SuppressionError(filename, nline,
                               '"fun:function_name" or "..." expected')
  except SuppressionError:
    input_file.close()
    raise
  return result


def MatchTest():
  """Tests the Suppression.Match() capabilities."""

  def GenSupp(*lines):
    return Suppression('', '', list(lines))
  empty = GenSupp()
  assert not empty.Match([])
  assert not empty.Match(['foo', 'bar'])
  asterisk = GenSupp('*bar')
  assert asterisk.Match(['foobar', 'foobaz'])
  assert not asterisk.Match(['foobaz', 'foobar'])
  ellipsis = GenSupp('...', 'foo')
  assert ellipsis.Match(['foo', 'bar'])
  assert ellipsis.Match(['bar', 'baz', 'foo'])
  assert not ellipsis.Match(['bar', 'baz', 'bah'])
  mixed = GenSupp('...', 'foo*', 'function')
  assert mixed.Match(['foobar', 'foobaz', 'function'])
  assert not mixed.Match(['foobar', 'blah', 'function'])
  at_and_dollar = GenSupp('foo@GLIBC', 'bar@NOCANCEL')
  assert at_and_dollar.Match(['foo@GLIBC', 'bar@NOCANCEL'])
  re_chars = GenSupp('.*')
  assert re_chars.Match(['.foobar'])
  assert not re_chars.Match(['foobar'])
  print 'PASS'

if __name__ == '__main__':
  MatchTest()
