
Issue #19857 has been updated by ioquatix (Samuel Williams). Backport changed from 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN to 3.0: DONTNEED, 3.1: DONTNEED, 3.2: REQUIRED
Currently only the coverage of the last call to Kernel#eval is kept.
This is not true. Coverage is stored in a global map of path -> coverage. Every attempt is made to use the same coverage for a given path. If you load or eval the same path multiple times, the same coverage will be reused. The bug is because `iseq_set_sequence` sets the coverage to zero for executable lines, for the lines it covers. So, it will: 1. Load the current shared coverage for a given path. 2. Based on the eval line number, update that coverage. 3. For each executable instruction, assign to the `coverage[instruction_line + eval_line_number]`. So, it won't keep the last result, it just resets some or all of the coverage, depending on how the `eval` call is invoked. In theory, the same problem can apply to `require` and `load`, but would be, I expect, a little more involved to reproduce. ---------------------------------------- Bug #19857: Eval coverage is reset after each `eval`. https://bugs.ruby-lang.org/issues/19857#change-104411 * Author: ioquatix (Samuel Williams) * Status: Open * Priority: Normal * Assignee: ioquatix (Samuel Williams) * Backport: 3.0: DONTNEED, 3.1: DONTNEED, 3.2: REQUIRED ---------------------------------------- It seems like `eval` based coverage is reset every time eval is invoked. ```ruby #!/usr/bin/env ruby require 'coverage' def measure(flag) c = Class.new c.class_eval(<<~RUBY, "foo.rb", 1) def foo(flag) if flag puts "foo" else puts "bar" end end RUBY return c.new.foo(flag) end Coverage.start(lines: true, eval: true) # Depending on the order of these two operations, different computation is calculated, because the evaluation of the code is considered different, even if the content/path is the same. measure(false) measure(true) p Coverage.result ``` Further investigation is required. -- https://bugs.ruby-lang.org/