(outputs: List[str], func: Callable, mode: str = "branch")
| 37 | |
| 38 | |
| 39 | def parse_lcov(outputs: List[str], func: Callable, mode: str = "branch"): |
| 40 | switch, extracted_outputs = False, [] |
| 41 | for line in outputs: |
| 42 | if switch == False and "tmp_src" in line: |
| 43 | switch = True |
| 44 | if switch == True and "end_of_record" in line: |
| 45 | switch = False |
| 46 | if switch: |
| 47 | extracted_outputs.append(line) |
| 48 | |
| 49 | src, start_lineno = inspect.getsourcelines(func) |
| 50 | end_lineno = start_lineno + len(src) - 1 |
| 51 | |
| 52 | if mode == "branch": |
| 53 | branch, branch_covered = [], [] |
| 54 | for line in extracted_outputs: |
| 55 | if line.startswith("BRDA"): |
| 56 | # BRDA format: BR:<lineno>,<blockno>,<branchno>,<taken> |
| 57 | lineno, blockno, branchno, taken = line[5:].split(",") |
| 58 | branch_sig = f"BR:{lineno},{blockno},{branchno}" |
| 59 | branch.append(branch_sig) |
| 60 | if taken not in ["0", "-"]: |
| 61 | branch_covered.append(branch_sig) |
| 62 | per = 1.0 if len(branch) == 0 else len(branch_covered) / len(branch) |
| 63 | return per, branch, branch_covered |
| 64 | else: |
| 65 | not_covered_lines = [] |
| 66 | for line in extracted_outputs: |
| 67 | if line.startswith("DA"): |
| 68 | # DA format: DA:<lineno>,<exec_count>[,...] |
| 69 | lineno, exec_count = line[3:].split(",")[:2] |
| 70 | if start_lineno <= int(lineno) <= end_lineno: |
| 71 | if exec_count == "0": |
| 72 | not_covered_lines.append(int(lineno)) |
| 73 | for lineno in not_covered_lines: |
| 74 | line = src[lineno - start_lineno] |
| 75 | if line.strip() != "" and "def" not in line: |
| 76 | src[lineno - start_lineno] = line[:-1] + " # Not executed\n" |
| 77 | return "".join(src) |
| 78 | |
| 79 | |
| 80 | def test_code_coverage( |
no outgoing calls