Module: SixthSense::Runners::CheckedCoverageTrace
- Defined in:
- lib/sixth_sense/runners/checked_coverage_trace.rb
Class Method Summary collapse
- .assertion_method?(method_id) ⇒ Boolean
- .assertion_stack ⇒ Object
- .assertion_stack=(value) ⇒ Object
-
.capture ⇒ Object
Paper basis: Schuler/Zeller 2011 (doi:10.1109/ICST.2011.32).
- .clear_recent_lines ⇒ Object
- .mark_recent_lines(checked) ⇒ Object
- .recent_lines ⇒ Object
- .recent_window ⇒ Object
- .remember_line(path, line) ⇒ Object
- .sut_path?(path) ⇒ Boolean
- .sut_paths ⇒ Object
-
.tracepoint(executed, checked) ⇒ Object
Paper basis: Schuler/Zeller 2011; assertion calls are treated as oracle boundaries, and SUT lines observed inside that boundary are checked.
- .write_snapshot(executed, checked) ⇒ Object
Class Method Details
.assertion_method?(method_id) ⇒ Boolean
50 51 52 53 54 55 56 |
# File 'lib/sixth_sense/runners/checked_coverage_trace.rb', line 50 def assertion_method?(method_id) name = method_id.to_s return true if %w[expect should should_not flunk].include?(name) return true if name.start_with?("assert", "refute", "must_", "wont_") false end |
.assertion_stack ⇒ Object
66 67 68 |
# File 'lib/sixth_sense/runners/checked_coverage_trace.rb', line 66 def assertion_stack Thread.current[:sixth_sense_assertion_stack].to_i end |
.assertion_stack=(value) ⇒ Object
70 71 72 |
# File 'lib/sixth_sense/runners/checked_coverage_trace.rb', line 70 def assertion_stack=(value) Thread.current[:sixth_sense_assertion_stack] = value end |
.capture ⇒ Object
Paper basis: Schuler/Zeller 2011 (doi:10.1109/ICST.2011.32). This captures a TracePoint approximation of checked coverage rather than their full VM-level dynamic backward slicing.
14 15 16 17 18 19 20 21 22 23 |
# File 'lib/sixth_sense/runners/checked_coverage_trace.rb', line 14 def capture executed = Hash.new { |hash, key| hash[key] = Set.new } checked = Hash.new { |hash, key| hash[key] = Set.new } trace = tracepoint(executed, checked) trace.enable yield ensure trace.disable if trace write_snapshot(executed, checked) if executed && checked end |
.clear_recent_lines ⇒ Object
85 86 87 |
# File 'lib/sixth_sense/runners/checked_coverage_trace.rb', line 85 def clear_recent_lines Thread.current[:sixth_sense_recent_sut_lines] = [] end |
.mark_recent_lines(checked) ⇒ Object
79 80 81 82 83 |
# File 'lib/sixth_sense/runners/checked_coverage_trace.rb', line 79 def mark_recent_lines(checked) recent_lines.each do |path, line| checked[path] << line end end |
.recent_lines ⇒ Object
89 90 91 |
# File 'lib/sixth_sense/runners/checked_coverage_trace.rb', line 89 def recent_lines Thread.current[:sixth_sense_recent_sut_lines] ||= [] end |
.recent_window ⇒ Object
93 94 95 |
# File 'lib/sixth_sense/runners/checked_coverage_trace.rb', line 93 def recent_window ENV.fetch("SIXTH_SENSE_CHECKED_WINDOW", "20").to_i end |
.remember_line(path, line) ⇒ Object
74 75 76 77 |
# File 'lib/sixth_sense/runners/checked_coverage_trace.rb', line 74 def remember_line(path, line) recent_lines << [path, line] recent_lines.shift while recent_lines.length > recent_window end |
.sut_path?(path) ⇒ Boolean
58 59 60 |
# File 'lib/sixth_sense/runners/checked_coverage_trace.rb', line 58 def sut_path?(path) sut_paths.include?(File.(path)) end |
.sut_paths ⇒ Object
62 63 64 |
# File 'lib/sixth_sense/runners/checked_coverage_trace.rb', line 62 def sut_paths @sut_paths ||= ENV.fetch("SIXTH_SENSE_SUT_PATHS", "").split(File::PATH_SEPARATOR).map { |path| File.(path) }.to_set end |
.tracepoint(executed, checked) ⇒ Object
Paper basis: Schuler/Zeller 2011; assertion calls are treated as oracle boundaries, and SUT lines observed inside that boundary are checked.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/sixth_sense/runners/checked_coverage_trace.rb', line 27 def tracepoint(executed, checked) TracePoint.new(:line, :call, :c_call, :return, :c_return) do |event| case event.event when :line next unless sut_path?(event.path) executed[event.path] << event.lineno remember_line(event.path, event.lineno) checked[event.path] << event.lineno if assertion_stack.positive? when :call, :c_call next unless assertion_method?(event.method_id) mark_recent_lines(checked) self.assertion_stack += 1 when :return, :c_return next unless assertion_method?(event.method_id) && assertion_stack.positive? self.assertion_stack -= 1 clear_recent_lines end end end |
.write_snapshot(executed, checked) ⇒ Object
97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/sixth_sense/runners/checked_coverage_trace.rb', line 97 def write_snapshot(executed, checked) File.write( ENV.fetch("SIXTH_SENSE_CHECKED_OUTPUT"), JSON.generate( { executed_lines: executed.transform_values(&:to_a), checked_lines: checked.transform_values(&:to_a) } ) ) end |