| Index: tools/heapcheck/suppressions.py
|
| diff --git a/tools/heapcheck/suppressions.py b/tools/heapcheck/suppressions.py
|
| deleted file mode 100755
|
| index 506caa670f8d15ae506b89194782953a8b476351..0000000000000000000000000000000000000000
|
| --- a/tools/heapcheck/suppressions.py
|
| +++ /dev/null
|
| @@ -1,170 +0,0 @@
|
| -#!/usr/bin/env python
|
| -# Copyright (c) 2011 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.
|
| -
|
| -"""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()
|
|
|