1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
require "coverage"
Coverage.start(lines: true, branches: true, methods: true)
TEST_COVERAGE_DATA_FILE = "test-coverage.dat"
FILTER_PATHS = %w[
lib/bundler/vendor
lib/rubygems/resolver/molinillo
lib/rubygems/tsort
lib/rubygems/optparse
tool
test
spec
]
def merge_coverage_data(res1, res2)
res1.each do |path, cov1|
cov2 = res2[path]
if cov2
cov1[:lines].each_with_index do |count1, i|
next unless count1
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
else
cov2[:branches][base_key] = targets1
end
end
cov1[:methods].each do |key, count1|
add_count(cov2[:methods], key, count1)
end
else
res2[path] = cov1
end
end
res2
end
def add_count(h, key, count)
if h[key]
h[key] += count
else
h[key] = count
end
end
def save_coverage_data(res1)
res1.each do |_path, cov|
if cov[:methods]
h = {}
cov[:methods].each do |(klass, *key), count|
h[[klass.name, *key]] = count
end
cov[:methods].replace h
end
end
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
# XXX docile-x.y.z and simplecov-x.y.z, simplecov-html-x.y.z, simplecov_json_formatter-x.y.z
%w[simplecov simplecov-html simplecov_json_formatter docile].each do |f|
Dir.glob("#{__dir__}/../.bundle/gems/#{f}-*/lib").each do |d|
$LOAD_PATH.unshift d
end
end
require "simplecov"
res = Marshal.load(File.binread(TEST_COVERAGE_DATA_FILE))
simplecov_result = {}
base_dir = File.dirname(__dir__)
cur_dir = Dir.pwd
res.each do |path, cov|
next unless path.start_with?(base_dir) || path.start_with?(cur_dir)
next if FILTER_PATHS.any? {|dir| path.start_with?(File.join(base_dir, dir))}
simplecov_result[path] = cov
end
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
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
|