gcov2x 0.2.2 → 0.2.3

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.
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