Exemple #1
0
 def setUpClass(cls):
     dir_path = os.path.dirname(os.path.realpath(__file__))
     gcno_path = os.path.join(dir_path, cls.GOLDEN_GCNO_PATH)
     with open(gcno_path, 'rb') as file:
         gcno_summary = gcno_parser.GCNOParser(file).Parse()
     gcda_path = os.path.join(dir_path, cls.GOLDEN_GCDA_PATH)
     with open(gcda_path, 'rb') as file:
         parser = gcda_parser.GCDAParser(file)
         parser.Parse(gcno_summary)
     cls.gcno_summary = gcno_summary
 def setUpClass(cls):
     root_dir = os.path.join(os.getenv('ANDROID_BUILD_TOP'),
                             'test/vts/utils/python/coverage/testdata/')
     gcno_path = os.path.join(root_dir, 'sample.gcno')
     with open(gcno_path, 'rb') as file:
         gcno_summary = gcno_parser.GCNOParser(file).Parse()
     gcda_path = os.path.join(root_dir, 'sample.gcda')
     with open(gcda_path, 'rb') as file:
         parser = gcda_parser.GCDAParser(file)
         parser.Parse(gcno_summary)
     cls.gcno_summary = gcno_summary
Exemple #3
0
 def testReadFunction(self):
     """Verifies that the correct function is read and returned.
     """
     ident = 100
     checksum = 0
     fs = file_summary.FileSummary()
     func = function_summary.FunctionSummary(ident, 'test', 'test.c', 0)
     fs.functions[ident] = func
     self.stream = MockStream.concat_int(self.stream, ident)
     self.stream = MockStream.concat_int(self.stream, 0)
     self.stream = MockStream.concat_int(self.stream, 0)
     self.stream = MockStream.concat_string(self.stream, 'test')
     length = 5
     parser = gcda_parser.GCDAParser(self.stream)
     parser.file_summary = fs
     func = parser.ReadFunction(5)
     assert (func.ident == ident)
Exemple #4
0
    def testReadCountsNormal(self):
        """Verifies that counts are read correctly.

        Verifies that arcs are marked as resolved and count is correct.
        """
        n = 5
        fs = file_summary.FileSummary()
        func = function_summary.FunctionSummary(0, 'test', 'test.c', 0)
        blocks = [block_summary.BlockSummary(i, 0) for i in range(n)]
        func.blocks = blocks
        fs.functions[func.ident] = func
        for i in range(1, n):
            arc = arc_summary.ArcSummary(blocks[0], blocks[i], 0)
            blocks[0].exit_arcs.append(arc)
            blocks[i].entry_arcs.append(arc)
            self.stream = MockStream.concat_int64(self.stream, i)
        parser = gcda_parser.GCDAParser(self.stream)
        parser.file_summary = fs
        parser.ReadCounts(func)
        for i, arc in zip(range(1, n), blocks[0].exit_arcs):
            self.assertEqual(i, arc.count)
            self.assertTrue(arc.resolved)
Exemple #5
0
    def testReadCountsFakeOrOnTree(self):
        """Verifies that counts are read correctly when there are skipped arcs.

        Verifies that the fake arc and the arc on the tree are skipped while other
        arcs are read and resolved correctly.
        """
        n = 10
        fs = file_summary.FileSummary()
        func = function_summary.FunctionSummary(0, 'test', 'test.c', 0)
        blocks = [block_summary.BlockSummary(i, 0) for i in range(n)]
        func.blocks = blocks
        fs.functions[func.ident] = func

        arc = arc_summary.ArcSummary(blocks[0], blocks[1],
                                     arc_summary.ArcSummary.GCOV_ARC_FAKE)
        blocks[0].exit_arcs.append(arc)
        blocks[1].entry_arcs.append(arc)

        arc = arc_summary.ArcSummary(blocks[0], blocks[2],
                                     arc_summary.ArcSummary.GCOV_ARC_ON_TREE)
        blocks[0].exit_arcs.append(arc)
        blocks[2].entry_arcs.append(arc)

        for i in range(3, n):
            arc = arc_summary.ArcSummary(blocks[0], blocks[i], 0)
            blocks[0].exit_arcs.append(arc)
            blocks[i].entry_arcs.append(arc)
            self.stream = MockStream.concat_int64(self.stream, i)

        parser = gcda_parser.GCDAParser(self.stream)
        parser.file_summary = fs
        parser.ReadCounts(func)
        self.assertFalse(blocks[0].exit_arcs[0].resolved)
        self.assertFalse(blocks[0].exit_arcs[1].resolved)
        for i, arc in zip(range(3, n), blocks[0].exit_arcs[2:]):
            self.assertEqual(i, arc.count)
            self.assertTrue(arc.resolved)
Exemple #6
0
    def _ManualProcess(self, cov_zip, revision_dict, gcda_dict, isGlobal):
        """Process coverage data and appends coverage reports to the report message.

        Opens the gcno files in the cov_zip for the specified modules and matches
        gcno/gcda files. Then, coverage vectors are generated for each set of matching
        gcno/gcda files and appended as a CoverageReportMessage to the provided
        report message. Unlike AutoProcess, coverage information is only processed
        for the modules explicitly defined in 'modules'.

        Args:
            cov_zip: the ZipFile object containing the gcno coverage artifacts.
            revision_dict: the dictionary from project name to project version.
            gcda_dict: the dictionary of gcda basenames to gcda content (binary string)
            isGlobal: boolean, True if the coverage data is for the entire test, False if only for
                      the current test case.
        """
        output_coverage_report = getattr(
            self, keys.ConfigKeys.IKEY_OUTPUT_COVERAGE_REPORT, True)
        modules = getattr(self, keys.ConfigKeys.IKEY_MODULES, None)
        covered_modules = set(cov_zip.namelist())
        for module in modules:
            if MODULE_NAME not in module or GIT_PROJECT not in module:
                logging.error(
                    "Coverage module must specify name and git project: %s",
                    module)
                continue
            project = module[GIT_PROJECT]
            if PATH not in project or NAME not in project:
                logging.error("Project name and path not specified: %s",
                              project)
                continue

            name = str(module[MODULE_NAME]) + COVERAGE_SUFFIX
            git_project = str(project[NAME])
            git_project_path = str(project[PATH])

            if name not in covered_modules:
                logging.error("No coverage information for module %s", name)
                continue
            if git_project not in revision_dict:
                logging.error(
                    "Git project not present in device revision dict: %s",
                    git_project)
                continue

            revision = str(revision_dict[git_project])
            archive = archive_parser.Archive(cov_zip.open(name).read())
            try:
                archive.Parse()
            except ValueError:
                logging.error("Archive could not be parsed: %s", name)
                continue

            for gcno_file_path in archive.files:
                file_name_path = gcno_file_path.rsplit(".", 1)[0]
                file_name = os.path.basename(file_name_path)
                gcno_content = archive.files[gcno_file_path]
                gcno_stream = io.BytesIO(gcno_content)
                try:
                    gcno_summary = gcno_parser.GCNOParser(gcno_stream).Parse()
                except FileFormatError:
                    logging.error("Error parsing gcno file %s", gcno_file_path)
                    continue
                src_file_path = None

                # Match gcno file with gcda file
                gcda_name = file_name + GCDA_SUFFIX
                if gcda_name not in gcda_dict:
                    logging.error("No gcda file found %s.", gcda_name)
                    continue

                src_file_path = self._ExtractSourceName(
                    gcno_summary, file_name)

                if not src_file_path:
                    logging.error("No source file found for %s.",
                                  gcno_file_path)
                    continue

                # Process and merge gcno/gcda data
                gcda_content = gcda_dict[gcda_name]
                gcda_stream = io.BytesIO(gcda_content)
                try:
                    gcda_parser.GCDAParser(gcda_stream).Parse(gcno_summary)
                except FileFormatError:
                    logging.error("Error parsing gcda file %s", gcda_content)
                    continue

                if self.web and self.web.enabled:
                    coverage_vec = coverage_report.GenerateLineCoverageVector(
                        src_file_path, gcno_summary)
                    total_count, covered_count = coverage_report.GetCoverageStats(
                        coverage_vec)
                    self.web.AddCoverageReport(coverage_vec, src_file_path,
                                               git_project, git_project_path,
                                               revision, covered_count,
                                               total_count, isGlobal)

        if output_coverage_report:
            self._OutputCoverageReport(isGlobal)
Exemple #7
0
    def _AutoProcess(self, cov_zip, revision_dict, gcda_dict, isGlobal):
        """Process coverage data and appends coverage reports to the report message.

        Matches gcno files with gcda files and processes them into a coverage report
        with references to the original source code used to build the system image.
        Coverage information is appended as a CoverageReportMessage to the provided
        report message.

        Git project information is automatically extracted from the build info and
        the source file name enclosed in each gcno file. Git project names must
        resemble paths and may differ from the paths to their project root by at
        most one. If no match is found, then coverage information will not be
        be processed.

        e.g. if the project path is test/vts, then its project name may be
             test/vts or <some folder>/test/vts in order to be recognized.

        Args:
            cov_zip: the ZipFile object containing the gcno coverage artifacts.
            revision_dict: the dictionary from project name to project version.
            gcda_dict: the dictionary of gcda basenames to gcda content (binary string)
            isGlobal: boolean, True if the coverage data is for the entire test, False if only for
                      the current test case.
        """
        checksum_gcno_dict = self._GetChecksumGcnoDict(cov_zip)
        output_coverage_report = getattr(
            self, keys.ConfigKeys.IKEY_OUTPUT_COVERAGE_REPORT, False)
        exclude_coverage_path = getattr(
            self, keys.ConfigKeys.IKEY_EXCLUDE_COVERAGE_PATH, [])
        for idx, path in enumerate(exclude_coverage_path):
            base_name = os.path.basename(path)
            if base_name and "." not in base_name:
                path = path if path.endswith("/") else path + "/"
                exclude_coverage_path[idx] = path
        exclude_coverage_path.extend(self._DEFAULT_EXCLUDE_PATHS)

        coverage_dict = dict()
        coverage_report_message = ReportMsg.TestReportMessage()

        for gcda_name in gcda_dict:
            if GEN_TAG in gcda_name:
                # skip coverage measurement for intermediate code.
                logging.warn("Skip for gcda file: %s", gcda_name)
                continue

            gcda_stream = io.BytesIO(gcda_dict[gcda_name])
            gcda_file_parser = gcda_parser.GCDAParser(gcda_stream)
            file_name = gcda_name.rsplit(".", 1)[0]

            if not gcda_file_parser.checksum in checksum_gcno_dict:
                logging.info("No matching gcno file for gcda: %s", gcda_name)
                continue
            gcno_file_parsers = checksum_gcno_dict[gcda_file_parser.checksum]
            gcno_summary = self._FindGcnoSummary(file_name, gcno_file_parsers)
            if gcno_summary is None:
                logging.error("No gcno file found for gcda %s.", gcda_name)
                continue

            # Process and merge gcno/gcda data
            try:
                gcda_file_parser.Parse(gcno_summary)
            except FileFormatError:
                logging.error("Error parsing gcda file %s", gcda_name)
                continue

            coverage_report.GenerateLineCoverageVector(
                gcno_summary, exclude_coverage_path, coverage_dict)

        for src_file_path in coverage_dict:
            # Get the git project information
            # Assumes that the project name and path to the project root are similar
            revision = None
            for project_name in revision_dict:
                # Matches cases when source file root and project name are the same
                if src_file_path.startswith(str(project_name)):
                    git_project_name = str(project_name)
                    git_project_path = str(project_name)
                    revision = str(revision_dict[project_name])
                    logging.debug("Source file '%s' matched with project '%s'",
                                  src_file_path, git_project_name)
                    break

                parts = os.path.normpath(str(project_name)).split(os.sep, 1)
                # Matches when project name has an additional prefix before the
                # project path root.
                if len(parts) > 1 and src_file_path.startswith(parts[-1]):
                    git_project_name = str(project_name)
                    git_project_path = parts[-1]
                    revision = str(revision_dict[project_name])
                    logging.debug("Source file '%s' matched with project '%s'",
                                  src_file_path, git_project_name)
                    break

            if not revision:
                logging.info("Could not find git info for %s", src_file_path)
                continue

            coverage_vec = coverage_dict[src_file_path]
            total_count, covered_count = coverage_report.GetCoverageStats(
                coverage_vec)
            if self.web and self.web.enabled:
                self.web.AddCoverageReport(coverage_vec, src_file_path,
                                           git_project_name, git_project_path,
                                           revision, covered_count,
                                           total_count, isGlobal)
            else:
                coverage = coverage_report_message.coverage.add()
                coverage.total_line_count = total_count
                coverage.covered_line_count = covered_count
                coverage.line_coverage_vector.extend(coverage_vec)

                src_file_path = os.path.relpath(src_file_path,
                                                git_project_path)
                coverage.file_path = src_file_path
                coverage.revision = revision
                coverage.project_name = git_project_name

        if output_coverage_report:
            self._OutputCoverageReport(isGlobal, coverage_report_message)
    def _AutoProcess(self, gcda_dict, isGlobal):
        """Process coverage data and appends coverage reports to the report message.

        Matches gcno files with gcda files and processes them into a coverage report
        with references to the original source code used to build the system image.
        Coverage information is appended as a CoverageReportMessage to the provided
        report message.

        Git project information is automatically extracted from the build info and
        the source file name enclosed in each gcno file. Git project names must
        resemble paths and may differ from the paths to their project root by at
        most one. If no match is found, then coverage information will not be
        be processed.

        e.g. if the project path is test/vts, then its project name may be
             test/vts or <some folder>/test/vts in order to be recognized.

        Args:
            gcda_dict: the dictionary of gcda basenames to gcda content (binary string)
            isGlobal: boolean, True if the coverage data is for the entire test, False if only for
                      the current test case.
        """
        revision_dict = getattr(self, _REVISION_DICT, None)
        checksum_gcno_dict = getattr(self, _CHECKSUM_GCNO_DICT, None)
        output_coverage_report = getattr(
            self, keys.ConfigKeys.IKEY_OUTPUT_COVERAGE_REPORT, False)

        for gcda_name in gcda_dict:
            gcda_stream = io.BytesIO(gcda_dict[gcda_name])
            gcda_file_parser = gcda_parser.GCDAParser(gcda_stream)

            if not gcda_file_parser.checksum in checksum_gcno_dict:
                logging.info("No matching gcno file for gcda: %s", gcda_name)
                continue
            gcno_file_parser = checksum_gcno_dict[gcda_file_parser.checksum]

            try:
                gcno_summary = gcno_file_parser.Parse()
            except FileFormatError:
                logging.error("Error parsing gcno for gcda %s", gcda_name)
                continue

            file_name = gcda_name.rsplit(".", 1)[0]
            src_file_path = self._ExtractSourceName(gcno_summary, file_name)

            if not src_file_path:
                logging.error("No source file found for gcda %s.", gcda_name)
                continue

            # Process and merge gcno/gcda data
            try:
                gcda_file_parser.Parse(gcno_summary)
            except FileFormatError:
                logging.error("Error parsing gcda file %s", gcda_name)
                continue

            # Get the git project information
            # Assumes that the project name and path to the project root are similar
            revision = None
            for project_name in revision_dict:
                # Matches cases when source file root and project name are the same
                if src_file_path.startswith(str(project_name)):
                    git_project_name = str(project_name)
                    git_project_path = str(project_name)
                    revision = str(revision_dict[project_name])
                    logging.info("Source file '%s' matched with project '%s'",
                                 src_file_path, git_project_name)
                    break

                parts = os.path.normpath(str(project_name)).split(os.sep, 1)
                # Matches when project name has an additional prefix before the
                # project path root.
                if len(parts) > 1 and src_file_path.startswith(parts[-1]):
                    git_project_name = str(project_name)
                    git_project_path = parts[-1]
                    revision = str(revision_dict[project_name])
                    logging.info("Source file '%s' matched with project '%s'",
                                 src_file_path, git_project_name)

            if not revision:
                logging.info("Could not find git info for %s", src_file_path)
                continue

            if self.web and self.web.enabled:
                coverage_vec = coverage_report.GenerateLineCoverageVector(
                    src_file_path, gcno_summary)
                total_count, covered_count = coverage_report.GetCoverageStats(
                    coverage_vec)
                self.web.AddCoverageReport(coverage_vec, src_file_path,
                                           git_project_name, git_project_path,
                                           revision, covered_count,
                                           total_count, isGlobal)

        if output_coverage_report:
            self._OutputCoverageReport(isGlobal)