gcovtools 1.0.0
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 +7 -0
- data/.gitignore +37 -0
- data/.travis.yml +3 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +25 -0
- data/Rakefile +2 -0
- data/bin/gcovtools +138 -0
- data/gcovtools.gemspec +28 -0
- data/lib/ansii_formatter.rb +34 -0
- data/lib/file.rb +149 -0
- data/lib/gcovtools.rb +4 -0
- data/lib/html_formatter.rb +84 -0
- data/lib/html_view.html.erb +237 -0
- data/lib/json_formatter.rb +43 -0
- data/lib/line.rb +55 -0
- data/lib/logging.rb +19 -0
- data/lib/project.rb +146 -0
- data/lib/version.rb +3 -0
- data/lib/xml_formatter.rb +58 -0
- data/spec/gcovtools/concat/test_cat.cpp.gcov +35 -0
- data/spec/gcovtools/data/data2/test3.cpp.gcov +22 -0
- data/spec/gcovtools/data/test.cpp.gcov +14 -0
- data/spec/gcovtools/data/test1.cpp.gcov +21 -0
- data/spec/gcovtools/data/test2.cpp.gcov +22 -0
- data/spec/gcovtools/file_spec.rb +140 -0
- data/spec/gcovtools/line_spec.rb +93 -0
- data/spec/gcovtools/project_spec.rb +299 -0
- data/spec/spec_helper.rb +14 -0
- data/src/Makefile +48 -0
- data/src/test.cpp +9 -0
- data/src/test.h +7 -0
- data/src/test1.cpp +16 -0
- data/src/test2.cpp +17 -0
- data/src/test3.cpp +17 -0
- data/tasks/rubygems.rake +3 -0
- data/tasks/spec.rake +8 -0
- metadata +193 -0
data/lib/project.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
require_relative './file'
|
2
|
+
require_relative './line'
|
3
|
+
require_relative './logging'
|
4
|
+
|
5
|
+
module GCOVTOOLS
|
6
|
+
|
7
|
+
class Project
|
8
|
+
|
9
|
+
attr_reader :files, :stats
|
10
|
+
attr_accessor :name
|
11
|
+
|
12
|
+
def initialize name=""
|
13
|
+
@name = name
|
14
|
+
@files = {}
|
15
|
+
@adding = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def <<(file)
|
19
|
+
if @files.has_key?file.name
|
20
|
+
@files[file.name].merge! file
|
21
|
+
else
|
22
|
+
@files[file.name] = file
|
23
|
+
end
|
24
|
+
_update_stats unless @adding
|
25
|
+
end
|
26
|
+
|
27
|
+
def files
|
28
|
+
@files.sort{|a,b|
|
29
|
+
if ::File.basename(a[0]) < ::File.basename(b[0])
|
30
|
+
-1
|
31
|
+
elsif ::File.basename(a[0]) == ::File.basename(b[0])
|
32
|
+
0
|
33
|
+
else
|
34
|
+
1
|
35
|
+
end }.map{|key,val|val}
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_files &block
|
39
|
+
# suspend stat updates until done adding files
|
40
|
+
fail "add_files requires a block" unless block_given?
|
41
|
+
|
42
|
+
# guard against nested calls
|
43
|
+
was_adding = @adding
|
44
|
+
@adding = true
|
45
|
+
yield
|
46
|
+
@adding = was_adding
|
47
|
+
|
48
|
+
_update_stats unless @adding
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
def _update_stats
|
53
|
+
@stats = {
|
54
|
+
:missed_lines => 0,
|
55
|
+
:exec_lines => 0,
|
56
|
+
:empty_lines => 0,
|
57
|
+
:total_exec => 0,
|
58
|
+
:total_lines => 0,
|
59
|
+
:lines => 0,
|
60
|
+
:coverage => 0.0,
|
61
|
+
:hits_per_line => 0
|
62
|
+
}
|
63
|
+
|
64
|
+
@files.each do |name,file|
|
65
|
+
@stats[:missed_lines] += file.stats[:missed_lines]
|
66
|
+
@stats[:exec_lines] += file.stats[:exec_lines]
|
67
|
+
@stats[:total_exec] += file.stats[:total_exec]
|
68
|
+
@stats[:empty_lines] += file.stats[:empty_lines]
|
69
|
+
end
|
70
|
+
|
71
|
+
@stats[:lines] = @stats[:exec_lines] + @stats[:missed_lines]
|
72
|
+
@stats[:total_lines] = @stats[:lines] + @stats[:empty_lines]
|
73
|
+
|
74
|
+
if @stats[:lines] > 0
|
75
|
+
@stats[:coverage] = @stats[:exec_lines].to_f / @stats[:lines].to_f
|
76
|
+
@stats[:hits_per_line] = @stats[:total_exec].to_f / @stats[:lines]
|
77
|
+
else
|
78
|
+
@stats[:coverage] = 1
|
79
|
+
@stats[:hits_per_line] = 0
|
80
|
+
end
|
81
|
+
|
82
|
+
@stats[:coverage_s] = sprintf("%0.01f%",100.0*@stats[:coverage])
|
83
|
+
@stats[:hits_per_line_s] = sprintf("%0.02f",@stats[:hits_per_line])
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
def _add_file path, hash_={}
|
88
|
+
GCOVTOOLS::logger.info "parsing file: #{path}"
|
89
|
+
|
90
|
+
hash = hash_.dup
|
91
|
+
|
92
|
+
files = GCOVTOOLS::File.load(path)
|
93
|
+
|
94
|
+
# apply _inclusive_ filters first
|
95
|
+
files.select!{ |file|
|
96
|
+
hash[:include].nil? or hash[:include].empty? or !hash[:include].select{|f| f.match(::Pathname.new(file.meta['Source']).cleanpath.to_s) }.empty?
|
97
|
+
}
|
98
|
+
|
99
|
+
GCOVTOOLS::logger.info "included #{files.size} files"
|
100
|
+
|
101
|
+
old_size = files.size
|
102
|
+
|
103
|
+
# apply _exclusive_ filters next
|
104
|
+
files.select!{ |file|
|
105
|
+
hash[:exclude].nil? or hash[:exclude].empty? or hash[:exclude].select{|f| f.match(::Pathname.new(file.meta['Source']).cleanpath.to_s) }.empty?
|
106
|
+
}
|
107
|
+
|
108
|
+
GCOVTOOLS::logger.info "excluded #{old_size-files.size} files"
|
109
|
+
|
110
|
+
# add all the files that survived the gauntlet
|
111
|
+
files.map{ |file| self << file }
|
112
|
+
end
|
113
|
+
|
114
|
+
def add_dir path, hash_={}
|
115
|
+
GCOVTOOLS::logger.info "searching: #{path}"
|
116
|
+
hash = hash_.dup
|
117
|
+
if hash[:recursive] == true
|
118
|
+
filenames = Dir["#{path}/**/*.gcov"]
|
119
|
+
else
|
120
|
+
filenames = Dir["#{path}/*.gcov"]
|
121
|
+
end
|
122
|
+
|
123
|
+
GCOVTOOLS::logger.info "found: #{filenames}"
|
124
|
+
|
125
|
+
add_files do
|
126
|
+
filenames.each do |filename|
|
127
|
+
_add_file filename, hash
|
128
|
+
end # each filename
|
129
|
+
end # add_files
|
130
|
+
end # #add_dir
|
131
|
+
|
132
|
+
def add_file path, hash_={}
|
133
|
+
hash = hash_.dup
|
134
|
+
add_files do
|
135
|
+
_add_file path, hash
|
136
|
+
end # add_files
|
137
|
+
end # #add_file
|
138
|
+
|
139
|
+
def self.load_dir path, hash={}
|
140
|
+
project = GCOVTOOLS::Project.new
|
141
|
+
project.add_dir path, hash
|
142
|
+
project
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
data/lib/version.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
|
2
|
+
require_relative './project'
|
3
|
+
require_relative './file'
|
4
|
+
require_relative './line'
|
5
|
+
|
6
|
+
# require 'gyoku'
|
7
|
+
require 'builder'
|
8
|
+
|
9
|
+
module GCOVTOOLS
|
10
|
+
|
11
|
+
class XMLFormatter
|
12
|
+
|
13
|
+
def initialize project, va={}
|
14
|
+
@project = project
|
15
|
+
@xsl = va[:xsl]
|
16
|
+
|
17
|
+
# @hash = { :files => { :file => [] } }
|
18
|
+
@xml = Builder::XmlMarkup.new( :indent => 2 )
|
19
|
+
@xml.instruct! :xml, :encoding => "UTF-8"
|
20
|
+
|
21
|
+
if @xsl
|
22
|
+
@xml.instruct! :"xml-stylesheet", :href => @xsl, :type => "text/xsl"
|
23
|
+
end
|
24
|
+
|
25
|
+
@xml.projects do |xprojects|
|
26
|
+
xprojects.project(:name=>"Test") do |xproject|
|
27
|
+
xproject.files do |xfiles|
|
28
|
+
@project.files.each do |file|
|
29
|
+
xfiles.file(:name => file.name) do |xfile|
|
30
|
+
xfile.lines do |xlines|
|
31
|
+
file.lines.select{|line| line.number > 0}.each do |line|
|
32
|
+
xlines.line(:number=>line.number,:count=>line.count) do |xline|
|
33
|
+
xline.count line.count
|
34
|
+
xline.text do |xtext|
|
35
|
+
xtext.cdata! line.text
|
36
|
+
end # xtext
|
37
|
+
end # xline
|
38
|
+
end # line
|
39
|
+
end # xlines
|
40
|
+
end # xfile
|
41
|
+
end # file
|
42
|
+
end # xfiles
|
43
|
+
end # xproject
|
44
|
+
end # xprojects
|
45
|
+
end # initialize
|
46
|
+
|
47
|
+
def print
|
48
|
+
# puts "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
49
|
+
# if @xslt
|
50
|
+
# puts "<?xml-stylesheet href=\"#{@xslt}\" type=\"text/xsl\"?>"
|
51
|
+
# end
|
52
|
+
# puts Gyoku.xml( @hash )
|
53
|
+
puts @xml.target!
|
54
|
+
end # XMLFormatter#print
|
55
|
+
|
56
|
+
end # XMLFormatter
|
57
|
+
|
58
|
+
end # GCOVTOOLS
|
@@ -0,0 +1,35 @@
|
|
1
|
+
-: 0:Source:test.cpp
|
2
|
+
-: 0:Graph:test.gcno
|
3
|
+
-: 0:Data:test.gcda
|
4
|
+
-: 0:Runs:1
|
5
|
+
-: 0:Programs:1
|
6
|
+
-: 1:#include "test.h"
|
7
|
+
-: 2:
|
8
|
+
-: 3:int main( int argc, const char* argv[] )
|
9
|
+
-: 4:{
|
10
|
+
1: 5: reached(2);
|
11
|
+
1: 6: reached2(2);
|
12
|
+
1: 7: reached3(2);
|
13
|
+
1: 8: return 0;
|
14
|
+
-: 9:}
|
15
|
+
-: 0:Source:test1.cpp
|
16
|
+
-: 0:Graph:test1.gcno
|
17
|
+
-: 0:Data:test1.gcda
|
18
|
+
-: 0:Runs:2
|
19
|
+
-: 0:Programs:1
|
20
|
+
-: 1:
|
21
|
+
-: 2:int reached( int i )
|
22
|
+
-: 3:{
|
23
|
+
2: 4: int j = i;
|
24
|
+
-: 5:
|
25
|
+
2: 6: if( j == 2 )
|
26
|
+
2: 7: return j;
|
27
|
+
-: 8:
|
28
|
+
#####: 9: return 3;
|
29
|
+
2: 10:}
|
30
|
+
-: 11:
|
31
|
+
-: 12:int unreached( int x )
|
32
|
+
-: 13:{
|
33
|
+
#####: 14: int y = x;
|
34
|
+
#####: 15: return y+3;
|
35
|
+
-: 16:}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
-: 0:Source:test3.cpp
|
2
|
+
-: 0:Graph:test3.gcno
|
3
|
+
-: 0:Data:test3.gcda
|
4
|
+
-: 0:Runs:4
|
5
|
+
-: 0:Programs:1
|
6
|
+
-: 1:
|
7
|
+
-: 2:int unreached3( int x )
|
8
|
+
-: 3:{
|
9
|
+
#####: 4: int y = x;
|
10
|
+
#####: 5: return y+3;
|
11
|
+
-: 6:}
|
12
|
+
-: 7:
|
13
|
+
-: 8:int reached3( int i )
|
14
|
+
-: 9:{
|
15
|
+
4: 10: int j = i;
|
16
|
+
-: 11:
|
17
|
+
4: 12: if( j == 2 )
|
18
|
+
4: 13: return j;
|
19
|
+
-: 14:
|
20
|
+
#####: 15: return 3;
|
21
|
+
4: 16:}
|
22
|
+
-: 17:
|
@@ -0,0 +1,14 @@
|
|
1
|
+
-: 0:Source:test.cpp
|
2
|
+
-: 0:Graph:test.gcno
|
3
|
+
-: 0:Data:test.gcda
|
4
|
+
-: 0:Runs:1
|
5
|
+
-: 0:Programs:1
|
6
|
+
-: 1:#include "test.h"
|
7
|
+
-: 2:
|
8
|
+
-: 3:int main( int argc, const char* argv[] )
|
9
|
+
-: 4:{
|
10
|
+
1: 5: reached(2);
|
11
|
+
1: 6: reached2(2);
|
12
|
+
1: 7: reached3(2);
|
13
|
+
1: 8: return 0;
|
14
|
+
-: 9:}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
-: 0:Source:test1.cpp
|
2
|
+
-: 0:Graph:test1.gcno
|
3
|
+
-: 0:Data:test1.gcda
|
4
|
+
-: 0:Runs:2
|
5
|
+
-: 0:Programs:1
|
6
|
+
-: 1:
|
7
|
+
-: 2:int reached( int i )
|
8
|
+
-: 3:{
|
9
|
+
2: 4: int j = i;
|
10
|
+
-: 5:
|
11
|
+
2: 6: if( j == 2 )
|
12
|
+
2: 7: return j;
|
13
|
+
-: 8:
|
14
|
+
#####: 9: return 3;
|
15
|
+
2: 10:}
|
16
|
+
-: 11:
|
17
|
+
-: 12:int unreached( int x )
|
18
|
+
-: 13:{
|
19
|
+
#####: 14: int y = x;
|
20
|
+
#####: 15: return y+3;
|
21
|
+
-: 16:}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
-: 0:Source:test2.cpp
|
2
|
+
-: 0:Graph:test2.gcno
|
3
|
+
-: 0:Data:test2.gcda
|
4
|
+
-: 0:Runs:3
|
5
|
+
-: 0:Programs:1
|
6
|
+
-: 1:
|
7
|
+
-: 2:int unreached2( int x )
|
8
|
+
-: 3:{
|
9
|
+
#####: 4: int y = x;
|
10
|
+
#####: 5: return y+3;
|
11
|
+
-: 6:}
|
12
|
+
-: 7:
|
13
|
+
-: 8:int reached2( int i )
|
14
|
+
-: 9:{
|
15
|
+
3: 10: int j = i;
|
16
|
+
-: 11:
|
17
|
+
3: 12: if( j == 2 )
|
18
|
+
3: 13: return j;
|
19
|
+
-: 14:
|
20
|
+
#####: 15: return 3;
|
21
|
+
3: 16:}
|
22
|
+
-: 17:
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe GCOVTOOLS::File do
|
4
|
+
|
5
|
+
it "requires a filename" do
|
6
|
+
expect{ file = GCOVTOOLS::File.new }.to raise_error
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#name" do
|
10
|
+
it "returns the filename it was given" do
|
11
|
+
file = GCOVTOOLS::File.new "myfile.cpp"
|
12
|
+
expect(file.name).to eq("myfile.cpp")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#<<" do
|
17
|
+
it "doesn't allow adding lines outside of the add_lines block" do
|
18
|
+
file = GCOVTOOLS::File.new "myfile.cpp"
|
19
|
+
expect{
|
20
|
+
file << GCOVTOOLS::Line.new(1,4,"line 1")
|
21
|
+
}.to raise_error
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#add_lines" do
|
26
|
+
it "computes stats after adding lines" do
|
27
|
+
file = GCOVTOOLS::File.new "myfile.cpp"
|
28
|
+
file.add_lines do
|
29
|
+
file << GCOVTOOLS::Line.new(1,4,"line 1")
|
30
|
+
file << GCOVTOOLS::Line.new(2,23,"line 2")
|
31
|
+
file << GCOVTOOLS::Line.new(3,:none,"line 3")
|
32
|
+
file << GCOVTOOLS::Line.new(4,:missed,"line 4")
|
33
|
+
file << GCOVTOOLS::Line.new(5,:missed,"line 5")
|
34
|
+
end
|
35
|
+
expect(file.stats[:lines]).to eq(4)
|
36
|
+
expect(file.stats[:total_lines]).to eq(5)
|
37
|
+
expect(file.stats[:total_exec]).to eq(27)
|
38
|
+
expect(file.stats[:empty_lines]).to eq(1)
|
39
|
+
expect(file.stats[:exec_lines]).to eq(2)
|
40
|
+
expect(file.stats[:missed_lines]).to eq(2)
|
41
|
+
expect(file.stats[:coverage]).to eq(0.5)
|
42
|
+
expect(file.stats[:hits_per_line]).to eq(27.0/4)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "handles files with 0 executable lines" do
|
46
|
+
file = GCOVTOOLS::File.new "myfile.cpp"
|
47
|
+
file.add_lines do
|
48
|
+
file << GCOVTOOLS::Line.new(1,:none,"line 1")
|
49
|
+
file << GCOVTOOLS::Line.new(2,:none,"line 2")
|
50
|
+
file << GCOVTOOLS::Line.new(3,:none,"line 3")
|
51
|
+
file << GCOVTOOLS::Line.new(4,:none,"line 4")
|
52
|
+
end
|
53
|
+
expect(file.stats[:lines]).to eq(0)
|
54
|
+
expect(file.stats[:coverage]).to eq(1)
|
55
|
+
expect(file.stats[:hits_per_line]).to eq(0)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#lines" do
|
60
|
+
it "returns no lines by default" do
|
61
|
+
file = GCOVTOOLS::File.new "myfile.cpp"
|
62
|
+
expect(file.lines.count).to eq(0)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should return the lines it was given, sorted by number" do
|
66
|
+
file = GCOVTOOLS::File.new "myfile.cpp"
|
67
|
+
file.add_lines do
|
68
|
+
file << GCOVTOOLS::Line.new(2,23,"line 2")
|
69
|
+
file << GCOVTOOLS::Line.new(1,4,"line 1")
|
70
|
+
end
|
71
|
+
expect(file.lines.count).to eq(2)
|
72
|
+
expect(file.lines[0].number).to eq(1)
|
73
|
+
expect(file.lines[1].number).to eq(2)
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
describe ".load" do
|
79
|
+
it "can load a gcov file" do
|
80
|
+
file = GCOVTOOLS::File.load(File.join(File.dirname(__FILE__),"data/test.cpp.gcov"))[0]
|
81
|
+
expect(file.lines.count).to eq(9)
|
82
|
+
expect(file.meta["Graph"]).to eq("test.gcno")
|
83
|
+
expect(file.meta["Runs"].to_i).to eq(1)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should split concatenated gcov files into multiple objects" do
|
87
|
+
files = GCOVTOOLS::File.load(File.join(File.dirname(__FILE__),"concat/test_cat.cpp.gcov"))
|
88
|
+
|
89
|
+
expect(files.count).to eq(2)
|
90
|
+
expect(files[0].meta["Source"]).to eq("test.cpp")
|
91
|
+
expect(files[1].meta["Source"]).to eq("test1.cpp")
|
92
|
+
|
93
|
+
expect(files[0].lines.count).to eq(9)
|
94
|
+
expect(files[0].meta["Graph"]).to eq("test.gcno")
|
95
|
+
expect(files[0].meta["Runs"].to_i).to eq(1)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe ".demangle" do
|
100
|
+
it "should demangle file names with nonexisting components" do
|
101
|
+
demangled = GCOVTOOLS::File.demangle( "testfile.cpp.###Applications#Xcode.app#Nonexisting#Path#Contents#Developer#Toolchains#XcodeDefault.xctoolchain#usr#bin#^#include#c++#v1#streambuf.gcov" )
|
102
|
+
expect( demangled ).to eq("/Applications/Xcode.app/Nonexisting/Path/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/streambuf")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "#merge" do
|
107
|
+
|
108
|
+
it "should merge the counts of each line and recompute stats" do
|
109
|
+
file = GCOVTOOLS::File.new "myfile.cpp"
|
110
|
+
file.add_lines do
|
111
|
+
file << GCOVTOOLS::Line.new(1,4,"line 1")
|
112
|
+
file << GCOVTOOLS::Line.new(2,23,"line 2")
|
113
|
+
file << GCOVTOOLS::Line.new(3,:none,"line 3")
|
114
|
+
file << GCOVTOOLS::Line.new(4,:missed,"line 4")
|
115
|
+
file << GCOVTOOLS::Line.new(5,:missed,"line 5")
|
116
|
+
end
|
117
|
+
|
118
|
+
file2 = GCOVTOOLS::File.new "myfile.cpp"
|
119
|
+
file2.add_lines do
|
120
|
+
file2 << GCOVTOOLS::Line.new(1,1,"line 1")
|
121
|
+
file2 << GCOVTOOLS::Line.new(2,:missed,"line 2")
|
122
|
+
file2 << GCOVTOOLS::Line.new(3,:none,"line 3")
|
123
|
+
file2 << GCOVTOOLS::Line.new(4,4,"line 4")
|
124
|
+
file2 << GCOVTOOLS::Line.new(5,:missed,"line 5")
|
125
|
+
end
|
126
|
+
|
127
|
+
file3 = file.merge file2
|
128
|
+
|
129
|
+
expect(file3.stats[:lines]).to eq(4)
|
130
|
+
expect(file3.stats[:total_lines]).to eq(5)
|
131
|
+
expect(file3.stats[:total_exec]).to eq(32)
|
132
|
+
expect(file3.stats[:empty_lines]).to eq(1)
|
133
|
+
expect(file3.stats[:exec_lines]).to eq(3)
|
134
|
+
expect(file3.stats[:missed_lines]).to eq(1)
|
135
|
+
expect(file3.stats[:coverage]).to eq(0.75)
|
136
|
+
expect(file3.stats[:hits_per_line]).to eq(32.0/4)
|
137
|
+
|
138
|
+
end # it
|
139
|
+
end # describe
|
140
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe GCOVTOOLS::Line do
|
4
|
+
describe "#number" do
|
5
|
+
it "returns the number it was given" do
|
6
|
+
line = GCOVTOOLS::Line.new 2, 4, "abcdef"
|
7
|
+
expect(line.number).to eq(2)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#count" do
|
12
|
+
it "returns the count it was given" do
|
13
|
+
line = GCOVTOOLS::Line.new 2, 4, "abcdef"
|
14
|
+
expect(line.count).to eq(4)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#text" do
|
19
|
+
it "returns the text it was given" do
|
20
|
+
line = GCOVTOOLS::Line.new 2, 4, "abcdef"
|
21
|
+
expect(line.text).to eq("abcdef")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe ".parse" do
|
26
|
+
it "parses gcov format line with count" do
|
27
|
+
line = GCOVTOOLS::Line.parse " 2: 55: std::string StringUtil::ltrim( const std::string &s ) "
|
28
|
+
expect(line.number).to eq(55)
|
29
|
+
expect(line.count).to eq(2)
|
30
|
+
expect(line.text).to eq(" std::string StringUtil::ltrim( const std::string &s ) ")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "parses empty gcov format line" do
|
34
|
+
line = GCOVTOOLS::Line.parse " -: 35: * don't worry about excessive copying."
|
35
|
+
expect(line.number).to eq(35)
|
36
|
+
expect(line.count).to eq(:none)
|
37
|
+
expect(line.text).to eq(" * don't worry about excessive copying.")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "parses missed gcov format line" do
|
41
|
+
line = GCOVTOOLS::Line.parse " #####: 89: } "
|
42
|
+
expect(line.number).to eq(89)
|
43
|
+
expect(line.count).to eq(:missed)
|
44
|
+
expect(line.text).to eq(" } ")
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#state" do
|
50
|
+
it "should return :exec if it has positive count" do
|
51
|
+
line = GCOVTOOLS::Line.new 3,5,"line x"
|
52
|
+
expect(line.state).to eq(:exec)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return :missed if it was missed" do
|
56
|
+
line = GCOVTOOLS::Line.new 3,:missed,"line x"
|
57
|
+
expect(line.state).to eq(:missed)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should return :none if it is not relevant" do
|
61
|
+
line = GCOVTOOLS::Line.new 3,:none,"line x"
|
62
|
+
expect(line.state).to eq(:none)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#merge" do
|
67
|
+
it "should add hit counts" do
|
68
|
+
line = GCOVTOOLS::Line.new 3,4, "abcdef"
|
69
|
+
line2 = GCOVTOOLS::Line.new 3,1, "abcdef"
|
70
|
+
line3 = line.merge line2
|
71
|
+
expect(line3.count).to eq(5)
|
72
|
+
|
73
|
+
line = GCOVTOOLS::Line.new 3,:missed, "abcdef"
|
74
|
+
line2 = GCOVTOOLS::Line.new 3,1, "abcdef"
|
75
|
+
line3 = line.merge line2
|
76
|
+
expect(line3.count).to eq(1)
|
77
|
+
|
78
|
+
line = GCOVTOOLS::Line.new 3,1, "abcdef"
|
79
|
+
line2 = GCOVTOOLS::Line.new 3,:missed, "abcdef"
|
80
|
+
line3 = line.merge line2
|
81
|
+
expect(line3.count).to eq(1)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should give missed (0) presedence over none" do
|
85
|
+
line = GCOVTOOLS::Line.new 3,:missed, "abcdef"
|
86
|
+
line2 = GCOVTOOLS::Line.new 3,:none, "abcdef"
|
87
|
+
line3 = line.merge line2
|
88
|
+
expect(line3.count).to eq(:missed)
|
89
|
+
end
|
90
|
+
|
91
|
+
end # describe #merge
|
92
|
+
|
93
|
+
end
|