Class: Evilution::CoverageExampleFilter

Inherits:
Object
  • Object
show all
Defined in:
lib/evilution/coverage_example_filter.rb

Overview

Per-mutation example targeting backed by a real line-coverage Map (EV-ndjd). Honours the same contract as the lexical Evilution::ExampleFilter – call(mutation, spec_paths) -> Array | spec_paths | nil – so it drops straight into the existing ExampleFilter seam.

Resolution order for the mutated source file F at line L:

- F not fully built in the map (digest miss / partial build) -> delegate to
  the lexical filter (safe fallback) with the original spec_paths.
- F built and L covered by examples -> run exactly those covering examples
  (a SUBSET of what the resolved spec runs, so a strict speedup that cannot
  lose a kill full-file would catch).
- F not built, or L attributed to no example -> defer to lexical/full-file.

Accuracy-first: coverage ONLY narrows the example set when it positively knows the covering examples. It never marks a mutation :unresolved on “no coverage” – on real repos a line can be exercised indirectly (before(:all), load time, a spec the per-example diff did not attribute), and asserting a gap there loses kills (EV-7uui validation). When coverage has no answer, the proven lexical path decides.

Instance Method Summary collapse

Constructor Details

#initialize(map:, lexical:, project_root: Evilution::PROJECT_ROOT) ⇒ CoverageExampleFilter

Returns a new instance of CoverageExampleFilter.



26
27
28
29
30
# File 'lib/evilution/coverage_example_filter.rb', line 26

def initialize(map:, lexical:, project_root: Evilution::PROJECT_ROOT)
  @map = map
  @lexical = lexical
  @project_root = project_root.to_s
end

Instance Method Details

#call(mutation, spec_paths) ⇒ Object



32
33
34
35
36
37
38
39
40
# File 'lib/evilution/coverage_example_filter.rb', line 32

def call(mutation, spec_paths)
  file = File.expand_path(mutation.file_path, @project_root)
  return @lexical.call(mutation, spec_paths) unless @map.built?(file)

  examples = @map.examples_for(file, mutation.line)
  return examples unless examples.empty?

  @lexical.call(mutation, spec_paths)
end