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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 86e9963bfe5c1d5e50a80853ce8e9772123efd9f
4
- data.tar.gz: 7c201f588c22f3f5c2296e3e45874518cf084ad8
3
+ metadata.gz: a051bec21f907b37d3ff469c65e53854dbd711b5
4
+ data.tar.gz: 651d542e2a2afc95ebf79c9ad6c9e88ce88d8c94
5
5
  SHA512:
6
- metadata.gz: c2551f66a91913ef11c5a54e877bb7801a7ced9b320e1349a51505deaa09d226c09402aa9d4131f7735031b62f62257184d4102cfc5bff8400357fe7b5d054d4
7
- data.tar.gz: 57b0e1c8d95ccc1ae41eb0859abbe792306da800f953a6c42139e33e9868d8c33576bc82dd153ebeae2d2c2dc63b310058d8fbad34652772a6dfb40928861332
6
+ metadata.gz: 71db31ffc9c095e681ce72d9784851ecdf14793f53cc6a292fdde681cae9fccc4f1f3609f6d5365b9b25659bdb87c9c2ed8d5920af8f66249f5844f80e801305
7
+ data.tar.gz: b7aa7ba5fc36665e383c13102da3ae9fd5bd3646b09f84fcb0057b4242e254de88b54bc2b8ca32fe8948b5d1b7f198a6bf67882c29f305a5c0d4fb79e8eaf7f6
data/Gemfile CHANGED
@@ -9,3 +9,4 @@ gem "mixlib-cli"
9
9
  gem 'gyoku', '~> 1.0'
10
10
  gem 'rake'
11
11
  gem 'rubygems-tasks'
12
+ gem 'simplecov', :require => false, :group => :test
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
- rake (10.3.2)
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
- end
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
@@ -39,15 +39,23 @@ EOF
39
39
  end
40
40
  end
41
41
 
42
- def class_of_stat value, &block
43
- fail "class_of_stat needs a block" unless block_given?
44
- return ( (yield value) ? "value" : "value_bad" )
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
- case file.stats[:missed_lines]
49
- when 0 then "header good"
50
- else "header bad"
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
 
@@ -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 .good {
41
+ .container .ok {
42
42
  background-color:#bbffbb;
43
43
  }
44
44
 
45
- .container .bad {
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 .value_bad {
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 file%>"><%=file.meta['Source']%> (<%=file.stats[:coverage_s]%>)</div>
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]) {|v| v >= 0.9 } %>"><%=file.stats[:coverage_s]%></div></div>
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]) {|v| v == 0 } %>"><%=file.stats[:missed_lines]%></div></div>
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
@@ -29,9 +29,6 @@ module GCOV
29
29
  GCOV::Line.new number,count,text
30
30
  end
31
31
 
32
- def to_s
33
- "#{@number}:#{@count}:#{@text}"
34
- end
35
32
  end
36
33
 
37
34
  end
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 demangle filename
21
- result = filename
22
- if start = result.index(/###/)
23
- result = result[start..-1]
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
- result.gsub!( /(###|#|\^|\.gcov$)/, {"###"=>"/","#"=>"/","^"=>"..",".gcov"=>""} )
27
- STDERR.puts "demangled: #{result}"
28
- result = ::File.realpath(result)
29
- STDERR.puts "realpath: #{result}"
30
- result
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
- if hash[:recursive] == true
35
- filenames = Dir["#{path}/**/*.gcov"]
36
- else
37
- filenames = Dir["#{path}/*.gcov"]
38
- end
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
- end # files
46
- STDERR.puts "files: #{files.map{|f|f.name}}"
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
- if hash[:filter].nil? or !hash[:filter].match(demangle(path))
51
- file = GCOV::File.load(path)
52
- if hash[:filter].nil? or !hash[:filter].match( ::File.realpath(file.meta['Source']) )
53
- self << file
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 # if
87
+ end # add_files
56
88
  end # add_file
57
89
 
58
90
  def self.load_dir path, hash={}
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module GCOV
2
- VERSION = '0.2.2'
2
+ VERSION = '0.2.3'
3
3
  end
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[:total_exec]).to eq(27)
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
@@ -1,5 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
+ require 'simplecov'
4
+ SimpleCov.start
5
+
3
6
  require_relative '../lib/line'
4
7
  require_relative '../lib/file'
5
8
  require_relative '../lib/project'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gcov2x
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattias Bergbom