2017-07-04 12:02:19 -04:00
|
|
|
#!ruby
|
|
|
|
require "pathname"
|
|
|
|
require "open3"
|
2017-09-26 00:59:39 -04:00
|
|
|
require "tmpdir"
|
2017-07-04 12:02:19 -04:00
|
|
|
|
|
|
|
def backup_gcda_files(gcda_files)
|
|
|
|
gcda_files = gcda_files.map do |gcda|
|
|
|
|
[gcda, gcda.sub_ext(".bak")]
|
|
|
|
end
|
|
|
|
begin
|
|
|
|
gcda_files.each do |before, after|
|
|
|
|
before.rename(after)
|
|
|
|
end
|
|
|
|
yield
|
|
|
|
ensure
|
|
|
|
gcda_files.each do |before, after|
|
|
|
|
after.rename(before)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-09-25 10:04:59 -04:00
|
|
|
def run_lcov(*args)
|
|
|
|
system("lcov", "--rc", "lcov_branch_coverage=1", *args)
|
|
|
|
end
|
|
|
|
|
2017-07-04 12:02:19 -04:00
|
|
|
$info_files = []
|
2017-09-25 10:04:59 -04:00
|
|
|
def run_lcov_capture(dir, info)
|
2017-07-04 12:02:19 -04:00
|
|
|
$info_files << info
|
2017-09-25 10:04:59 -04:00
|
|
|
run_lcov("--capture", "-d", dir, "-o", info)
|
|
|
|
end
|
|
|
|
|
|
|
|
def run_lcov_merge(files, info)
|
|
|
|
run_lcov(*files.flat_map {|f| ["--add-tracefile", f] }, "-o", info)
|
|
|
|
end
|
|
|
|
|
|
|
|
def run_lcov_remove(info_src, info_out)
|
2017-09-26 00:59:39 -04:00
|
|
|
dirs = %w(/usr/*)
|
|
|
|
dirs << File.join(Dir.tmpdir, "*")
|
2017-09-25 10:04:59 -04:00
|
|
|
%w(
|
|
|
|
test/*
|
|
|
|
ext/-test-/*
|
|
|
|
ext/nkf/nkf-utf8/nkf.c
|
|
|
|
).each {|f| dirs << File.join(File.dirname(__dir__), f) }
|
|
|
|
run_lcov("--remove", info_src, *dirs, "-o", info_out)
|
|
|
|
end
|
|
|
|
|
|
|
|
def run_genhtml(info, out)
|
|
|
|
system("genhtml", "--branch-coverage", "--ignore-errors", "source", info, "-o", out)
|
2017-07-04 12:02:19 -04:00
|
|
|
end
|
|
|
|
|
2017-09-09 09:09:21 -04:00
|
|
|
def gen_rb_lcov(file)
|
|
|
|
res = Marshal.load(File.binread(file))
|
|
|
|
|
|
|
|
open("lcov-rb-all.info", "w") do |f|
|
|
|
|
f.puts "TN:" # no test name
|
|
|
|
base_dir = File.dirname(__dir__)
|
|
|
|
res.each do |path, cov|
|
|
|
|
next unless path.start_with?(base_dir)
|
|
|
|
next if path.start_with?(File.join(base_dir, "test"))
|
|
|
|
f.puts "SF:#{ path }"
|
|
|
|
|
|
|
|
total = covered = 0
|
|
|
|
cov.each_with_index do |count, lineno|
|
|
|
|
next unless count
|
|
|
|
f.puts "DA:#{ lineno + 1 },#{ count }"
|
|
|
|
total += 1
|
|
|
|
covered += 1 if count > 0
|
|
|
|
end
|
|
|
|
f.puts "LF:#{ total }"
|
|
|
|
f.puts "LH:#{ covered }"
|
|
|
|
|
|
|
|
f.puts "end_of_record"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-09-14 02:07:05 -04:00
|
|
|
def gen_rb_lcov(file)
|
|
|
|
res = Marshal.load(File.binread(file))
|
|
|
|
|
|
|
|
open("lcov-rb-all.info", "w") do |f|
|
|
|
|
f.puts "TN:" # no test name
|
|
|
|
base_dir = File.dirname(File.dirname(__dir__))
|
|
|
|
res.each do |path, cov|
|
|
|
|
next unless path.start_with?(base_dir)
|
|
|
|
next if path.start_with?(File.join(base_dir, "test"))
|
|
|
|
f.puts "SF:#{ path }"
|
|
|
|
|
|
|
|
# function coverage
|
|
|
|
total = covered = 0
|
2017-09-17 00:30:30 -04:00
|
|
|
cov[:methods].each do |(name, _, lineno), count|
|
2017-09-14 02:07:05 -04:00
|
|
|
f.puts "FN:#{ lineno },#{ name }"
|
|
|
|
total += 1
|
|
|
|
covered += 1 if count > 0
|
|
|
|
end
|
|
|
|
f.puts "FNF:#{ total }"
|
|
|
|
f.puts "FNF:#{ covered }"
|
|
|
|
cov[:methods].each do |(name, _), count|
|
|
|
|
f.puts "FNDA:#{ count },#{ name }"
|
|
|
|
end
|
|
|
|
|
|
|
|
# line coverage
|
|
|
|
total = covered = 0
|
|
|
|
cov[:lines].each_with_index do |count, lineno|
|
|
|
|
next unless count
|
|
|
|
f.puts "DA:#{ lineno + 1 },#{ count }"
|
|
|
|
total += 1
|
|
|
|
covered += 1 if count > 0
|
|
|
|
end
|
|
|
|
f.puts "LF:#{ total }"
|
|
|
|
f.puts "LH:#{ covered }"
|
|
|
|
|
|
|
|
# branch coverage
|
|
|
|
total = covered = 0
|
|
|
|
id = 0
|
2017-09-25 10:04:59 -04:00
|
|
|
cov[:branches].each do |(_base_type, _, base_lineno), targets|
|
2017-09-14 02:07:05 -04:00
|
|
|
i = 0
|
2017-09-25 10:04:59 -04:00
|
|
|
targets.each do |(_target_type, _target_lineno), count|
|
2017-09-14 02:07:05 -04:00
|
|
|
f.puts "BRDA:#{ base_lineno },#{ id },#{ i },#{ count }"
|
|
|
|
total += 1
|
|
|
|
covered += 1 if count > 0
|
|
|
|
i += 1
|
|
|
|
end
|
|
|
|
id += 1
|
|
|
|
end
|
|
|
|
f.puts "BRF:#{ total }"
|
|
|
|
f.puts "BRH:#{ covered }"
|
|
|
|
f.puts "end_of_record"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-07-04 12:02:19 -04:00
|
|
|
gcda_files = Pathname.glob("**/*.gcda")
|
|
|
|
ext_gcda_files = gcda_files.select {|f| f.fnmatch("ext/*") }
|
|
|
|
rubyspec_temp_gcda_files = gcda_files.select {|f| f.fnmatch("rubyspec_temp/*") }
|
|
|
|
|
|
|
|
backup_gcda_files(rubyspec_temp_gcda_files) do
|
2017-09-09 09:09:21 -04:00
|
|
|
if ext_gcda_files != []
|
|
|
|
backup_gcda_files(ext_gcda_files) do
|
|
|
|
info = "lcov-root.info"
|
2017-09-25 10:04:59 -04:00
|
|
|
run_lcov_capture(".", info)
|
2017-09-09 09:09:21 -04:00
|
|
|
end
|
2017-07-04 12:02:19 -04:00
|
|
|
end
|
|
|
|
ext_gcda_files.group_by {|f| f.descend.to_a[1] }.each do |key, files|
|
|
|
|
info = "lcov-#{ key.to_s.gsub(File::Separator, "-") }.info"
|
2017-09-25 10:04:59 -04:00
|
|
|
run_lcov_capture(key.to_s, info)
|
2017-07-04 12:02:19 -04:00
|
|
|
end
|
|
|
|
end
|
2017-09-09 09:09:21 -04:00
|
|
|
if $info_files != []
|
2017-09-25 10:04:59 -04:00
|
|
|
run_lcov_merge($info_files, "lcov-c-all.info")
|
|
|
|
run_lcov_remove("lcov-c-all.info", "lcov-c-all-filtered.info")
|
|
|
|
run_genhtml("lcov-c-all-filtered.info", "lcov-c-out")
|
2017-09-09 09:09:21 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
if File.readable?("test-coverage.dat")
|
|
|
|
gen_rb_lcov("test-coverage.dat")
|
2017-09-25 10:04:59 -04:00
|
|
|
run_lcov_remove("lcov-rb-all.info", "lcov-rb-all-filtered.info")
|
|
|
|
run_genhtml("lcov-rb-all-filtered.info", "lcov-rb-out")
|
2017-09-09 09:09:21 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
if File.readable?("lcov-c-all.info") && File.readable?("lcov-rb-all.info")
|
2017-09-25 10:04:59 -04:00
|
|
|
run_lcov_merge(%w(lcov-c-all.info lcov-rb-all.info), "lcov-all.info")
|
|
|
|
run_lcov_remove("lcov-all.info", "lcov-all-filtered.info")
|
|
|
|
run_genhtml("lcov-all-filtered.info", "lcov-out")
|
2017-09-09 09:09:21 -04:00
|
|
|
end
|