nano-fast-box 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/nano-fast-box.gemspec +12 -0
- data/simplecov-0.22.0/CHANGELOG.md +191 -0
- data/simplecov-0.22.0/LICENSE +20 -0
- data/simplecov-0.22.0/README.md +974 -0
- data/simplecov-0.22.0/doc/alternate-formatters.md +71 -0
- data/simplecov-0.22.0/doc/commercial-services.md +25 -0
- data/simplecov-0.22.0/doc/editor-integration.md +18 -0
- data/simplecov-0.22.0/lib/minitest/simplecov_plugin.rb +15 -0
- data/simplecov-0.22.0/lib/simplecov/combine/branches_combiner.rb +32 -0
- data/simplecov-0.22.0/lib/simplecov/combine/files_combiner.rb +24 -0
- data/simplecov-0.22.0/lib/simplecov/combine/lines_combiner.rb +43 -0
- data/simplecov-0.22.0/lib/simplecov/combine/results_combiner.rb +60 -0
- data/simplecov-0.22.0/lib/simplecov/combine.rb +30 -0
- data/simplecov-0.22.0/lib/simplecov/command_guesser.rb +64 -0
- data/simplecov-0.22.0/lib/simplecov/configuration.rb +500 -0
- data/simplecov-0.22.0/lib/simplecov/coverage_statistics.rb +56 -0
- data/simplecov-0.22.0/lib/simplecov/default_formatter.rb +20 -0
- data/simplecov-0.22.0/lib/simplecov/defaults.rb +53 -0
- data/simplecov-0.22.0/lib/simplecov/exit_codes/exit_code_handling.rb +29 -0
- data/simplecov-0.22.0/lib/simplecov/exit_codes/maximum_coverage_drop_check.rb +83 -0
- data/simplecov-0.22.0/lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb +54 -0
- data/simplecov-0.22.0/lib/simplecov/exit_codes/minimum_overall_coverage_check.rb +53 -0
- data/simplecov-0.22.0/lib/simplecov/exit_codes.rb +15 -0
- data/simplecov-0.22.0/lib/simplecov/file_list.rb +120 -0
- data/simplecov-0.22.0/lib/simplecov/filter.rb +94 -0
- data/simplecov-0.22.0/lib/simplecov/formatter/multi_formatter.rb +32 -0
- data/simplecov-0.22.0/lib/simplecov/formatter/simple_formatter.rb +25 -0
- data/simplecov-0.22.0/lib/simplecov/formatter.rb +10 -0
- data/simplecov-0.22.0/lib/simplecov/last_run.rb +28 -0
- data/simplecov-0.22.0/lib/simplecov/lines_classifier.rb +48 -0
- data/simplecov-0.22.0/lib/simplecov/load_global_config.rb +8 -0
- data/simplecov-0.22.0/lib/simplecov/no_defaults.rb +4 -0
- data/simplecov-0.22.0/lib/simplecov/process.rb +19 -0
- data/simplecov-0.22.0/lib/simplecov/profiles/bundler_filter.rb +5 -0
- data/simplecov-0.22.0/lib/simplecov/profiles/hidden_filter.rb +5 -0
- data/simplecov-0.22.0/lib/simplecov/profiles/rails.rb +18 -0
- data/simplecov-0.22.0/lib/simplecov/profiles/root_filter.rb +10 -0
- data/simplecov-0.22.0/lib/simplecov/profiles/test_frameworks.rb +8 -0
- data/simplecov-0.22.0/lib/simplecov/profiles.rb +35 -0
- data/simplecov-0.22.0/lib/simplecov/result.rb +94 -0
- data/simplecov-0.22.0/lib/simplecov/result_adapter.rb +30 -0
- data/simplecov-0.22.0/lib/simplecov/result_merger.rb +194 -0
- data/simplecov-0.22.0/lib/simplecov/simulate_coverage.rb +29 -0
- data/simplecov-0.22.0/lib/simplecov/source_file/branch.rb +84 -0
- data/simplecov-0.22.0/lib/simplecov/source_file/line.rb +72 -0
- data/simplecov-0.22.0/lib/simplecov/source_file.rb +355 -0
- data/simplecov-0.22.0/lib/simplecov/useless_results_remover.rb +18 -0
- data/simplecov-0.22.0/lib/simplecov/version.rb +5 -0
- data/simplecov-0.22.0/lib/simplecov.rb +470 -0
- metadata +90 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
#
|
|
5
|
+
# Profiles are SimpleCov configuration procs that can be easily
|
|
6
|
+
# loaded using SimpleCov.start :rails and defined using
|
|
7
|
+
# SimpleCov.profiles.define :foo do
|
|
8
|
+
# # SimpleCov configuration here, same as in SimpleCov.configure
|
|
9
|
+
# end
|
|
10
|
+
#
|
|
11
|
+
class Profiles < Hash
|
|
12
|
+
#
|
|
13
|
+
# Define a SimpleCov profile:
|
|
14
|
+
# SimpleCov.profiles.define 'rails' do
|
|
15
|
+
# # Same as SimpleCov.configure do .. here
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
def define(name, &blk)
|
|
19
|
+
name = name.to_sym
|
|
20
|
+
raise "SimpleCov Profile '#{name}' is already defined" unless self[name].nil?
|
|
21
|
+
|
|
22
|
+
self[name] = blk
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Applies the profile of given name on SimpleCov.configure
|
|
27
|
+
#
|
|
28
|
+
def load(name)
|
|
29
|
+
name = name.to_sym
|
|
30
|
+
raise "Could not find SimpleCov Profile called '#{name}'" unless key?(name)
|
|
31
|
+
|
|
32
|
+
SimpleCov.configure(&self[name])
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "digest/sha1"
|
|
4
|
+
require "forwardable"
|
|
5
|
+
|
|
6
|
+
module SimpleCov
|
|
7
|
+
#
|
|
8
|
+
# A simplecov code coverage result, initialized from the Hash Ruby's built-in coverage
|
|
9
|
+
# library generates (Coverage.result).
|
|
10
|
+
#
|
|
11
|
+
class Result
|
|
12
|
+
extend Forwardable
|
|
13
|
+
# Returns the original Coverage.result used for this instance of SimpleCov::Result
|
|
14
|
+
attr_reader :original_result
|
|
15
|
+
# Returns all files that are applicable to this result (sans filters!) as instances of SimpleCov::SourceFile. Aliased as :source_files
|
|
16
|
+
attr_reader :files
|
|
17
|
+
alias source_files files
|
|
18
|
+
# Explicitly set the Time this result has been created
|
|
19
|
+
attr_writer :created_at
|
|
20
|
+
# Explicitly set the command name that was used for this coverage result. Defaults to SimpleCov.command_name
|
|
21
|
+
attr_writer :command_name
|
|
22
|
+
|
|
23
|
+
def_delegators :files, :covered_percent, :covered_percentages, :least_covered_file, :covered_strength, :covered_lines, :missed_lines, :total_branches, :covered_branches, :missed_branches, :coverage_statistics, :coverage_statistics_by_file
|
|
24
|
+
def_delegator :files, :lines_of_code, :total_lines
|
|
25
|
+
|
|
26
|
+
# Initialize a new SimpleCov::Result from given Coverage.result (a Hash of filenames each containing an array of
|
|
27
|
+
# coverage data)
|
|
28
|
+
def initialize(original_result, command_name: nil, created_at: nil)
|
|
29
|
+
result = original_result
|
|
30
|
+
@original_result = result.freeze
|
|
31
|
+
@command_name = command_name
|
|
32
|
+
@created_at = created_at
|
|
33
|
+
@files = SimpleCov::FileList.new(result.map do |filename, coverage|
|
|
34
|
+
SimpleCov::SourceFile.new(filename, JSON.parse(JSON.dump(coverage))) if File.file?(filename)
|
|
35
|
+
end.compact.sort_by(&:filename))
|
|
36
|
+
filter!
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Returns all filenames for source files contained in this result
|
|
40
|
+
def filenames
|
|
41
|
+
files.map(&:filename)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Returns a Hash of groups for this result. Define groups using SimpleCov.add_group 'Models', 'app/models'
|
|
45
|
+
def groups
|
|
46
|
+
@groups ||= SimpleCov.grouped(files)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Applies the configured SimpleCov.formatter on this result
|
|
50
|
+
def format!
|
|
51
|
+
SimpleCov.formatter.new.format(self)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Defines when this result has been created. Defaults to Time.now
|
|
55
|
+
def created_at
|
|
56
|
+
@created_at ||= Time.now
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# The command name that launched this result.
|
|
60
|
+
# Delegated to SimpleCov.command_name if not set manually
|
|
61
|
+
def command_name
|
|
62
|
+
@command_name ||= SimpleCov.command_name
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Returns a hash representation of this Result that can be used for marshalling it into JSON
|
|
66
|
+
def to_hash
|
|
67
|
+
{
|
|
68
|
+
command_name => {
|
|
69
|
+
"coverage" => coverage,
|
|
70
|
+
"timestamp" => created_at.to_i
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Loads a SimpleCov::Result#to_hash dump
|
|
76
|
+
def self.from_hash(hash)
|
|
77
|
+
hash.map do |command_name, data|
|
|
78
|
+
new(data.fetch("coverage"), command_name: command_name, created_at: Time.at(data["timestamp"]))
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
def coverage
|
|
85
|
+
keys = original_result.keys & filenames
|
|
86
|
+
Hash[keys.zip(original_result.values_at(*keys))]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Applies all configured SimpleCov filters on this result's source files
|
|
90
|
+
def filter!
|
|
91
|
+
@files = SimpleCov.filtered(files)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
#
|
|
5
|
+
# Responsible for adapting the format of the coverage result whether it's default or with statistics
|
|
6
|
+
#
|
|
7
|
+
class ResultAdapter
|
|
8
|
+
attr_reader :result
|
|
9
|
+
|
|
10
|
+
def initialize(result)
|
|
11
|
+
@result = result
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.call(*args)
|
|
15
|
+
new(*args).adapt
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def adapt
|
|
19
|
+
return unless result
|
|
20
|
+
|
|
21
|
+
result.each_with_object({}) do |(file_name, cover_statistic), adapted_result|
|
|
22
|
+
if cover_statistic.is_a?(Array)
|
|
23
|
+
adapted_result.merge!(file_name => {"lines" => cover_statistic})
|
|
24
|
+
else
|
|
25
|
+
adapted_result.merge!(file_name => cover_statistic)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module SimpleCov
|
|
6
|
+
#
|
|
7
|
+
# Singleton that is responsible for caching, loading and merging
|
|
8
|
+
# SimpleCov::Results into a single result for coverage analysis based
|
|
9
|
+
# upon multiple test suites.
|
|
10
|
+
#
|
|
11
|
+
module ResultMerger
|
|
12
|
+
class << self
|
|
13
|
+
# The path to the .resultset.json cache file
|
|
14
|
+
def resultset_path
|
|
15
|
+
File.join(SimpleCov.coverage_path, ".resultset.json")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def resultset_writelock
|
|
19
|
+
File.join(SimpleCov.coverage_path, ".resultset.json.lock")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def merge_and_store(*file_paths, ignore_timeout: false)
|
|
23
|
+
result = merge_results(*file_paths, ignore_timeout: ignore_timeout)
|
|
24
|
+
store_result(result) if result
|
|
25
|
+
result
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def merge_results(*file_paths, ignore_timeout: false)
|
|
29
|
+
# It is intentional here that files are only read in and parsed one at a time.
|
|
30
|
+
#
|
|
31
|
+
# In big CI setups you might deal with 100s of CI jobs and each one producing Megabytes
|
|
32
|
+
# of data. Reading them all in easily produces Gigabytes of memory consumption which
|
|
33
|
+
# we want to avoid.
|
|
34
|
+
#
|
|
35
|
+
# For similar reasons a SimpleCov::Result is only created in the end as that'd create
|
|
36
|
+
# even more data especially when it also reads in all source files.
|
|
37
|
+
initial_memo = valid_results(file_paths.shift, ignore_timeout: ignore_timeout)
|
|
38
|
+
|
|
39
|
+
command_names, coverage = file_paths.reduce(initial_memo) do |memo, file_path|
|
|
40
|
+
merge_coverage(memo, valid_results(file_path, ignore_timeout: ignore_timeout))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
create_result(command_names, coverage)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def valid_results(file_path, ignore_timeout: false)
|
|
47
|
+
results = parse_file(file_path)
|
|
48
|
+
merge_valid_results(results, ignore_timeout: ignore_timeout)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def parse_file(path)
|
|
52
|
+
data = read_file(path)
|
|
53
|
+
parse_json(data)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def read_file(path)
|
|
57
|
+
return unless File.exist?(path)
|
|
58
|
+
|
|
59
|
+
data = File.read(path)
|
|
60
|
+
return if data.nil? || data.length < 2
|
|
61
|
+
|
|
62
|
+
data
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def parse_json(content)
|
|
66
|
+
return {} unless content
|
|
67
|
+
|
|
68
|
+
JSON.parse(content) || {}
|
|
69
|
+
rescue StandardError
|
|
70
|
+
warn "[SimpleCov]: Warning! Parsing JSON content of resultset file failed"
|
|
71
|
+
{}
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def merge_valid_results(results, ignore_timeout: false)
|
|
75
|
+
results = results.select { |_command_name, data| within_merge_timeout?(data) } unless ignore_timeout
|
|
76
|
+
|
|
77
|
+
command_plus_coverage = results.map do |command_name, data|
|
|
78
|
+
[[command_name], adapt_result(data.fetch("coverage"))]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# one file itself _might_ include multiple test runs
|
|
82
|
+
merge_coverage(*command_plus_coverage)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def within_merge_timeout?(data)
|
|
86
|
+
time_since_result_creation(data) < SimpleCov.merge_timeout
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def time_since_result_creation(data)
|
|
90
|
+
Time.now - Time.at(data.fetch("timestamp"))
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def create_result(command_names, coverage)
|
|
94
|
+
return nil unless coverage
|
|
95
|
+
|
|
96
|
+
command_name = command_names.reject(&:empty?).sort.join(", ")
|
|
97
|
+
SimpleCov::Result.new(coverage, command_name: command_name)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def merge_coverage(*results)
|
|
101
|
+
return [[""], nil] if results.empty?
|
|
102
|
+
return results.first if results.size == 1
|
|
103
|
+
|
|
104
|
+
results.reduce do |(memo_command, memo_coverage), (command, coverage)|
|
|
105
|
+
# timestamp is dropped here, which is intentional (we merge it, it gets a new time stamp as of now)
|
|
106
|
+
merged_coverage = Combine.combine(Combine::ResultsCombiner, memo_coverage, coverage)
|
|
107
|
+
merged_command = memo_command + command
|
|
108
|
+
|
|
109
|
+
[merged_command, merged_coverage]
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
#
|
|
114
|
+
# Gets all SimpleCov::Results stored in resultset, merges them and produces a new
|
|
115
|
+
# SimpleCov::Result with merged coverage data and the command_name
|
|
116
|
+
# for the result consisting of a join on all source result's names
|
|
117
|
+
def merged_result
|
|
118
|
+
# conceptually this is just doing `merge_results(resultset_path)`
|
|
119
|
+
# it's more involved to make syre `synchronize_resultset` is only used around reading
|
|
120
|
+
resultset_hash = read_resultset
|
|
121
|
+
command_names, coverage = merge_valid_results(resultset_hash)
|
|
122
|
+
|
|
123
|
+
create_result(command_names, coverage)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def read_resultset
|
|
127
|
+
resultset_content =
|
|
128
|
+
synchronize_resultset do
|
|
129
|
+
read_file(resultset_path)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
parse_json(resultset_content)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Saves the given SimpleCov::Result in the resultset cache
|
|
136
|
+
def store_result(result)
|
|
137
|
+
synchronize_resultset do
|
|
138
|
+
# Ensure we have the latest, in case it was already cached
|
|
139
|
+
new_resultset = read_resultset
|
|
140
|
+
|
|
141
|
+
# A single result only ever has one command_name, see `SimpleCov::Result#to_hash`
|
|
142
|
+
command_name, data = result.to_hash.first
|
|
143
|
+
new_resultset[command_name] = data
|
|
144
|
+
File.open(resultset_path, "w+") do |f_|
|
|
145
|
+
f_.puts JSON.pretty_generate(new_resultset)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
true
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Ensure only one process is reading or writing the resultset at any
|
|
152
|
+
# given time
|
|
153
|
+
def synchronize_resultset
|
|
154
|
+
# make it reentrant
|
|
155
|
+
return yield if defined?(@resultset_locked) && @resultset_locked
|
|
156
|
+
|
|
157
|
+
begin
|
|
158
|
+
@resultset_locked = true
|
|
159
|
+
File.open(resultset_writelock, "w+") do |f|
|
|
160
|
+
f.flock(File::LOCK_EX)
|
|
161
|
+
yield
|
|
162
|
+
end
|
|
163
|
+
ensure
|
|
164
|
+
@resultset_locked = false
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# We changed the format of the raw result data in simplecov, as people are likely
|
|
169
|
+
# to have "old" resultsets lying around (but not too old so that they're still
|
|
170
|
+
# considered we can adapt them).
|
|
171
|
+
# See https://github.com/simplecov-ruby/simplecov/pull/824#issuecomment-576049747
|
|
172
|
+
def adapt_result(result)
|
|
173
|
+
if pre_simplecov_0_18_result?(result)
|
|
174
|
+
adapt_pre_simplecov_0_18_result(result)
|
|
175
|
+
else
|
|
176
|
+
result
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# pre 0.18 coverage data pointed from file directly to an array of line coverage
|
|
181
|
+
def pre_simplecov_0_18_result?(result)
|
|
182
|
+
_key, data = result.first
|
|
183
|
+
|
|
184
|
+
data.is_a?(Array)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def adapt_pre_simplecov_0_18_result(result)
|
|
188
|
+
result.transform_values do |line_coverage_data|
|
|
189
|
+
{"lines" => line_coverage_data}
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
#
|
|
5
|
+
# Responsible for producing file coverage metrics.
|
|
6
|
+
#
|
|
7
|
+
module SimulateCoverage
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# Simulate normal file coverage report on
|
|
12
|
+
# ruby 2.5 and return similar hash with lines and branches keys
|
|
13
|
+
#
|
|
14
|
+
# Happens when a file wasn't required but still tracked.
|
|
15
|
+
#
|
|
16
|
+
# @return [Hash]
|
|
17
|
+
#
|
|
18
|
+
def call(absolute_path)
|
|
19
|
+
lines = File.foreach(absolute_path)
|
|
20
|
+
|
|
21
|
+
{
|
|
22
|
+
"lines" => LinesClassifier.new.classify(lines),
|
|
23
|
+
# we don't want to parse branches ourselves...
|
|
24
|
+
# requiring files can have side effects and we don't want to trigger that
|
|
25
|
+
"branches" => {}
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
class SourceFile
|
|
5
|
+
#
|
|
6
|
+
# Representing single branch that has been detected in coverage report.
|
|
7
|
+
# Give us support methods that handle needed calculations.
|
|
8
|
+
class Branch
|
|
9
|
+
attr_reader :start_line, :end_line, :coverage, :type
|
|
10
|
+
|
|
11
|
+
# rubocop:disable Metrics/ParameterLists
|
|
12
|
+
def initialize(start_line:, end_line:, coverage:, inline:, type:)
|
|
13
|
+
@start_line = start_line
|
|
14
|
+
@end_line = end_line
|
|
15
|
+
@coverage = coverage
|
|
16
|
+
@inline = inline
|
|
17
|
+
@type = type
|
|
18
|
+
@skipped = false
|
|
19
|
+
end
|
|
20
|
+
# rubocop:enable Metrics/ParameterLists
|
|
21
|
+
|
|
22
|
+
def inline?
|
|
23
|
+
@inline
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
#
|
|
27
|
+
# Return true if there is relevant count defined > 0
|
|
28
|
+
#
|
|
29
|
+
# @return [Boolean]
|
|
30
|
+
#
|
|
31
|
+
def covered?
|
|
32
|
+
!skipped? && coverage.positive?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
#
|
|
36
|
+
# Check if branche missed or not
|
|
37
|
+
#
|
|
38
|
+
# @return [Boolean]
|
|
39
|
+
#
|
|
40
|
+
def missed?
|
|
41
|
+
!skipped? && coverage.zero?
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# The line on which we want to report the coverage
|
|
45
|
+
#
|
|
46
|
+
# Usually we choose the line above the start of the branch (so that it shows up
|
|
47
|
+
# at if/else) because that
|
|
48
|
+
# * highlights the condition
|
|
49
|
+
# * makes it distinguishable if the first line of the branch is an inline branch
|
|
50
|
+
# (see the nested_branches fixture)
|
|
51
|
+
#
|
|
52
|
+
def report_line
|
|
53
|
+
if inline?
|
|
54
|
+
start_line
|
|
55
|
+
else
|
|
56
|
+
start_line - 1
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Flags the branch as skipped
|
|
61
|
+
def skipped!
|
|
62
|
+
@skipped = true
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Returns true if the branch was marked skipped by virtue of nocov comments.
|
|
66
|
+
def skipped?
|
|
67
|
+
@skipped
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def overlaps_with?(line_range)
|
|
71
|
+
start_line <= line_range.end && end_line >= line_range.begin
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
#
|
|
75
|
+
# Return array with coverage count and badge
|
|
76
|
+
#
|
|
77
|
+
# @return [Array]
|
|
78
|
+
#
|
|
79
|
+
def report
|
|
80
|
+
[type, coverage]
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
class SourceFile
|
|
5
|
+
# Representation of a single line in a source file including
|
|
6
|
+
# this specific line's source code, line_number and code coverage,
|
|
7
|
+
# with the coverage being either nil (coverage not applicable, e.g. comment
|
|
8
|
+
# line), 0 (line not covered) or >1 (the amount of times the line was
|
|
9
|
+
# executed)
|
|
10
|
+
class Line
|
|
11
|
+
# The source code for this line. Aliased as :source
|
|
12
|
+
attr_reader :src
|
|
13
|
+
# The line number in the source file. Aliased as :line, :number
|
|
14
|
+
attr_reader :line_number
|
|
15
|
+
# The coverage data for this line: either nil (never), 0 (missed) or >=1 (times covered)
|
|
16
|
+
attr_reader :coverage
|
|
17
|
+
# Whether this line was skipped
|
|
18
|
+
attr_reader :skipped
|
|
19
|
+
|
|
20
|
+
# Lets grab some fancy aliases, shall we?
|
|
21
|
+
alias source src
|
|
22
|
+
alias line line_number
|
|
23
|
+
alias number line_number
|
|
24
|
+
|
|
25
|
+
def initialize(src, line_number, coverage)
|
|
26
|
+
raise ArgumentError, "Only String accepted for source" unless src.is_a?(String)
|
|
27
|
+
raise ArgumentError, "Only Integer accepted for line_number" unless line_number.is_a?(Integer)
|
|
28
|
+
raise ArgumentError, "Only Integer and nil accepted for coverage" unless coverage.is_a?(Integer) || coverage.nil?
|
|
29
|
+
|
|
30
|
+
@src = src
|
|
31
|
+
@line_number = line_number
|
|
32
|
+
@coverage = coverage
|
|
33
|
+
@skipped = false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Returns true if this is a line that should have been covered, but was not
|
|
37
|
+
def missed?
|
|
38
|
+
!never? && !skipped? && coverage.zero?
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Returns true if this is a line that has been covered
|
|
42
|
+
def covered?
|
|
43
|
+
!never? && !skipped? && coverage.positive?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns true if this line is not relevant for coverage
|
|
47
|
+
def never?
|
|
48
|
+
!skipped? && coverage.nil?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Flags this line as skipped
|
|
52
|
+
def skipped!
|
|
53
|
+
@skipped = true
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Returns true if this line was skipped, false otherwise. Lines are skipped if they are wrapped with
|
|
57
|
+
# # :nocov: comment lines.
|
|
58
|
+
def skipped?
|
|
59
|
+
skipped
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# The status of this line - either covered, missed, skipped or never. Useful i.e. for direct use
|
|
63
|
+
# as a css class in report generation
|
|
64
|
+
def status
|
|
65
|
+
return "skipped" if skipped?
|
|
66
|
+
return "never" if never?
|
|
67
|
+
return "missed" if missed?
|
|
68
|
+
return "covered" if covered?
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|