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))
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)))
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))
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)