diff --git a/src/fuzz_introspector/code_coverage.py b/src/fuzz_introspector/code_coverage.py index 275dd09..99cf535 100644 --- a/src/fuzz_introspector/code_coverage.py +++ b/src/fuzz_introspector/code_coverage.py @@ -180,9 +180,11 @@ def _python_ast_funcname_to_cov_file(self, function_name) -> Optional[str]: # Resolve name if required. This is needed to normalise filenames. logger.debug("Resolving name") potential_paths = [] + init_paths = [] current_path = "" for module_name in function_name.split("."): current_path += module_name + init_paths.append(current_path + "/__init__.py") potential_paths.append(current_path + ".py") current_path += "/" @@ -193,6 +195,24 @@ def _python_ast_funcname_to_cov_file(self, function_name) -> Optional[str]: if potential_key.endswith(potential_path): logger.debug(f"Found key: {str(potential_key)}") return potential_key + # We found no matches when filenames exclude __init__.py. Try to + # include these now. + init_matches = [] + # Iterate based in init paths since we want to have the longest match + # at the end of __init__matches list. + logger.info("Scanning for init paths") + for potential_init_path in init_paths: + logger.info("Trying %s" % (potential_init_path)) + for potential_key in self.file_map: + logger.debug(f"Scanning {str(potential_key)}") + if potential_key.endswith(potential_init_path): + logger.debug(f"Found __init__ match: {str(potential_key)}") + init_matches.append(potential_key) + + # Return the last match, as this signals the path with most precise + # matching. + if len(init_matches) > 0: + return init_matches[-1] # If this is reached then no match was found. Return None. logger.debug("Could not find key") @@ -639,7 +659,6 @@ def load_python_json_coverage(json_file: str, 'executed_lines'] cp.dual_file_map[cov_entry]['missing_lines'] = data['files'][entry][ 'missing_lines'] - return cp diff --git a/src/fuzz_introspector/utils.py b/src/fuzz_introspector/utils.py index fe1f940..0305eb3 100644 --- a/src/fuzz_introspector/utils.py +++ b/src/fuzz_introspector/utils.py @@ -200,11 +200,13 @@ def approximate_python_coverage_files(src1: str, src2: str) -> bool: # Generate list of potential candidates possible_candidates = [] + possible_init_candidates = [] splits = src1.split(".") curr_str = "" for s2 in splits: curr_str = curr_str + s2 possible_candidates.append(curr_str + ".py") + possible_init_candidates.append("/__init__.py") curr_str = curr_str + "/" # Start from backwards to find te longest possible candidate @@ -218,6 +220,16 @@ def approximate_python_coverage_files(src1: str, src2: str) -> bool: target = candidate break + if target is None: + for init_candidate in reversed(possible_init_candidates): + if src2.endswith(init_candidate): + # ensure the entire filename is matched in the event of not slashes + if "/" not in init_candidate: + if not src2.split("/")[-1] == init_candidate: + continue + target = init_candidate + break + if target is not None: logger.debug(f"Found target {target}") return True