Skip to content

Commit 7100f1c

Browse files
committed
[GR-18163] Adjust Coverage.start to accept arguments
PullRequest: truffleruby/3955
2 parents 00307c2 + 27ce948 commit 7100f1c

File tree

6 files changed

+377
-31
lines changed

6 files changed

+377
-31
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Compatibility:
2929
* Set `RbConfig::CONFIG['configure_args']` for openssl and libyaml (#3170, #3303, @eregon).
3030
* Support `Socket.sockaddr_in(port, Socket::INADDR_ANY)` (#3361, @mtortonesi).
3131
* Implement the `Data` class from Ruby 3.2 (#3039, @moste00, @eregon).
32+
* Make `Coverage.start` and `Coverage.result` accept parameters (#3149, @mtortonesi, @andrykonchin).
3233

3334
Performance:
3435

lib/truffle/coverage.rb

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,61 @@
1010
# GNU Lesser General Public License version 2.1.
1111

1212
module Coverage
13+
def self.supported?(mode)
14+
mode == :lines
15+
end
16+
17+
def self.start(modes = Truffle::UNDEFINED)
18+
if Truffle::Coverage.enabled?
19+
raise 'coverage measurement is already setup'
20+
end
21+
22+
if modes == :all || Primitive.undefined?(modes)
23+
options = {}
24+
else
25+
options = Truffle::Type.rb_convert_type(modes, Hash, :to_hash)
26+
end
1327

14-
def self.start
28+
if options[:lines] && options[:oneshot_lines]
29+
raise 'cannot enable lines and oneshot_lines simultaneously'
30+
end
31+
32+
@default_mode = Primitive.undefined?(modes)
1533
Truffle::Coverage.enable
34+
35+
nil
1636
end
1737

18-
def self.result
38+
def self.result(**options)
39+
if options.empty?
40+
stop = true
41+
clear = true
42+
else
43+
stop = options[:stop]
44+
clear = options[:clear]
45+
end
46+
47+
if stop && !clear
48+
warn 'stop implies clear', uplevel: 1
49+
end
50+
1951
result = peek_result
20-
Truffle::Coverage.disable
52+
53+
# TODO: There should be a difference between :stop and :clear in a way they affect counters.
54+
# :stop means to remove all the counters at all, :clear - to set 0 values only.
55+
# Now we remove counters in both cases.
56+
Truffle::Coverage.disable if stop || clear
57+
Truffle::Coverage.enable if !stop && clear
58+
59+
# By default provides only lines coverage measurement.
60+
# If some mode was specified explicitly then return counters per mode separately (e.g. for :lines, :branches, etc).
61+
# Support only :lines for now.
62+
if !@default_mode
63+
result.transform_values! do |lines|
64+
{ lines: lines }
65+
end
66+
end
67+
2168
result
2269
end
2370

spec/ruby/library/coverage/result_spec.rb

Lines changed: 241 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,16 @@
88
@eval_code_file = fixture __FILE__, 'eval_code.rb'
99
end
1010

11+
before :each do
12+
Coverage.running?.should == false
13+
end
14+
1115
after :each do
1216
$LOADED_FEATURES.delete(@class_file)
1317
$LOADED_FEATURES.delete(@config_file)
1418
$LOADED_FEATURES.delete(@eval_code_file)
19+
20+
Coverage.result if Coverage.running?
1521
end
1622

1723
it 'gives the covered files as a hash with arrays of count or nil' do
@@ -26,6 +32,41 @@
2632
}
2733
end
2834

35+
ruby_version_is "3.2" do
36+
it 'returns results for each mode separately when enabled :all modes' do
37+
Coverage.start(:all)
38+
require @class_file.chomp('.rb')
39+
result = Coverage.result
40+
41+
result.should == {
42+
@class_file => {
43+
lines: [
44+
nil, nil, 1, nil, nil, 1, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil
45+
],
46+
branches: {},
47+
methods: {
48+
[SomeClass, :some_method, 6, 2, 11, 5] => 0
49+
}
50+
}
51+
}
52+
end
53+
54+
it 'returns results for each mode separately when enabled any mode explicitly' do
55+
Coverage.start(lines: true)
56+
require @class_file.chomp('.rb')
57+
result = Coverage.result
58+
59+
result.should == {
60+
@class_file =>
61+
{
62+
lines: [
63+
nil, nil, 1, nil, nil, 1, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil
64+
]
65+
}
66+
}
67+
end
68+
end
69+
2970
it 'no requires/loads should give empty hash' do
3071
Coverage.start
3172
result = Coverage.result
@@ -75,17 +116,6 @@
75116
end
76117
end
77118

78-
ruby_version_is '3.1' do
79-
it 'second Coverage.start give exception' do
80-
Coverage.start
81-
-> {
82-
require @config_file.chomp('.rb')
83-
}.should raise_error(RuntimeError, 'coverage measurement is already setup')
84-
ensure
85-
Coverage.result
86-
end
87-
end
88-
89119
it 'does not include the file starting coverage since it is not tracked' do
90120
require @config_file.chomp('.rb')
91121
Coverage.result.should_not include(@config_file)
@@ -98,18 +128,14 @@
98128
result = Coverage.result
99129

100130
result.should == {
101-
@eval_code_file => [
102-
1, nil, 1, nil, 1, nil, nil, nil, nil, nil, 1
103-
]
131+
@eval_code_file => [
132+
1, nil, 1, nil, 1, nil, nil, nil, nil, nil, 1
133+
]
104134
}
105135
end
106136
end
107137

108138
ruby_version_is '3.2' do
109-
it 'indicates support for different features' do
110-
Coverage.supported?(:lines).should == true
111-
end
112-
113139
it 'returns the correct results when eval coverage is enabled' do
114140
Coverage.supported?(:eval).should == true
115141

@@ -118,24 +144,214 @@
118144
result = Coverage.result
119145

120146
result.should == {
121-
@eval_code_file => {
122-
lines: [1, nil, 1, nil, 1, 1, nil, nil, nil, nil, 1]
123-
}
147+
@eval_code_file => {
148+
lines: [1, nil, 1, nil, 1, 1, nil, nil, nil, nil, 1]
149+
}
124150
}
125151
end
126152

127-
it 'returns the correct results when eval coverage is enabled' do
153+
it 'returns the correct results when eval coverage is disabled' do
128154
Coverage.supported?(:eval).should == true
129155

130156
Coverage.start(lines: true, eval: false)
131157
require @eval_code_file.chomp('.rb')
132158
result = Coverage.result
133159

134160
result.should == {
135-
@eval_code_file => {
136-
lines: [1, nil, 1, nil, 1, nil, nil, nil, nil, nil, 1]
137-
}
161+
@eval_code_file => {
162+
lines: [1, nil, 1, nil, 1, nil, nil, nil, nil, nil, 1]
163+
}
138164
}
139165
end
140166
end
167+
168+
it "disables coverage measurement when stop option is not specified" do
169+
Coverage.start
170+
require @class_file.chomp('.rb')
171+
172+
Coverage.result
173+
Coverage.running?.should == false
174+
end
175+
176+
it "disables coverage measurement when stop: true option is specified" do
177+
Coverage.start
178+
require @class_file.chomp('.rb')
179+
180+
-> {
181+
Coverage.result(stop: true)
182+
}.should complain /warning: stop implies clear/
183+
184+
Coverage.running?.should == false
185+
end
186+
187+
it "does not disable coverage measurement when stop: false option is specified" do
188+
Coverage.start
189+
require @class_file.chomp('.rb')
190+
191+
Coverage.result(stop: false)
192+
Coverage.running?.should == true
193+
end
194+
195+
it "does not disable coverage measurement when stop option is not specified but clear: true specified" do
196+
Coverage.start
197+
require @class_file.chomp('.rb')
198+
199+
Coverage.result(clear: true)
200+
Coverage.running?.should == true
201+
end
202+
203+
it "does not disable coverage measurement when stop option is not specified but clear: false specified" do
204+
Coverage.start
205+
require @class_file.chomp('.rb')
206+
207+
Coverage.result(clear: false)
208+
Coverage.running?.should == true
209+
end
210+
211+
it "disables coverage measurement when stop: true and clear: true specified" do
212+
Coverage.start
213+
require @class_file.chomp('.rb')
214+
215+
Coverage.result(stop: true, clear: true)
216+
Coverage.running?.should == false
217+
end
218+
219+
it "disables coverage measurement when stop: true and clear: false specified" do
220+
Coverage.start
221+
require @class_file.chomp('.rb')
222+
223+
-> {
224+
Coverage.result(stop: true, clear: false)
225+
}.should complain /warning: stop implies clear/
226+
227+
Coverage.running?.should == false
228+
end
229+
230+
it "does not disable coverage measurement when stop: false and clear: true specified" do
231+
Coverage.start
232+
require @class_file.chomp('.rb')
233+
234+
Coverage.result(stop: false, clear: true)
235+
Coverage.running?.should == true
236+
end
237+
238+
it "does not disable coverage measurement when stop: false and clear: false specified" do
239+
Coverage.start
240+
require @class_file.chomp('.rb')
241+
242+
Coverage.result(stop: false, clear: false)
243+
Coverage.running?.should == true
244+
end
245+
246+
it "resets counters (remove them) when stop: true specified but clear option is not specified" do
247+
Coverage.start
248+
require @class_file.chomp('.rb')
249+
250+
-> {
251+
Coverage.result(stop: true) # clears counters
252+
}.should complain /warning: stop implies clear/
253+
254+
Coverage.start
255+
Coverage.peek_result.should == {}
256+
end
257+
258+
it "resets counters (remove them) when stop: true and clear: true specified" do
259+
Coverage.start
260+
require @class_file.chomp('.rb')
261+
262+
Coverage.result(stop: true, clear: true) # clears counters
263+
264+
Coverage.start
265+
Coverage.peek_result.should == {}
266+
end
267+
268+
it "resets counters (remove them) when stop: true and clear: false specified" do
269+
Coverage.start
270+
require @class_file.chomp('.rb')
271+
272+
-> {
273+
Coverage.result(stop: true, clear: false) # clears counters
274+
}.should complain /warning: stop implies clear/
275+
276+
Coverage.start
277+
Coverage.peek_result.should == {}
278+
end
279+
280+
it "resets counters (remove them) when both stop and clear options are not specified" do
281+
Coverage.start
282+
require @class_file.chomp('.rb')
283+
284+
Coverage.result # clears counters
285+
286+
Coverage.start
287+
Coverage.peek_result.should == {}
288+
end
289+
290+
it "clears counters (sets 0 values) when stop is not specified but clear: true specified" do
291+
Coverage.start
292+
require @class_file.chomp('.rb')
293+
294+
Coverage.result(clear: true) # clears counters
295+
296+
Coverage.peek_result.should == {
297+
@class_file => [
298+
nil, nil, 0, nil, nil, 0, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil
299+
]
300+
}
301+
end
302+
303+
it "does not clear counters when stop is not specified but clear: false specified" do
304+
Coverage.start
305+
require @class_file.chomp('.rb')
306+
307+
result = Coverage.result(clear: false) # doesn't clear counters
308+
result.should == {
309+
@class_file => [
310+
nil, nil, 1, nil, nil, 1, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil
311+
]
312+
}
313+
314+
Coverage.peek_result.should == result
315+
end
316+
317+
it "does not clear counters when stop: false and clear is not specified" do
318+
Coverage.start
319+
require @class_file.chomp('.rb')
320+
321+
result = Coverage.result(stop: false) # doesn't clear counters
322+
result.should == {
323+
@class_file => [
324+
nil, nil, 1, nil, nil, 1, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil
325+
]
326+
}
327+
328+
Coverage.peek_result.should == result
329+
end
330+
331+
it "clears counters (sets 0 values) when stop: false and clear: true specified" do
332+
Coverage.start
333+
require @class_file.chomp('.rb')
334+
335+
Coverage.result(stop: false, clear: true) # clears counters
336+
337+
Coverage.peek_result.should == {
338+
@class_file => [
339+
nil, nil, 0, nil, nil, 0, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil
340+
]
341+
}
342+
end
343+
344+
it "does not clear counters when stop: false and clear: false specified" do
345+
Coverage.start
346+
require @class_file.chomp('.rb')
347+
348+
result = Coverage.result(stop: false, clear: false) # doesn't clear counters
349+
result.should == {
350+
@class_file => [
351+
nil, nil, 1, nil, nil, 1, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil
352+
]
353+
}
354+
355+
Coverage.peek_result.should == result
356+
end
141357
end

0 commit comments

Comments
 (0)