rcov 0.5.0.1-mswin32
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.
- data/BLURB +117 -0
- data/CHANGES +75 -0
- data/LEGAL +36 -0
- data/LICENSE +56 -0
- data/README.API +42 -0
- data/README.en +128 -0
- data/README.rake +62 -0
- data/README.rant +68 -0
- data/Rakefile +161 -0
- data/Rantfile +75 -0
- data/THANKS +29 -0
- data/bin/rcov +1839 -0
- data/ext/rcovrt/extconf.rb +3 -0
- data/ext/rcovrt/rcov.c +404 -0
- data/lib/rcov.rb +909 -0
- data/lib/rcov/lowlevel.rb +139 -0
- data/lib/rcov/rant.rb +85 -0
- data/lib/rcov/rcovtask.rb +156 -0
- data/lib/rcov/version.rb +13 -0
- data/lib/rcovrt.so +0 -0
- data/mingw-rbconfig.rb +174 -0
- data/setup.rb +1585 -0
- data/test/sample_01.rb +7 -0
- data/test/sample_02.rb +5 -0
- data/test/sample_03.rb +20 -0
- data/test/test_CallSiteAnalyzer.rb +172 -0
- data/test/test_CodeCoverageAnalyzer.rb +183 -0
- data/test/test_FileStatistics.rb +403 -0
- data/test/turn_off_rcovrt.rb +4 -0
- metadata +79 -0
data/test/sample_01.rb
ADDED
data/test/sample_02.rb
ADDED
data/test/sample_03.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
module Rcov; module Test; module Temporary; class Sample03
|
3
|
+
def f1 # MUST NOT CHANGE the position or the tests will break
|
4
|
+
10.times { f2 }
|
5
|
+
end
|
6
|
+
|
7
|
+
def f2; 1 end
|
8
|
+
|
9
|
+
def f3
|
10
|
+
10.times{ f1 }
|
11
|
+
100.times{ f2 }
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.g1
|
15
|
+
10.times{ g2 }
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.g2; 1 end
|
19
|
+
# safe from here ...
|
20
|
+
end end end end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'rcov'
|
5
|
+
|
6
|
+
class Test_CallSiteAnalyzer < Test::Unit::TestCase
|
7
|
+
|
8
|
+
sample_file = File.join(File.dirname(__FILE__), "sample_03.rb")
|
9
|
+
load sample_file
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@a = Rcov::CallSiteAnalyzer.new
|
13
|
+
@o = Rcov::Test::Temporary::Sample03.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def verify_callsites_equal(expected, actual)
|
17
|
+
callsites = expected.inject({}) do |s,(desc, count)|
|
18
|
+
s[Rcov::CallSiteAnalyzer::CallSite.new(desc)] = count
|
19
|
+
s
|
20
|
+
end
|
21
|
+
assert_equal(callsites, actual)
|
22
|
+
end
|
23
|
+
|
24
|
+
def verify_defsite_equal(expected, actual)
|
25
|
+
assert_equal(Rcov::CallSiteAnalyzer::DefSite.new(*expected), actual)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_callsite_compute_raw_difference
|
29
|
+
src = [
|
30
|
+
{ ["Foo", "foo"] => {"bar" => 1},
|
31
|
+
["Foo", "bar"] => {"baz" => 10} },
|
32
|
+
{ ["Foo", "foo"] => ["foo.rb", 10] }
|
33
|
+
]
|
34
|
+
dst = [
|
35
|
+
{ ["Foo", "foo"] => {"bar" => 1, "fubar" => 10},
|
36
|
+
["Foo", "baz"] => {"baz" => 10} },
|
37
|
+
{ ["Foo", "foo"] => ["fooredef.rb", 10],
|
38
|
+
["Foo", "baz"] => ["foo.rb", 20]}
|
39
|
+
]
|
40
|
+
expected = [
|
41
|
+
{ ["Foo", "foo"] => {"fubar" => 10},
|
42
|
+
["Foo", "baz"] => {"baz" => 10} },
|
43
|
+
{ ["Foo", "foo"] => ["fooredef.rb", 10],
|
44
|
+
["Foo", "baz"] => ["foo.rb", 20] }
|
45
|
+
]
|
46
|
+
|
47
|
+
assert_equal(expected,
|
48
|
+
@a.instance_eval{ compute_raw_data_difference(src, dst) } )
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_return_values_when_no_match
|
52
|
+
@a.run_hooked{ @o.f1 }
|
53
|
+
assert_equal(nil, @a.defsite("Foobar#bogus"))
|
54
|
+
assert_equal(nil, @a.defsite("Foobar", "bogus"))
|
55
|
+
assert_equal(nil, @a.callsites("Foobar", "bogus"))
|
56
|
+
assert_equal(nil, @a.callsites("Foobar.bogus"))
|
57
|
+
assert_equal(nil, @a.callsites("<Class:Foobar>", "bogus"))
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_basic_defsite_recording
|
61
|
+
@a.run_hooked{ @o.f1 }
|
62
|
+
verify_defsite_equal(["./test/sample_03.rb", 3],
|
63
|
+
@a.defsite("Rcov::Test::Temporary::Sample03", "f1"))
|
64
|
+
verify_defsite_equal(["./test/sample_03.rb", 7],
|
65
|
+
@a.defsite("Rcov::Test::Temporary::Sample03", "f2"))
|
66
|
+
verify_defsite_equal(["./test/sample_03.rb", 7],
|
67
|
+
@a.defsite("Rcov::Test::Temporary::Sample03#f2"))
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_basic_callsite_recording
|
71
|
+
@a.run_hooked{ @o.f1 }
|
72
|
+
assert(@a.analyzed_classes.include?("Rcov::Test::Temporary::Sample03"))
|
73
|
+
assert_equal(%w[f1 f2], @a.analyzed_methods("Rcov::Test::Temporary::Sample03"))
|
74
|
+
verify_callsites_equal({["./test/sample_03.rb:4:in `f1'"] => 10},
|
75
|
+
@a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
|
76
|
+
verify_callsites_equal({["./test/sample_03.rb:4:in `f1'"] => 10},
|
77
|
+
@a.callsites("Rcov::Test::Temporary::Sample03#f2"))
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_basic_callsite_recording_API
|
81
|
+
@a.run_hooked{ @o.f1 }
|
82
|
+
assert(@a.analyzed_classes.include?("Rcov::Test::Temporary::Sample03"))
|
83
|
+
assert_equal(%w[f1 f2], @a.analyzed_methods("Rcov::Test::Temporary::Sample03"))
|
84
|
+
verify_callsites_equal({["./test/sample_03.rb:4:in `f1'"] => 10},
|
85
|
+
@a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
|
86
|
+
callsites = @a.callsites("Rcov::Test::Temporary::Sample03", "f2")
|
87
|
+
callsite = callsites.keys[0]
|
88
|
+
assert_equal("./test/sample_03.rb", callsite.file)
|
89
|
+
assert_equal(4, callsite.line)
|
90
|
+
assert_equal("f1", callsite.calling_method)
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_basic_callsite_recording_with_singleton_classes
|
94
|
+
@a.run_hooked{ @o.class.g1 }
|
95
|
+
assert(@a.analyzed_classes.include?("#<Class:Rcov::Test::Temporary::Sample03>"))
|
96
|
+
assert_equal(%w[g1 g2], @a.analyzed_methods("#<Class:Rcov::Test::Temporary::Sample03>"))
|
97
|
+
verify_callsites_equal({["./test/sample_03.rb:15:in `g1'"] => 10},
|
98
|
+
@a.callsites("Rcov::Test::Temporary::Sample03.g2"))
|
99
|
+
verify_callsites_equal({["./test/sample_03.rb:15:in `g1'"] => 10},
|
100
|
+
@a.callsites("#<Class:Rcov::Test::Temporary::Sample03>","g2"))
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
def test_differential_callsite_recording
|
105
|
+
@a.run_hooked{ @o.f1 }
|
106
|
+
assert(@a.analyzed_classes.include?("Rcov::Test::Temporary::Sample03"))
|
107
|
+
assert_equal(%w[f1 f2], @a.analyzed_methods("Rcov::Test::Temporary::Sample03"))
|
108
|
+
verify_callsites_equal({["./test/sample_03.rb:4:in `f1'"] => 10},
|
109
|
+
@a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
|
110
|
+
|
111
|
+
@a.run_hooked{ @o.f1 }
|
112
|
+
assert(@a.analyzed_classes.include?("Rcov::Test::Temporary::Sample03"))
|
113
|
+
assert_equal(%w[f1 f2], @a.analyzed_methods("Rcov::Test::Temporary::Sample03"))
|
114
|
+
verify_callsites_equal({["./test/sample_03.rb:4:in `f1'"] => 20},
|
115
|
+
@a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
|
116
|
+
|
117
|
+
@a.run_hooked{ @o.f3 }
|
118
|
+
assert_equal(%w[f1 f2 f3], @a.analyzed_methods("Rcov::Test::Temporary::Sample03"))
|
119
|
+
verify_callsites_equal({["./test/sample_03.rb:4:in `f1'"] => 120,
|
120
|
+
["./test/sample_03.rb:11:in `f3'"]=>100 },
|
121
|
+
@a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_reset
|
125
|
+
@a.run_hooked do
|
126
|
+
10.times{ @o.f1 }
|
127
|
+
@a.reset
|
128
|
+
@o.f1
|
129
|
+
end
|
130
|
+
assert(@a.analyzed_classes.include?("Rcov::Test::Temporary::Sample03"))
|
131
|
+
assert_equal(%w[f1 f2], @a.analyzed_methods("Rcov::Test::Temporary::Sample03"))
|
132
|
+
verify_callsites_equal({["./test/sample_03.rb:4:in `f1'"] => 10},
|
133
|
+
@a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_nested_callsite_recording
|
138
|
+
a = Rcov::CallSiteAnalyzer.new
|
139
|
+
b = Rcov::CallSiteAnalyzer.new
|
140
|
+
a.run_hooked do
|
141
|
+
b.run_hooked { @o.f1 }
|
142
|
+
assert(b.analyzed_classes.include?("Rcov::Test::Temporary::Sample03"))
|
143
|
+
assert_equal(%w[f1 f2], b.analyzed_methods("Rcov::Test::Temporary::Sample03"))
|
144
|
+
verify_callsites_equal({["./test/sample_03.rb:4:in `f1'"] => 10},
|
145
|
+
b.callsites("Rcov::Test::Temporary::Sample03", "f2"))
|
146
|
+
|
147
|
+
@o.f1
|
148
|
+
assert_equal(%w[f1 f2], b.analyzed_methods("Rcov::Test::Temporary::Sample03"))
|
149
|
+
verify_callsites_equal({["./test/sample_03.rb:4:in `f1'"] => 10},
|
150
|
+
b.callsites("Rcov::Test::Temporary::Sample03", "f2"))
|
151
|
+
|
152
|
+
assert(a.analyzed_classes.include?("Rcov::Test::Temporary::Sample03"))
|
153
|
+
assert_equal(%w[f1 f2], a.analyzed_methods("Rcov::Test::Temporary::Sample03"))
|
154
|
+
verify_callsites_equal({["./test/sample_03.rb:4:in `f1'"] => 20},
|
155
|
+
a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
|
156
|
+
end
|
157
|
+
b.run_hooked{ @o.f3 }
|
158
|
+
assert_equal(%w[f1 f2 f3], b.analyzed_methods("Rcov::Test::Temporary::Sample03"))
|
159
|
+
verify_callsites_equal({["./test/sample_03.rb:4:in `f1'"] => 110,
|
160
|
+
["./test/sample_03.rb:11:in `f3'"]=>100 },
|
161
|
+
b.callsites("Rcov::Test::Temporary::Sample03", "f2"))
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_expand_name
|
165
|
+
assert_equal(["Foo", "foo"], @a.instance_eval{ expand_name("Foo#foo") })
|
166
|
+
assert_equal(["Foo", "foo"], @a.instance_eval{ expand_name("Foo", "foo") })
|
167
|
+
assert_equal(["#<Class:Foo>", "foo"],
|
168
|
+
@a.instance_eval{ expand_name("Foo.foo") })
|
169
|
+
assert_equal(["#<Class:Foo>", "foo"],
|
170
|
+
@a.instance_eval{ expand_name("#<Class:Foo>", "foo") })
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
|
2
|
+
require 'test/unit'
|
3
|
+
require 'rcov'
|
4
|
+
|
5
|
+
class Test_CodeCoverageAnalyzer < Test::Unit::TestCase
|
6
|
+
LINES = <<-EOF.to_a
|
7
|
+
puts 1
|
8
|
+
if foo
|
9
|
+
bar
|
10
|
+
baz
|
11
|
+
end
|
12
|
+
5.times do
|
13
|
+
foo
|
14
|
+
bar if baz
|
15
|
+
end
|
16
|
+
EOF
|
17
|
+
|
18
|
+
def setup
|
19
|
+
if defined? Rcov::Test::Temporary
|
20
|
+
Rcov::Test::Temporary.constants.each do |name|
|
21
|
+
Rcov::Test::Temporary.module_eval{ remove_const(name) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_refine_coverage_info
|
27
|
+
analyzer = Rcov::CodeCoverageAnalyzer.new
|
28
|
+
cover = [1, 1, nil, nil, 0, 5, 5, 5, 0]
|
29
|
+
line_info, marked_info,
|
30
|
+
count_info = analyzer.instance_eval{ refine_coverage_info(LINES, cover) }
|
31
|
+
assert_equal(LINES.map{|l| l.chomp}, line_info)
|
32
|
+
assert_equal([true] * 2 + [false] * 3 + [true] * 3 + [false], marked_info)
|
33
|
+
assert_equal([1, 1, 0, 0, 0, 5, 5, 5, 0], count_info)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_analyzed_files_no_analysis
|
37
|
+
analyzer = Rcov::CodeCoverageAnalyzer.new
|
38
|
+
assert_equal([], analyzer.analyzed_files)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_raw_coverage_info
|
42
|
+
sample_file = File.join(File.dirname(__FILE__), "sample_01.rb")
|
43
|
+
lines = File.readlines(sample_file)
|
44
|
+
analyzer = Rcov::CodeCoverageAnalyzer.new
|
45
|
+
analyzer.run_hooked{ load sample_file }
|
46
|
+
|
47
|
+
assert_equal(lines, SCRIPT_LINES__[sample_file][0, lines.size])
|
48
|
+
assert(analyzer.analyzed_files.include?(sample_file))
|
49
|
+
line_info, cov_info, count_info = analyzer.data(sample_file)
|
50
|
+
assert_equal(lines.map{|l| l.chomp}, line_info)
|
51
|
+
assert_equal([true, true, false, false, true, false, true], cov_info)
|
52
|
+
assert_equal([1, 2, 0, 0, 1, 0, 11], count_info)
|
53
|
+
analyzer.reset
|
54
|
+
assert_equal(nil, analyzer.data(sample_file))
|
55
|
+
assert_equal([], analyzer.analyzed_files)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_script_lines_workaround_detects_correctly
|
59
|
+
analyzer = Rcov::CodeCoverageAnalyzer.new
|
60
|
+
lines = ["puts a", "foo", "bar"] * 3
|
61
|
+
coverage = [true] * 3 + [false] * 6
|
62
|
+
counts = [1] * 3 + [0] * 6
|
63
|
+
nlines, ncoverage, ncounts = analyzer.instance_eval do
|
64
|
+
script_lines_workaround(lines, coverage, counts)
|
65
|
+
end
|
66
|
+
|
67
|
+
assert_equal(["puts a", "foo", "bar"], nlines)
|
68
|
+
assert_equal([true, true, true], ncoverage)
|
69
|
+
assert_equal([1, 1, 1], ncounts)
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_script_lines_workaround_no_false_positives
|
73
|
+
analyzer = Rcov::CodeCoverageAnalyzer.new
|
74
|
+
lines = ["puts a", "foo", "bar"] * 2 + ["puts a", "foo", "baz"]
|
75
|
+
coverage = [true] * 9
|
76
|
+
counts = [1] * 9
|
77
|
+
nlines, ncoverage, ncounts = analyzer.instance_eval do
|
78
|
+
script_lines_workaround(lines, coverage, counts)
|
79
|
+
end
|
80
|
+
assert_equal(lines, nlines)
|
81
|
+
assert_equal(coverage, ncoverage)
|
82
|
+
assert_equal(counts, ncounts)
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_differential_coverage_data
|
86
|
+
sample_file = File.join(File.dirname(__FILE__), "sample_01.rb")
|
87
|
+
lines = File.readlines(sample_file)
|
88
|
+
analyzer = Rcov::CodeCoverageAnalyzer.new
|
89
|
+
analyzer.run_hooked{ load sample_file }
|
90
|
+
line_info, cov_info, count_info = analyzer.data(sample_file)
|
91
|
+
assert_equal([1, 2, 0, 0, 1, 0, 11], count_info)
|
92
|
+
|
93
|
+
analyzer.reset
|
94
|
+
|
95
|
+
sample_file = File.join(File.dirname(__FILE__), "sample_02.rb")
|
96
|
+
analyzer.run_hooked{ load sample_file }
|
97
|
+
line_info, cov_info, count_info = analyzer.data(sample_file)
|
98
|
+
assert_equal([8, 1, 0, 0, 0], count_info)
|
99
|
+
|
100
|
+
analyzer.reset
|
101
|
+
assert_equal([], analyzer.analyzed_files)
|
102
|
+
analyzer.run_hooked{ Rcov::Test::Temporary::Sample02.foo(1, 1) }
|
103
|
+
line_info, cov_info, count_info = analyzer.data(sample_file)
|
104
|
+
assert_equal([0, 1, 1, 1, 0], count_info)
|
105
|
+
analyzer.run_hooked do
|
106
|
+
10.times{ Rcov::Test::Temporary::Sample02.foo(1, 1) }
|
107
|
+
end
|
108
|
+
line_info, cov_info, count_info = analyzer.data(sample_file)
|
109
|
+
assert_equal([0, 11, 11, 11, 0], count_info)
|
110
|
+
10.times{ analyzer.run_hooked{ Rcov::Test::Temporary::Sample02.foo(1, 1) } }
|
111
|
+
line_info, cov_info, count_info = analyzer.data(sample_file)
|
112
|
+
assert_equal([0, 21, 21, 21, 0], count_info)
|
113
|
+
|
114
|
+
count_info2 = nil
|
115
|
+
10.times do |i|
|
116
|
+
analyzer.run_hooked do
|
117
|
+
Rcov::Test::Temporary::Sample02.foo(1, 1)
|
118
|
+
line_info, cov_info, count_info = analyzer.data(sample_file) if i == 3
|
119
|
+
line_info2, cov_info2, count_info2 = analyzer.data(sample_file)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
assert_equal([0, 25, 25, 25, 0], count_info)
|
123
|
+
assert_equal([0, 31, 31, 31, 0], count_info2)
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_nested_analyzer_blocks
|
127
|
+
a1 = Rcov::CodeCoverageAnalyzer.new
|
128
|
+
a2 = Rcov::CodeCoverageAnalyzer.new
|
129
|
+
|
130
|
+
sample_file = File.join(File.dirname(__FILE__), "sample_02.rb")
|
131
|
+
load sample_file
|
132
|
+
|
133
|
+
a1.run_hooked do
|
134
|
+
100.times{ Rcov::Test::Temporary::Sample02.foo(1, 1) }
|
135
|
+
a2.run_hooked do
|
136
|
+
10.times{ Rcov::Test::Temporary::Sample02.foo(1, 1) }
|
137
|
+
end
|
138
|
+
100.times{ Rcov::Test::Temporary::Sample02.foo(1, 1) }
|
139
|
+
end
|
140
|
+
|
141
|
+
a2.run_hooked do
|
142
|
+
100.times{ Rcov::Test::Temporary::Sample02.foo(1, 1) }
|
143
|
+
10.times{ a1.run_hooked { Rcov::Test::Temporary::Sample02.foo(1, 1) } }
|
144
|
+
end
|
145
|
+
|
146
|
+
a1.install_hook
|
147
|
+
Rcov::Test::Temporary::Sample02.foo(1, 1)
|
148
|
+
a1.remove_hook
|
149
|
+
|
150
|
+
a2.install_hook
|
151
|
+
Rcov::Test::Temporary::Sample02.foo(1, 1)
|
152
|
+
a2.remove_hook
|
153
|
+
|
154
|
+
_, _, counts1 = a1.data(sample_file)
|
155
|
+
_, _, counts2 = a2.data(sample_file)
|
156
|
+
assert_equal([0, 221, 221, 221, 0], counts1)
|
157
|
+
assert_equal([0, 121, 121, 121, 0], counts2)
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_reset
|
161
|
+
a1 = Rcov::CodeCoverageAnalyzer.new
|
162
|
+
|
163
|
+
sample_file = File.join(File.dirname(__FILE__), "sample_02.rb")
|
164
|
+
load sample_file
|
165
|
+
|
166
|
+
a1.run_hooked do
|
167
|
+
100.times do |i|
|
168
|
+
Rcov::Test::Temporary::Sample02.foo(1, 1)
|
169
|
+
a1.reset if i == 49
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
assert_equal([0, 50, 50, 50, 0], a1.data(sample_file)[2])
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_compute_raw_difference
|
177
|
+
first = {"a" => [1,1,1,1,1]}
|
178
|
+
last = {"a" => [2,1,5,2,1], "b" => [1,2,3,4,5]}
|
179
|
+
a = Rcov::CodeCoverageAnalyzer.new
|
180
|
+
assert_equal({"a" => [1,0,4,1,0], "b" => [1,2,3,4,5]},
|
181
|
+
a.instance_eval{ compute_raw_data_difference(first, last)} )
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,403 @@
|
|
1
|
+
|
2
|
+
require 'test/unit'
|
3
|
+
require 'rcov'
|
4
|
+
|
5
|
+
class Test_FileStatistics < Test::Unit::TestCase
|
6
|
+
def test_trailing_end_is_inferred
|
7
|
+
verify_everything_marked "trailing end", <<-EOF
|
8
|
+
1 class X
|
9
|
+
1 def foo
|
10
|
+
2 "foo"
|
11
|
+
0 end
|
12
|
+
0 end
|
13
|
+
EOF
|
14
|
+
verify_everything_marked "trailing end with comments", <<-EOF
|
15
|
+
1 class X
|
16
|
+
1 def foo
|
17
|
+
2 "foo"
|
18
|
+
0 end
|
19
|
+
0 # foo bar
|
20
|
+
0 =begin
|
21
|
+
0 ....
|
22
|
+
0 =end
|
23
|
+
0 end
|
24
|
+
EOF
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_begin_ensure_else_case_are_inferred
|
28
|
+
verify_everything_marked "begin ensure else case", <<-EOF
|
29
|
+
0 begin
|
30
|
+
# bleh
|
31
|
+
2 puts a
|
32
|
+
0 begin
|
33
|
+
2 raise "foo"
|
34
|
+
0 rescue Exception => e
|
35
|
+
2 puts b
|
36
|
+
0 ensure
|
37
|
+
2 puts c
|
38
|
+
0 end
|
39
|
+
2 if a()
|
40
|
+
1 b
|
41
|
+
0 else
|
42
|
+
1 c
|
43
|
+
0 end
|
44
|
+
0 case
|
45
|
+
2 when bar =~ /foo/
|
46
|
+
1 puts "bar"
|
47
|
+
0 else
|
48
|
+
1 puts "baz"
|
49
|
+
0 end
|
50
|
+
0 end
|
51
|
+
EOF
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_rescue_is_inferred
|
55
|
+
verify_everything_marked "rescue", <<-EOF
|
56
|
+
0 begin
|
57
|
+
1 foo
|
58
|
+
0 rescue
|
59
|
+
1 puts "bar"
|
60
|
+
0 end
|
61
|
+
EOF
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_code_metrics_are_computed_correctly
|
65
|
+
lines, coverage, counts = code_info_from_string <<-EOF
|
66
|
+
1 a = 1
|
67
|
+
0 # this is a comment
|
68
|
+
1 if bar
|
69
|
+
0 b = 2
|
70
|
+
0 end
|
71
|
+
0 =begin
|
72
|
+
0 this too
|
73
|
+
0 bleh
|
74
|
+
0 =end
|
75
|
+
0 puts <<EOF
|
76
|
+
0 bleh
|
77
|
+
0 EOF
|
78
|
+
3 c.times{ i += 1}
|
79
|
+
EOF
|
80
|
+
sf = Rcov::FileStatistics.new("metrics", lines, counts)
|
81
|
+
assert_in_delta(0.307, sf.total_coverage, 0.01)
|
82
|
+
assert_in_delta(0.375, sf.code_coverage, 0.01)
|
83
|
+
assert_equal(8, sf.num_code_lines)
|
84
|
+
assert_equal(13, sf.num_lines)
|
85
|
+
assert_equal([true, :inferred, true, false, false, false, false, false,
|
86
|
+
false, false, false, false, true], sf.coverage.to_a)
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_merge
|
90
|
+
lines, coverage, counts = code_info_from_string <<-EOF
|
91
|
+
1 a = 1
|
92
|
+
1 if bar
|
93
|
+
0 b = 2
|
94
|
+
0 end
|
95
|
+
0 puts <<EOF
|
96
|
+
0 bleh
|
97
|
+
0 EOF
|
98
|
+
3 c.times{ i += 1}
|
99
|
+
EOF
|
100
|
+
sf = Rcov::FileStatistics.new("merge", lines, counts)
|
101
|
+
lines, coverage, counts = code_info_from_string <<-EOF
|
102
|
+
1 a = 1
|
103
|
+
1 if bar
|
104
|
+
1 b = 2
|
105
|
+
0 end
|
106
|
+
1 puts <<EOF
|
107
|
+
0 bleh
|
108
|
+
0 EOF
|
109
|
+
10 c.times{ i += 1}
|
110
|
+
EOF
|
111
|
+
sf2 = Rcov::FileStatistics.new("merge", lines, counts)
|
112
|
+
expected = [true, true, true, :inferred, true, :inferred, :inferred, true]
|
113
|
+
assert_equal(expected, sf2.coverage.to_a)
|
114
|
+
sf.merge(sf2.lines, sf2.coverage, sf2.counts)
|
115
|
+
assert_equal(expected, sf.coverage.to_a)
|
116
|
+
assert_equal([2, 2, 1, 0, 1, 0, 0, 13], sf.counts)
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_heredocs_basic
|
120
|
+
verify_everything_marked "heredocs-basic.rb", <<-EOF
|
121
|
+
1 puts 1 + 1
|
122
|
+
1 puts <<HEREDOC
|
123
|
+
0 first line of the heredoc
|
124
|
+
0 not marked
|
125
|
+
0 but should be
|
126
|
+
0 HEREDOC
|
127
|
+
1 puts 1
|
128
|
+
EOF
|
129
|
+
verify_everything_marked "squote", <<-EOF
|
130
|
+
1 puts <<'HEREDOC'
|
131
|
+
0 first line of the heredoc
|
132
|
+
0 HEREDOC
|
133
|
+
EOF
|
134
|
+
verify_everything_marked "dquote", <<-EOF
|
135
|
+
1 puts <<"HEREDOC"
|
136
|
+
0 first line of the heredoc
|
137
|
+
0 HEREDOC
|
138
|
+
EOF
|
139
|
+
verify_everything_marked "xquote", <<-EOF
|
140
|
+
1 puts <<`HEREDOC`
|
141
|
+
0 first line of the heredoc
|
142
|
+
0 HEREDOC
|
143
|
+
EOF
|
144
|
+
verify_everything_marked "stuff-after-heredoc", <<-EOF
|
145
|
+
1 full_message = build_message(msg, <<EOT, object1, object2)
|
146
|
+
0 <?> and <?> do not contain the same elements
|
147
|
+
0 EOT
|
148
|
+
EOF
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_heredocs_multiple
|
152
|
+
verify_everything_marked "multiple-unquoted", <<-EOF
|
153
|
+
1 puts <<HEREDOC, <<HERE2
|
154
|
+
0 first line of the heredoc
|
155
|
+
0 HEREDOC
|
156
|
+
0 second heredoc
|
157
|
+
0 HERE2
|
158
|
+
EOF
|
159
|
+
verify_everything_marked "multiple-quoted", <<-EOF
|
160
|
+
1 puts <<'HEREDOC', <<`HERE2`, <<"HERE3"
|
161
|
+
0 first line of the heredoc
|
162
|
+
0 HEREDOC
|
163
|
+
0 second heredoc
|
164
|
+
0 HERE2
|
165
|
+
0 dsfdsfffd
|
166
|
+
0 HERE3
|
167
|
+
EOF
|
168
|
+
verify_everything_marked "same-identifier", <<-EOF
|
169
|
+
1 puts <<H, <<H
|
170
|
+
0 foo
|
171
|
+
0 H
|
172
|
+
0 bar
|
173
|
+
0 H
|
174
|
+
EOF
|
175
|
+
verify_everything_marked "stuff-after-heredoc", <<-EOF
|
176
|
+
1 full_message = build_message(msg, <<EOT, object1, object2, <<EOT)
|
177
|
+
0 <?> and <?> do not contain the same elements
|
178
|
+
0 EOT
|
179
|
+
0 <?> and <?> are foo bar baz
|
180
|
+
0 EOT
|
181
|
+
EOF
|
182
|
+
end
|
183
|
+
def test_ignore_non_heredocs
|
184
|
+
verify_marked_exactly "bitshift-numeric", [0], <<-EOF
|
185
|
+
1 puts 1<<2
|
186
|
+
0 return if foo
|
187
|
+
0 do_stuff()
|
188
|
+
0 2
|
189
|
+
EOF
|
190
|
+
verify_marked_exactly "bitshift-symbolic", [0], <<-EOF
|
191
|
+
1 puts 1<<LSHIFT
|
192
|
+
0 return if bar
|
193
|
+
0 do_stuff()
|
194
|
+
0 LSHIFT
|
195
|
+
EOF
|
196
|
+
verify_marked_exactly "bitshift-symbolic-multi", 0..3, <<-EOF
|
197
|
+
1 puts <<EOF, 1<<LSHIFT
|
198
|
+
0 random text
|
199
|
+
0 EOF
|
200
|
+
1 return if bar
|
201
|
+
0 puts "foo"
|
202
|
+
0 LSHIFT
|
203
|
+
EOF
|
204
|
+
verify_marked_exactly "bitshift-symshift-evil", 0..2, <<-EOF
|
205
|
+
1 foo = 1
|
206
|
+
1 puts foo<<CONS
|
207
|
+
1 return if bar
|
208
|
+
0 foo + baz
|
209
|
+
EOF
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_handle_multiline_expressions
|
213
|
+
verify_everything_marked "expression", <<-EOF
|
214
|
+
1 puts 1, 2.
|
215
|
+
0 abs +
|
216
|
+
0 1 -
|
217
|
+
0 1 *
|
218
|
+
0 1 /
|
219
|
+
0 1, 1 <
|
220
|
+
0 2, 3 >
|
221
|
+
0 4 %
|
222
|
+
0 3 &&
|
223
|
+
0 true ||
|
224
|
+
0 foo <<
|
225
|
+
0 bar(
|
226
|
+
0 baz[
|
227
|
+
0 {
|
228
|
+
0 1,2}] =
|
229
|
+
0 1 )
|
230
|
+
EOF
|
231
|
+
verify_everything_marked "boolean expression", <<-EOF
|
232
|
+
1 x = (foo and
|
233
|
+
0 bar) or
|
234
|
+
0 baz
|
235
|
+
EOF
|
236
|
+
verify_marked_exactly "code blocks", [0, 3, 6], <<-EOF
|
237
|
+
1 x = foo do # stuff
|
238
|
+
0 baz
|
239
|
+
0 end
|
240
|
+
1 bar do |x|
|
241
|
+
0 baz
|
242
|
+
0 end
|
243
|
+
1 bar {|a, b| # bleh | +1
|
244
|
+
0 baz
|
245
|
+
0 }
|
246
|
+
EOF
|
247
|
+
verify_everything_marked "escaped linebreaks", <<-EOF
|
248
|
+
1 def t2
|
249
|
+
0 puts \\
|
250
|
+
1 "foo"
|
251
|
+
0 end
|
252
|
+
0 end
|
253
|
+
EOF
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_handle_multiline_expression_1st_line_ends_in_block_header
|
257
|
+
# excerpt taken from mongrel/handlers.rb
|
258
|
+
verify_everything_marked "multiline with block starting on 1st", <<-EOF
|
259
|
+
1 uris = listener.classifier.handler_map
|
260
|
+
0 results << table("handlers", uris.map {|uri,handlers|
|
261
|
+
1 [uri,
|
262
|
+
0 "<pre>" +
|
263
|
+
1 handlers.map {|h| h.class.to_s }.join("\n") +
|
264
|
+
0 "</pre>"
|
265
|
+
0 ]
|
266
|
+
1 })
|
267
|
+
EOF
|
268
|
+
end
|
269
|
+
|
270
|
+
def test_handle_multiple_block_end_delimiters_in_empty_line
|
271
|
+
verify_everything_marked "multiline with }) delimiter, forward", <<-EOF
|
272
|
+
1 assert(@c.config == {
|
273
|
+
0 'host' => 'myhost.tld',
|
274
|
+
0 'port' => 1234
|
275
|
+
0 })
|
276
|
+
EOF
|
277
|
+
verify_everything_marked "multiline with }) delimiter, backwards", <<-EOF
|
278
|
+
0 assert(@c.config == {
|
279
|
+
0 'host' => 'myhost.tld',
|
280
|
+
0 'port' => 1234
|
281
|
+
1 })
|
282
|
+
EOF
|
283
|
+
end
|
284
|
+
|
285
|
+
STRING_DELIMITER_PAIRS = [
|
286
|
+
%w-%{ }-, %w-%q{ }-, %w-%Q{ }-, %w{%[ ]}, %w{%q[ ]},
|
287
|
+
%w{%( )}, %w{%Q( )}, %w{%Q[ ]}, %w{%q! !}, %w{%! !},
|
288
|
+
]
|
289
|
+
|
290
|
+
def test_multiline_strings_basic
|
291
|
+
STRING_DELIMITER_PAIRS.each do |s_delim, e_delim|
|
292
|
+
verify_everything_marked "multiline strings, basic #{s_delim}", <<-EOF
|
293
|
+
1 PATTERN_TEXT = #{s_delim}
|
294
|
+
0 NUMBERS = 'one|two|three|four|five'
|
295
|
+
0 ON_OFF = 'on|off'
|
296
|
+
0 #{e_delim}
|
297
|
+
EOF
|
298
|
+
end
|
299
|
+
STRING_DELIMITER_PAIRS.each do |s_delim, e_delim|
|
300
|
+
verify_marked_exactly "multiline strings, escaped #{s_delim}", [0], <<-EOF
|
301
|
+
1 PATTERN_TEXT = #{s_delim} foooo bar baz \\#{e_delim} baz #{e_delim}
|
302
|
+
0 NUMBERS = 'one|two|three|four|five'
|
303
|
+
0 ON_OFF = 'on|off'
|
304
|
+
EOF
|
305
|
+
|
306
|
+
verify_marked_exactly "multiline strings, #{s_delim}, interpolation",
|
307
|
+
[0], <<-EOF
|
308
|
+
1 PATTERN_TEXT = #{s_delim} \#{#{s_delim} foo #{e_delim}} \\#{e_delim} baz #{e_delim}
|
309
|
+
0 NUMBERS = 'one|two|three|four|five'
|
310
|
+
0 ON_OFF = 'on|off'
|
311
|
+
EOF
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def test_multiline_strings_escaped_delimiter
|
316
|
+
STRING_DELIMITER_PAIRS.each do |s_delim, e_delim|
|
317
|
+
verify_everything_marked "multiline, escaped #{s_delim}", <<-EOF
|
318
|
+
1 PATTERN_TEXT = #{s_delim} foo \\#{e_delim}
|
319
|
+
0 NUMBERS = 'one|two|three|four|five'
|
320
|
+
0 ON_OFF = 'on|off'
|
321
|
+
0 #{e_delim}
|
322
|
+
EOF
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
def test_handle_multiline_expressions_with_heredocs
|
327
|
+
verify_everything_marked "multiline and heredocs", <<-EOF
|
328
|
+
1 puts <<EOF +
|
329
|
+
0 testing
|
330
|
+
0 one two three
|
331
|
+
0 EOF
|
332
|
+
0 somevar
|
333
|
+
EOF
|
334
|
+
end
|
335
|
+
|
336
|
+
def test_begin_end_comment_blocks
|
337
|
+
verify_everything_marked "=begin/=end", <<-EOF
|
338
|
+
1 x = foo
|
339
|
+
0 =begin
|
340
|
+
0 return if bar(x)
|
341
|
+
0 =end
|
342
|
+
1 y = 1
|
343
|
+
EOF
|
344
|
+
end
|
345
|
+
|
346
|
+
def test_is_code_p
|
347
|
+
verify_is_code "basic", [true] + [false] * 5 + [true], <<-EOF
|
348
|
+
1 x = foo
|
349
|
+
0 =begin
|
350
|
+
0 return if bar
|
351
|
+
0 =end
|
352
|
+
0 # foo
|
353
|
+
0 # bar
|
354
|
+
1 y = 1
|
355
|
+
EOF
|
356
|
+
end
|
357
|
+
|
358
|
+
def test_is_code_p_tricky_heredocs
|
359
|
+
verify_is_code "tricky heredocs", [true] * 4, <<-EOF
|
360
|
+
2 x = foo <<EOF and return
|
361
|
+
0 =begin
|
362
|
+
0 EOF
|
363
|
+
0 z = x + 1
|
364
|
+
EOF
|
365
|
+
end
|
366
|
+
|
367
|
+
def verify_is_code(testname, is_code_arr, str)
|
368
|
+
lines, coverage, counts = code_info_from_string str
|
369
|
+
|
370
|
+
sf = Rcov::FileStatistics.new(testname, lines, counts)
|
371
|
+
is_code_arr.each_with_index do |val,i|
|
372
|
+
assert_equal(val, sf.is_code?(i),
|
373
|
+
"Unable to detect =begin comments properly: #{lines[i].inspect}")
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
def verify_marked_exactly(testname, marked_indices, str)
|
378
|
+
lines, coverage, counts = code_info_from_string(str)
|
379
|
+
|
380
|
+
sf = Rcov::FileStatistics.new(testname, lines, counts)
|
381
|
+
lines.size.times do |i|
|
382
|
+
if marked_indices.include? i
|
383
|
+
assert(sf.coverage[i], "Test #{testname}; " +
|
384
|
+
"line should have been marked: #{lines[i].inspect}.")
|
385
|
+
else
|
386
|
+
assert(!sf.coverage[i], "Test #{testname}; " +
|
387
|
+
"line should not have been marked: #{lines[i].inspect}.")
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
def verify_everything_marked(testname, str)
|
393
|
+
verify_marked_exactly(testname, (0...str.size).to_a, str)
|
394
|
+
end
|
395
|
+
|
396
|
+
|
397
|
+
def code_info_from_string(str)
|
398
|
+
str = str.gsub(/^\s*/,"")
|
399
|
+
[ str.map{|line| line.sub(/^\d+ /, "") },
|
400
|
+
str.map{|line| line[/^\d+/].to_i > 0},
|
401
|
+
str.map{|line| line[/^\d+/].to_i } ]
|
402
|
+
end
|
403
|
+
end
|