gcovtools 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|