JuliaCI / JuliaCI/CoverageTools.jl

`amend_coverage_from_src!` marks macro call lines as uncovered code that no test can cover

Open
#90 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Julia
Stars
9
Forks
7
PR merge metrics
No merged PRs in 30d

Description

amend_coverage_from_src! marks the line of a macro call as uncovered code, but Julia never emits a coverage counter for such a line. The line can therefore never become a hit.

Reproducer

# src.jl
module Repro

function hit(x)
  throw(ArgumentError(
    lazy"value $x is not allowed",
  ))
end

function miss(x)
  throw(ArgumentError(
    lazy"value $x is not allowed",
  ))
end

end
# run.jl
include("src.jl")
try
  Repro.hit(1)
catch
end
julia> run(`$(Base.julia_cmd()) --startup-file=no --code-coverage=user run.jl`);

julia> CoverageTools.process_file("src.jl", ".").coverage

annotated onto the source (- is nothing; CoverageTools 1.4.1, same on Julia 1.10.12 and
1.12.7):

 -  module Repro
 -
 1  function hit(x)
 1    throw(ArgumentError(
 -      lazy"value $x is not allowed",
 -    ))
 -  end
 -
 0  function miss(x)
 0    throw(ArgumentError(
 0      lazy"value $x is not allowed",
 -    ))
 -  end
 -
 -  end

miss was never called, so its lines are reported as uncovered. But the lazy"..." line in
hit, which was executed, is nothing: Julia counts the statement at the throw( line and
emits nothing for the wrapped argument. No test can turn that line into a hit, so in miss it
is a permanent miss.

Cause

A macro call parses as Expr(:macrocall, name, LineNumberNode, args...), where the
LineNumberNode records the call site. function_body_lines! walks every argument of every
Expr, so it collects that node as a body line and amend_coverage_from_src! marks the line
for functions the run did not execute.

The rest of a multi-line statement is unaffected because only macro calls carry a
LineNumberNode: Julia emits no counter for the ArgumentError( lines either, and the
heuristic does not mark them. A macro call that is itself a statement is also unaffected — its
line comes from the enclosing block, which Julia does count.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with function_body_lines! and amend_coverage_from_src!, then run the Julia reproducer from the issue with CoverageTools.process_file. The fix is complete when a macro call's LineNumberNode is not marked as uncovered, while the surrounding multi-line statement and counted standalone macro calls retain their current coverage behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
julia
Domain
testing, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.