deep-cover 0.6.2 → 0.6.3.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/.rspec +2 -1
- data/.rspec_all +2 -1
- data/.rubocop.yml +8 -9
- data/Gemfile +2 -0
- data/Rakefile +32 -6
- data/bin/cov +3 -3
- data/deep_cover.gemspec +3 -16
- data/exe/deep-cover +5 -0
- data/lib/deep_cover/cli/debugger.rb +1 -1
- data/lib/deep_cover/cli/exec.rb +1 -1
- data/lib/deep_cover/cli/instrumented_clone_reporter.rb +5 -3
- data/lib/deep_cover/cli/runner.rb +2 -2
- data/lib/deep_cover/{tools/dump_covered_code.rb → dump_covered_code.rb} +2 -0
- metadata +10 -203
- data/lib/deep-cover.rb +0 -3
- data/lib/deep_cover.rb +0 -22
- data/lib/deep_cover/analyser.rb +0 -23
- data/lib/deep_cover/analyser/base.rb +0 -104
- data/lib/deep_cover/analyser/branch.rb +0 -41
- data/lib/deep_cover/analyser/covered_code_source.rb +0 -21
- data/lib/deep_cover/analyser/function.rb +0 -14
- data/lib/deep_cover/analyser/node.rb +0 -54
- data/lib/deep_cover/analyser/per_char.rb +0 -38
- data/lib/deep_cover/analyser/per_line.rb +0 -41
- data/lib/deep_cover/analyser/ruby25_like_branch.rb +0 -211
- data/lib/deep_cover/analyser/statement.rb +0 -33
- data/lib/deep_cover/analyser/stats.rb +0 -54
- data/lib/deep_cover/analyser/subset.rb +0 -27
- data/lib/deep_cover/auto_run.rb +0 -71
- data/lib/deep_cover/autoload_tracker.rb +0 -215
- data/lib/deep_cover/backports.rb +0 -22
- data/lib/deep_cover/base.rb +0 -117
- data/lib/deep_cover/basics.rb +0 -22
- data/lib/deep_cover/builtin_takeover.rb +0 -10
- data/lib/deep_cover/config.rb +0 -104
- data/lib/deep_cover/config_setter.rb +0 -33
- data/lib/deep_cover/core_ext/autoload_overrides.rb +0 -112
- data/lib/deep_cover/core_ext/coverage_replacement.rb +0 -61
- data/lib/deep_cover/core_ext/exec_callbacks.rb +0 -27
- data/lib/deep_cover/core_ext/instruction_sequence_load_iseq.rb +0 -32
- data/lib/deep_cover/core_ext/load_overrides.rb +0 -19
- data/lib/deep_cover/core_ext/require_overrides.rb +0 -28
- data/lib/deep_cover/coverage.rb +0 -125
- data/lib/deep_cover/coverage/analysis.rb +0 -42
- data/lib/deep_cover/coverage/persistence.rb +0 -84
- data/lib/deep_cover/covered_code.rb +0 -145
- data/lib/deep_cover/custom_requirer.rb +0 -187
- data/lib/deep_cover/flag_comment_associator.rb +0 -68
- data/lib/deep_cover/load.rb +0 -66
- data/lib/deep_cover/memoize.rb +0 -48
- data/lib/deep_cover/module_override.rb +0 -39
- data/lib/deep_cover/node.rb +0 -23
- data/lib/deep_cover/node/arguments.rb +0 -51
- data/lib/deep_cover/node/assignments.rb +0 -273
- data/lib/deep_cover/node/base.rb +0 -155
- data/lib/deep_cover/node/begin.rb +0 -27
- data/lib/deep_cover/node/block.rb +0 -61
- data/lib/deep_cover/node/branch.rb +0 -32
- data/lib/deep_cover/node/case.rb +0 -113
- data/lib/deep_cover/node/collections.rb +0 -31
- data/lib/deep_cover/node/const.rb +0 -12
- data/lib/deep_cover/node/def.rb +0 -40
- data/lib/deep_cover/node/empty_body.rb +0 -32
- data/lib/deep_cover/node/exceptions.rb +0 -79
- data/lib/deep_cover/node/if.rb +0 -73
- data/lib/deep_cover/node/keywords.rb +0 -86
- data/lib/deep_cover/node/literals.rb +0 -100
- data/lib/deep_cover/node/loops.rb +0 -74
- data/lib/deep_cover/node/mixin/can_augment_children.rb +0 -65
- data/lib/deep_cover/node/mixin/check_completion.rb +0 -18
- data/lib/deep_cover/node/mixin/child_can_be_empty.rb +0 -27
- data/lib/deep_cover/node/mixin/executed_after_children.rb +0 -15
- data/lib/deep_cover/node/mixin/execution_location.rb +0 -66
- data/lib/deep_cover/node/mixin/filters.rb +0 -47
- data/lib/deep_cover/node/mixin/flow_accounting.rb +0 -71
- data/lib/deep_cover/node/mixin/has_child.rb +0 -145
- data/lib/deep_cover/node/mixin/has_child_handler.rb +0 -75
- data/lib/deep_cover/node/mixin/has_tracker.rb +0 -46
- data/lib/deep_cover/node/mixin/is_statement.rb +0 -20
- data/lib/deep_cover/node/mixin/rewriting.rb +0 -35
- data/lib/deep_cover/node/mixin/wrapper.rb +0 -15
- data/lib/deep_cover/node/module.rb +0 -66
- data/lib/deep_cover/node/root.rb +0 -20
- data/lib/deep_cover/node/send.rb +0 -161
- data/lib/deep_cover/node/short_circuit.rb +0 -42
- data/lib/deep_cover/node/splat.rb +0 -15
- data/lib/deep_cover/node/variables.rb +0 -16
- data/lib/deep_cover/parser_ext/range.rb +0 -21
- data/lib/deep_cover/problem_with_diagnostic.rb +0 -63
- data/lib/deep_cover/reporter.rb +0 -10
- data/lib/deep_cover/reporter/base.rb +0 -68
- data/lib/deep_cover/reporter/html.rb +0 -15
- data/lib/deep_cover/reporter/html/base.rb +0 -14
- data/lib/deep_cover/reporter/html/index.rb +0 -59
- data/lib/deep_cover/reporter/html/site.rb +0 -70
- data/lib/deep_cover/reporter/html/source.rb +0 -136
- data/lib/deep_cover/reporter/html/template/assets/32px.png +0 -0
- data/lib/deep_cover/reporter/html/template/assets/40px.png +0 -0
- data/lib/deep_cover/reporter/html/template/assets/deep_cover.css.sass +0 -336
- data/lib/deep_cover/reporter/html/template/assets/jquery-3.2.1.min.js +0 -4
- data/lib/deep_cover/reporter/html/template/assets/jquery-3.2.1.min.map +0 -1
- data/lib/deep_cover/reporter/html/template/assets/jstree.css +0 -1108
- data/lib/deep_cover/reporter/html/template/assets/jstree.js +0 -8424
- data/lib/deep_cover/reporter/html/template/assets/jstreetable.js +0 -1069
- data/lib/deep_cover/reporter/html/template/assets/throbber.gif +0 -0
- data/lib/deep_cover/reporter/html/template/index.html.erb +0 -75
- data/lib/deep_cover/reporter/html/template/source.html.erb +0 -35
- data/lib/deep_cover/reporter/istanbul.rb +0 -184
- data/lib/deep_cover/reporter/text.rb +0 -58
- data/lib/deep_cover/reporter/tree/util.rb +0 -86
- data/lib/deep_cover/tools.rb +0 -22
- data/lib/deep_cover/tools/blank.rb +0 -25
- data/lib/deep_cover/tools/builtin_coverage.rb +0 -55
- data/lib/deep_cover/tools/camelize.rb +0 -13
- data/lib/deep_cover/tools/content_tag.rb +0 -11
- data/lib/deep_cover/tools/covered.rb +0 -9
- data/lib/deep_cover/tools/execute_sample.rb +0 -34
- data/lib/deep_cover/tools/format.rb +0 -18
- data/lib/deep_cover/tools/format_char_cover.rb +0 -19
- data/lib/deep_cover/tools/format_generated_code.rb +0 -27
- data/lib/deep_cover/tools/indent_string.rb +0 -26
- data/lib/deep_cover/tools/merge.rb +0 -16
- data/lib/deep_cover/tools/number_lines.rb +0 -22
- data/lib/deep_cover/tools/our_coverage.rb +0 -11
- data/lib/deep_cover/tools/profiling.rb +0 -68
- data/lib/deep_cover/tools/render_template.rb +0 -13
- data/lib/deep_cover/tools/require_relative_dir.rb +0 -12
- data/lib/deep_cover/tools/scan_match_datas.rb +0 -10
- data/lib/deep_cover/tools/silence_warnings.rb +0 -18
- data/lib/deep_cover/tools/slice.rb +0 -9
- data/lib/deep_cover/tools/strip_heredoc.rb +0 -18
- data/lib/deep_cover/tools/truncate_backtrace.rb +0 -32
- data/lib/deep_cover/tracker_bucket.rb +0 -50
- data/lib/deep_cover/tracker_hits_per_path.rb +0 -35
- data/lib/deep_cover/tracker_storage.rb +0 -76
- data/lib/deep_cover/tracker_storage_per_path.rb +0 -34
- data/lib/deep_cover/version.rb +0 -5
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'subset'
|
4
|
-
|
5
|
-
module DeepCover
|
6
|
-
class Analyser::Statement < Analyser
|
7
|
-
include Analyser::Subset
|
8
|
-
# Returns a map of Range => runs
|
9
|
-
def results
|
10
|
-
each_node.map do |node|
|
11
|
-
[node.expression, node_runs(node)]
|
12
|
-
end.to_h
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def in_subset?(node, parent)
|
18
|
-
is_statement = node.is_statement
|
19
|
-
if node.expression.nil?
|
20
|
-
false
|
21
|
-
elsif is_statement != :if_incompatible
|
22
|
-
is_statement
|
23
|
-
else
|
24
|
-
!compatible_runs?(node_runs(parent), node_runs(node))
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def compatible_runs?(expression_runs, sub_expression_runs)
|
29
|
-
sub_expression_runs.nil? ||
|
30
|
-
(sub_expression_runs == 0) == (expression_runs == 0)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module DeepCover
|
4
|
-
class Analyser::StatsBase
|
5
|
-
DECIMALS = 2
|
6
|
-
include Memoize
|
7
|
-
memoize :to_h, :total
|
8
|
-
|
9
|
-
VALUES = %i[executed not_executed not_executable ignored].freeze # All are exclusive
|
10
|
-
|
11
|
-
attr_reader(*VALUES)
|
12
|
-
|
13
|
-
def to_h
|
14
|
-
VALUES.map { |val| [val, public_send(val)] }.to_h
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize(executed: 0, not_executed: 0, not_executable: 0, ignored: 0)
|
18
|
-
@executed = executed
|
19
|
-
@not_executed = not_executed
|
20
|
-
@not_executable = not_executable
|
21
|
-
@ignored = ignored
|
22
|
-
freeze
|
23
|
-
end
|
24
|
-
|
25
|
-
def +(other)
|
26
|
-
self.class.new(to_h.merge(other.to_h) { |k, a, b| a + b })
|
27
|
-
end
|
28
|
-
|
29
|
-
def total
|
30
|
-
to_h.values.inject(:+)
|
31
|
-
end
|
32
|
-
|
33
|
-
def with(**values)
|
34
|
-
self.class.new(to_h.merge(values))
|
35
|
-
end
|
36
|
-
|
37
|
-
def potentially_executable
|
38
|
-
total - not_executable
|
39
|
-
end
|
40
|
-
|
41
|
-
def percent_covered
|
42
|
-
return 100 if potentially_executable == 0
|
43
|
-
(100 * (1 - not_executed.fdiv(potentially_executable))).round(DECIMALS)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
class Analyser::Stats < Analyser::StatsBase
|
48
|
-
memoize :percent
|
49
|
-
|
50
|
-
def percent
|
51
|
-
Analyser::StatsBase.new(to_h.transform_values { |v| (100 * v).fdiv(total).round(DECIMALS) })
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module DeepCover
|
4
|
-
# A module to create a subset from a criteria called `in_subset?`
|
5
|
-
# Including classes can refine it, or specify SUBSET_CLASSES
|
6
|
-
module Analyser::Subset
|
7
|
-
def node_children(node)
|
8
|
-
find_children(node)
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
def find_children(from, parent = from)
|
14
|
-
@source.node_children(from).flat_map do |node|
|
15
|
-
if in_subset?(node, parent)
|
16
|
-
[node]
|
17
|
-
else
|
18
|
-
find_children(node, parent)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def in_subset?(node, _parent)
|
24
|
-
self.class::SUBSET_CLASSES.any? { |klass| node.is_a?(klass) }
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
data/lib/deep_cover/auto_run.rb
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'core_ext/exec_callbacks'
|
4
|
-
|
5
|
-
module DeepCover
|
6
|
-
module AutoRun
|
7
|
-
class Runner
|
8
|
-
def initialize(covered_path)
|
9
|
-
@covered_path = covered_path
|
10
|
-
@saved = !(DeepCover.respond_to?(:running?) && DeepCover.running?)
|
11
|
-
end
|
12
|
-
|
13
|
-
def run!
|
14
|
-
after_tests { save }
|
15
|
-
ExecCallbacks.before_exec { save }
|
16
|
-
self
|
17
|
-
end
|
18
|
-
|
19
|
-
def report!(**options)
|
20
|
-
after_tests { puts report(**options) }
|
21
|
-
self
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def saved?
|
27
|
-
@saved
|
28
|
-
end
|
29
|
-
|
30
|
-
def coverage
|
31
|
-
@coverage ||= if saved?
|
32
|
-
Coverage.load(@covered_path, with_trackers: false)
|
33
|
-
else
|
34
|
-
DeepCover.coverage
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def save
|
39
|
-
require_relative '../deep_cover'
|
40
|
-
coverage.save(@covered_path) unless saved?
|
41
|
-
coverage.save_trackers(@covered_path)
|
42
|
-
end
|
43
|
-
|
44
|
-
def report(**options)
|
45
|
-
coverage.report(**options)
|
46
|
-
end
|
47
|
-
|
48
|
-
def after_tests
|
49
|
-
use_at_exit = true
|
50
|
-
if defined?(Minitest)
|
51
|
-
use_at_exit = false
|
52
|
-
Minitest.after_run { yield }
|
53
|
-
end
|
54
|
-
if defined?(Rspec)
|
55
|
-
use_at_exit = false
|
56
|
-
RSpec.configure do |config|
|
57
|
-
config.after(:suite) { yield }
|
58
|
-
end
|
59
|
-
end
|
60
|
-
if use_at_exit
|
61
|
-
at_exit { yield }
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def self.run!(covered_path)
|
67
|
-
@runners ||= {}
|
68
|
-
@runners[covered_path] ||= Runner.new(covered_path).run!
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,215 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'weakref'
|
4
|
-
|
5
|
-
# TODO: if a constant is removed, AutoloadEntries should be removed
|
6
|
-
|
7
|
-
module DeepCover
|
8
|
-
class AutoloadTracker
|
9
|
-
AutoloadEntry = Struct.new(:weak_mod, :name, :target_path, :interceptor_path) do
|
10
|
-
# If the ref is dead, will return nil
|
11
|
-
# If the target is frozen, will warn and return nil
|
12
|
-
# Otherwise return the target
|
13
|
-
def mod_if_available
|
14
|
-
mod = weak_mod.__getobj__
|
15
|
-
if mod.frozen?
|
16
|
-
AutoloadTracker.warn_frozen_module(mod)
|
17
|
-
nil
|
18
|
-
else
|
19
|
-
mod
|
20
|
-
end
|
21
|
-
rescue WeakRef::RefError
|
22
|
-
nil
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
attr_reader :autoloads_by_basename, :interceptor_files_by_path
|
27
|
-
def initialize
|
28
|
-
@autoloads_by_basename = {}
|
29
|
-
@interceptor_files_by_path = {}
|
30
|
-
end
|
31
|
-
|
32
|
-
def autoload_path_for(mod, name, path)
|
33
|
-
interceptor_path = setup_interceptor_for(mod, name, path)
|
34
|
-
|
35
|
-
if DeepCover.custom_requirer.is_being_required?(path)
|
36
|
-
already_loaded_feature
|
37
|
-
else
|
38
|
-
interceptor_path
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def possible_autoload_target?(requested_path)
|
43
|
-
basename = basename_without_extension(requested_path)
|
44
|
-
autoloads = @autoloads_by_basename[basename]
|
45
|
-
autoloads && !autoloads.empty?
|
46
|
-
end
|
47
|
-
|
48
|
-
def wrap_require(requested_path, absolute_path_found) # &block
|
49
|
-
entries = entries_for_target(requested_path, absolute_path_found)
|
50
|
-
|
51
|
-
begin
|
52
|
-
entries.each do |entry|
|
53
|
-
mod = entry.mod_if_available
|
54
|
-
next unless mod
|
55
|
-
mod.autoload_without_deep_cover(entry.name, already_loaded_feature)
|
56
|
-
end
|
57
|
-
|
58
|
-
yield
|
59
|
-
ensure
|
60
|
-
entries = entries_for_target(requested_path, absolute_path_found)
|
61
|
-
entries.each do |entry|
|
62
|
-
mod = entry.mod_if_available
|
63
|
-
next unless mod
|
64
|
-
# Putting the autoloads back back since we couldn't complete the require
|
65
|
-
mod.autoload_without_deep_cover(entry.name, entry.interceptor_path)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# This is only used on MRI, so ObjectSpace is alright.
|
71
|
-
def initialize_autoloaded_paths(mods = ObjectSpace.each_object(Module)) # &do_autoload_block
|
72
|
-
mods.each do |mod|
|
73
|
-
# Module's constants are shared with Object. But if you set autoloads directly on Module, they
|
74
|
-
# appear on multiple classes. So just skip, Object will take care of those.
|
75
|
-
next if mod == Module
|
76
|
-
|
77
|
-
if mod.frozen?
|
78
|
-
if mod.constants.any? { |name| mod.autoload?(name) }
|
79
|
-
self.class.warn_frozen_module(mod)
|
80
|
-
end
|
81
|
-
next
|
82
|
-
end
|
83
|
-
|
84
|
-
mod.constants.each do |name|
|
85
|
-
path = mod.autoload?(name)
|
86
|
-
next unless path
|
87
|
-
interceptor_path = setup_interceptor_for(mod, name, path)
|
88
|
-
yield mod, name, interceptor_path
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# We need to remove the interceptor hooks, otherwise, the problem if manually requiring
|
94
|
-
# something that is autoloaded will cause issues.
|
95
|
-
def remove_interceptors # &do_autoload_block
|
96
|
-
@autoloads_by_basename.each do |basename, entries|
|
97
|
-
entries.each do |entry|
|
98
|
-
mod = entry.mod_if_available
|
99
|
-
next unless mod
|
100
|
-
# Module's constants are shared with Object. But if you set autoloads directly on Module, they
|
101
|
-
# appear on multiple classes. So just skip, Object will take care of those.
|
102
|
-
next if mod == Module
|
103
|
-
yield mod, entry.name, entry.target_path
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
@autoloaded_paths = {}
|
108
|
-
@interceptor_files_by_path = {}
|
109
|
-
end
|
110
|
-
|
111
|
-
class << self
|
112
|
-
attr_accessor :warned_for_frozen_module
|
113
|
-
end
|
114
|
-
self.warned_for_frozen_module = false
|
115
|
-
|
116
|
-
# Using frozen modules/classes is almost unheard of, but a warning makes things easier if someone does it
|
117
|
-
def self.warn_frozen_module(mod)
|
118
|
-
return if warned_for_frozen_module
|
119
|
-
self.warned_for_frozen_module ||= true
|
120
|
-
warn "There is an autoload on a frozen module/class: #{mod}, DeepCover cannot handle those, failure is probable. " \
|
121
|
-
"This warning won't be displayed again (even for different module/class)"
|
122
|
-
end
|
123
|
-
|
124
|
-
protected
|
125
|
-
|
126
|
-
def setup_interceptor_for(mod, name, path)
|
127
|
-
interceptor_path = autoload_interceptor_for(path)
|
128
|
-
entry = AutoloadEntry.new(WeakRef.new(mod), name, path, interceptor_path)
|
129
|
-
|
130
|
-
basename = basename_without_extension(path)
|
131
|
-
|
132
|
-
@autoloads_by_basename[basename] ||= []
|
133
|
-
@autoloads_by_basename[basename] << entry
|
134
|
-
interceptor_path
|
135
|
-
end
|
136
|
-
|
137
|
-
def entries_for_target(requested_path, absolute_path_found)
|
138
|
-
basename = basename_without_extension(requested_path)
|
139
|
-
autoloads = @autoloads_by_basename[basename] || []
|
140
|
-
|
141
|
-
if absolute_path_found
|
142
|
-
autoloads.select { |entry| entry_is_target?(entry, requested_path, absolute_path_found) }
|
143
|
-
elsif requested_path == File.absolute_path(requested_path)
|
144
|
-
[]
|
145
|
-
elsif requested_path.start_with?('./', '../')
|
146
|
-
[]
|
147
|
-
else
|
148
|
-
# We didn't find a path that goes through the $LOAD_PATH
|
149
|
-
# It's possible that RubyGems will actually add the $LOAD_PATH and require an actual file
|
150
|
-
# So we must make a best-guest for possible matches
|
151
|
-
requested_path_to_compare = without_extension(requested_path)
|
152
|
-
autoloads.select { |entry| requested_path_to_compare == without_extension(entry.target_path) }
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
def entry_is_target?(entry, requested_path, absolute_path_found)
|
157
|
-
return true if entry.target_path == requested_path
|
158
|
-
target_path_rb = with_rb_extension(entry.target_path)
|
159
|
-
return true if target_path_rb == requested_path
|
160
|
-
|
161
|
-
# Even though this is not efficient, it's safer to resolve entries' target_path each time
|
162
|
-
# instead of storing the result, in case subsequent changes to $LOAD_PATH gives different results
|
163
|
-
entry_absolute_path = DeepCover.custom_requirer.resolve_path(entry.target_path)
|
164
|
-
return true if entry_absolute_path == absolute_path_found
|
165
|
-
false
|
166
|
-
end
|
167
|
-
|
168
|
-
def basename_without_extension(path)
|
169
|
-
without_extension(File.basename(path))
|
170
|
-
end
|
171
|
-
|
172
|
-
def with_rb_extension(path)
|
173
|
-
path += '.rb' unless has_supported_extension?(path)
|
174
|
-
path
|
175
|
-
end
|
176
|
-
|
177
|
-
def without_extension(path)
|
178
|
-
path = path[0...-3] if has_supported_extension?(path)
|
179
|
-
path
|
180
|
-
end
|
181
|
-
|
182
|
-
def has_supported_extension?(path)
|
183
|
-
path.end_with?('.rb', '.so')
|
184
|
-
end
|
185
|
-
|
186
|
-
# It is not possible to simply remove an autoload. So, instead, we must change the
|
187
|
-
# autoload to an already loaded path.
|
188
|
-
# The autoload will be set back to what it was once the require returns. This is
|
189
|
-
# needed in case that required path wasn't the one that fulfilled the autoload, or
|
190
|
-
# if the constant and $LOADED_FEATURES gets removed, since in that situation,
|
191
|
-
# the autoload is supposed to be active again.
|
192
|
-
def already_loaded_feature
|
193
|
-
$LOADED_FEATURES.first
|
194
|
-
end
|
195
|
-
|
196
|
-
def autoload_interceptor_for(path)
|
197
|
-
existing_files = @interceptor_files_by_path[path] || []
|
198
|
-
reusable_file = existing_files.detect { |f| !$LOADED_FEATURES.include?(f.path) }
|
199
|
-
return reusable_file.path if reusable_file
|
200
|
-
|
201
|
-
new_file = Tempfile.new([File.basename(path), '.rb'])
|
202
|
-
# Need to store all the tempfiles so that they are not GCed, which would delete the files themselves.
|
203
|
-
# Keeping them by path allows us to reuse them.
|
204
|
-
@interceptor_files_by_path[path] ||= []
|
205
|
-
@interceptor_files_by_path[path] << new_file
|
206
|
-
new_file.write(<<-RUBY)
|
207
|
-
# Intermediary file for ruby's autoload made by deep-cover
|
208
|
-
require #{path.to_s.inspect}
|
209
|
-
RUBY
|
210
|
-
new_file.close
|
211
|
-
|
212
|
-
new_file.path
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
data/lib/deep_cover/backports.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# We use a few features newer than our target of Ruby 2.1+:
|
4
|
-
class Module
|
5
|
-
public :define_method
|
6
|
-
end
|
7
|
-
require 'pathname'
|
8
|
-
class Pathname
|
9
|
-
def write(*args)
|
10
|
-
File.write(to_path, *args)
|
11
|
-
end unless method_defined? :write
|
12
|
-
def binwrite(*args)
|
13
|
-
File.binwrite(to_path, *args)
|
14
|
-
end unless method_defined? :binwrite
|
15
|
-
end # nocov
|
16
|
-
require 'backports/2.4.0/false_class/dup'
|
17
|
-
require 'backports/2.4.0/true_class/dup'
|
18
|
-
require 'backports/2.4.0/hash/transform_values'
|
19
|
-
require 'backports/2.4.0/enumerable/sum'
|
20
|
-
require 'backports/2.5.0/hash/slice'
|
21
|
-
require 'backports/2.5.0/hash/transform_keys'
|
22
|
-
require 'backports/2.5.0/kernel/yield_self'
|
data/lib/deep_cover/base.rb
DELETED
@@ -1,117 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module DeepCover
|
4
|
-
module Base
|
5
|
-
def running?
|
6
|
-
@started ||= false # rubocop:disable Naming/MemoizedInstanceVariableName [#5648]
|
7
|
-
end
|
8
|
-
|
9
|
-
def start
|
10
|
-
return if running?
|
11
|
-
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
12
|
-
# Autoload is not supported in JRuby. We currently need to use binding_of_caller
|
13
|
-
# and that is not available in JRuby. An extension may be able to replace this requirement.
|
14
|
-
# require_relative 'core_ext/autoload_overrides'
|
15
|
-
# AutoloadOverride.active = true
|
16
|
-
require_relative 'core_ext/load_overrides'
|
17
|
-
require_relative 'core_ext/require_overrides'
|
18
|
-
LoadOverride.active = RequireOverride.active = true
|
19
|
-
elsif RUBY_VERSION >= '2.3.0'
|
20
|
-
require_relative 'core_ext/instruction_sequence_load_iseq'
|
21
|
-
else
|
22
|
-
require_relative 'core_ext/autoload_overrides'
|
23
|
-
require_relative 'core_ext/load_overrides'
|
24
|
-
require_relative 'core_ext/require_overrides'
|
25
|
-
AutoloadOverride.active = LoadOverride.active = RequireOverride.active = true
|
26
|
-
autoload_tracker.initialize_autoloaded_paths { |mod, name, path| mod.autoload_without_deep_cover(name, path) }
|
27
|
-
end
|
28
|
-
|
29
|
-
config # actualize configuration
|
30
|
-
@lookup_paths = nil
|
31
|
-
@started = true
|
32
|
-
end
|
33
|
-
|
34
|
-
def stop
|
35
|
-
if defined? AutoloadOverride
|
36
|
-
AutoloadOverride.active = false
|
37
|
-
autoload_tracker.remove_interceptors { |mod, name, path| mod.autoload_without_deep_cover(name, path) }
|
38
|
-
end
|
39
|
-
RequireOverride.active = false if defined? RequireOverride
|
40
|
-
|
41
|
-
@started = false
|
42
|
-
end
|
43
|
-
|
44
|
-
def line_coverage(filename)
|
45
|
-
coverage.line_coverage(handle_relative_filename(filename), **config.to_h)
|
46
|
-
end
|
47
|
-
|
48
|
-
def covered_code(filename)
|
49
|
-
coverage.covered_code(handle_relative_filename(filename))
|
50
|
-
end
|
51
|
-
|
52
|
-
def cover(paths: nil)
|
53
|
-
if paths
|
54
|
-
prev = config.paths
|
55
|
-
config.paths(paths)
|
56
|
-
end
|
57
|
-
start
|
58
|
-
yield
|
59
|
-
ensure
|
60
|
-
stop
|
61
|
-
config.paths(prev) if paths
|
62
|
-
end
|
63
|
-
|
64
|
-
def config_changed(what)
|
65
|
-
case what
|
66
|
-
when :paths
|
67
|
-
warn "Changing DeepCover's paths after starting coverage is highly discouraged" if running?
|
68
|
-
@lookup_paths = nil
|
69
|
-
when :tracker_global
|
70
|
-
raise NotImplementedError, "Changing DeepCover's tracker global after starting coverage is not supported" if running?
|
71
|
-
@coverage = nil
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def reset
|
76
|
-
stop if running?
|
77
|
-
@coverage = @custom_requirer = @autoload_tracker = @lookup_paths = nil
|
78
|
-
config.reset
|
79
|
-
self
|
80
|
-
end
|
81
|
-
|
82
|
-
def coverage
|
83
|
-
@coverage ||= Coverage.new(tracker_global: config.tracker_global)
|
84
|
-
end
|
85
|
-
|
86
|
-
def lookup_paths
|
87
|
-
return @lookup_paths if @lookup_paths
|
88
|
-
lookup_paths = config.paths || Dir.getwd
|
89
|
-
lookup_paths = Array(lookup_paths).map { |p| File.expand_path(p) }
|
90
|
-
lookup_paths = ['/'] if lookup_paths.include?('/')
|
91
|
-
@lookup_paths = lookup_paths
|
92
|
-
end
|
93
|
-
|
94
|
-
def within_lookup_paths?(path)
|
95
|
-
lookup_paths.any? { |lookup_path| path.start_with?(lookup_path) }
|
96
|
-
end
|
97
|
-
|
98
|
-
def custom_requirer
|
99
|
-
@custom_requirer ||= CustomRequirer.new
|
100
|
-
end
|
101
|
-
|
102
|
-
def autoload_tracker
|
103
|
-
@autoload_tracker ||= AutoloadTracker.new
|
104
|
-
end
|
105
|
-
|
106
|
-
private
|
107
|
-
|
108
|
-
def handle_relative_filename(filename)
|
109
|
-
unless Pathname.new(filename).absolute?
|
110
|
-
relative_to = File.dirname(caller(2..2).first.partition(/\.rb:\d/).first)
|
111
|
-
filename = File.absolute_path(filename, relative_to)
|
112
|
-
end
|
113
|
-
filename += '.rb' unless filename =~ /\.rb$/
|
114
|
-
filename
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|