diff --git a/.gitignore b/.gitignore index 33f56563..8a8ca41b 100644 --- a/.gitignore +++ b/.gitignore @@ -86,6 +86,7 @@ bin/ include/ local/ pip-selfcheck.json +pyvenv.cfg # Spyder project settings .spyderproject @@ -98,3 +99,6 @@ pip-selfcheck.json # Offline version file src/mlx/warnings/__version__.py + +# plantuml generation +src/*.plantuml diff --git a/README.rst b/README.rst index 8d49f172..77dd723f 100644 --- a/README.rst +++ b/README.rst @@ -286,6 +286,64 @@ input file. When this setting is missing, the default value ``true`` is used. .. |--xunit report.xml| replace:: ``--xunit report.xml`` .. _`--xunit report.xml`: https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#xunit-compatible-result-file +Parse for Polyspace Failures +---------------------------- + +The Polyspace checker requires as input a TSV file exported by Polyspace. +You can find instructions on exporting TSV files in the Polyspace documentation. + +Exporting Polyspace Results +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following commands instruct Polyspace to export the results as a TSV file: + +.. code-block:: bash + + polyspace-results-export -format csv -results-dir + # or + polyspace-results-export -format csv -host -run-id + +The csv format outputs tab-separated values (TSV). +Each result in the TSV format consists of tab-separated information in columns. +Starting from Polyspace version R2024a these columns are available: +ID, Family, Group, Color, New, Check, Information, Function, File, Status, Severity, Comment, Key, Line and Col. +In previous versions of Polyspace the Line and Col column are not available yet. + +This file is required when you enable Polyspace in the configuration file. + +Configuration +^^^^^^^^^^^^^ + +Polyspace checking can only be enabled with a configuration file, +and it cannot be used together with other checkers enabled. +In this case, only the Polyspace checker will run. + +When you enable Polyspace checking in the configuration file, +the checks consist of a key that represents the "family" column of the TSV file. +For example, "run-time check" is the family of Code Prover and "defect" is the family of Bug Finder. +The value of that key is a list, which contains the name of the column to check as a key and +the value of that column to check together with ``min`` and ``max`` values. + +Example Checks +^^^^^^^^^^^^^^ + +In case of Code Prover, you might want to check the ``color`` column on ``red`` or ``orange`` issues. +In case of Bug Finder, you might want to check the ``information`` column on ``impact: high``, ``impact: medium``, or even ``impact: low``. +Other issues, such as "Global variable", can also be handled. +You can specify any column and value you want to check in the configuration file. + +Running the mlx-warnings plugin +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following commands demonstrate how to run the mlx-warnings plugin with the TSV file: + +.. code-block:: bash + + # basic Polyspace checker + mlx-warnings --config + # Polyspace checker with code quality export + mlx-warnings --code-quality path/to/code_quality.json --config + ---------------------------------- Configuration File to Pass Options ---------------------------------- @@ -341,6 +399,20 @@ The values for 'min' and 'max' can be set with environment variables via a "max": 0 } ] + }, + "polyspace": { + "enabled": false, + "cq_description_template": "$PRODUCT $family: $check", + "exclude": [ + ".+\\tdummy_function\\(\\)\\tdummy_file_name\\.c\\t" + ], + "run-time check": [ + { + "color": "red", + "min": 0, + "max": 0 + } + ] } } @@ -392,6 +464,30 @@ An example configuration for the sphinx checker is given below: } } +You can define regular expressions to exclude certain Polyspace results, i.e. specific rows of the TSV file, +when they match against the string that represents the row. This string is a concatenation of the values +of all cells in the row, separated by a tab character (`\t`). +Note: backslashes need to be escaped in JSON syntax. + +.. code-block:: json + + { + "polyspace": { + "enabled": true, + "cq_description_template": "$PRODUCT $family: $check", + "exclude": [ + ".+\\tdummy_function\\(\\)\\tdummy_file_name\\.c\\t" + ], + "run-time check": [ + { + "color": "red", + "min": 0, + "max": 0 + } + ] + } + } + Exclude Sphinx Deprecation Warnings ----------------------------------- @@ -411,7 +507,7 @@ Code Quality Report ------------------- Use ``-C, --code-quality`` to let the plugin generate `a Code Quality report`_ for GitLab CI. All counted -Sphinx, Doxygen and XMLRunner will be included. Other checker types are not supported by this feature. The report is +Sphinx, Doxygen, XMLRunner and Polyspace warnings/errors/failures will be included. Other checker types are not yet supported by this feature. The report is a JSON file that implements `a subset of the Code Climate spec`_. Define this file `as a codequality report artifact`_ of the CI job. @@ -419,8 +515,20 @@ If a warning doesn't contain a path, ``"cq_default_path"`` from the `configurati If not configured, ``.gitlab-ci.yml`` will be used as a fallback path. You can customize the description with ``"cq_description_template"``, see `configuration file to pass options`_. -Its value should be a template for Python's |string.Template|_. The template should contain ``$description`` and has -access to all environment variables, e.g. ``$HOME``. +Its value should be a template for Python's |string.Template|_. The template has access to all environment variables, +e.g. ``$HOME``, and other variables that depend on the checker type: + +Polyspace + Any field of a Polyspace defect can be included by using the corresponding + `column title `_ in lowercase as the variable name. + The default template is ``Polyspace: $check``. + +Other + The template should contain ``$description``, which is the default. + +The Polyspace checker generates the fingerprint (a unique identifier) for each row in the TSV file that is exported as finding. +Specific columns (``new``, ``status``, ``severity``, ``comment``, and ``key``) are excluded as they might contain transient information. +The remaining values in the row are hashed using a MD5 function to create the fingerprint. ======================= Issues and New Features diff --git a/docs/design.rst b/docs/design.rst index 327a848a..f43b9e03 100644 --- a/docs/design.rst +++ b/docs/design.rst @@ -10,57 +10,166 @@ Software Design Class Diagram ============= +.. uml generated by `pyreverse mlx.warnings --filter ALL -o plantuml` .. uml:: - @startuml - class WarningsPlugin { - #checkerList : WarningsChecker - +__init__(sphinx=False, doxygen=False, junit=False, verbose=False) + @startuml classes + set namespaceSeparator none + class "CoverityChecker" as mlx.warnings.regex_checker.CoverityChecker { + CLASSIFICATION : str + count + name : str + pattern + check(content) } - - class WarningsChecker { - #min_count = 0 - #max_count = 0 - #count = 0 - #verbose = False - - #{abstract} __init__(name, verbose=False) - +set_limits(min_count=0, max_count=0, - +{abstract}check(content) - +get_count() + class "DoxyChecker" as mlx.warnings.regex_checker.DoxyChecker { + name : str + pattern } - - class RegexChecker { - #{abstract} __init__(name, regex, verbose=False) - +check(content) + class "JUnitChecker" as mlx.warnings.junit_checker.JUnitChecker { + count + name : str + _check_testcase(testcase) + check(content) + prepare_tree(root_input) } - - class SphinxChecker { - #{static} String name - #{static} String regex - +__init__(verbose=False) + class "PolyspaceChecker" as mlx.warnings.polyspace_checker.PolyspaceChecker { + _cq_description_template : Template + checkers : list + count : int + counted_warnings + cq_default_path + cq_description_template + maximum + minimum + name : str + __init__(verbose) + check(content) + parse_config(config) + return_check_limits() + return_count() } - - class DoxyChecker { - #{static} String name - #{static} String regex - +__init__(verbose=False) + class "PolyspaceFamilyChecker" as mlx.warnings.polyspace_checker.PolyspaceFamilyChecker { + _cq_description_template + check_value + code_quality_severity : dict + column_name + count + cq_description_template + cq_findings : list + family_value + __init__(family_value, column_name, check_value) + add_code_quality_finding(row) + check(content) + return_count() } - - class JUnitChecker { - #{static} String name - +__init__(verbose=False) - +check(content) + class "RegexChecker" as mlx.warnings.regex_checker.RegexChecker { + SEVERITY_MAP : dict + count + name : str + pattern : NoneType + add_code_quality_finding(match) + check(content) } - - WarningsPlugin o-- WarningsChecker - WarningsChecker <|-- RegexChecker - RegexChecker <|-- SphinxChecker - RegexChecker <|-- DoxyChecker - WarningsChecker <|-- JUnitChecker - + class "RobotChecker" as mlx.warnings.robot_checker.RobotChecker { + checkers : list + count : int + counted_warnings + maximum + minimum + name : str + check(content) + parse_config(config) + return_check_limits() + return_count() + } + class "RobotSuiteChecker" as mlx.warnings.robot_checker.RobotSuiteChecker { + check_suite_name : bool + is_valid_suite_name : bool + name + __init__(name, check_suite_name) + _check_testcase(testcase) + check(content) + return_count() + } + class "SphinxChecker" as mlx.warnings.regex_checker.SphinxChecker { + name : str + pattern + sphinx_deprecation_regex : str + sphinx_deprecation_regex_in_match : str + include_sphinx_deprecation() + } + class "WarningsChecker" as mlx.warnings.warnings_checker.WarningsChecker { + _counted_warnings : list + _cq_description_template : Template + _maximum : int + _minimum : int + count : int + counted_warnings + cq_default_path : str + cq_description_template + cq_enabled : bool + cq_findings : list + exclude_patterns : list + include_patterns : list + maximum + minimum + name : str + verbose : bool + __init__(verbose) + _is_excluded(content) + _return_error_code() + _search_patterns(content, patterns) + add_patterns(regexes, pattern_container) + {abstract}check(content) + parse_config(config) + print_when_verbose(message) + return_check_limits() + return_count() + } + class "WarningsConfigError" as mlx.warnings.exceptions.WarningsConfigError { + } + class "WarningsPlugin" as mlx.warnings.warnings.WarningsPlugin { + _maximum : int + _minimum : int + activated_checkers : dict + count : int + cq_enabled : bool + printout : bool + public_checkers : list + verbose : bool + __init__(verbose, config_file, cq_enabled) + activate_checker(checker) + activate_checker_name(name) + check(content) + check_logfile(file) + config_parser(config) + configure_maximum(maximum) + configure_minimum(minimum) + get_checker(name) + return_check_limits(name) + return_count(name) + toggle_printout(printout) + write_code_quality_report(out_file) + write_counted_warnings(out_file) + } + class "XMLRunnerChecker" as mlx.warnings.regex_checker.XMLRunnerChecker { + name : str + pattern + } + mlx.warnings.junit_checker.JUnitChecker --|> mlx.warnings.warnings_checker.WarningsChecker + mlx.warnings.polyspace_checker.PolyspaceChecker --|> mlx.warnings.warnings_checker.WarningsChecker + mlx.warnings.polyspace_checker.PolyspaceFamilyChecker --|> mlx.warnings.warnings_checker.WarningsChecker + mlx.warnings.regex_checker.CoverityChecker --|> mlx.warnings.regex_checker.RegexChecker + mlx.warnings.regex_checker.DoxyChecker --|> mlx.warnings.regex_checker.RegexChecker + mlx.warnings.regex_checker.RegexChecker --|> mlx.warnings.warnings_checker.WarningsChecker + mlx.warnings.regex_checker.SphinxChecker --|> mlx.warnings.regex_checker.RegexChecker + mlx.warnings.regex_checker.XMLRunnerChecker --|> mlx.warnings.regex_checker.RegexChecker + mlx.warnings.robot_checker.RobotChecker --|> mlx.warnings.warnings_checker.WarningsChecker + mlx.warnings.robot_checker.RobotSuiteChecker --|> mlx.warnings.junit_checker.JUnitChecker @enduml + String Handling =============== diff --git a/src/mlx/warnings/__init__.py b/src/mlx/warnings/__init__.py index 4d048aa6..e5f8d689 100644 --- a/src/mlx/warnings/__init__.py +++ b/src/mlx/warnings/__init__.py @@ -4,6 +4,8 @@ 'CoverityChecker', 'DoxyChecker', 'JUnitChecker', + 'PolyspaceChecker', + 'PolyspaceFamilyChecker', 'RobotChecker', 'RobotSuiteChecker', 'SphinxChecker', @@ -21,5 +23,6 @@ from .junit_checker import JUnitChecker from .regex_checker import CoverityChecker, DoxyChecker, SphinxChecker, XMLRunnerChecker from .robot_checker import RobotChecker, RobotSuiteChecker +from .polyspace_checker import PolyspaceChecker, PolyspaceFamilyChecker from .warnings import WarningsPlugin, warnings_wrapper from .warnings_checker import WarningsChecker diff --git a/src/mlx/warnings/polyspace_checker.py b/src/mlx/warnings/polyspace_checker.py new file mode 100644 index 00000000..d7ec3c97 --- /dev/null +++ b/src/mlx/warnings/polyspace_checker.py @@ -0,0 +1,270 @@ +import csv +import hashlib +from io import TextIOWrapper +import os +from string import Template + +from .exceptions import WarningsConfigError +from .warnings_checker import WarningsChecker + + +class PolyspaceChecker(WarningsChecker): + name = 'polyspace' + checkers = [] + + def __init__(self, verbose): + '''Constructor to set the default code quality description template to "Polyspace: $check"''' + super().__init__(verbose) + self._cq_description_template = Template('Polyspace: $check') + + @property + def counted_warnings(self): + ''' List: list of counted warnings (str) ''' + all_counted_warnings = [] + for checker in self.checkers: + all_counted_warnings.extend(checker.counted_warnings) + return all_counted_warnings + + @property + def cq_description_template(self): + ''' Template: string.Template instance based on the configured template string ''' + return self._cq_description_template + + @cq_description_template.setter + def cq_description_template(self, template_obj): + self._cq_description_template = template_obj + + @property + def minimum(self): + ''' Gets the lowest minimum amount of warnings + + Returns: + int: the lowest minimum for warnings + ''' + if self.checkers: + return min(x.minimum for x in self.checkers) + return 0 + + @minimum.setter + def minimum(self, minimum): + for checker in self.checkers: + checker.minimum = minimum + + @property + def maximum(self): + ''' Gets the highest minimum amount of warnings + + Returns: + int: the highest maximum for warnings + ''' + if self.checkers: + return max(x.maximum for x in self.checkers) + return 0 + + @maximum.setter + def maximum(self, maximum): + for checker in self.checkers: + checker.maximum = maximum + + def check(self, content): + ''' + Function for counting the number of failures in a TSV file exported by Polyspace + + Args: + content (_io.TextIOWrapper): The open file to parse + ''' + if not isinstance(content, TextIOWrapper): + raise TypeError( + f"{self.__class__.__name__} can't handle this type; expected {type(TextIOWrapper)}; got {type(content)}" + ) + reader = csv.DictReader(content, dialect='excel-tab') + # set column names to lowercase + reader.fieldnames = [name.lower() for name in reader.fieldnames] + + for row in reader: + for checker in self.checkers: + if row['family'].lower() == checker.family_value: + checker.check(row) + + def return_count(self): + ''' Getter function for the amount of warnings found + + Returns: + int: Number of warnings found + ''' + self.count = 0 + for checker in self.checkers: + self.count += checker.return_count() + return self.count + + def return_check_limits(self): + ''' Function for checking whether the warning count is within the configured limits + + Returns: + int: 0 if the amount of warnings is within limits, the count of warnings otherwise + (or 1 in case of a count of 0 warnings) + ''' + count = 0 + for checker in self.checkers: + print( + 'Counted failures for family {!r} \'{}\': \'{}\'' + .format(checker.family_value, checker.column_name, checker.check_value) + ) + count += checker.return_check_limits() + return count + + def parse_config(self, config): + """Parsing configuration dict extracted by previously opened JSON or yaml/yml file + + Args: + config (dict): Content of configuration file + + Raises: + ValueError: Expected a list of dicts as value of the key which represents the value of the 'Family' column. + These dicts need to consist 3 key-value pairs (Note: if 'min' or 'max' is not defined, it will get the + default value of 0): + {\n : ,\n min: ,\n max: \n} + """ + self.checkers = [] + for family_value, data in config.items(): + if family_value == "enabled": + continue + if family_value == "cq_description_template": + self.cq_description_template = Template(config['cq_description_template']) + continue + if family_value == "cq_default_path": + self.cq_default_path = config['cq_default_path'] + continue + if family_value == "exclude": + self.add_patterns(config.get("exclude"), self.exclude_patterns) + continue + for check in data: + for key, value in check.items(): + if key in ["min", "max"]: + continue + column_name = key.lower() + check_value = value.lower() + checker = PolyspaceFamilyChecker(family_value, column_name, check_value, verbose=self.verbose) + checker.parse_config(check) + checker.cq_findings = self.cq_findings # share object with sub-checkers + self.checkers.append(checker) + if not (column_name and check_value): + raise ValueError( + "Expected a list of dicts as value of the key which represents the value of the " + "'Family' column. These dicts need to consist 3 key-value pairs (Note: if 'min' or " + "'max' is not defined, it will get the default value of 0):\n" + "{\n : ,\n min: ,\n max: \n};" + f"got {column_name} as column_name and {check_value} as value_to_check" + ) + for checker in self.checkers: + checker.cq_enabled = self.cq_enabled + checker.exclude_patterns = self.exclude_patterns + checker.cq_description_template = self.cq_description_template + checker.cq_default_path = self.cq_default_path + + +class PolyspaceFamilyChecker(WarningsChecker): + code_quality_severity = { + "impact: high": "critical", + "impact: medium": "major", + "impact: low": "minor", + "red": "critical", + "orange": "major", + } + + def __init__(self, family_value, column_name, check_value, **kwargs): + """Initialize the PolyspaceFamilyChecker + + Args: + family_value (str): The value to search for in the 'Family' column + column_name (str): The name of the column + check_value (str): The value to check in the column + minimum (int): The minimum amount the check_value can occur + maximum (int): The maximum amount the check_value can occur + """ + super().__init__(**kwargs) + self.family_value = family_value + self.column_name = column_name + self.check_value = check_value + + @property + def cq_description_template(self): + ''' Template: string.Template instance based on the configured template string ''' + return self._cq_description_template + + @cq_description_template.setter + def cq_description_template(self, template_obj): + self._cq_description_template = template_obj + + def return_count(self): + ''' Getter function for the amount of warnings found + + Returns: + int: Number of warnings found + ''' + print("{} warnings found for {!r}: {!r}".format(self.count, self.column_name, self.check_value)) + return self.count + + def add_code_quality_finding(self, row): + '''Add code quality finding + + Args: + row (dict): The row of the warning with the corresponding colomn names + ''' + finding = { + "severity": "major", + "location": { + "path": self.cq_default_path, + "positions": { + "begin": { + "line": 1, + "column": 1 + } + } + } + } + + try: + description = self.cq_description_template.substitute(os.environ, **row) + except KeyError as err: + raise WarningsConfigError(f"Failed to find environment variable from configuration value " + f"'cq_description_template': {err}") from err + + # Attention to bug finder: items have color red for impact: high, medium and low. + if row["information"].lower() in self.code_quality_severity.keys(): + finding["severity"] = self.code_quality_severity[row["information"].lower()] + elif row["color"].lower() in self.code_quality_severity.keys(): + finding["severity"] = self.code_quality_severity[row["color"].lower()] + else: + finding["severity"] = "info" + + if row["file"]: + finding["location"]["path"] = row["file"] + if "line" in row: + finding["location"]["positions"]["begin"]["line"] = row["line"] + if "col" in row: + finding["location"]["positions"]["begin"]["column"] = row["line"] + finding["description"] = description + exclude = ("new", "status", "severity", "comment", "key") + row_without_key = [value for key, value in row.items() if key not in exclude] + finding["fingerprint"] = hashlib.md5(str(row_without_key).encode('utf8')).hexdigest() + self.cq_findings.append(finding) + + def check(self, content): + ''' + Function for counting the number of failures in a TSV/CSV file exported by Polyspace + + Args: + content (dict): The row of the TSV file + ''' + if content[self.column_name].lower() == self.check_value: + tab_sep_string = "\t".join(content.values()) + if not self._is_excluded(tab_sep_string): + self.count = self.count + 1 + self.counted_warnings.append('family: {} -> {}: {}'.format( + self.family_value, + self.column_name, + self.check_value + )) + if self.cq_enabled and content["color"].lower() != "green": + self.add_code_quality_finding(content) diff --git a/src/mlx/warnings/robot_checker.py b/src/mlx/warnings/robot_checker.py index bb03d6a5..5a1e7c04 100644 --- a/src/mlx/warnings/robot_checker.py +++ b/src/mlx/warnings/robot_checker.py @@ -18,43 +18,37 @@ def counted_warnings(self): all_counted_warnings.extend(checker.counted_warnings) return all_counted_warnings - def get_minimum(self): + @property + def minimum(self): ''' Gets the lowest minimum amount of warnings Returns: int: the lowest minimum for warnings ''' if self.checkers: - return min(x.get_minimum() for x in self.checkers) + return min(x.minimum for x in self.checkers) return 0 - def set_minimum(self, minimum): - ''' Setter function for the minimum amount of warnings - - Args: - minimum (int): minimum amount of warnings allowed - ''' + @minimum.setter + def minimum(self, minimum): for checker in self.checkers: - checker.set_minimum(minimum) + checker.minimum = minimum - def get_maximum(self): + @property + def maximum(self): ''' Gets the highest minimum amount of warnings Returns: int: the highest maximum for warnings ''' if self.checkers: - return max(x.get_maximum() for x in self.checkers) + return max(x.maximum for x in self.checkers) return 0 - def set_maximum(self, maximum): - ''' Setter function for the maximum amount of warnings - - Args: - maximum (int): maximum amount of warnings allowed - ''' + @maximum.setter + def maximum(self, maximum): for checker in self.checkers: - checker.set_maximum(maximum) + checker.maximum = maximum def check(self, content): ''' diff --git a/src/mlx/warnings/warnings.py b/src/mlx/warnings/warnings.py index 1c2ca7f5..948c5c2d 100644 --- a/src/mlx/warnings/warnings.py +++ b/src/mlx/warnings/warnings.py @@ -18,6 +18,7 @@ from .junit_checker import JUnitChecker from .regex_checker import CoverityChecker, DoxyChecker, SphinxChecker, XMLRunnerChecker from .robot_checker import RobotChecker +from .polyspace_checker import PolyspaceChecker __version__ = distribution('mlx.warnings').version @@ -58,7 +59,7 @@ def __init__(self, verbose=False, config_file=None, cq_enabled=False): self.cq_enabled = cq_enabled self.public_checkers = [SphinxChecker(self.verbose), DoxyChecker(self.verbose), JUnitChecker(self.verbose), XMLRunnerChecker(self.verbose), CoverityChecker(self.verbose), - RobotChecker(self.verbose)] + RobotChecker(self.verbose), PolyspaceChecker(self.verbose)] if config_file: with open(config_file, 'r', encoding='utf-8') as open_file: @@ -68,8 +69,8 @@ def __init__(self, verbose=False, config_file=None, cq_enabled=False): config = json.load(open_file) self.config_parser(config) - self.warn_min = 0 - self.warn_max = 0 + self._minimum = 0 + self._maximum = 0 self.count = 0 self.printout = False @@ -80,7 +81,7 @@ def activate_checker(self, checker): Args: checker (WarningsChecker): checker object ''' - checker.cq_enabled = self.cq_enabled and checker.name in ('doxygen', 'sphinx', 'xmlrunner') + checker.cq_enabled = self.cq_enabled and checker.name in ('doxygen', 'sphinx', 'xmlrunner', 'polyspace') self.activated_checkers[checker.name] = checker def activate_checker_name(self, name): @@ -112,37 +113,55 @@ def get_checker(self, name): def check(self, content): ''' - Function for counting the number of warnings in a specific text + Count the number of warnings in a specified content Args: - content (str): The text to parse + content (str): The content to parse ''' if self.printout: print(content) + if not self.activated_checkers: + print("No checkers activated. Please use activate_checker function") + else: + for checker in self.activated_checkers.values(): + if checker.name == "polyspace": + raise WarningsConfigError("Function check() cannot be used with Polyspace checker.") + else: + checker.check(content) + def check_logfile(self, file): + ''' + Count the number of warnings in a specified content + + Args: + content (_io.TextIOWrapper): The open file to parse + ''' if not self.activated_checkers: print("No checkers activated. Please use activate_checker function") + elif "polyspace" in self.activated_checkers: + self.activated_checkers["polyspace"].check(file) else: + content = file.read() for checker in self.activated_checkers.values(): checker.check(content) - def set_maximum(self, maximum): - ''' Setter function for the maximum amount of warnings + def configure_maximum(self, maximum): + ''' Configure the maximum amount of warnings for each activated checker Args: maximum (int): maximum amount of warnings allowed ''' for checker in self.activated_checkers.values(): - checker.set_maximum(maximum) + checker.maximum = maximum - def set_minimum(self, minimum): - ''' Setter function for the minimum amount of warnings + def configure_minimum(self, minimum): + ''' Configure the minimum amount of warnings for each activated checker Args: minimum (int): minimum amount of warnings allowed ''' for checker in self.activated_checkers.values(): - checker.set_minimum(minimum) + checker.minimum = minimum def return_count(self, name=None): ''' Getter function for the amount of found warnings @@ -200,7 +219,7 @@ def toggle_printout(self, printout): self.printout = printout def config_parser(self, config): - ''' Parsing configuration dict extracted by previously opened JSON file + ''' Parsing configuration dict extracted by previously opened JSON or YAML file Args: config (dict): Content of configuration file @@ -260,7 +279,7 @@ def warnings_wrapper(args): help='Exact amount of warnings expected') group2 = parser.add_argument_group('Configuration file with options') group2.add_argument('--config', dest='configfile', action='store', required=False, type=Path, - help='Config file in JSON format provides toggle of checkers and their limits') + help='Config file in JSON or YAML format provides toggle of checkers and their limits') group2.add_argument('--include-sphinx-deprecation', dest='include_sphinx_deprecation', action='store_true', help="Sphinx checker will include warnings matching (RemovedInSphinx\\d+Warning) regex") parser.add_argument('-o', '--output', @@ -279,7 +298,6 @@ def warnings_wrapper(args): args = parser.parse_args(args) code_quality_enabled = bool(args.code_quality) - # Read config file if args.configfile is not None: checker_flags = args.sphinx or args.doxygen or args.junit or args.coverity or args.xmlrunner or args.robot @@ -310,16 +328,18 @@ def warnings_wrapper(args): if args.maxwarnings | args.minwarnings: print("expected-warnings cannot be provided with maxwarnings or minwarnings") sys.exit(2) - warnings.set_maximum(args.exact_warnings) - warnings.set_minimum(args.exact_warnings) + warnings.configure_maximum(args.exact_warnings) + warnings.configure_minimum(args.exact_warnings) else: - warnings.set_maximum(args.maxwarnings) - warnings.set_minimum(args.minwarnings) + warnings.configure_maximum(args.maxwarnings) + warnings.configure_minimum(args.minwarnings) if args.include_sphinx_deprecation and 'sphinx' in warnings.activated_checkers.keys(): warnings.get_checker('sphinx').include_sphinx_deprecation() if args.command: + if "polyspace" in warnings.activated_checkers: + raise WarningsConfigError("Input argument command cannot be combined with Polyspace checker enabled") cmd = args.logfile if args.flags: cmd.extend(args.flags) @@ -406,8 +426,8 @@ def warnings_logfile(warnings, log): for file_wildcard in log: if glob.glob(file_wildcard): for logfile in glob.glob(file_wildcard): - with open(logfile, 'r') as loghandle: - warnings.check(loghandle.read()) + with open(logfile, "r") as file: + warnings.check_logfile(file) else: print("FILE: %s does not exist" % file_wildcard) return 1 diff --git a/src/mlx/warnings/warnings_checker.py b/src/mlx/warnings/warnings_checker.py index 780eb262..8a655031 100644 --- a/src/mlx/warnings/warnings_checker.py +++ b/src/mlx/warnings/warnings_checker.py @@ -18,8 +18,8 @@ def __init__(self, verbose=False): ''' self.verbose = verbose self.count = 0 - self.warn_min = 0 - self.warn_max = 0 + self._minimum = 0 + self._maximum = 0 self._counted_warnings = [] self.cq_findings = [] self.cq_enabled = False @@ -47,6 +47,38 @@ def cq_description_template(self, template_obj): f"'cq_description_template': {err}") from err self._cq_description_template = template_obj + @property + def maximum(self): + ''' Getter function for the maximum amount of warnings + + Returns: + int: Maximum amount of warnings + ''' + return self._maximum + + @maximum.setter + def maximum(self, maximum): + if self._minimum > maximum: + raise ValueError("Invalid argument: maximum limit must be higher than minimum limit ({min}); cannot " + "set {max}.".format(max=maximum, min=self._minimum)) + self._maximum = maximum + + @property + def minimum(self): + ''' Getter function for the minimum amount of warnings + + Returns: + int: Minimum amount of warnings + ''' + return self._minimum + + @minimum.setter + def minimum(self, minimum): + if minimum > self._maximum: + raise ValueError("Invalid argument: minimum limit must be lower than maximum limit ({max}); cannot " + "set {min}.".format(min=minimum, max=self._maximum)) + self._minimum = minimum + @abc.abstractmethod def check(self, content): ''' Function for counting the number of warnings in a specific text @@ -70,50 +102,6 @@ def add_patterns(self, regexes, pattern_container): for regex in regexes: pattern_container.append(re.compile(regex)) - def set_maximum(self, maximum): - ''' Setter function for the maximum amount of warnings - - Args: - maximum (int): maximum amount of warnings allowed - - Raises: - ValueError: Invalid argument (min limit higher than max limit) - ''' - if self.warn_min > maximum: - raise ValueError("Invalid argument: maximum limit must be higher than minimum limit ({min}); cannot " - "set {max}.".format(max=maximum, min=self.warn_min)) - self.warn_max = maximum - - def get_maximum(self): - ''' Getter function for the maximum amount of warnings - - Returns: - int: Maximum amount of warnings - ''' - return self.warn_max - - def set_minimum(self, minimum): - ''' Setter function for the minimum amount of warnings - - Args: - minimum (int): minimum amount of warnings allowed - - Raises: - ValueError: Invalid argument (min limit higher than max limit) - ''' - if minimum > self.warn_max: - raise ValueError("Invalid argument: minimum limit must be lower than maximum limit ({max}); cannot " - "set {min}.".format(min=minimum, max=self.warn_max)) - self.warn_min = minimum - - def get_minimum(self): - ''' Getter function for the minimum amount of warnings - - Returns: - int: Minimum amount of warnings - ''' - return self.warn_min - def return_count(self): ''' Getter function for the amount of warnings found @@ -130,13 +118,13 @@ def return_check_limits(self): int: 0 if the amount of warnings is within limits, the count of warnings otherwise (or 1 in case of a count of 0 warnings) ''' - if self.count > self.warn_max or self.count < self.warn_min: + if self.count > self._maximum or self.count < self._minimum: return self._return_error_code() - elif self.warn_min == self.warn_max and self.count == self.warn_max: + elif self._minimum == self._maximum and self.count == self._maximum: print("Number of warnings ({0.count}) is exactly as expected. Well done." .format(self)) else: - print("Number of warnings ({0.count}) is between limits {0.warn_min} and {0.warn_max}. Well done." + print("Number of warnings ({0.count}) is between limits {0._minimum} and {0._maximum}. Well done." .format(self)) return 0 @@ -146,10 +134,10 @@ def _return_error_code(self): Returns: int: The count of warnings (or 1 in case of a count of 0 warnings) ''' - if self.count > self.warn_max: - error_reason = "higher than the maximum limit ({0.warn_max})".format(self) + if self.count > self._maximum: + error_reason = "higher than the maximum limit ({0._maximum})".format(self) else: - error_reason = "lower than the minimum limit ({0.warn_min})".format(self) + error_reason = "lower than the minimum limit ({0._minimum})".format(self) error_code = self.count if error_code == 0: @@ -168,8 +156,8 @@ def print_when_verbose(self, message): print(message) def parse_config(self, config): - self.set_maximum(int(config['max'])) - self.set_minimum(int(config['min'])) + self.maximum = int(config['max']) + self.minimum = int(config['min']) self.add_patterns(config.get("exclude"), self.exclude_patterns) if 'cq_default_path' in config: self.cq_default_path = config['cq_default_path'] diff --git a/tests/test_config.py b/tests/test_config.py index e2143c20..6fef8791 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -327,7 +327,7 @@ def test_sphinx_config_max(self): } warnings.config_parser(tmpjson) - self.assertEqual(warnings.get_checker(SphinxChecker().name).get_maximum(), 5) + self.assertEqual(warnings.get_checker(SphinxChecker().name).maximum, 5) def test_doxygen_config_max(self): warnings = WarningsPlugin() @@ -340,7 +340,7 @@ def test_doxygen_config_max(self): } warnings.config_parser(tmpjson) - self.assertEqual(warnings.get_checker(DoxyChecker().name).get_maximum(), 5) + self.assertEqual(warnings.get_checker(DoxyChecker().name).maximum, 5) def test_junit_config_max(self): warnings = WarningsPlugin() @@ -353,7 +353,7 @@ def test_junit_config_max(self): } warnings.config_parser(tmpjson) - self.assertEqual(warnings.get_checker(JUnitChecker().name).get_maximum(), 5) + self.assertEqual(warnings.get_checker(JUnitChecker().name).maximum, 5) def test_xmlrunner_config_max(self): warnings = WarningsPlugin() @@ -366,7 +366,7 @@ def test_xmlrunner_config_max(self): } warnings.config_parser(tmpjson) - self.assertEqual(warnings.get_checker(XMLRunnerChecker().name).get_maximum(), 5) + self.assertEqual(warnings.get_checker(XMLRunnerChecker().name).maximum, 5) def test_all_config_max(self): warnings = WarningsPlugin() @@ -414,11 +414,11 @@ def test_all_config_max(self): } warnings.config_parser(tmpjson) - self.assertEqual(warnings.get_checker(SphinxChecker().name).get_maximum(), 4) - self.assertEqual(warnings.get_checker(DoxyChecker().name).get_maximum(), 5) - self.assertEqual(warnings.get_checker(JUnitChecker().name).get_maximum(), 6) - self.assertEqual(warnings.get_checker(XMLRunnerChecker().name).get_maximum(), 6) - self.assertEqual(warnings.get_checker(RobotChecker().name).get_maximum(), 9) + self.assertEqual(warnings.get_checker(SphinxChecker().name).maximum, 4) + self.assertEqual(warnings.get_checker(DoxyChecker().name).maximum, 5) + self.assertEqual(warnings.get_checker(JUnitChecker().name).maximum, 6) + self.assertEqual(warnings.get_checker(XMLRunnerChecker().name).maximum, 6) + self.assertEqual(warnings.get_checker(RobotChecker().name).maximum, 9) def test_sphinx_config_min(self): warnings = WarningsPlugin() @@ -431,7 +431,7 @@ def test_sphinx_config_min(self): } warnings.config_parser(tmpjson) - self.assertEqual(warnings.get_checker(SphinxChecker().name).get_minimum(), 5) + self.assertEqual(warnings.get_checker(SphinxChecker().name).minimum, 5) def test_doxygen_config_min(self): warnings = WarningsPlugin() @@ -444,7 +444,7 @@ def test_doxygen_config_min(self): } warnings.config_parser(tmpjson) - self.assertEqual(warnings.get_checker(DoxyChecker().name).get_minimum(), 5) + self.assertEqual(warnings.get_checker(DoxyChecker().name).minimum, 5) def test_junit_config_min(self): warnings = WarningsPlugin() @@ -457,7 +457,7 @@ def test_junit_config_min(self): } warnings.config_parser(tmpjson) - self.assertEqual(warnings.get_checker(JUnitChecker().name).get_minimum(), 5) + self.assertEqual(warnings.get_checker(JUnitChecker().name).minimum, 5) def test_xmlrunner_config_min(self): warnings = WarningsPlugin() @@ -470,7 +470,7 @@ def test_xmlrunner_config_min(self): } warnings.config_parser(tmpjson) - self.assertEqual(warnings.get_checker(XMLRunnerChecker().name).get_minimum(), 5) + self.assertEqual(warnings.get_checker(XMLRunnerChecker().name).minimum, 5) def test_all_config_min(self): warnings = WarningsPlugin() @@ -518,11 +518,11 @@ def test_all_config_min(self): } warnings.config_parser(tmpjson) - self.assertEqual(warnings.get_checker(SphinxChecker().name).get_minimum(), 4) - self.assertEqual(warnings.get_checker(DoxyChecker().name).get_minimum(), 3) - self.assertEqual(warnings.get_checker(JUnitChecker().name).get_minimum(), 5) - self.assertEqual(warnings.get_checker(XMLRunnerChecker().name).get_minimum(), 5) - self.assertEqual(warnings.get_checker(RobotChecker().name).get_minimum(), 1) + self.assertEqual(warnings.get_checker(SphinxChecker().name).minimum, 4) + self.assertEqual(warnings.get_checker(DoxyChecker().name).minimum, 3) + self.assertEqual(warnings.get_checker(JUnitChecker().name).minimum, 5) + self.assertEqual(warnings.get_checker(XMLRunnerChecker().name).minimum, 5) + self.assertEqual(warnings.get_checker(RobotChecker().name).minimum, 1) def test_invalid_config(self): warnings = WarningsPlugin() diff --git a/tests/test_in/config_cq_description_format.json b/tests/test_in/config_cq_description_format.json index 091bf92d..d27cdcfe 100644 --- a/tests/test_in/config_cq_description_format.json +++ b/tests/test_in/config_cq_description_format.json @@ -27,5 +27,8 @@ }, "robot": { "enabled": false + }, + "polyspace": { + "enabled": false } } diff --git a/tests/test_in/config_example.json b/tests/test_in/config_example.json index d1c48d77..04d827ac 100644 --- a/tests/test_in/config_example.json +++ b/tests/test_in/config_example.json @@ -40,5 +40,8 @@ "max": 0 } ] + }, + "polyspace": { + "enabled": false } } diff --git a/tests/test_in/config_example_exclude.json b/tests/test_in/config_example_exclude.json index 5b2df8be..87791701 100644 --- a/tests/test_in/config_example_exclude.json +++ b/tests/test_in/config_example_exclude.json @@ -42,5 +42,8 @@ "max": 0 } ] + }, + "polyspace": { + "enabled": false } } diff --git a/tests/test_in/config_example_exclude.yml b/tests/test_in/config_example_exclude.yml index 1f02a50e..b0720552 100644 --- a/tests/test_in/config_example_exclude.yml +++ b/tests/test_in/config_example_exclude.yml @@ -30,3 +30,29 @@ robot: - name: Suite name 2 min: 0 max: 0 +polyspace: + enabled: false + run-time check: + - color: red + min: 0 + max: 0 + - color: orange + min: 0 + max: 10 + global variable: + - color: red + min: 0 + max: 0 + - color: orange + min: 0 + max: 10 + defect: + - information: "impact: high" + min: 0 + max: 0 + - information: "impact: medium" + min: 0 + max: 10 + - information: "impact: low" + min: 0 + max: 30 diff --git a/tests/test_in/config_example_polyspace.yml b/tests/test_in/config_example_polyspace.yml new file mode 100644 index 00000000..4a2e4710 --- /dev/null +++ b/tests/test_in/config_example_polyspace.yml @@ -0,0 +1,38 @@ +sphinx: + enabled: false +doxygen: + enabled: false +junit: + enabled: false +xmlrunner: + enabled: false +coverity: + enabled: false +robot: + enabled: false +polyspace: + enabled: true + run-time check: + - color: red + min: 0 + max: 0 + - color: orange + min: 0 + max: 10 + global variable: + - color: red + min: 0 + max: 0 + - color: orange + min: 0 + max: 10 + defect: + - information: "impact: high" + min: 0 + max: 0 + - information: "impact: medium" + min: 0 + max: 10 + - information: "impact: low" + min: 0 + max: 30 diff --git a/tests/test_in/config_example_polyspace_exclude.json b/tests/test_in/config_example_polyspace_exclude.json new file mode 100644 index 00000000..2707d066 --- /dev/null +++ b/tests/test_in/config_example_polyspace_exclude.json @@ -0,0 +1,79 @@ +{ + "sphinx": { + "enabled": false, + "min": 0, + "max": 0 + }, + "doxygen": { + "enabled": false, + "min": 0, + "max": 0 + }, + "junit": { + "enabled": false, + "min": 0, + "max": 0 + }, + "xmlrunner": { + "enabled": false, + "min": 0, + "max": 0 + }, + "coverity": { + "enabled": false, + "min": 0, + "max": 0 + }, + "robot": { + "enabled": false + }, + "polyspace": { + "enabled": true, + "cq_description_template": "$PRODUCT $family: $check", + "exclude": [ + ".+\\tdummy_function\\(\\)\\tdummy_file_name\\.c\\t" + ], + "run-time check": [ + { + "color": "red", + "min": 0, + "max": 0 + }, + { + "color": "orange", + "min": 0, + "max": 10 + } + ], + "global variable": [ + { + "color": "red", + "min": 0, + "max": 0 + }, + { + "color": "orange", + "min": 0, + "max": 10 + } + ], + "defect": [ + { + "information": "impact: high", + "min": 0, + "max": 0 + }, + { + "information": "impact: medium", + "min": 0, + "max": 10 + }, + { + "information": "impact: low", + "min": 0, + "max": 30 + } + ] + + } +} diff --git a/tests/test_in/config_example_polyspace_exclude.yml b/tests/test_in/config_example_polyspace_exclude.yml new file mode 100644 index 00000000..b1944842 --- /dev/null +++ b/tests/test_in/config_example_polyspace_exclude.yml @@ -0,0 +1,41 @@ +sphinx: + enabled: false +doxygen: + enabled: false +junit: + enabled: false +xmlrunner: + enabled: false +coverity: + enabled: false +robot: + enabled: false +polyspace: + enabled: true + cq_description_template: '$PRODUCT $family: $check' + exclude: + - '.+\tdummy_function\(\)\tdummy_file_name\.c\t' + run-time check: + - color: red + min: 0 + max: 0 + - color: orange + min: 0 + max: 10 + global variable: + - color: red + min: 0 + max: 0 + - color: orange + min: 0 + max: 10 + defect: + - information: 'impact: high' + min: 0 + max: 0 + - information: 'impact: medium' + min: 0 + max: 10 + - information: 'impact: low' + min: 0 + max: 30 diff --git a/tests/test_in/config_example_polyspace_green.yml b/tests/test_in/config_example_polyspace_green.yml new file mode 100644 index 00000000..e1f89b4b --- /dev/null +++ b/tests/test_in/config_example_polyspace_green.yml @@ -0,0 +1,45 @@ +sphinx: + enabled: false +doxygen: + enabled: false +junit: + enabled: false +xmlrunner: + enabled: false +coverity: + enabled: false +robot: + enabled: false +polyspace: + enabled: true + cq_description_template: "Polyspace: $check" + run-time check: + - color: red + min: 0 + max: 0 + - color: orange + min: 0 + max: 10 + - color: green + min: 0 + max: 1000 + global variable: + - color: red + min: 0 + max: 0 + - color: orange + min: 0 + max: 10 + - color: green + min: 0 + max: 1000 + defect: + - information: "impact: high" + min: 0 + max: 0 + - information: "impact: medium" + min: 0 + max: 10 + - information: "impact: low" + min: 0 + max: 30 diff --git a/tests/test_in/config_example_robot.json b/tests/test_in/config_example_robot.json index 680ecdac..86f74c5a 100644 --- a/tests/test_in/config_example_robot.json +++ b/tests/test_in/config_example_robot.json @@ -49,5 +49,8 @@ "max": 0 } ] + }, + "polyspace": { + "enabled": false } } diff --git a/tests/test_in/config_example_robot_invalid_suite.json b/tests/test_in/config_example_robot_invalid_suite.json index 4dd36cca..20fdd18f 100644 --- a/tests/test_in/config_example_robot_invalid_suite.json +++ b/tests/test_in/config_example_robot_invalid_suite.json @@ -43,5 +43,8 @@ "max": 2 } ] + }, + "polyspace": { + "enabled": false } } diff --git a/tests/test_in/polyspace.tsv b/tests/test_in/polyspace.tsv new file mode 100644 index 00000000..a7c04cbf --- /dev/null +++ b/tests/test_in/polyspace.tsv @@ -0,0 +1,140 @@ +ID Family Group Color New Check Information Function File Status Severity Comment Key Line Col +2004 Run-time Check Numerical Green no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 62CCB9F4CA9126346E 1 1 +22002 Run-time Check Numerical Green no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 62CCB9F4CA91263264 1 2 +21998 Run-time Check Numerical Green no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 62CCB9F4CA91263364 2 3 +22009 Run-time Check Data flow Green no Non-initialized local variable dummy_function() dummy_file_name.c Unreviewed Unset 62CCC1E42995263162 2 4 +22005 Run-time Check Data flow Green no Non-initialized local variable dummy_function() dummy_file_name.c Unreviewed Unset 62CCB9E4299526356C 3 5 +22003 Run-time Check Data flow Green no Non-initialized local variable dummy_function() dummy_file_name.c Unreviewed Unset 62CCB9E4299526346E 3 6 +21997 Run-time Check Data flow Green no Non-initialized local variable dummy_function() dummy_file_name.c Unreviewed Unset 62CCB9E42995263364 2 7 +22001 Run-time Check Data flow Green no Non-initialized variable dummy_function() dummy_file_name.c Unreviewed Unset 3166DC7294CACC98 2 8 +21999 Run-time Check Data flow Green no Non-initialized pointer dummy_function() dummy_file_name.c Unreviewed Unset 3166DC72940A8C19 3 9 +22187 Run-time Check Data flow Green no Non-initialized local variable dummy_function() dummy_file_name.c Unreviewed Unset 62D889E42995263162 3 10 +22185 Run-time Check Data flow Green no Non-initialized local variable dummy_function() dummy_file_name.c Unreviewed Unset 316AD87294CA131C 4 1 +22184 Run-time Check Data flow Green no Return value not initialized dummy_function() dummy_file_name.c Unreviewed Unset 316AD04A25CA8C1C 4 2 +22011 Run-time Check Numerical Green no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 3660C87A65C8131C 3 2 +22014 Run-time Check Data flow Green no Non-initialized local variable dummy_function() dummy_file_name.c Unreviewed Unset 6CC0B9E42995263162 3 3 +22010 Run-time Check Data flow Green no Non-initialized local variable dummy_function() dummy_file_name.c Unreviewed Unset 3660C87294CA131C 4 4 +22013 Run-time Check Data flow Green no Non-initialized variable dummy_function() dummy_file_name.c Unreviewed Unset 3660CC7294CA4C9B 4 5 +22012 Run-time Check Data flow Green no Return value not initialized dummy_function() dummy_file_name.c Unreviewed Unset 3660D44A25CA4C9B 5 6 +22176 Run-time Check Data flow Green no Non-initialized local variable dummy_function() dummy_file_name.c Unreviewed Unset 62DC89E42995263162 5 7 +22175 Run-time Check Data flow Green no Return value not initialized dummy_function() dummy_file_name.c Unreviewed Unset 316EC04A25CA8C98 4 8 +22180 Run-time Check Numerical Green no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 68C8B9F4CA9126326E 4 9 +22178 Run-time Check Numerical Green no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 68C8A9F4CA91263172 5 10 +22179 Run-time Check Data flow Green no Non-initialized local variable dummy_function() dummy_file_name.c Unreviewed Unset 68C8B9E4299526326E 5 2 +22177 Run-time Check Data flow Green no Non-initialized variable dummy_function() dummy_file_name.c Unreviewed Unset 3464D47294CA8C19 6 3 +22036 Run-time Check Numerical Green no Overflow dummy_function() dummy_file_name.c Unreviewed Unset C4992326D32B4698C491 6 4 +22065 Run-time Check Data flow Green no Non-initialized local variable dummy_function() dummy_file_name.c Unreviewed Unset C49953E693A45698C489 5 5 +22035 Run-time Check Data flow Green no Non-initialized local variable dummy_function() dummy_file_name.c Unreviewed Unset C499232693A45698C491 5 6 +21989 Run-time Check Numerical Green no Overflow dummy_function() dummy_file_name.c Unreviewed Unset C4997327D32B4698C881 6 7 +19928 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 62C8B1F4CA9126336A 6 8 +19962 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 62D8A9F4CA91263472 7 9 +19526 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C899F4CA9126316A 7 10 +19424 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.h Unreviewed Unset 62E489F4CA91263262 6 11 +19429 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.h Unreviewed Unset 62E4A1F4CA91263162 6 2 +19442 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.h Unreviewed Unset 62C091F4CA91263170 7 3 +19450 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.h Unreviewed Unset 62C091F4CA91263170 7 3 +19375 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C089F4CA9126326C 8 4 +19378 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C091F4CA9126316E 8 5 +19377 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C091F4CA9126336A 7 6 +19357 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8A9F4CA91263368 7 7 +19352 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8A9F4CA91263760 8 8 +19351 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8A9F4CA91263862 8 9 +19355 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8A9F4CA91263962 9 10 +19354 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset CC9153E995234C62C091 9 11 +19358 Run-time Check Numerical Orange no Overflow Origin: Path related issue dummy_function() dummy_file_name.c Unreviewed Unset CC9153E995234C62C0C1 8 3 +19360 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8B1F4CA91263262 8 4 +19349 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8C1F4CA91263262 9 5 +19345 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8C1F4CA91263470 9 6 +19344 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8C1F4CA91263572 10 7 +19339 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66CC91F4CA91263464 10 8 +19338 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66CC91F4CA91263468 9 9 +19336 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66CC91F4CA91263970 9 10 +19335 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset CC9923E995234C62C0C9 10 11 +28766 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 19396855722507 10 12 +28750 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62C8C193AA93293362 11 3 +28728 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62C88983AA9329356C 11 4 +28699 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62C89163AA9329316C 10 4 +28700 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62C89193AA9329316C 10 5 +28703 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62C89923AA9329316C 11 6 +28706 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62C89953AA9329316C 11 7 +28709 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62C89983AA9329316C 12 8 +28713 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62C8A113AA9329316C 12 9 +28716 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62C8A143AA9329316C 11 10 +28720 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62C8A983AA93293368 11 11 +28696 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3966D8AAE44ACC19 12 12 +21985 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62CCC983AA93293366 12 4 +21975 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62D08103AA93293460 13 5 +29090 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62D08973AA93293366 13 6 +29082 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62D09913AA9329356A 12 7 +29081 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 62D0A103AA9329346E 12 8 +22037 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166C89155C9941C 13 9 +22038 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166C89955C9941C 13 10 +22039 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166C8A155C9941C 14 11 +22040 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166C8A955C9941C 14 12 +22041 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166C8B155C9941C 13 13 +22042 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166C8B955C9941C 13 4 +22043 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166C8C155C9941C 14 5 +22044 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166C8C955C9941C 14 5 +22045 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166CC8155C9941C 15 6 +22046 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166CC8955C9941C 15 7 +22047 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166CC9155C9941C 14 8 +22048 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166CC9955C9941C 14 9 +22049 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166CCA155C9941C 15 10 +22050 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166CCA955C9941C 15 11 +22051 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166CCB155C9941C 16 12 +22052 Run-time Check Data flow Gray no Unreachable code dummy_function() dummy_file_name.c Unreviewed Unset 3166CCB955C9941C 16 13 +17503 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.h Unreviewed Unset CD99338805A214EB94A0438AC8A9 15 5 +17504 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.h Unreviewed Unset CD99378805A214EB94A0438AC8A9 15 6 +17505 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 4C18398805A214EB94A0438AC4A9 16 7 +17506 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 668D2241A805FA2528D0A23360 16 8 +17507 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.h Unreviewed Unset 4E19328805A214EB94A0438AC8A1 17 9 +17508 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.h Unreviewed Unset 0E9B328805A214EB94A0438AC8A1 17 10 +17509 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset E6CD2241A805FA2528D0A2316A 16 11 +17510 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 27CD2241A805FA2528D0A2316C 16 12 +17511 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset A60C2241A805FA2528D0A2316A 17 13 +17512 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 86CC2241A805FA2528D0A2316C 17 14 +17513 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 534611A054827D921468511C 18 5 +17514 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 070C2241A805FA2528D0A2326A 18 6 +17515 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.h Unreviewed Unset CD1A378805A214EB94A0438AC8A9 17 6 +17516 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 864E2241A805FA2528D0A23268 17 7 +17517 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.h Unreviewed Unset 8D9C328805A214EB94A0438AC8A9 18 8 +17518 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.h Unreviewed Unset CD9C378805A214EB94A0438AC8A1 18 9 +17519 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset E60C2241A805FA2528D0A23170 19 10 +17520 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset E60C2241A805FA2528D0A23170 19 11 +17521 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset A60C2241A805FA2528D0A2316A 18 12 +17522 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 4C9B398805A214EB94A0438ACC99 18 13 +17523 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset A64D2241A805FA2528D0A2316A 19 14 +17524 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 278C2241A805FA2528D0A2326C 19 6 +17525 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset A60C2241A805FA2528D0A2316A 20 7 +17526 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 4C18358805A214EB94A0438AC4A9 20 8 +17527 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset E60C2241A805FA2528D0A23170 19 9 +17528 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset E60C2241A805FA2528D0A23170 19 10 +17529 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.h Unreviewed Unset CD1A358805A214EB94A0438AC8A9 20 11 +17530 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.h Unreviewed Unset CD1C338805A214EB94A0438AC8A9 20 12 +17531 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset C60C2241A805FA2528D0A23172 21 13 +17532 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 738611A054827D921468519C 21 14 +17533 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 630711A054827D921468519C 20 15 +17534 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset E60C2241A805FA2528D0A23170 20 6 +17535 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.h Unreviewed Unset 0E1C398805A214EB94A0438AC8A1 21 7 +17536 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.h Unreviewed Unset 4E1A358805A214EB94A0438AC8A1 21 7 +17537 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 278C2241A805FA2528D0A2326C 22 8 +17538 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.h Unreviewed Unset CD9A338805A214EB94A0438AC8A9 22 9 +17539 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset C68C2241A805FA2528D0A2316A 21 10 +17540 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset A60C2241A805FA2528D0A2316A 21 11 +17541 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 830711A054827D921468511C 22 12 +17542 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.h Unreviewed Unset CD1C348805A214EB94A0438AC8A9 22 13 +17543 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset A68C2241A805FA2528D0A2316A 23 14 +17544 Defect Concurrency Red no Data race Impact: High File Scope dummy_file_name.c Unreviewed Unset 070C2241A805FA2528D0A2316A 23 15 +17559 Defect Numerical Red no Sign change integer conversion overflow Impact: Medium dummy_function() dummy_file_name.c Unreviewed Unset 3366C89A94E893AF4390057274A84E1C 22 7 +17560 Defect Numerical Red no Sign change integer conversion overflow Impact: Medium dummy_function() dummy_file_name.c Unreviewed Unset 3364E09A94E893AF4390057274A80D1C 22 8 +17561 Defect Numerical Red no Sign change integer conversion overflow Impact: Medium dummy_function() dummy_file_name.c Unreviewed Unset 3364D49A94E893AF4390057274A8CD18 23 9 +17562 Defect Numerical Red no Sign change integer conversion overflow Impact: Medium dummy_function() dummy_file_name.c Unreviewed Unset 3364D49A94E893AF4390057274A84E98 23 10 +17563 Defect Numerical Red no Sign change integer conversion overflow Impact: Medium dummy_function() dummy_file_name.c Unreviewed Unset 3364D89A94E893AF4390057274A88C98 24 11 +17568 Defect Numerical Red no Sign change integer conversion overflow Impact: Medium dummy_function() dummy_file_name.c Unreviewed Unset 3970D09A94E893AF4390057274A84C9B 24 12 +17569 Defect Numerical Red no Sign change integer conversion overflow Impact: Medium dummy_function() dummy_file_name.c Unreviewed Unset 62C099936A52A34EBE0D4214C9D1A2366E 23 13 +17570 Defect Numerical Red no Sign change integer conversion overflow Impact: Medium dummy_function() dummy_file_name.c Unreviewed Unset 62C0A1436A52A34EBE0D4214C9D1A2366E 23 14 +17571 Defect Numerical Red no Sign change integer conversion overflow Impact: Medium dummy_function() dummy_file_name.c Unreviewed Unset 62C0A9436A52A34EBE0D4214C9D1A23162 24 15 +17557 Defect Data flow Red no Dead code Impact: Low dummy_function() dummy_file_name.c Unreviewed Unset 0E1B3288150A44EBD0A7448AC489 24 16 +17564 Defect Data flow Red no Dead code Impact: Low dummy_function() dummy_file_name.c Unreviewed Unset 070C1B448A0522F568D3224568 25 7 +17565 Defect Data flow Red no Dead code Impact: Low dummy_function() dummy_file_name.c Unreviewed Unset 074C9B448A0522F568D3224568 25 8 +17566 Defect Data flow Red no Dead code Impact: Low dummy_function() dummy_file_name.c Unreviewed Unset 07CC98448A0522F568D3224570 24 8 diff --git a/tests/test_in/polyspace_code_quality.json b/tests/test_in/polyspace_code_quality.json new file mode 100644 index 00000000..a3635430 --- /dev/null +++ b/tests/test_in/polyspace_code_quality.json @@ -0,0 +1,1108 @@ +[ + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "6", + "column": "6" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "07bf7b7981eea1d6f5a95d69c9b0d05d" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "7", + "column": "7" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "29a5e4588709eb7271a30605d4fd3bd3" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "7", + "column": "7" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "1e18bf5563037b1193f838617b4be1af" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "6", + "column": "6" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "839e418eda6b091c2413aa0722796fb9" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "6", + "column": "6" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "cabd96c885bd6d9ed3fe867b227e8128" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "7", + "column": "7" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "1961351c7f028d02202f915a6d36c658" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "7", + "column": "7" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "fb6455c4794157cb304be4106e115e35" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "8", + "column": "8" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "187908fe3b88f8c6e304bd5aebd2fa7b" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "8", + "column": "8" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "872e350adf6f6de0e3d530eef532876a" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "7", + "column": "7" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "0c01c54227a1a7529293c8d814d55bce" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "7", + "column": "7" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "ed5eb28ed0310f70d012bb13cf95f794" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "8", + "column": "8" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "e790d2d7f4e8fc2fb244ab0f74beca64" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "8", + "column": "8" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "2848e52a5925a6e7d35aacf6cbf5afed" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "9", + "column": "9" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "71afd01823400c4504d8d0fb125fba4b" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "9", + "column": "9" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "c94b3a08f0577dd14445bb53bb8f810f" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "8", + "column": "8" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "863424d52785aa5300b20cf60b9ada57" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "8", + "column": "8" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "4073ecbcb0efc2c87ae28c56e40672a9" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "9", + "column": "9" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "9cf71035380a184965966250b7cc78c7" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "9", + "column": "9" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "b277b928287c7dd51390ae8079db12f9" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "10", + "column": "10" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "591d152475bd60b07e0e7f00ec000229" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "10", + "column": "10" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "c1886be8c04e07b85f86f2571f0fa03d" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "9", + "column": "9" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "df6c0d8aa86f4d937c674635753a5f46" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "9", + "column": "9" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "4a7e2e12cae10b03859b3b0e0a592b38" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "10", + "column": "10" + } + } + }, + "description": "Polyspace: Overflow", + "fingerprint": "ac3cbdf7ee478c09ddf35b1eec469211" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "15", + "column": "15" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "f4386da30a89e4923f3ab11f0300a5b1" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "15", + "column": "15" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "d95f456b2787e9043443e73f3fc58aad" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "16", + "column": "16" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "507064b5f812014fa76db4d182f10ef9" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "16", + "column": "16" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "8fbf02530e02a7a59fb7983f5f4b6730" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "17", + "column": "17" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "ff3442b2b4d93ba99df38dab2de5fa58" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "17", + "column": "17" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "d81f5651853816b9307a1e708c602f45" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "16", + "column": "16" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "aeaa0e8647882ca64437f80574ff6f43" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "16", + "column": "16" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "c97c42c094fb4136830063eec4efba5a" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "17", + "column": "17" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "2b34873a1dec1df49fba7e4efcb8ed44" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "17", + "column": "17" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "c0772453dfe0d42bc001f4364fe81aa5" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "18", + "column": "18" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "46d63703689a4e9affa63d753e731bb4" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "18", + "column": "18" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "8ad2982125a25d4080d9cf1bffbf35f3" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "17", + "column": "17" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "24e1d7c73a8a75e4aae91535d3107bdf" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "17", + "column": "17" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "77bba0241d8b0ab1416e5a40019fe569" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "18", + "column": "18" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "000c466b7c9f3e654a9451b34d3ca2b9" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "18", + "column": "18" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "08bd07ff0d862e7d6838f18ec9770d71" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "19", + "column": "19" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "b4288f0f2c21f3b74ff67ca44c1770f3" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "19", + "column": "19" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "0e80b89973f7ce6ee7e0b7019f560203" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "18", + "column": "18" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "348768724ae6b4582714b7cba122cccf" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "18", + "column": "18" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "88de3b477121b6d96b1b461858bef89a" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "19", + "column": "19" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "1fcccf3c922c431c7fd13e2d543cb93b" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "19", + "column": "19" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "48047596758b4de4642eb6a8d4187636" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "20", + "column": "20" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "beff306f5b48db5b53e825c93bcf99e8" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "20", + "column": "20" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "e704200bcf976066d129699ed18bca5a" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "19", + "column": "19" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "847843859724033ca453baa07514d2ab" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "19", + "column": "19" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "e44901228d9133623c9213cc2de0fa03" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "20", + "column": "20" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "e1a9645dbe789ab9067ab4841e00e757" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "20", + "column": "20" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "904db74d6533868571599af54a576e6f" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "21", + "column": "21" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "0ae50553c92012904994af8fc028daf6" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "21", + "column": "21" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "a7f1fe9a9eef30de1c690da89cd1df6c" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "20", + "column": "20" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "6dd5de4df76e03f814ffa3737fed8472" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "20", + "column": "20" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "954a867487289986ec5376f2e3153322" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "21", + "column": "21" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "b136cd326ac8fc169cdb853dff7629f6" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "21", + "column": "21" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "1ec7c2c9d9590d54896c21a422fedc9f" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "22", + "column": "22" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "8daff69c6394864723ef2270e08df5c6" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "22", + "column": "22" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "09a0975abac18772472f95038c66c3ac" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "21", + "column": "21" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "7e32a22a66763d665e954d5840a4ce4f" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "21", + "column": "21" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "7f7694b77bfa1f2f31c819ea3bbac911" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "22", + "column": "22" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "7ac65d0792b130472117eb7845b47c78" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "22", + "column": "22" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "25f58aa6ae27914be357df591b857c12" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "23", + "column": "23" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "f851f1962ae59883cabeda61613d989a" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "23", + "column": "23" + } + } + }, + "description": "Polyspace: Data race", + "fingerprint": "f610cc31147b59a271436e925845247d" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "22", + "column": "22" + } + } + }, + "description": "Polyspace: Sign change integer conversion overflow", + "fingerprint": "33e52e2708064ec03c02f4d5fea9177d" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "22", + "column": "22" + } + } + }, + "description": "Polyspace: Sign change integer conversion overflow", + "fingerprint": "96c5ccd9570a83ad30a80aec37354a25" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "23", + "column": "23" + } + } + }, + "description": "Polyspace: Sign change integer conversion overflow", + "fingerprint": "761c46473d2baba43807c2436af41516" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "23", + "column": "23" + } + } + }, + "description": "Polyspace: Sign change integer conversion overflow", + "fingerprint": "aed8d3bdc16ae565024bf537e3fb309e" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "24", + "column": "24" + } + } + }, + "description": "Polyspace: Sign change integer conversion overflow", + "fingerprint": "971b4e1ccd3512a0fc36cdcda90b6b72" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "24", + "column": "24" + } + } + }, + "description": "Polyspace: Sign change integer conversion overflow", + "fingerprint": "ec35a2ca1a81a27f7954f417129c0d08" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "23", + "column": "23" + } + } + }, + "description": "Polyspace: Sign change integer conversion overflow", + "fingerprint": "ed87e9679203350ce4b74e5872bbb6a3" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "23", + "column": "23" + } + } + }, + "description": "Polyspace: Sign change integer conversion overflow", + "fingerprint": "515eddb9bc378eed8762559d6608a181" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "24", + "column": "24" + } + } + }, + "description": "Polyspace: Sign change integer conversion overflow", + "fingerprint": "d02eea0a48ec32debb50e4fe0a1038f4" + }, + { + "severity": "minor", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "24", + "column": "24" + } + } + }, + "description": "Polyspace: Dead code", + "fingerprint": "4fc4aa18191faedbcd3158961ab32e29" + }, + { + "severity": "minor", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "25", + "column": "25" + } + } + }, + "description": "Polyspace: Dead code", + "fingerprint": "b602a67f00eaee672407241d386c2cda" + }, + { + "severity": "minor", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "25", + "column": "25" + } + } + }, + "description": "Polyspace: Dead code", + "fingerprint": "25b08a6b66361fa8f0c988d4831339ca" + }, + { + "severity": "minor", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "24", + "column": "24" + } + } + }, + "description": "Polyspace: Dead code", + "fingerprint": "de0523fb6c1ad76ccdcb524c7185648b" + } +] diff --git a/tests/test_in/polyspace_code_quality_exclude.json b/tests/test_in/polyspace_code_quality_exclude.json new file mode 100644 index 00000000..401a7e49 --- /dev/null +++ b/tests/test_in/polyspace_code_quality_exclude.json @@ -0,0 +1,646 @@ +[ + { + "severity": "major", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "6", + "column": "6" + } + } + }, + "description": "12345 Run-time Check: Overflow", + "fingerprint": "839e418eda6b091c2413aa0722796fb9" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "6", + "column": "6" + } + } + }, + "description": "12345 Run-time Check: Overflow", + "fingerprint": "cabd96c885bd6d9ed3fe867b227e8128" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "7", + "column": "7" + } + } + }, + "description": "12345 Run-time Check: Overflow", + "fingerprint": "1961351c7f028d02202f915a6d36c658" + }, + { + "severity": "major", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "7", + "column": "7" + } + } + }, + "description": "12345 Run-time Check: Overflow", + "fingerprint": "fb6455c4794157cb304be4106e115e35" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "15", + "column": "15" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "f4386da30a89e4923f3ab11f0300a5b1" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "15", + "column": "15" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "d95f456b2787e9043443e73f3fc58aad" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "16", + "column": "16" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "507064b5f812014fa76db4d182f10ef9" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "16", + "column": "16" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "8fbf02530e02a7a59fb7983f5f4b6730" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "17", + "column": "17" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "ff3442b2b4d93ba99df38dab2de5fa58" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "17", + "column": "17" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "d81f5651853816b9307a1e708c602f45" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "16", + "column": "16" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "aeaa0e8647882ca64437f80574ff6f43" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "16", + "column": "16" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "c97c42c094fb4136830063eec4efba5a" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "17", + "column": "17" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "2b34873a1dec1df49fba7e4efcb8ed44" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "17", + "column": "17" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "c0772453dfe0d42bc001f4364fe81aa5" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "18", + "column": "18" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "46d63703689a4e9affa63d753e731bb4" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "18", + "column": "18" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "8ad2982125a25d4080d9cf1bffbf35f3" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "17", + "column": "17" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "24e1d7c73a8a75e4aae91535d3107bdf" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "17", + "column": "17" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "77bba0241d8b0ab1416e5a40019fe569" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "18", + "column": "18" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "000c466b7c9f3e654a9451b34d3ca2b9" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "18", + "column": "18" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "08bd07ff0d862e7d6838f18ec9770d71" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "19", + "column": "19" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "b4288f0f2c21f3b74ff67ca44c1770f3" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "19", + "column": "19" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "0e80b89973f7ce6ee7e0b7019f560203" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "18", + "column": "18" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "348768724ae6b4582714b7cba122cccf" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "18", + "column": "18" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "88de3b477121b6d96b1b461858bef89a" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "19", + "column": "19" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "1fcccf3c922c431c7fd13e2d543cb93b" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "19", + "column": "19" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "48047596758b4de4642eb6a8d4187636" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "20", + "column": "20" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "beff306f5b48db5b53e825c93bcf99e8" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "20", + "column": "20" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "e704200bcf976066d129699ed18bca5a" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "19", + "column": "19" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "847843859724033ca453baa07514d2ab" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "19", + "column": "19" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "e44901228d9133623c9213cc2de0fa03" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "20", + "column": "20" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "e1a9645dbe789ab9067ab4841e00e757" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "20", + "column": "20" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "904db74d6533868571599af54a576e6f" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "21", + "column": "21" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "0ae50553c92012904994af8fc028daf6" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "21", + "column": "21" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "a7f1fe9a9eef30de1c690da89cd1df6c" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "20", + "column": "20" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "6dd5de4df76e03f814ffa3737fed8472" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "20", + "column": "20" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "954a867487289986ec5376f2e3153322" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "21", + "column": "21" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "b136cd326ac8fc169cdb853dff7629f6" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "21", + "column": "21" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "1ec7c2c9d9590d54896c21a422fedc9f" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "22", + "column": "22" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "8daff69c6394864723ef2270e08df5c6" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "22", + "column": "22" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "09a0975abac18772472f95038c66c3ac" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "21", + "column": "21" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "7e32a22a66763d665e954d5840a4ce4f" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "21", + "column": "21" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "7f7694b77bfa1f2f31c819ea3bbac911" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "22", + "column": "22" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "7ac65d0792b130472117eb7845b47c78" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.h", + "positions": { + "begin": { + "line": "22", + "column": "22" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "25f58aa6ae27914be357df591b857c12" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "23", + "column": "23" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "f851f1962ae59883cabeda61613d989a" + }, + { + "severity": "critical", + "location": { + "path": "dummy_file_name.c", + "positions": { + "begin": { + "line": "23", + "column": "23" + } + } + }, + "description": "12345 Defect: Data race", + "fingerprint": "f610cc31147b59a271436e925845247d" + } +] diff --git a/tests/test_limits.py b/tests/test_limits.py index e97c98b5..61fa97e1 100644 --- a/tests/test_limits.py +++ b/tests/test_limits.py @@ -11,31 +11,31 @@ def setUp(self): def test_set_maximum(self): for x in range(0, 10): - self.warnings.set_maximum(x) - self.assertEqual(self.warnings.get_checker(DoxyChecker.name).get_maximum(), x) + self.warnings.configure_maximum(x) + self.assertEqual(self.warnings.get_checker(DoxyChecker.name).maximum, x) def test_set_minimum(self): # Setting minimum is tricky - we need to max out maximum - self.warnings.set_maximum(11) + self.warnings.configure_maximum(11) for x in range(0, 10): - self.warnings.set_minimum(x) - self.assertEqual(self.warnings.get_checker(DoxyChecker.name).get_minimum(), x) + self.warnings.configure_minimum(x) + self.assertEqual(self.warnings.get_checker(DoxyChecker.name).minimum, x) def test_set_minimum_fail(self): - self.warnings.set_maximum(5) + self.warnings.configure_maximum(5) for x in range(1, 5): - self.warnings.set_minimum(x) - self.assertEqual(self.warnings.get_checker(DoxyChecker.name).get_minimum(), x) + self.warnings.configure_minimum(x) + self.assertEqual(self.warnings.get_checker(DoxyChecker.name).minimum, x) for x in range(6, 10): - self.assertRaises(ValueError, self.warnings.set_minimum, x) + self.assertRaises(ValueError, self.warnings.configure_minimum, x) def test_return_values_maximum_decrease(self): self.warnings.check('testfile.c:6: warning: group test: ignoring title "Some test functions" that does not match old title "Some freaky test functions"') self.assertEqual(self.warnings.return_count(), 1) - self.warnings.set_maximum(1) + self.warnings.configure_maximum(1) self.assertEqual(self.warnings.return_check_limits(), 0) - self.warnings.set_maximum(0) + self.warnings.configure_maximum(0) self.assertEqual(self.warnings.return_check_limits(), 1) def test_return_values_maximum_increase(self): @@ -43,9 +43,9 @@ def test_return_values_maximum_increase(self): self.assertEqual(self.warnings.return_count(), 1) self.warnings.check('testfile.c:12: warning: group test: ignoring title "Some test functions" that does not match old title "Some freaky test functions"') self.assertEqual(self.warnings.return_count(), 2) - self.warnings.set_maximum(1) + self.warnings.configure_maximum(1) self.assertEqual(self.warnings.return_check_limits(), 2) - self.warnings.set_maximum(2) + self.warnings.configure_maximum(2) self.assertEqual(self.warnings.return_check_limits(), 0) def test_return_values_minimum_increase(self): @@ -57,25 +57,25 @@ def test_return_values_minimum_increase(self): self.assertEqual(self.warnings.return_check_limits(), 2) # to set minimum we need to make maximum higher - self.warnings.set_maximum(10) + self.warnings.configure_maximum(10) for x in range(1, 10): if x <= 3: self.assertEqual(self.warnings.return_check_limits(), 0) else: self.assertEqual(self.warnings.return_check_limits(), 2) - self.warnings.set_minimum(x) + self.warnings.configure_minimum(x) def test_invalid_minimum(self): - self.warnings.set_maximum(10) + self.warnings.configure_maximum(10) with self.assertRaises(ValueError) as c_m: - self.warnings.set_minimum(11) + self.warnings.configure_minimum(11) self.assertEqual(str(c_m.exception), 'Invalid argument: minimum limit must be lower than maximum limit (10); cannot set 11.') def test_invalid_maximum(self): - self.warnings.set_maximum(10) - self.warnings.set_minimum(10) + self.warnings.configure_maximum(10) + self.warnings.configure_minimum(10) with self.assertRaises(ValueError) as c_m: - self.warnings.set_maximum(9) + self.warnings.configure_maximum(9) self.assertEqual(str(c_m.exception), 'Invalid argument: maximum limit must be higher than minimum limit (10); cannot set 9.') diff --git a/tests/test_polyspace.py b/tests/test_polyspace.py new file mode 100644 index 00000000..793e3566 --- /dev/null +++ b/tests/test_polyspace.py @@ -0,0 +1,137 @@ +import os +from io import StringIO +import unittest +from pathlib import Path +import filecmp + +from unittest.mock import patch + +from mlx.warnings import PolyspaceFamilyChecker, WarningsPlugin, warnings_wrapper + +TEST_IN_DIR = Path(__file__).parent / 'test_in' +TEST_OUT_DIR = Path(__file__).parent / 'test_out' + + +class TestCodeProverWarnings(unittest.TestCase): + def setUp(self): + self.warnings = WarningsPlugin(verbose=True) + self.dut = self.warnings.activate_checker_name('polyspace') + self.dut.checkers = [ + PolyspaceFamilyChecker("run-time check", "color", "red"), + PolyspaceFamilyChecker("run-time check", "color", "orange"), + ] + + def test_code_prover_tsv_file(self): + with open(TEST_IN_DIR / 'polyspace.tsv', newline="") as file: + with patch('sys.stdout', new=StringIO()) as fake_out: + self.warnings.check_logfile(file) + count = self.warnings.return_count() + stdout_log = fake_out.getvalue() + + count_sum = 0 + for checker in self.dut.checkers: + count_sum += checker.count + self.assertIn( + f"{checker.count} warnings found for '{checker.column_name}': '{checker.check_value}'", + stdout_log + ) + self.assertEqual(count, count_sum) + self.assertEqual(count, 24) + + +class TestBugFinderWarnings(unittest.TestCase): + def setUp(self): + self.warnings = WarningsPlugin(verbose=True) + self.dut = self.warnings.activate_checker_name('polyspace') + self.dut.checkers = [ + PolyspaceFamilyChecker("defect", "information", "impact: high"), + PolyspaceFamilyChecker("defect", "information", "impact: medium"), + PolyspaceFamilyChecker("defect", "information", "impact: low"), + ] + + def test_bug_finder_tsv_file(self): + with open(TEST_IN_DIR / 'polyspace.tsv', newline="") as file: + with patch('sys.stdout', new=StringIO()) as fake_out: + self.warnings.check_logfile(file) + count = self.warnings.return_count() + stdout_log = fake_out.getvalue() + + for checker in self.dut.checkers: + self.assertIn( + f"{checker.count} warnings found for '{checker.column_name}': '{checker.check_value}'", + stdout_log + ) + self.assertEqual(count, 55) + + +class TestPolyspaceWarnings(unittest.TestCase): + def setUp(self): + os.environ['MIN_SPHINX_WARNINGS'] = '0' + os.environ['MAX_SPHINX_WARNINGS'] = '0' + + def tearDown(self): + for var in ('MIN_SPHINX_WARNINGS', 'MAX_SPHINX_WARNINGS'): + if var in os.environ: + del os.environ[var] + + def test_config_file(self): + retval = warnings_wrapper([ + '--config', str(TEST_IN_DIR / 'config_example_polyspace.yml'), + str(TEST_IN_DIR / 'polyspace.tsv') + ]) + self.assertEqual(66, retval) + + def test_code_quality(self): + filename = 'polyspace_code_quality.json' + out_file = str(TEST_OUT_DIR / filename) + ref_file = str(TEST_IN_DIR / filename) + retval = warnings_wrapper([ + '--code-quality', out_file, + '--config', str(TEST_IN_DIR / 'config_example_polyspace.yml'), + str(TEST_IN_DIR / 'polyspace.tsv'), + ]) + self.assertEqual(66, retval) + self.assertTrue(filecmp.cmp(out_file, ref_file)) + + def test_code_quality_no_green(self): + out_file = str(TEST_OUT_DIR / 'polyspace_code_quality_green.json') + ref_file = str(TEST_IN_DIR / 'polyspace_code_quality.json') + retval = warnings_wrapper([ + '--code-quality', out_file, + '--config', str(TEST_IN_DIR / 'config_example_polyspace_green.yml'), + str(TEST_IN_DIR / 'polyspace.tsv'), + ]) + self.assertEqual(66, retval) + self.assertTrue(filecmp.cmp(out_file, ref_file)) + + def test_exclude_yaml_config(self): + os.environ['PRODUCT'] = '12345' + filename = "polyspace_code_quality_exclude.json" + out_file = str(TEST_OUT_DIR / filename) + ref_file = str(TEST_IN_DIR / filename) + retval = warnings_wrapper([ + '--code-quality', out_file, + '--config', str(TEST_IN_DIR / 'config_example_polyspace_exclude.yml'), + str(TEST_IN_DIR / 'polyspace.tsv'), + ]) + self.assertEqual(42, retval) + self.assertTrue(filecmp.cmp(out_file, ref_file)) + del os.environ["PRODUCT"] + + def test_exclude_json_config(self): + os.environ['PRODUCT'] = '12345' + filename = "polyspace_code_quality_exclude.json" + out_file = str(TEST_OUT_DIR / filename) + ref_file = str(TEST_IN_DIR / filename) + retval = warnings_wrapper([ + '--code-quality', out_file, + '--config', str(TEST_IN_DIR / 'config_example_polyspace_exclude.json'), + str(TEST_IN_DIR / 'polyspace.tsv'), + ]) + self.assertEqual(42, retval) + self.assertTrue(filecmp.cmp(out_file, ref_file)) + del os.environ["PRODUCT"] + + +if __name__ == '__main__': + unittest.main()