Beispiel #1
0
    def GenerateReportMessage(self, requested, executed):
        """Uploads the result to the web service.

        Requires the feature to be enabled; no-op otherwise.

        Args:
            requested: list, A list of test case records requested to run
            executed: list, A list of test case records that were executed

        Returns:
            binary string, serialized report message.
            None if web is not enabled.
        """
        if not self.enabled:
            return None

        # Handle case when runner fails, tests aren't executed
        if (not getattr(self, keys.ConfigKeys.RUN_AS_VTS_SELFTEST, False)
                and executed and executed[-1].test_name == "setup_class"):
            # Test failed during setup, all tests were not executed
            start_index = 0
        else:
            # Runner was aborted. Remaining tests weren't executed
            start_index = len(executed)

        for test in requested[start_index:]:
            msg = self.report_msg.test_case.add()
            msg.name = test.test_name
            msg.start_timestamp = feature_utils.GetTimestamp()
            msg.end_timestamp = msg.start_timestamp
            msg.test_result = ReportMsg.TEST_CASE_RESULT_FAIL

        self.report_msg.end_timestamp = feature_utils.GetTimestamp()

        build = getattr(self, keys.ConfigKeys.IKEY_BUILD)
        if keys.ConfigKeys.IKEY_BUILD_ID in build:
            build_id = str(build[keys.ConfigKeys.IKEY_BUILD_ID])
            self.report_msg.build_info.id = build_id

        logging.info("_tearDownClass hook: start (username: %s)",
                     getpass.getuser())

        if len(self.report_msg.test_case) == 0:
            logging.info("_tearDownClass hook: skip uploading (no test case)")
            return ''

        post_msg = ReportMsg.DashboardPostMessage()
        post_msg.test_report.extend([self.report_msg])

        self.rest_client.AddAuthToken(post_msg)

        message_b = base64.b64encode(post_msg.SerializeToString())

        logging.info('Result proto message generated. size: %s',
                     len(message_b))

        logging.info("_tearDownClass hook: status upload time stamp %s",
                     str(self.report_msg.start_timestamp))

        return message_b
Beispiel #2
0
    def _OutputCoverageReport(self, isGlobal, coverage_report_msg=None):
        logging.info("Outputing coverage data")
        timestamp_seconds = str(int(time.time() * 1000000))
        coverage_report_file_name = "coverage_report_" + timestamp_seconds + ".txt"
        if self._coverage_report_file_prefix:
            coverage_report_file_name = "coverage_report_" + self._coverage_report_file_prefix + ".txt"

        coverage_report_file = None
        if (self._coverage_report_dir):
            if not os.path.exists(self._coverage_report_dir):
                os.makedirs(self._coverage_report_dir)
            coverage_report_file = os.path.join(self._coverage_report_dir,
                                                coverage_report_file_name)
        else:
            coverage_report_file = os.path.join(self.local_coverage_path,
                                                coverage_report_file_name)

        logging.info("Storing coverage report to: %s", coverage_report_file)
        if self.web and self.web.enabled:
            coverage_report_msg = ReportMsg.TestReportMessage()
            if isGlobal:
                for c in self.web.report_msg.coverage:
                    coverage = coverage_report_msg.coverage.add()
                    coverage.CopyFrom(c)
            else:
                for c in self.web.current_test_report_msg.coverage:
                    coverage = coverage_report_msg.coverage.add()
                    coverage.CopyFrom(c)
        if coverage_report_msg is not None:
            with open(coverage_report_file, "w+") as f:
                f.write(str(coverage_report_msg))
Beispiel #3
0
    def __init__(self, user_params):
        """Initializes the web feature.

        Parses the arguments and initializes the web functionality.

        Args:
            user_params: A dictionary from parameter name (String) to parameter value.
        """
        self.ParseParameters(toggle_param_name=self._TOGGLE_PARAM,
                             required_param_names=self._REQUIRED_PARAMS,
                             optional_param_names=self._OPTIONAL_PARAMS,
                             user_params=user_params)
        if not self.enabled:
            return

        # Initialize the dashboard client
        post_cmd = getattr(self, keys.ConfigKeys.IKEY_DASHBOARD_POST_COMMAND)
        service_json_path = str(
            getattr(self, keys.ConfigKeys.IKEY_SERVICE_JSON_PATH))
        self.rest_client = dashboard_rest_client.DashboardRestClient(
            post_cmd, service_json_path)
        if not self.rest_client.Initialize():
            self.enabled = False

        self.report_msg = ReportMsg.TestReportMessage()
        self.report_msg.test = str(
            getattr(self, keys.ConfigKeys.KEY_TESTBED_NAME))

        if getattr(self, keys.ConfigKeys.IKEY_ENABLE_PROFILING, False):
            logging.info("Profiling test")
            self.report_msg.test += "Profiling"

        self.report_msg.test_type = ReportMsg.VTS_HOST_DRIVEN_STRUCTURAL
        self.report_msg.start_timestamp = feature_utils.GetTimestamp()
        self.report_msg.host_info.hostname = socket.gethostname()

        android_devices = getattr(self, keys.ConfigKeys.IKEY_ANDROID_DEVICE,
                                  None)
        if not android_devices or not isinstance(android_devices, list):
            logging.warn("android device information not available")
            return

        for device_spec in android_devices:
            dev_info = self.report_msg.device_info.add()
            for elem in [
                    keys.ConfigKeys.IKEY_PRODUCT_TYPE,
                    keys.ConfigKeys.IKEY_PRODUCT_VARIANT,
                    keys.ConfigKeys.IKEY_BUILD_FLAVOR,
                    keys.ConfigKeys.IKEY_BUILD_ID, keys.ConfigKeys.IKEY_BRANCH,
                    keys.ConfigKeys.IKEY_BUILD_ALIAS,
                    keys.ConfigKeys.IKEY_API_LEVEL, keys.ConfigKeys.IKEY_SERIAL
            ]:
                if elem in device_spec:
                    setattr(dev_info, elem, str(device_spec[elem]))
            # TODO: get abi information differently for multi-device support.
            setattr(dev_info, keys.ConfigKeys.IKEY_ABI_NAME,
                    str(getattr(self, keys.ConfigKeys.IKEY_ABI_NAME)))
            setattr(dev_info, keys.ConfigKeys.IKEY_ABI_BITNESS,
                    str(getattr(self, keys.ConfigKeys.IKEY_ABI_BITNESS)))
Beispiel #4
0
    def GenerateReportMessage(self, requested, executed):
        """Uploads the result to the web service.

        Requires the feature to be enabled; no-op otherwise.

        Args:
            requested: list, A list of test case records requested to run
            executed: list, A list of test case records that were executed

        Returns:
            binary string, serialized report message.
            None if web is not enabled.
        """
        if not self.enabled:
            return None

        for test in requested[len(executed):]:
            msg = self.report_msg.test_case.add()
            msg.name = test.test_name
            msg.start_timestamp = feature_utils.GetTimestamp()
            msg.end_timestamp = msg.start_timestamp
            msg.test_result = ReportMsg.TEST_CASE_RESULT_FAIL

        self.report_msg.end_timestamp = feature_utils.GetTimestamp()

        build = getattr(self, keys.ConfigKeys.IKEY_BUILD)
        if keys.ConfigKeys.IKEY_BUILD_ID in build:
            build_id = str(build[keys.ConfigKeys.IKEY_BUILD_ID])
            self.report_msg.build_info.id = build_id

        logging.debug("_tearDownClass hook: start (username: %s)",
                      getpass.getuser())

        if len(self.report_msg.test_case) == 0:
            logging.warn("_tearDownClass hook: skip uploading (no test case)")
            return ''

        post_msg = ReportMsg.DashboardPostMessage()
        post_msg.test_report.extend([self.report_msg])

        self.rest_client.AddAuthToken(post_msg)

        message_b = base64.b64encode(post_msg.SerializeToString())

        logging.debug('Result proto message generated. size: %s',
                      len(message_b))

        logging.debug("_tearDownClass hook: status upload time stamp %s",
                      str(self.report_msg.start_timestamp))

        return message_b
    def Upload(self, requested, executed):
        """Uploads the result to the web service.

        Requires the feature to be enabled; no-op otherwise.

        Args:
            requested: list, A list of test case names requested to run
            executed: list, A list of test case names that were executed
        """
        if not self.enabled:
            return

        # Handle case when runner fails, tests aren't executed
        if (executed and executed[-1].test_name == "setup_class"):
            # Test failed during setup, all tests were not executed
            start_index = 0
        else:
            # Runner was aborted. Remaining tests weren't executed
            start_index = len(executed)

        for test in requested[start_index:]:
            msg = self.report_msg.test_case.add()
            msg.name = test
            msg.start_timestamp = feature_utils.GetTimestamp()
            msg.end_timestamp = msg.start_timestamp
            msg.test_result = ReportMsg.TEST_CASE_RESULT_FAIL

        self.report_msg.end_timestamp = feature_utils.GetTimestamp()

        build = getattr(self, keys.ConfigKeys.IKEY_BUILD)
        if keys.ConfigKeys.IKEY_BUILD_ID in build:
            build_id = str(build[keys.ConfigKeys.IKEY_BUILD_ID])
            self.report_msg.build_info.id = build_id

        logging.info("_tearDownClass hook: start (username: %s)",
                     getpass.getuser())

        if len(self.report_msg.test_case) > 0:
            post_msg = ReportMsg.DashboardPostMessage()
            post_msg.test_report.extend([self.report_msg])

            # Post new data to the dashboard
            self.rest_client.PostData(post_msg)

            logging.info("_tearDownClass hook: status upload time stamp %s",
                         str(self.report_msg.start_timestamp))
        else:
            logging.info("_tearDownClass hook: skip uploading (no test case)")
 def _OutputCoverageReport(self, isGlobal):
     logging.info("outputing coverage data")
     timestamp_seconds = str(int(time.time() * 1000000))
     coverage_report_file = os.path.join(
         self.local_coverage_path,
         "coverage_report_" + timestamp_seconds + ".txt")
     logging.info("Storing coverage report to: %s", coverage_report_file)
     coverage_report_msg = ReportMsg.TestReportMessage()
     if isGlobal:
         for c in self.web.report_msg.coverage:
             coverage = coverage_report_msg.coverage.add()
             coverage.CopyFrom(c)
     else:
         for c in self.web.current_test_report_msg.coverage:
             coverage = coverage_report_msg.coverage.add()
             coverage.CopyFrom(c)
     with open(coverage_report_file, 'w+') as f:
         f.write(str(coverage_report_msg))
Beispiel #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)