gcov2x 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/Gemfile.lock +9 -1
- data/bin/gcov2x +2 -5
- data/lib/file.rb +18 -2
- data/lib/html_formatter.rb +15 -7
- data/lib/html_view.html.erb +27 -7
- data/lib/line.rb +0 -3
- data/lib/project.rb +60 -28
- data/lib/version.rb +1 -1
- data/spec/file_spec.rb +9 -1
- data/spec/project_spec.rb +39 -0
- data/spec/spec_helper.rb +3 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a051bec21f907b37d3ff469c65e53854dbd711b5
|
4
|
+
data.tar.gz: 651d542e2a2afc95ebf79c9ad6c9e88ce88d8c94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71db31ffc9c095e681ce72d9784851ecdf14793f53cc6a292fdde681cae9fccc4f1f3609f6d5365b9b25659bdb87c9c2ed8d5920af8f66249f5844f80e801305
|
7
|
+
data.tar.gz: b7aa7ba5fc36665e383c13102da3ae9fd5bd3646b09f84fcb0057b4242e254de88b54bc2b8ca32fe8948b5d1b7f198a6bf67882c29f305a5c0d4fb79e8eaf7f6
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -3,10 +3,12 @@ GEM
|
|
3
3
|
specs:
|
4
4
|
builder (3.2.2)
|
5
5
|
diff-lcs (1.2.5)
|
6
|
+
docile (1.1.5)
|
6
7
|
gyoku (1.2.2)
|
7
8
|
builder (>= 2.1.2)
|
8
9
|
mixlib-cli (1.5.0)
|
9
|
-
|
10
|
+
multi_json (1.10.1)
|
11
|
+
rake (10.4.2)
|
10
12
|
rspec (3.1.0)
|
11
13
|
rspec-core (~> 3.1.0)
|
12
14
|
rspec-expectations (~> 3.1.0)
|
@@ -20,6 +22,11 @@ GEM
|
|
20
22
|
rspec-support (~> 3.1.0)
|
21
23
|
rspec-support (3.1.2)
|
22
24
|
rubygems-tasks (0.2.4)
|
25
|
+
simplecov (0.9.1)
|
26
|
+
docile (~> 1.1.0)
|
27
|
+
multi_json (~> 1.0)
|
28
|
+
simplecov-html (~> 0.8.0)
|
29
|
+
simplecov-html (0.8.0)
|
23
30
|
term-ansicolor (1.3.0)
|
24
31
|
tins (~> 1.0)
|
25
32
|
terminal-table (1.4.5)
|
@@ -34,5 +41,6 @@ DEPENDENCIES
|
|
34
41
|
rake
|
35
42
|
rspec
|
36
43
|
rubygems-tasks
|
44
|
+
simplecov
|
37
45
|
term-ansicolor
|
38
46
|
terminal-table
|
data/bin/gcov2x
CHANGED
@@ -63,18 +63,15 @@ filenames = cli.parse_options
|
|
63
63
|
|
64
64
|
fail "Got no filename" unless filenames.is_a? Array and filenames.count > 0
|
65
65
|
|
66
|
-
STDERR.puts "filter: #{cli.config[:filter]}"
|
67
|
-
|
68
66
|
proj = GCOV::Project.new
|
69
67
|
|
70
68
|
filter = case cli.config[:filter]
|
71
|
-
when :xcode then /Developer\/Toolchains\/.*\/usr\/include\//
|
69
|
+
when :xcode then /Developer\/(Toolchains|Platforms)\/.*\/usr\/include\//
|
72
70
|
when :linux then /\/usr\/include\//
|
71
|
+
when nil then nil
|
73
72
|
else /#{cli.config[:filter]}/
|
74
73
|
end
|
75
74
|
|
76
|
-
STDERR.puts "filter regex: #{filter}"
|
77
|
-
|
78
75
|
filenames.each do |filename|
|
79
76
|
if File.directory? filename
|
80
77
|
proj.add_dir filename, :recursive => cli.config[:recursive], :filter => filter
|
data/lib/file.rb
CHANGED
@@ -24,6 +24,7 @@ module GCOV
|
|
24
24
|
@lines = []
|
25
25
|
@meta = {}
|
26
26
|
@stats = {}
|
27
|
+
_update_stats
|
27
28
|
end
|
28
29
|
|
29
30
|
def add_lines &block
|
@@ -42,7 +43,8 @@ module GCOV
|
|
42
43
|
:total_exec => 0,
|
43
44
|
:total_lines => 0,
|
44
45
|
:lines => 0,
|
45
|
-
:coverage => 0.0
|
46
|
+
:coverage => 0.0,
|
47
|
+
:hits_per_line => 0.0
|
46
48
|
}
|
47
49
|
|
48
50
|
@lines.each do |line|
|
@@ -56,6 +58,8 @@ module GCOV
|
|
56
58
|
@stats[:total_lines] = @stats[:lines] + @stats[:empty_lines]
|
57
59
|
@stats[:coverage] = @stats[:exec_lines].to_f / @stats[:lines].to_f
|
58
60
|
@stats[:coverage_s] = sprintf("%0.01f%",100.0*@stats[:coverage])
|
61
|
+
@stats[:hits_per_line] = @stats[:total_exec].to_f / @stats[:lines]
|
62
|
+
@stats[:hits_per_line_s] = sprintf("%0.02f",@stats[:hits_per_line])
|
59
63
|
end
|
60
64
|
|
61
65
|
def <<(line)
|
@@ -79,6 +83,18 @@ module GCOV
|
|
79
83
|
end
|
80
84
|
file
|
81
85
|
end
|
82
|
-
|
86
|
+
|
87
|
+
def self.demangle filename
|
88
|
+
result = filename
|
89
|
+
if start = result.index(/###/)
|
90
|
+
result = result[start..-1]
|
91
|
+
end
|
92
|
+
|
93
|
+
result.gsub!( /(###|#|\^|\.gcov$)/, {"###"=>"/","#"=>"/","^"=>"..",".gcov"=>""} )
|
94
|
+
result = ::File.realpath(result)
|
95
|
+
result
|
96
|
+
end
|
97
|
+
|
98
|
+
end # class File
|
83
99
|
|
84
100
|
end
|
data/lib/html_formatter.rb
CHANGED
@@ -39,15 +39,23 @@ EOF
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
def class_of_stat value,
|
43
|
-
|
44
|
-
|
42
|
+
def class_of_stat value, error_level, warning_level=nil
|
43
|
+
if value <= error_level
|
44
|
+
return "value_error"
|
45
|
+
elsif !warning_level.nil? and value < warning_level
|
46
|
+
return "value_warning"
|
47
|
+
else
|
48
|
+
return "value_ok"
|
49
|
+
end
|
45
50
|
end
|
46
51
|
|
47
|
-
def class_of_file file
|
48
|
-
|
49
|
-
|
50
|
-
|
52
|
+
def class_of_file file, error_level, warning_level=nil
|
53
|
+
if file.stats[:coverage] <= error_level
|
54
|
+
return "header error"
|
55
|
+
elsif !warning_level.nil? and file.stats[:coverage] < warning_level
|
56
|
+
return "header warning"
|
57
|
+
else
|
58
|
+
return "header ok"
|
51
59
|
end
|
52
60
|
end
|
53
61
|
|
data/lib/html_view.html.erb
CHANGED
@@ -38,14 +38,18 @@ if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c
|
|
38
38
|
font-family: Sans-serif;
|
39
39
|
}
|
40
40
|
|
41
|
-
.container .
|
41
|
+
.container .ok {
|
42
42
|
background-color:#bbffbb;
|
43
43
|
}
|
44
44
|
|
45
|
-
.container .
|
45
|
+
.container .error {
|
46
46
|
background-color:#ffbbbb;
|
47
47
|
}
|
48
48
|
|
49
|
+
.container .warning {
|
50
|
+
background-color:#ffdd99;
|
51
|
+
}
|
52
|
+
|
49
53
|
.container .content {
|
50
54
|
display: none;
|
51
55
|
padding : 5px;
|
@@ -124,10 +128,14 @@ if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c
|
|
124
128
|
.stats .value {
|
125
129
|
}
|
126
130
|
|
127
|
-
.stats .
|
131
|
+
.stats .value_error {
|
128
132
|
color:red;
|
129
133
|
}
|
130
134
|
|
135
|
+
.stats .value_warning {
|
136
|
+
color:orange;
|
137
|
+
}
|
138
|
+
|
131
139
|
.stats .stats_header {
|
132
140
|
background-color:#d3d3d3;
|
133
141
|
padding: 2px;
|
@@ -162,17 +170,29 @@ if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c
|
|
162
170
|
</div>
|
163
171
|
|
164
172
|
<div class="toplevel">
|
173
|
+
<div class="stats">
|
174
|
+
<div class="stats_header">Project Statistics</div>
|
175
|
+
<div class="stats_line"><div class="title">Files</div><div class="value"><%=@project.files.count%></div></div>
|
176
|
+
<div class="stats_line"><div class="title">Coverage</div><div class="<%= class_of_stat(@project.stats[:coverage], 0.9, 1)%>"><%=@project.stats[:coverage_s]%></div></div>
|
177
|
+
<div class="stats_line"><div class="title">Total lines</div><div class="value"><%=@project.stats[:total_lines]%></div></div>
|
178
|
+
<div class="stats_line"><div class="title">Executable lines</div><div class="value"><%=@project.stats[:lines]%></div></div>
|
179
|
+
<div class="stats_line"><div class="title">Executed lines</div><div class="value"><%=@project.stats[:exec_lines]%></div></div>
|
180
|
+
<div class="stats_line"><div class="title">Missed lines</div><div class="<%= class_of_stat(@project.stats[:missed_lines],0) %>"><%=@project.stats[:missed_lines]%></div></div>
|
181
|
+
<div class="stats_line"><div class="title">Hits per line</div><div class="value"><%=@project.stats[:hits_per_line_s]%></div></div>
|
182
|
+
</div>
|
183
|
+
<br/ >
|
165
184
|
<% @project.files.each do |file| %>
|
166
185
|
<div class="container">
|
167
|
-
<div class="<%=class_of_file
|
186
|
+
<div class="<%=class_of_file(file,0.9,1)%>"><%=file.meta['Source']%> (<%=file.stats[:coverage_s]%>)</div>
|
168
187
|
<div class="content">
|
169
188
|
<div class="stats">
|
170
|
-
<div class="stats_header">Statistics</div>
|
171
|
-
<div class="stats_line"><div class="title">Coverage</div><div class="<%= class_of_stat(file.stats[:coverage]
|
189
|
+
<div class="stats_header">File Statistics</div>
|
190
|
+
<div class="stats_line"><div class="title">Coverage</div><div class="<%= class_of_stat(file.stats[:coverage], 0.9, 1) %>"><%=file.stats[:coverage_s]%></div></div>
|
172
191
|
<div class="stats_line"><div class="title">Total lines</div><div class="value"><%=file.stats[:total_lines]%></div></div>
|
173
192
|
<div class="stats_line"><div class="title">Executable lines</div><div class="value"><%=file.stats[:lines]%></div></div>
|
174
193
|
<div class="stats_line"><div class="title">Executed lines</div><div class="value"><%=file.stats[:exec_lines]%></div></div>
|
175
|
-
<div class="stats_line"><div class="title">Missed lines</div><div class="<%= class_of_stat(file.stats[:missed_lines])
|
194
|
+
<div class="stats_line"><div class="title">Missed lines</div><div class="<%= class_of_stat(file.stats[:missed_lines],0) %>"><%=file.stats[:missed_lines]%></div></div>
|
195
|
+
<div class="stats_line"><div class="title">Hits per line</div><div class="value"><%=file.stats[:hits_per_line_s]%></div></div>
|
176
196
|
</div>
|
177
197
|
<div class="code">
|
178
198
|
<% file.lines.each do |line| %><div class="<%= class_of line %>"><%= encode(line.text) %></div><% end %>
|
data/lib/line.rb
CHANGED
data/lib/project.rb
CHANGED
@@ -5,54 +5,86 @@ module GCOV
|
|
5
5
|
|
6
6
|
class Project
|
7
7
|
|
8
|
-
attr_reader :files
|
8
|
+
attr_reader :files, :stats
|
9
9
|
attr_accessor :name
|
10
10
|
|
11
11
|
def initialize name=""
|
12
12
|
@name = name
|
13
13
|
@files = []
|
14
|
+
@adding = false
|
14
15
|
end
|
15
16
|
|
16
17
|
def <<(file)
|
17
18
|
@files << file
|
19
|
+
_update_stats unless @adding
|
18
20
|
end
|
19
21
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
def add_files &block
|
23
|
+
# suspend stat updates until done adding files
|
24
|
+
fail "add_files requires a block" unless block_given?
|
25
|
+
|
26
|
+
# guard against nested calls
|
27
|
+
was_adding = @adding
|
28
|
+
@adding = true
|
29
|
+
yield
|
30
|
+
@adding = was_adding
|
31
|
+
|
32
|
+
_update_stats unless @adding
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def _update_stats
|
37
|
+
@stats = {
|
38
|
+
:missed_lines => 0,
|
39
|
+
:exec_lines => 0,
|
40
|
+
:empty_lines => 0,
|
41
|
+
:total_exec => 0,
|
42
|
+
:total_lines => 0,
|
43
|
+
:lines => 0,
|
44
|
+
:coverage => 0.0,
|
45
|
+
:hits_per_line => 0
|
46
|
+
}
|
47
|
+
|
48
|
+
@files.each do |file|
|
49
|
+
@stats[:missed_lines] += file.stats[:missed_lines]
|
50
|
+
@stats[:exec_lines] += file.stats[:exec_lines]
|
51
|
+
@stats[:total_exec] += file.stats[:total_exec]
|
52
|
+
@stats[:empty_lines] += file.stats[:empty_lines]
|
24
53
|
end
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
54
|
+
|
55
|
+
@stats[:lines] = @stats[:exec_lines] + @stats[:missed_lines]
|
56
|
+
@stats[:total_lines] = @stats[:lines] + @stats[:empty_lines]
|
57
|
+
@stats[:coverage] = @stats[:exec_lines].to_f / @stats[:lines].to_f
|
58
|
+
@stats[:coverage_s] = sprintf("%0.01f%",100.0*@stats[:coverage])
|
59
|
+
@stats[:hits_per_line] = @stats[:total_exec].to_f / @stats[:lines]
|
60
|
+
@stats[:hits_per_line_s] = sprintf("%0.02f",@stats[:hits_per_line])
|
31
61
|
end
|
32
62
|
|
33
63
|
def add_dir path, hash={}
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
STDERR.puts "filenames: #{filenames}"
|
40
|
-
|
41
|
-
filenames.select{|filename| ( hash[:filter].nil? or !hash[:filter].match(demangle(filename))) }.map{|filename| GCOV::File.load filename }.each do |file|
|
42
|
-
if hash[:filter].nil? or !hash[:filter].match( ::File.realpath(file.meta['Source']) )
|
43
|
-
self << file
|
64
|
+
add_files do
|
65
|
+
if hash[:recursive] == true
|
66
|
+
filenames = Dir["#{path}/**/*.gcov"]
|
67
|
+
else
|
68
|
+
filenames = Dir["#{path}/*.gcov"]
|
44
69
|
end
|
45
|
-
|
46
|
-
|
70
|
+
|
71
|
+
filenames.select{|filename| ( hash[:filter].nil? or !hash[:filter].match(GCOV::File.demangle(filename))) }.map{|filename| GCOV::File.load filename }.each do |file|
|
72
|
+
if hash[:filter].nil? or !hash[:filter].match( ::File.realpath(file.meta['Source']) )
|
73
|
+
self << file
|
74
|
+
end
|
75
|
+
end # files
|
76
|
+
end
|
47
77
|
end
|
48
78
|
|
49
79
|
def add_file path, hash={}
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
80
|
+
add_files do
|
81
|
+
if hash[:filter].nil? or !hash[:filter].match(GCOV::File.demangle(path))
|
82
|
+
file = GCOV::File.load(path)
|
83
|
+
if hash[:filter].nil? or !hash[:filter].match( ::File.realpath(file.meta['Source']) )
|
84
|
+
self << file
|
85
|
+
end # if
|
54
86
|
end # if
|
55
|
-
end #
|
87
|
+
end # add_files
|
56
88
|
end # add_file
|
57
89
|
|
58
90
|
def self.load_dir path, hash={}
|
data/lib/version.rb
CHANGED
data/spec/file_spec.rb
CHANGED
@@ -39,7 +39,7 @@ describe GCOV::File do
|
|
39
39
|
expect(file.stats[:exec_lines]).to eq(2)
|
40
40
|
expect(file.stats[:missed_lines]).to eq(2)
|
41
41
|
expect(file.stats[:coverage]).to eq(0.5)
|
42
|
-
expect(file.stats[:
|
42
|
+
expect(file.stats[:hits_per_line]).to eq(27.0/4)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -70,4 +70,12 @@ describe GCOV::File do
|
|
70
70
|
expect(file.meta["Runs"].to_i).to eq(1)
|
71
71
|
end
|
72
72
|
end
|
73
|
+
|
74
|
+
describe ".demangle" do
|
75
|
+
it "should demangle file names" do
|
76
|
+
demangled = GCOV::File.demangle( "stringutil.cpp.###Applications#Xcode.app#Contents#Developer#Toolchains#XcodeDefault.xctoolchain#usr#bin#^#include#c++#v1#streambuf.gcov" )
|
77
|
+
expect( demangled ).to eq("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/streambuf")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
73
81
|
end
|
data/spec/project_spec.rb
CHANGED
@@ -81,4 +81,43 @@ describe GCOV::Project do
|
|
81
81
|
end
|
82
82
|
|
83
83
|
|
84
|
+
describe "#stats" do
|
85
|
+
it "should be computed based on file stats" do
|
86
|
+
project = GCOV::Project.new
|
87
|
+
|
88
|
+
project.add_files do
|
89
|
+
file = GCOV::File.new "myfile.cpp"
|
90
|
+
file.add_lines do
|
91
|
+
file << GCOV::Line.new(1,4,"line 1")
|
92
|
+
file << GCOV::Line.new(2,23,"line 2")
|
93
|
+
file << GCOV::Line.new(3,:none,"line 3")
|
94
|
+
file << GCOV::Line.new(4,:missed,"line 4")
|
95
|
+
file << GCOV::Line.new(5,:none,"line 5")
|
96
|
+
end
|
97
|
+
|
98
|
+
project << file
|
99
|
+
|
100
|
+
file = GCOV::File.new "myfile.cpp"
|
101
|
+
file.add_lines do
|
102
|
+
file << GCOV::Line.new(1,:missed,"line 1")
|
103
|
+
file << GCOV::Line.new(2,40,"line 2")
|
104
|
+
file << GCOV::Line.new(3,:none,"line 3")
|
105
|
+
file << GCOV::Line.new(4,:none,"line 4")
|
106
|
+
end
|
107
|
+
|
108
|
+
project << file
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
expect(project.stats[:lines]).to eq(5)
|
113
|
+
expect(project.stats[:total_lines]).to eq(9)
|
114
|
+
expect(project.stats[:total_exec]).to eq(67)
|
115
|
+
expect(project.stats[:empty_lines]).to eq(4)
|
116
|
+
expect(project.stats[:exec_lines]).to eq(3)
|
117
|
+
expect(project.stats[:missed_lines]).to eq(2)
|
118
|
+
expect(project.stats[:coverage]).to eq(3.0/5)
|
119
|
+
expect(project.stats[:hits_per_line]).to eq(67.0/5)
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
84
123
|
end
|
data/spec/spec_helper.rb
CHANGED