Exemple #1
0
    def report(self):
        """Execute CodePeer message reader and parses the output.

        Sets the exec_status property according to the success of the analysis:

            * ``GNAThub.EXEC_SUCCESS``: on successful execution and analysis
            * ``GNAThub.EXEC_FAILURE``: on any error
        """

        self.info('clear existing results if any')
        GNAThub.Tool.clear_references(self.name)

        self.info('extract results with msg_reader')
        proc = GNAThub.Run(self.output_dir,
                           self.__msg_reader_cmd_line(),
                           out=self.csv_report,
                           capture_stderr=False)

        if proc.status != 0:
            return GNAThub.EXEC_FAILURE

        self.info('analyse CSV report')
        self.tool = GNAThub.Tool(self.name)

        self.log.debug('parse report: %s', self.csv_report)

        if not os.path.isfile(self.csv_report):
            self.error('no report found')
            return GNAThub.EXEC_FAILURE

        with open(self.csv_report, 'rb') as report:
            # Compute the total number of lines for progress report (-1 because
            # the first line in irrelevant to the analysis).
            index, total = 0, len(report.readlines()) - 1

            # Reset the read cursor to the first byte
            report.seek(0)

            # Create the tag "New" for new CodePeer messages
            added_tag = GNAThub.Property('codepeer:added', 'Added')
            removed_tag = GNAThub.Property('codepeer:removed', 'Removed')
            unchanged_tag = GNAThub.Property('codepeer:unchanged', 'Unchanged')

            try:
                # Parse the file and drop the first line (containing the
                # columns name).
                reader = csv.reader(report, quotechar='\"')

                # Drop the first line (containing the columns name)
                header = reader.next()
                self.log.debug('drop header line: %s', header)

                # Iterate over each relevant record
                for index, record in enumerate(reader, start=1):
                    self.log.debug('parse record: %r', record)

                    # Each row is a list of strings:
                    #
                    #   File, Line, Column, Category, History, Has_Review,
                    #   Ranking, Kind, Message, Classification, CWE, Checks,
                    #   Primary_Checks, Subp, Timestamp, Approved By, Comment,
                    #   Message_Id
                    (source, line, column, rule, history, has_review, severity,
                     category, message, classification, cwe, checks, pchecks,
                     subp, timestamp, app_by, comment,
                     message_id) = record[:18]

                    if not severity or severity == 'suppressed':
                        # Some versions of codepeer report an empty severity
                        # for suppressed messages: map this to 'info'.
                        severity = 'info'

                    rule_id = rule.lower()
                    self.__add_message(source, line, column, rule_id, message,
                                       severity, message_id, [
                                           added_tag if history == 'added' else
                                           (removed_tag if history == 'removed'
                                            else unchanged_tag)
                                       ])

                    if index % 100 == 1 or index == total:
                        Console.progress(index,
                                         total,
                                         new_line=(index == total))

            except csv.Error as why:
                self.log.exception('failed to parse CSV report')
                self.error('%s (%s:%d)' %
                           (why, os.path.basename(self.csv_report), index))
                return GNAThub.EXEC_FAILURE

            else:
                self.__do_bulk_insert()
                return GNAThub.EXEC_SUCCESS
Exemple #2
0
    def report(self):
        """Parse GNATcheck output file report.

        Returns according to the success of the analysis:

            * ``GNAThub.EXEC_SUCCESS``: on successful execution and analysis
            * ``GNAThub.EXEC_FAILURE``: on any error

        Identify two type of messages with different format:

            * basic message
            * message for package instantiation
        """
        # Clear existing references only if not incremental run
        if not GNAThub.incremental():
            self.info('clear existing results if any')
            GNAThub.Tool.clear_references(self.name)

        self.info('analyse report')

        self.tool = GNAThub.Tool(self.name)
        self.log.debug('parse report: %s', self.output)

        if not os.path.exists(self.output):
            self.error('no report found')
            return GNAThub.EXEC_FAILURE

        try:
            with open(self.output, 'r') as output:
                lines = output.readlines()
                total = len(lines)

                # Local variables used for exemptions handling
                exempted_violation = False
                hide_exempted = GNAThub.gnatcheck_hide_exempted()

                # Add the tag "exempted" for GNATcheck exempted violations
                exempt_tag = GNAThub.Property('gnatcheck:exempted', 'Exempted')
                prev_line = ""

                for index, line in enumerate(lines, start=1):
                    self.log.debug('parse line: %s', line)

                    # check if is a section title
                    matchTitle = self._TITLE.match(line)
                    if matchTitle:
                        stitle = matchTitle.group('stitle')
                        exempted_violation = stitle in ('Exempted', 'EXEMPTED')

                    # filter messages if occurs in exempted violation section
                    import_violation = not exempted_violation or (
                       exempted_violation and not hide_exempted)
                    handle_exempted = exempted_violation and not hide_exempted

                    if import_violation:
                        if handle_exempted:
                            match1 = self._MESSAGE.match(line)
                            if match1:
                                self.log.debug('matched: %s',
                                               str(match1.groups()))
                                # Store this line in order to gather next line
                                # justification if any
                                if prev_line == "":
                                    prev_line = line
                                else:
                                    # Second line is a new violation report
                                    match_prev = self._MESSAGE.match(prev_line)
                                    if match_prev:
                                        self.__parse_line_exempted(
                                           match_prev, [exempt_tag])
                                        prev_line = line

                                # self.__parse_line_exempted(match1,
                                #                           [exempt_tag])
                            else:
                                if prev_line != "":
                                    if len(line.strip()) != 0:
                                        # Handle justification for prev_line
                                        pmatch = self._MESSAGE.match(prev_line)
                                        if pmatch:
                                            self.__parse_line_exempted(
                                              pmatch, [exempt_tag],
                                              line.strip())
                                            # Reset previous line value
                                            prev_line = ""

                        else:
                            match = self._MESSAGE.match(line)
                            if match:
                                self.log.debug('matched: %s',
                                               str(match.groups()))
                                self.__parse_line(match)
                            else:
                                match2 = self._MESSAGE_INST.match(line)
                                if match2:
                                    self.log.debug('matched 2: %s',
                                                   str(match2.groups()))
                                    self.__parse_line_inst(match2)

                    Console.progress(index, total, new_line=(index == total))

        except IOError as why:
            self.log.exception('failed to parse report')
            self.error('%s (%s:%d)' % (
                why, os.path.basename(self.output), total))
            return GNAThub.EXEC_FAILURE

        else:
            self.__do_bulk_insert()
            return GNAThub.EXEC_SUCCESS
Exemple #3
0
import GNAThub

from support.asserts import (
    assertEmpty, assertEqual, assertIsNotNone, assertNotEmpty, assertRaises
)


base = GNAThub.Project.source_file('simple.adb')
resource = GNAThub.Resource.get(base)
assertIsNotNone(resource)
tool = GNAThub.Tool('test-tool')
assertIsNotNone(tool)
rule = GNAThub.Rule('test-rule', 'test-rule-name', GNAThub.RULE_KIND, tool)
assertIsNotNone(rule)
prop0 = GNAThub.Property('test-prop-0', 'test-prop-name-0')
assertIsNotNone(prop0)
prop1 = GNAThub.Property('test-prop-1', 'test-prop-name-1')
assertIsNotNone(prop1)

msg0 = GNAThub.Message(rule, 'test message', properties=None)
assertIsNotNone(msg0)
assertEmpty(msg0.get_properties())

msg1 = GNAThub.Message(rule, 'test message', properties=[prop0, prop1])
assertIsNotNone(msg1)

for msg in msg0, msg1:
    resource.add_message(msg)

assertNotEmpty(msg1.get_properties())