relevance-rcov 0.8.2.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.
@@ -0,0 +1,471 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class TestFileStatistics < Test::Unit::TestCase
4
+ def test_trailing_end_is_inferred
5
+ verify_everything_marked "trailing end", <<-EOF
6
+ 1 class X
7
+ 1 def foo
8
+ 2 "foo"
9
+ 0 end
10
+ 0 end
11
+ EOF
12
+ verify_everything_marked "trailing end with comments", <<-EOF
13
+ 1 class X
14
+ 1 def foo
15
+ 2 "foo"
16
+ 0 end
17
+ 0 # foo bar
18
+ 0 =begin
19
+ 0 ....
20
+ 0 =end
21
+ 0 end
22
+ EOF
23
+ end
24
+
25
+ def test_begin_ensure_else_case_are_inferred
26
+ verify_everything_marked "begin ensure else case", <<-EOF
27
+ 0 begin
28
+ # bleh
29
+ 2 puts a
30
+ 0 begin
31
+ 2 raise "foo"
32
+ 0 rescue Exception => e
33
+ 2 puts b
34
+ 0 ensure
35
+ 2 puts c
36
+ 0 end
37
+ 2 if a()
38
+ 1 b
39
+ 0 else
40
+ 1 c
41
+ 0 end
42
+ 0 case
43
+ 2 when bar =~ /foo/
44
+ 1 puts "bar"
45
+ 0 else
46
+ 1 puts "baz"
47
+ 0 end
48
+ 0 end
49
+ EOF
50
+ end
51
+
52
+ def test_rescue_is_inferred
53
+ verify_everything_marked "rescue", <<-EOF
54
+ 0 begin
55
+ 1 foo
56
+ 0 rescue
57
+ 1 puts "bar"
58
+ 0 end
59
+ EOF
60
+ end
61
+
62
+ def test_code_metrics_are_computed_correctly
63
+ lines, coverage, counts = code_info_from_string <<-EOF
64
+ 1 a = 1
65
+ 0 # this is a comment
66
+ 1 if bar
67
+ 0 b = 2
68
+ 0 end
69
+ 0 =begin
70
+ 0 this too
71
+ 0 bleh
72
+ 0 =end
73
+ 0 puts <<EOF
74
+ 0 bleh
75
+ 0 EOF
76
+ 3 c.times{ i += 1}
77
+ EOF
78
+ sf = Rcov::FileStatistics.new("metrics", lines, counts)
79
+ assert_in_delta(0.307, sf.total_coverage, 0.01)
80
+ assert_in_delta(0.375, sf.code_coverage, 0.01)
81
+ assert_equal(8, sf.num_code_lines)
82
+ assert_equal(13, sf.num_lines)
83
+ assert_equal([true, :inferred, true, false, false, false, false, false,
84
+ false, false, false, false, true], sf.coverage.to_a)
85
+ end
86
+
87
+ def test_merge
88
+ lines, coverage, counts = code_info_from_string <<-EOF
89
+ 1 a = 1
90
+ 1 if bar
91
+ 0 b = 2
92
+ 0 end
93
+ 1 puts <<EOF
94
+ 0 bleh
95
+ 0 EOF
96
+ 3 c.times{ i += 1}
97
+ EOF
98
+ sf = Rcov::FileStatistics.new("merge", lines, counts)
99
+ lines, coverage, counts = code_info_from_string <<-EOF
100
+ 1 a = 1
101
+ 1 if bar
102
+ 1 b = 2
103
+ 0 end
104
+ 1 puts <<EOF
105
+ 0 bleh
106
+ 0 EOF
107
+ 10 c.times{ i += 1}
108
+ EOF
109
+ sf2 = Rcov::FileStatistics.new("merge", lines, counts)
110
+ expected = [true, true, true, :inferred, true, :inferred, :inferred, true]
111
+ assert_equal(expected, sf2.coverage.to_a)
112
+ sf.merge(sf2.lines, sf2.coverage, sf2.counts)
113
+ assert_equal(expected, sf.coverage.to_a)
114
+ assert_equal([2, 2, 1, 0, 2, 0, 0, 13], sf.counts)
115
+ end
116
+
117
+ def test_last_comment_block_is_marked
118
+ verify_everything_marked "last comment block", <<-EOF
119
+ 1 a = 1
120
+ 1 b = 1
121
+ 0 # foo
122
+ 0 # bar baz
123
+ EOF
124
+ verify_everything_marked "last comment block, =begin/=end", <<-EOF
125
+ 1 a = 1
126
+ 2 b = 1
127
+ 0 # fooo
128
+ 0 =begin
129
+ 0 bar baz
130
+ 0 =end
131
+ EOF
132
+ verify_everything_marked "last comment block, __END__", <<-EOF
133
+ 1 a = 1
134
+ 2 b = 1
135
+ 0 # fooo
136
+ 0 =begin
137
+ 0 bar baz
138
+ 0 =end
139
+ __END__
140
+ EOF
141
+ end
142
+
143
+ def test_heredocs_basic
144
+ verify_everything_marked "heredocs-basic.rb", <<-EOF
145
+ 1 puts 1 + 1
146
+ 1 puts <<HEREDOC
147
+ 0 first line of the heredoc
148
+ 0 not marked
149
+ 0 but should be
150
+ 0 HEREDOC
151
+ 1 puts 1
152
+ EOF
153
+ verify_everything_marked "squote", <<-EOF
154
+ 1 puts <<'HEREDOC'
155
+ 0 first line of the heredoc
156
+ 0 HEREDOC
157
+ EOF
158
+ verify_everything_marked "dquote", <<-EOF
159
+ 1 puts <<"HEREDOC"
160
+ 0 first line of the heredoc
161
+ 0 HEREDOC
162
+ EOF
163
+ verify_everything_marked "xquote", <<-EOF
164
+ 1 puts <<`HEREDOC`
165
+ 0 first line of the heredoc
166
+ 0 HEREDOC
167
+ EOF
168
+ verify_everything_marked "stuff-after-heredoc", <<-EOF
169
+ 1 full_message = build_message(msg, <<EOT, object1, object2)
170
+ 0 <?> and <?> do not contain the same elements
171
+ 0 EOT
172
+ EOF
173
+ end
174
+
175
+ def test_heredocs_multiple
176
+ verify_everything_marked "multiple-unquoted", <<-EOF
177
+ 1 puts <<HEREDOC, <<HERE2
178
+ 0 first line of the heredoc
179
+ 0 HEREDOC
180
+ 0 second heredoc
181
+ 0 HERE2
182
+ EOF
183
+ verify_everything_marked "multiple-quoted", <<-EOF
184
+ 1 puts <<'HEREDOC', <<`HERE2`, <<"HERE3"
185
+ 0 first line of the heredoc
186
+ 0 HEREDOC
187
+ 0 second heredoc
188
+ 0 HERE2
189
+ 0 dsfdsfffd
190
+ 0 HERE3
191
+ EOF
192
+ verify_everything_marked "same-identifier", <<-EOF
193
+ 1 puts <<H, <<H
194
+ 0 foo
195
+ 0 H
196
+ 0 bar
197
+ 0 H
198
+ EOF
199
+ verify_everything_marked "stuff-after-heredoc", <<-EOF
200
+ 1 full_message = build_message(msg, <<EOT, object1, object2, <<EOT)
201
+ 0 <?> and <?> do not contain the same elements
202
+ 0 EOT
203
+ 0 <?> and <?> are foo bar baz
204
+ 0 EOT
205
+ EOF
206
+ end
207
+ def test_ignore_non_heredocs
208
+ verify_marked_exactly "bitshift-numeric", [0], <<-EOF
209
+ 1 puts 1<<2
210
+ 0 return if foo
211
+ 0 do_stuff()
212
+ 0 2
213
+ EOF
214
+ verify_marked_exactly "bitshift-symbolic", [0], <<-EOF
215
+ 1 puts 1<<LSHIFT
216
+ 0 return if bar
217
+ 0 do_stuff()
218
+ 0 LSHIFT
219
+ EOF
220
+ verify_marked_exactly "bitshift-symbolic-multi", 0..3, <<-EOF
221
+ 1 puts <<EOF, 1<<LSHIFT
222
+ 0 random text
223
+ 0 EOF
224
+ 1 return if bar
225
+ 0 puts "foo"
226
+ 0 LSHIFT
227
+ EOF
228
+ verify_marked_exactly "bitshift-symshift-evil", 0..2, <<-EOF
229
+ 1 foo = 1
230
+ 1 puts foo<<CONS
231
+ 1 return if bar
232
+ 0 foo + baz
233
+ EOF
234
+ end
235
+
236
+ def test_heredocs_with_interpolation_alone_in_method
237
+ verify_everything_marked "lonely heredocs with interpolation", <<-'EOS'
238
+ 1 def to_s
239
+ 0 <<-EOF
240
+ 1 #{name}
241
+ 0 #{street}
242
+ 0 #{city}, #{state}
243
+ 0 #{zip}
244
+ 0 EOF
245
+ 0 end
246
+ EOS
247
+ end
248
+
249
+ def test_handle_multiline_expressions
250
+ verify_everything_marked "expression", <<-EOF
251
+ 1 puts 1, 2.
252
+ 0 abs +
253
+ 0 1 -
254
+ 0 1 *
255
+ 0 1 /
256
+ 0 1, 1 <
257
+ 0 2, 3 >
258
+ 0 4 %
259
+ 0 3 &&
260
+ 0 true ||
261
+ 0 foo <<
262
+ 0 bar(
263
+ 0 baz[
264
+ 0 {
265
+ 0 1,2}] =
266
+ 0 1 )
267
+ EOF
268
+ verify_everything_marked "boolean expression", <<-EOF
269
+ 1 x = (foo and
270
+ 0 bar) or
271
+ 0 baz
272
+ EOF
273
+ verify_marked_exactly "code blocks", [0, 3, 6], <<-EOF
274
+ 1 x = foo do # stuff
275
+ 0 baz
276
+ 0 end
277
+ 1 bar do |x|
278
+ 0 baz
279
+ 0 end
280
+ 1 bar {|a, b| # bleh | +1
281
+ 0 baz
282
+ 0 }
283
+ EOF
284
+ verify_everything_marked "escaped linebreaks", <<-EOF
285
+ 1 def t2
286
+ 0 puts \\
287
+ 1 "foo"
288
+ 0 end
289
+ 0 end
290
+ EOF
291
+ end
292
+
293
+ def test_handle_multiline_blocks_first_not_marked
294
+ verify_everything_marked "multiline block first not marked", <<-'EOF'
295
+ 1 blah = Array.new
296
+ 1 10.times do
297
+ 0 blah << lambda do |f|
298
+ 1 puts "I should say #{f}!"
299
+ 0 end
300
+ 0 end
301
+ EOF
302
+ end
303
+
304
+ def test_handle_multiline_blocks_last_line_not_marked
305
+ verify_everything_marked "multiline block last not marked", <<-'EOF'
306
+ 1 blee = [1, 2, 3]
307
+ 0 blee.map! do |e|
308
+ 1 [e, e]
309
+ 0 end.flatten!
310
+ 1 p blee
311
+ EOF
312
+ end
313
+
314
+ def test_handle_multiline_data_with_trailing_stuff_on_last_line
315
+ verify_everything_marked "multiline data hash", <<-'EOF'
316
+ 1 @review = Review.new({
317
+ 0 :product_id => params[:id],
318
+ 0 :user => current_user
319
+ 0 }.merge(params[:review])) #red
320
+ 1 @review.save
321
+ EOF
322
+ end
323
+
324
+ def test_handle_multiline_expression_1st_line_ends_in_block_header
325
+ # excerpt taken from mongrel/handlers.rb
326
+ verify_everything_marked "multiline with block starting on 1st", <<-EOF
327
+ 1 uris = listener.classifier.handler_map
328
+ 0 results << table("handlers", uris.map {|uri,handlers|
329
+ 1 [uri,
330
+ 0 "<pre>" +
331
+ 1 handlers.map {|h| h.class.to_s }.join("\n") +
332
+ 0 "</pre>"
333
+ 0 ]
334
+ 1 })
335
+ EOF
336
+ end
337
+
338
+ def test_handle_multiple_block_end_delimiters_in_empty_line
339
+ verify_everything_marked "multiline with }) delimiter, forward", <<-EOF
340
+ 1 assert(@c.config == {
341
+ 0 'host' => 'myhost.tld',
342
+ 0 'port' => 1234
343
+ 0 })
344
+ EOF
345
+ verify_everything_marked "multiline with }) delimiter, backwards", <<-EOF
346
+ 0 assert(@c.config == {
347
+ 0 'host' => 'myhost.tld',
348
+ 0 'port' => 1234
349
+ 1 })
350
+ EOF
351
+ end
352
+
353
+ STRING_DELIMITER_PAIRS = [
354
+ %w-%{ }-, %w-%q{ }-, %w-%Q{ }-, %w{%[ ]}, %w{%q[ ]},
355
+ %w{%( )}, %w{%Q( )}, %w{%Q[ ]}, %w{%q! !}, %w{%! !},
356
+ ]
357
+
358
+ def test_multiline_strings_basic
359
+ STRING_DELIMITER_PAIRS.each do |s_delim, e_delim|
360
+ verify_everything_marked "multiline strings, basic #{s_delim}", <<-EOF
361
+ 1 PATTERN_TEXT = #{s_delim}
362
+ 0 NUMBERS = 'one|two|three|four|five'
363
+ 0 ON_OFF = 'on|off'
364
+ 0 #{e_delim}
365
+ EOF
366
+ end
367
+ STRING_DELIMITER_PAIRS.each do |s_delim, e_delim|
368
+ verify_marked_exactly "multiline strings, escaped #{s_delim}", [0], <<-EOF
369
+ 1 PATTERN_TEXT = #{s_delim} foooo bar baz \\#{e_delim} baz #{e_delim}
370
+ 0 NUMBERS = 'one|two|three|four|five'
371
+ 0 ON_OFF = 'on|off'
372
+ EOF
373
+
374
+ verify_marked_exactly "multiline strings, #{s_delim}, interpolation",
375
+ [0], <<-EOF
376
+ 1 PATTERN_TEXT = #{s_delim} \#{#{s_delim} foo #{e_delim}} \\#{e_delim} baz #{e_delim}
377
+ 0 NUMBERS = 'one|two|three|four|five'
378
+ 0 ON_OFF = 'on|off'
379
+ EOF
380
+ end
381
+ end
382
+
383
+ def test_multiline_strings_escaped_delimiter
384
+ STRING_DELIMITER_PAIRS.each do |s_delim, e_delim|
385
+ verify_everything_marked "multiline, escaped #{s_delim}", <<-EOF
386
+ 1 PATTERN_TEXT = #{s_delim} foo \\#{e_delim}
387
+ 0 NUMBERS = 'one|two|three|four|five'
388
+ 0 ON_OFF = 'on|off'
389
+ 0 #{e_delim}
390
+ EOF
391
+ end
392
+ end
393
+
394
+ def test_handle_multiline_expressions_with_heredocs
395
+ verify_everything_marked "multiline and heredocs", <<-EOF
396
+ 1 puts <<EOF +
397
+ 0 testing
398
+ 0 one two three
399
+ 0 EOF
400
+ 0 somevar
401
+ EOF
402
+ end
403
+
404
+ def test_begin_end_comment_blocks
405
+ verify_everything_marked "=begin/=end", <<-EOF
406
+ 1 x = foo
407
+ 0 =begin
408
+ 0 return if bar(x)
409
+ 0 =end
410
+ 1 y = 1
411
+ EOF
412
+ end
413
+
414
+ def test_is_code_p
415
+ verify_is_code "basic", [true] + [false] * 5 + [true], <<-EOF
416
+ 1 x = foo
417
+ 0 =begin
418
+ 0 return if bar
419
+ 0 =end
420
+ 0 # foo
421
+ 0 # bar
422
+ 1 y = 1
423
+ EOF
424
+ end
425
+
426
+ def test_is_code_p_tricky_heredocs
427
+ verify_is_code "tricky heredocs", [true] * 4, <<-EOF
428
+ 2 x = foo <<EOF and return
429
+ 0 =begin
430
+ 0 EOF
431
+ 0 z = x + 1
432
+ EOF
433
+ end
434
+
435
+ def verify_is_code(testname, is_code_arr, str)
436
+ lines, coverage, counts = code_info_from_string str
437
+
438
+ sf = Rcov::FileStatistics.new(testname, lines, counts)
439
+ is_code_arr.each_with_index do |val,i|
440
+ assert_equal(val, sf.is_code?(i),
441
+ "Unable to detect =begin comments properly: #{lines[i].inspect}")
442
+ end
443
+ end
444
+
445
+ def verify_marked_exactly(testname, marked_indices, str)
446
+ lines, coverage, counts = code_info_from_string(str)
447
+
448
+ sf = Rcov::FileStatistics.new(testname, lines, counts)
449
+ lines.size.times do |i|
450
+ if marked_indices.include? i
451
+ assert(sf.coverage[i], "Test #{testname}; " +
452
+ "line should have been marked: #{lines[i].inspect}.")
453
+ else
454
+ assert(!sf.coverage[i], "Test #{testname}; " +
455
+ "line should not have been marked: #{lines[i].inspect}.")
456
+ end
457
+ end
458
+ end
459
+
460
+ def verify_everything_marked(testname, str)
461
+ verify_marked_exactly(testname, (0...str.size).to_a, str)
462
+ end
463
+
464
+
465
+ def code_info_from_string(str)
466
+ str = str.gsub(/^\s*/,"")
467
+ [ str.map{|line| line.sub(/^\d+ /, "") },
468
+ str.map{|line| line[/^\d+/].to_i > 0},
469
+ str.map{|line| line[/^\d+/].to_i } ]
470
+ end
471
+ end