File: filter_expected_warnings.py

package info (click to toggle)
cbmc 6.6.0-4
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 153,852 kB
  • sloc: cpp: 386,459; ansic: 114,466; java: 28,405; python: 6,003; yacc: 4,552; makefile: 4,041; lex: 2,487; xml: 2,388; sh: 2,050; perl: 557; pascal: 184; javascript: 163; ada: 36
file content (121 lines) | stat: -rwxr-xr-x 4,340 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/env python
"""Script to filter out old warnings from doxygen."""

import sys
import re


class DoxygenWarning(object):
    """Doxygen warning class."""

    def __init__(self, firstline, filename, warning):
        self.firstline = firstline
        self.filename = filename
        self.warning = warning
        self.otherlines = []

    def equals_ignoring_path_and_line_number(self, other):
        """Return true if warnings have same filename and warning message."""
        if self.filename != other.filename:
            return False
        if self.warning != other.warning:
            return False
        return self.otherlines == other.otherlines

    def print_with_prefix(self, prefix):
        print(prefix + self.firstline)
        for line in self.otherlines:
            print(prefix + '  ' + line)


class WarningsList(object):
    """List of Doxygen warnings."""

    def __init__(self, all_lines):
        """Create a list of the warnings in this file."""
        self.warnings_list = []
        current = None

        warning_start_expr = re.compile(r'[^:]+/([^:/]+):\d+: (warning.*$)')

        for line in all_lines:
            if line.isspace():
                continue

            # Allow comments in the list of expected warnings.
            if line.startswith('#'):
                continue

            matched = warning_start_expr.match(line)
            if matched:
                filename = matched.group(1)
                warning = matched.group(2)
                current = DoxygenWarning(line.strip(), filename, warning)
                self.warnings_list.append(current)
            elif line.startswith('  '):
                current.otherlines.append(line.strip())
            else:
                # Warnings are usually of the form [path:line: warning:...]
                # (and the warnings about too many nodes have been filtered out).
                # Treat any unexpected input lines as warnings.
                current = DoxygenWarning(line, '', line)
                self.warnings_list.append(current)

    def contains(self, warning):
        """Check if a similar warning is in this list."""
        for other in self.warnings_list:
            if warning.equals_ignoring_path_and_line_number(other):
                return True
        return False

    def print_warnings_not_in_other_list(self, other, prefix):
        """Check if this a subset of other, and print anything missing."""
        missing_element_found = False
        for warning in self.warnings_list:
            if not other.contains(warning):
                missing_element_found = True
                warning.print_with_prefix(prefix)
        return missing_element_found


def ignore_too_many_nodes(all_lines):
    """Filter out lines about graphs with too many nodes."""
    too_many_nodes_expr = re.compile(
        r'warning: Include(d by)? graph for .* not generated, too many '
        + r'nodes( \(\d+\), threshold is 60)?\. Consider increasing '
        + r'DOT_GRAPH_MAX_NODES\.')
    return [x for x in all_lines if not too_many_nodes_expr.match(x)]


def filter_expected_warnings(expected_warnings_path):
    """Filter lines from stdin and print to stdout."""
    with open(expected_warnings_path, "r") as warnings_file:
        expected_warnings = WarningsList(warnings_file.readlines())

    new_warnings = WarningsList(ignore_too_many_nodes(sys.stdin.readlines()))

    # print unexpected warnings
    unexpected_warning_found = new_warnings.print_warnings_not_in_other_list(
        expected_warnings, '')

    # print expected warnings which aren't found
    expected_warning_not_found = expected_warnings.print_warnings_not_in_other_list(
        new_warnings, '-')

    if expected_warning_not_found:
        print('NOTE: Warnings prefixed with \'-\' are expected ' +
              'warnings which weren\'t found.')
        print('      Please update the list of expected warnings.')

    return unexpected_warning_found or expected_warning_not_found


if __name__ == "__main__":

    if len(sys.argv) != 2:
        print('usage: filter_expected_warnings.py <expected_warnings_file>')
        print('(warnings from stdin are filtered and printed to stdout)')
        sys.exit(1)

    problem_found = filter_expected_warnings(sys.argv[1])
    sys.exit(1 if problem_found else 0)