2017-09-07 18:40:29 +03:00
|
|
|
require "coverage"
|
|
|
|
|
2017-09-14 09:07:05 +03:00
|
|
|
Coverage.start(lines: true, branches: true, methods: true)
|
2017-09-07 18:40:29 +03:00
|
|
|
|
|
|
|
TEST_COVERAGE_DATA_FILE = "test-coverage.dat"
|
|
|
|
|
|
|
|
def merge_coverage_data(res1, res2)
|
|
|
|
res1.each do |path, cov1|
|
|
|
|
cov2 = res2[path]
|
|
|
|
if cov2
|
2017-09-14 09:07:05 +03:00
|
|
|
cov1[:lines].each_with_index do |count1, i|
|
2017-09-07 18:40:29 +03:00
|
|
|
next unless count1
|
2017-09-14 09:07:05 +03:00
|
|
|
add_count(cov2[:lines], i, count1)
|
|
|
|
end
|
|
|
|
cov1[:branches].each do |base_key, targets1|
|
|
|
|
if cov2[:branches][base_key]
|
|
|
|
targets1.each do |target_key, count1|
|
|
|
|
add_count(cov2[:branches][base_key], target_key, count1)
|
|
|
|
end
|
2017-09-07 18:40:29 +03:00
|
|
|
else
|
2017-09-14 09:07:05 +03:00
|
|
|
cov2[:branches][base_key] = targets1
|
2017-09-07 18:40:29 +03:00
|
|
|
end
|
|
|
|
end
|
2017-09-14 09:07:05 +03:00
|
|
|
cov1[:methods].each do |key, count1|
|
|
|
|
add_count(cov2[:methods], key, count1)
|
|
|
|
end
|
2017-09-07 18:40:29 +03:00
|
|
|
else
|
|
|
|
res2[path] = cov1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
res2
|
|
|
|
end
|
|
|
|
|
2017-09-14 09:07:05 +03:00
|
|
|
def add_count(h, key, count)
|
|
|
|
if h[key]
|
|
|
|
h[key] += count
|
|
|
|
else
|
|
|
|
h[key] = count
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-09-07 18:40:29 +03:00
|
|
|
def save_coverage_data(res1)
|
2017-12-05 10:16:42 +03:00
|
|
|
res1.each do |_path, cov|
|
|
|
|
if cov[:methods]
|
|
|
|
h = {}
|
|
|
|
cov[:methods].each do |(klass, *key), count|
|
2020-05-28 08:39:53 +03:00
|
|
|
h[[klass.name, *key]] = count
|
2017-12-05 10:16:42 +03:00
|
|
|
end
|
|
|
|
cov[:methods].replace h
|
|
|
|
end
|
|
|
|
end
|
2017-09-07 18:40:29 +03:00
|
|
|
File.open(TEST_COVERAGE_DATA_FILE, File::RDWR | File::CREAT | File::BINARY) do |f|
|
|
|
|
f.flock(File::LOCK_EX)
|
|
|
|
s = f.read
|
|
|
|
res2 = s.size > 0 ? Marshal.load(s) : {}
|
|
|
|
res1 = merge_coverage_data(res1, res2)
|
|
|
|
f.rewind
|
|
|
|
f << Marshal.dump(res2)
|
|
|
|
f.flush
|
|
|
|
f.truncate(f.pos)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def invoke_simplecov_formatter
|
|
|
|
%w[doclie simplecov-html simplecov].each do |f|
|
|
|
|
$LOAD_PATH.unshift "#{__dir__}/../coverage/#{f}/lib"
|
|
|
|
end
|
|
|
|
|
|
|
|
require "simplecov"
|
|
|
|
res = Marshal.load(File.binread(TEST_COVERAGE_DATA_FILE))
|
|
|
|
simplecov_result = {}
|
|
|
|
base_dir = File.dirname(__dir__)
|
2018-04-05 04:05:16 +03:00
|
|
|
cur_dir = Dir.pwd
|
2017-09-07 18:40:29 +03:00
|
|
|
|
|
|
|
res.each do |path, cov|
|
2018-04-05 04:05:16 +03:00
|
|
|
next unless path.start_with?(base_dir) || path.start_with?(cur_dir)
|
2017-09-07 18:40:29 +03:00
|
|
|
next if path.start_with?(File.join(base_dir, "test"))
|
2017-09-14 09:07:05 +03:00
|
|
|
simplecov_result[path] = cov[:lines]
|
2017-09-07 18:40:29 +03:00
|
|
|
end
|
|
|
|
|
2018-04-05 04:05:16 +03:00
|
|
|
a, b = base_dir, cur_dir
|
|
|
|
until a == b
|
|
|
|
if a.size > b.size
|
|
|
|
a = File.dirname(a)
|
|
|
|
else
|
|
|
|
b = File.dirname(b)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
root_dir = a
|
|
|
|
|
|
|
|
SimpleCov.configure do
|
|
|
|
root(root_dir)
|
|
|
|
coverage_dir(File.join(cur_dir, "coverage"))
|
|
|
|
end
|
2017-09-07 18:40:29 +03:00
|
|
|
res = SimpleCov::Result.new(simplecov_result)
|
|
|
|
res.command_name = "Ruby's `make test-all`"
|
|
|
|
SimpleCov::Formatter::HTMLFormatter.new.format(res)
|
|
|
|
end
|
|
|
|
|
|
|
|
pid = $$
|
|
|
|
pwd = Dir.pwd
|
|
|
|
|
|
|
|
at_exit do
|
|
|
|
exit_exc = $!
|
|
|
|
|
|
|
|
Dir.chdir(pwd) do
|
|
|
|
save_coverage_data(Coverage.result)
|
|
|
|
if pid == $$
|
|
|
|
begin
|
|
|
|
nil while Process.waitpid(-1)
|
|
|
|
rescue Errno::ECHILD
|
|
|
|
invoke_simplecov_formatter
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
raise exit_exc if exit_exc
|
|
|
|
end
|