rubinius-coverage 2.0.3 → 2.1

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: b1b280b252772cabd1b6dae2f74cf7015922d8b8
4
- data.tar.gz: 6c0595e0f08af7f85c9fcfe9b3919ecee56f1626
3
+ metadata.gz: 22c19371e1c8ec5d8177165d91c12f992ebe7d3e
4
+ data.tar.gz: 893646e9c62de4bcc66de954693a37d3c6ff5615
5
5
  SHA512:
6
- metadata.gz: 980cc32e4a44471cf67f227f39d8f466ebcdf65b461b64947909df29af10eff230d806b21e3c2e34d42d2282b7deefa147413249de3102ac80283157c2c67598
7
- data.tar.gz: bcbc07ec393f6dba5189091382493d9e6d7c4197b7e346089890b3a2713d0c6a8a73bb2a5417158c7e2d9dc0f56eb0dfa501fdb114936f9bf541b8c6ebcf7263
6
+ metadata.gz: 02895b2ce0adefd94c062611273d0715be55416eb502ce557982141f2e6bff475dda338c0372e0f1e20b3bd674e805448ccc355154ba8d11bf43f759a385ade7
7
+ data.tar.gz: 12a4dcddd1d91c319186f4ae52edc46dbb404e089101563e60c86e5b2beb58ad1c71e185952e265750fb16213d5c51e8e5b2b677d6116ece850bed4b89c45278
data/Rakefile CHANGED
@@ -1 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ desc "Run the specs"
4
+ task :spec do
5
+ sh "rspec -I spec spec"
6
+ end
7
+
8
+ task :default => :spec
@@ -2,39 +2,186 @@ require "rubinius/coverage/version"
2
2
 
3
3
  module Rubinius
4
4
  class Coverage
5
- def self.loaded(flag)
6
- @loaded = flag
7
- end
5
+ class CFG
6
+ attr_accessor :code, :call_sites, :basic_blocks, :enter, :exit
8
7
 
9
- def self.loaded?
10
- @loaded == true
11
- end
8
+ def initialize(code, call_sites)
9
+ @code = code
10
+ @call_sites = call_sites
11
+ @basic_blocks = Hash.new { |h, k| h[k] = BasicBlock.new k }
12
+ end
12
13
 
13
- def self.load
14
- return if loaded?
14
+ def graph
15
+ iseq = @code.iseq
16
+ total = iseq.size
17
+ i = 0
15
18
 
16
- Rubinius::Tooling.load File.expand_path('../coverage/coverage', __FILE__)
17
- loaded true
19
+ @enter = BasicBlock.new 0
20
+ @enter.left = bb = @basic_blocks[0]
18
21
 
19
- self
20
- end
22
+ @exit = @basic_blocks[total]
23
+
24
+ while i < total
25
+ opcode = InstructionSet[iseq[i]]
26
+
27
+ if @basic_blocks.has_key? i
28
+ bb.exit_ip = i-1
29
+ bb = bb.left = @basic_blocks[i]
30
+ else
31
+ bb.exit_ip = i+opcode.width-1
32
+
33
+ case opcode.control_flow
34
+ when :branch
35
+ bb.left = @basic_blocks[iseq[i+1]]
36
+ bb.left.exit_ip = total
37
+
38
+ next_bb = @basic_blocks[i+opcode.width]
39
+ bb.right = next_bb if opcode.name != :goto
40
+
41
+ bb = next_bb
42
+ when :raise, :return
43
+ bb.left = @exit
44
+ bb = @basic_blocks[i+opcode.width]
45
+ end
46
+ end
47
+
48
+ i += opcode.width
49
+ end
50
+
51
+ @basic_blocks.values.each do |bb|
52
+ # Split if a jump target intersects our range
53
+ i = bb.enter_ip
54
+ while i < bb.exit_ip
55
+ opcode = InstructionSet[iseq[i]]
56
+ i += opcode.width
57
+
58
+ if @basic_blocks.has_key? i
59
+ bb.exit_ip = i-1
60
+
61
+ if opcode.control_flow != :branch
62
+ bb.left = @basic_blocks[i]
63
+ bb.right = nil
64
+ end
65
+
66
+ break
67
+ end
68
+ end
69
+
70
+ bb.coverage @code, @call_sites
71
+ end
72
+
73
+ stack = [@enter]
74
+ cycles = {}
75
+
76
+ until stack.empty?
77
+ bb = stack.shift
78
+
79
+ if left = bb.left
80
+ left.count = bb.count if bb.count > left.count
81
+ unless cycles.has_key? left
82
+ stack << left
83
+ cycles[left] = true
84
+ end
85
+ end
21
86
 
22
- attr_reader :results
87
+ if right = bb.right
88
+ right.count = bb.count if bb.count > right.count
89
+ unless cycles.has_key? right
90
+ stack << right
91
+ cycles[right] = true
92
+ end
93
+ end
94
+ end
23
95
 
24
- def initialize
25
- self.class.load
96
+ # Flow coverage counts backwards
97
+ @basic_blocks.values.each do |bb|
98
+ if bb.count == 0
99
+ if (bb.left and bb.left.count > 0) or
100
+ (bb.right and bb.right.count > 0)
101
+ bb.count = 1
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ class BasicBlock
108
+ attr_accessor :enter_ip, :exit_ip, :left, :right, :lines, :count
109
+
110
+ def initialize(enter_ip)
111
+ @enter_ip = @exit_ip = enter_ip
112
+ @lines = []
113
+ @count = 0
114
+ end
115
+
116
+ def coverage(code, call_sites)
117
+ total = code.lines.size - 2
118
+ i = 0
119
+
120
+ while i < total
121
+ if (@enter_ip < code.lines[i+2] and @exit_ip >= code.lines[i]) or
122
+ (code.lines[i+2] == 0 and @enter_ip == 0)
123
+ line = code.lines[i+1]
124
+ @lines << line unless @lines.include? line
125
+ end
126
+
127
+ i += 2
128
+ end
129
+
130
+ call_sites.each do |cs|
131
+ if cs.ip >= @enter_ip and cs.ip <= @exit_ip
132
+ cs_count = cs.invokes + cs.hits + cs.misses
133
+ @count = cs_count if cs_count > @count
134
+ end
135
+ end
136
+ end
137
+ end
26
138
  end
27
139
 
140
+ # Coverage methods
141
+
28
142
  def start
29
- Rubinius::Tooling.enable
143
+ ObjectSpace.each_object(Rubinius::CallSite) { |cs| cs.reset }
30
144
 
31
- self
145
+ nil
32
146
  end
33
147
 
34
- def stop
35
- @results = Rubinius::Tooling.disable
148
+ def coverage(code)
149
+ call_sites = code.call_sites
150
+ return unless call_sites.any? { |cs| cs.invokes + cs.hits + cs.misses > 0 }
151
+
152
+ cfg = CFG.new code, call_sites
153
+ cfg.graph
154
+
155
+ counts = {}
156
+
157
+ total = code.lines.size
158
+ i = 1
159
+
160
+ while i < total
161
+ counts[code.lines[i]] = 0
162
+ i += 2
163
+ end
164
+
165
+ cfg.basic_blocks.values.each do |bb|
166
+ bb.lines.each { |l| counts[l] = bb.count }
167
+ end
168
+
169
+ counts
170
+ end
171
+
172
+ def result
173
+ code_coverage = Hash.new { |h, k| h[k] = [] }
174
+
175
+ ObjectSpace.each_object(Rubinius::CompiledCode) do |code|
176
+ lines = code_coverage[code.file.to_s]
177
+ counts = coverage code
178
+ next unless counts
179
+
180
+ counts.each { |line, count| lines[line] = count }
181
+ end
36
182
 
37
- self
183
+ code_coverage.delete_if { |k, v| v.empty? }
184
+ code_coverage
38
185
  end
39
186
  end
40
187
  end
@@ -1,5 +1,5 @@
1
1
  module Rubinius
2
2
  class Coverage
3
- VERSION = "2.0.3"
3
+ VERSION = "2.1"
4
4
  end
5
5
  end
@@ -13,10 +13,10 @@ Gem::Specification.new do |spec|
13
13
 
14
14
  spec.files = `git ls-files`.split($/)
15
15
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
- spec.extensions = ["ext/rubinius/coverage/extconf.rb"]
17
16
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
17
  spec.require_paths = ["lib"]
19
18
 
20
19
  spec.add_development_dependency "bundler", "~> 1.3"
21
20
  spec.add_development_dependency "rake", "~> 10.0"
21
+ spec.add_development_dependency "rspec", "~> 3"
22
22
  end
@@ -0,0 +1,99 @@
1
+ require "spec_helper"
2
+
3
+ module CoverageSpecs
4
+ class DoubleBranch
5
+ def m
6
+ a = 1
7
+ if a == 2
8
+ 3
9
+ else
10
+ 2
11
+ end
12
+
13
+ 4
14
+ end
15
+ end
16
+ end
17
+
18
+ describe Rubinius::Coverage do
19
+ context "with a single branch" do
20
+ let(:obj) { CoverageSpecs::DoubleBranch.new }
21
+ let(:code) { obj.method(:m).executable }
22
+
23
+ describe Rubinius::Coverage::CFG do
24
+ let(:cfg) { Rubinius::Coverage::CFG.new code, code.call_sites }
25
+
26
+ before do
27
+ cfg.graph
28
+ end
29
+
30
+ describe "#graph" do
31
+ it "creates five BasicBlock instances" do
32
+ expect(cfg.basic_blocks.size).to eql(5)
33
+ end
34
+
35
+ it "creates a basic block at IP 0-13" do
36
+ bb = cfg.basic_blocks[0]
37
+
38
+ expect(bb.enter_ip).to eql(0)
39
+ expect(bb.exit_ip).to eql(13)
40
+ end
41
+
42
+ it "creates a basic block at IP 14-17" do
43
+ bb = cfg.basic_blocks[14]
44
+
45
+ expect(bb.enter_ip).to eql(14)
46
+ expect(bb.exit_ip).to eql(17)
47
+ end
48
+
49
+ it "creates a basic block at IP 18-19" do
50
+ bb = cfg.basic_blocks[18]
51
+
52
+ expect(bb.enter_ip).to eql(18)
53
+ expect(bb.exit_ip).to eql(19)
54
+ end
55
+
56
+ it "creates a basic block at IP 20-23" do
57
+ bb = cfg.basic_blocks[20]
58
+
59
+ expect(bb.enter_ip).to eql(20)
60
+ expect(bb.exit_ip).to eql(23)
61
+ end
62
+
63
+ it "set the count of the times the basic block was executed" do
64
+ obj.m
65
+ cfg.graph
66
+
67
+ bb = cfg.basic_blocks[0]
68
+
69
+ expect(bb.count).to eql(1)
70
+ end
71
+
72
+ it "sets the lines covered by the basic block" do
73
+ lines = cfg.basic_blocks[0].lines
74
+
75
+ expect(lines.size).to eql(3)
76
+ expect(lines[0]).to eql(5)
77
+ expect(lines[1]).to eql(6)
78
+ expect(lines[2]).to eql(7)
79
+ end
80
+ end
81
+ end
82
+
83
+ describe "#coverage" do
84
+ it "returns a map of source code lines to execution counts" do
85
+ coverage = Rubinius::Coverage.new.coverage code
86
+
87
+ expect(coverage.size).to eql(7)
88
+ expect(coverage[5]).to eql(1)
89
+ expect(coverage[6]).to eql(1)
90
+ expect(coverage[7]).to eql(1)
91
+ expect(coverage[8]).to eql(1)
92
+ # TODO: fix bug generating line info for lines 9, 11, 12 in the code
93
+ # above.
94
+ expect(coverage[10]).to eql(1)
95
+ expect(coverage[13]).to eql(1)
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,96 @@
1
+ require "spec_helper"
2
+
3
+ module CoverageSpecs
4
+ class LoopBranch
5
+ def m
6
+ i = 1
7
+ while i < 10
8
+ 2
9
+ i += 1
10
+ end
11
+
12
+ 4
13
+ end
14
+ end
15
+ end
16
+
17
+ describe Rubinius::Coverage do
18
+ context "with a loop branch" do
19
+ let(:obj) { CoverageSpecs::LoopBranch.new }
20
+ let(:code) { obj.method(:m).executable }
21
+
22
+ describe Rubinius::Coverage::CFG do
23
+ let(:cfg) { Rubinius::Coverage::CFG.new code, code.call_sites }
24
+
25
+ before do
26
+ cfg.graph
27
+ end
28
+
29
+ describe "#graph" do
30
+ it "creates five BasicBlock instances" do
31
+ expect(cfg.basic_blocks.size).to eql(5)
32
+ end
33
+
34
+ it "creates a basic block at IP 0-4" do
35
+ bb = cfg.basic_blocks[0]
36
+
37
+ expect(bb.enter_ip).to eql(0)
38
+ expect(bb.exit_ip).to eql(4)
39
+ end
40
+
41
+ it "creates a basic block at IP 5-13" do
42
+ bb = cfg.basic_blocks[5]
43
+
44
+ expect(bb.enter_ip).to eql(5)
45
+ expect(bb.exit_ip).to eql(13)
46
+ end
47
+
48
+ it "creates a basic block at IP 14-29" do
49
+ bb = cfg.basic_blocks[14]
50
+
51
+ expect(bb.enter_ip).to eql(14)
52
+ expect(bb.exit_ip).to eql(29)
53
+ end
54
+
55
+ it "creates a basic block at IP 30-34" do
56
+ bb = cfg.basic_blocks[30]
57
+
58
+ expect(bb.enter_ip).to eql(30)
59
+ expect(bb.exit_ip).to eql(34)
60
+ end
61
+
62
+ it "set the count of the times the basic block was executed" do
63
+ obj.m
64
+ cfg.graph
65
+
66
+ bb = cfg.basic_blocks[0]
67
+
68
+ expect(bb.count).to eql(1)
69
+ end
70
+
71
+ it "sets the lines covered by the basic block" do
72
+ lines = cfg.basic_blocks[0].lines
73
+
74
+ expect(lines.size).to eql(2)
75
+ expect(lines[0]).to eql(5)
76
+ expect(lines[1]).to eql(6)
77
+ end
78
+ end
79
+ end
80
+
81
+ describe "#coverage" do
82
+ it "returns a map of source code lines to execution counts" do
83
+ coverage = Rubinius::Coverage.new.coverage code
84
+
85
+ expect(coverage.size).to eql(7)
86
+ expect(coverage[5]).to eql(1)
87
+ expect(coverage[6]).to eql(1)
88
+ expect(coverage[7]).to eql(10)
89
+ expect(coverage[8]).to eql(9)
90
+ expect(coverage[9]).to eql(9)
91
+ # TODO: fix bug generating line info for lines 10, 11, 12 in the code
92
+ # above.
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,96 @@
1
+ require "spec_helper"
2
+
3
+ module CoverageSpecs
4
+ class SingleBranch
5
+ def m
6
+ a = 1
7
+ if a == 2
8
+ 3
9
+ end
10
+
11
+ 4
12
+ end
13
+ end
14
+ end
15
+
16
+ describe Rubinius::Coverage do
17
+ context "with a single branch" do
18
+ let(:obj) { CoverageSpecs::SingleBranch.new }
19
+ let(:code) { obj.method(:m).executable }
20
+
21
+ describe Rubinius::Coverage::CFG do
22
+ let(:cfg) { Rubinius::Coverage::CFG.new code, code.call_sites }
23
+
24
+ before do
25
+ cfg.graph
26
+ end
27
+
28
+ describe "#graph" do
29
+ it "creates five BasicBlock instances" do
30
+ expect(cfg.basic_blocks.size).to eql(5)
31
+ end
32
+
33
+ it "creates a basic block at IP 0-13" do
34
+ bb = cfg.basic_blocks[0]
35
+
36
+ expect(bb.enter_ip).to eql(0)
37
+ expect(bb.exit_ip).to eql(13)
38
+ end
39
+
40
+ it "creates a basic block at IP 14-17" do
41
+ bb = cfg.basic_blocks[14]
42
+
43
+ expect(bb.enter_ip).to eql(14)
44
+ expect(bb.exit_ip).to eql(17)
45
+ end
46
+
47
+ it "creates a basic block at IP 18-18" do
48
+ bb = cfg.basic_blocks[18]
49
+
50
+ expect(bb.enter_ip).to eql(18)
51
+ expect(bb.exit_ip).to eql(18)
52
+ end
53
+
54
+ it "creates a basic block at IP 19-22" do
55
+ bb = cfg.basic_blocks[19]
56
+
57
+ expect(bb.enter_ip).to eql(19)
58
+ expect(bb.exit_ip).to eql(22)
59
+ end
60
+
61
+ it "set the count of the times the basic block was executed" do
62
+ obj.m
63
+ cfg.graph
64
+
65
+ bb = cfg.basic_blocks[0]
66
+
67
+ expect(bb.count).to eql(1)
68
+ end
69
+
70
+ it "sets the lines covered by the basic block" do
71
+ lines = cfg.basic_blocks[0].lines
72
+
73
+ expect(lines.size).to eql(3)
74
+ expect(lines[0]).to eql(5)
75
+ expect(lines[1]).to eql(6)
76
+ expect(lines[2]).to eql(7)
77
+ end
78
+ end
79
+ end
80
+
81
+ describe "#coverage" do
82
+ it "returns a map of source code lines to execution counts" do
83
+ coverage = Rubinius::Coverage.new.coverage code
84
+
85
+ expect(coverage.size).to eql(6)
86
+ expect(coverage[5]).to eql(1)
87
+ expect(coverage[6]).to eql(1)
88
+ expect(coverage[7]).to eql(1)
89
+ expect(coverage[8]).to eql(1)
90
+ # TODO: fix bug generating line info for lines 9, 10 in the code
91
+ # above.
92
+ expect(coverage[11]).to eql(1)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,73 @@
1
+ require "spec_helper"
2
+
3
+ module CoverageSpecs
4
+ class Single
5
+ def m
6
+ a = 1
7
+ b = 2
8
+ c = a + b
9
+ c.to_s
10
+ end
11
+ end
12
+ end
13
+
14
+ describe Rubinius::Coverage do
15
+ context "with a single basic block" do
16
+ let(:obj) { CoverageSpecs::Single.new }
17
+ let(:code) { obj.method(:m).executable }
18
+
19
+ describe Rubinius::Coverage::CFG do
20
+ let(:cfg) { Rubinius::Coverage::CFG.new code, code.call_sites }
21
+
22
+ before do
23
+ cfg.graph
24
+ end
25
+
26
+ describe "#graph" do
27
+ it "creates a single BasicBlock instance" do
28
+ expect(cfg.basic_blocks.size).to eql(2)
29
+ end
30
+
31
+ it "sets the enter and exit IP for the basic block" do
32
+ bb = cfg.basic_blocks[0]
33
+
34
+ expect(bb.enter_ip).to eql(0)
35
+ expect(bb.exit_ip).to eql(24)
36
+ end
37
+
38
+ it "set the count of the times the basic block was executed" do
39
+ obj.m
40
+ cfg.graph
41
+
42
+ bb = cfg.basic_blocks[0]
43
+
44
+ expect(bb.count).to eql(1)
45
+ end
46
+
47
+ it "sets the lines covered by the basic block" do
48
+ lines = cfg.basic_blocks[0].lines
49
+
50
+ expect(lines.size).to eql(5)
51
+ expect(lines[0]).to eql(5)
52
+ expect(lines[1]).to eql(6)
53
+ expect(lines[2]).to eql(7)
54
+ expect(lines[3]).to eql(8)
55
+ expect(lines[4]).to eql(9)
56
+ end
57
+ end
58
+ end
59
+
60
+ describe "#coverage" do
61
+ it "returns a map of source code lines to execution counts" do
62
+ coverage = Rubinius::Coverage.new.coverage code
63
+
64
+ expect(coverage.size).to eql(5)
65
+ expect(coverage[5]).to eql(1)
66
+ expect(coverage[6]).to eql(1)
67
+ expect(coverage[7]).to eql(1)
68
+ expect(coverage[8]).to eql(1)
69
+ expect(coverage[9]).to eql(1)
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1 @@
1
+ require "rubinius/coverage"
metadata CHANGED
@@ -1,22 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubinius-coverage
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: '2.1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Shirai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-15 00:00:00.000000000 Z
11
+ date: 2016-05-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
16
  - - "~>"
18
17
  - !ruby/object:Gem::Version
19
18
  version: '1.3'
19
+ name: bundler
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
@@ -25,12 +25,12 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
29
28
  requirement: !ruby/object:Gem::Requirement
30
29
  requirements:
31
30
  - - "~>"
32
31
  - !ruby/object:Gem::Version
33
32
  version: '10.0'
33
+ name: rake
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
@@ -38,12 +38,25 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '3'
47
+ name: rspec
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3'
41
55
  description: Rubinius coverage tool.
42
56
  email:
43
57
  - brixen@gmail.com
44
58
  executables: []
45
- extensions:
46
- - ext/rubinius/coverage/extconf.rb
59
+ extensions: []
47
60
  extra_rdoc_files: []
48
61
  files:
49
62
  - ".gitignore"
@@ -51,11 +64,14 @@ files:
51
64
  - LICENSE
52
65
  - README.md
53
66
  - Rakefile
54
- - ext/rubinius/coverage/coverage.cpp
55
- - ext/rubinius/coverage/extconf.rb
56
67
  - lib/rubinius/coverage.rb
57
68
  - lib/rubinius/coverage/version.rb
58
69
  - rubinius-coverage.gemspec
70
+ - spec/basic_block/double_branch_spec.rb
71
+ - spec/basic_block/loop_spec.rb
72
+ - spec/basic_block/single_branch_spec.rb
73
+ - spec/basic_block/single_spec.rb
74
+ - spec/spec_helper.rb
59
75
  homepage: https://github.com/rubinius/rubinius-coverage
60
76
  licenses:
61
77
  - BSD
@@ -76,9 +92,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
92
  version: '0'
77
93
  requirements: []
78
94
  rubyforge_project:
79
- rubygems_version: 2.0.7
95
+ rubygems_version: 2.6.2
80
96
  signing_key:
81
97
  specification_version: 4
82
98
  summary: Rubinius coverage tool.
83
- test_files: []
84
- has_rdoc:
99
+ test_files:
100
+ - spec/basic_block/double_branch_spec.rb
101
+ - spec/basic_block/loop_spec.rb
102
+ - spec/basic_block/single_branch_spec.rb
103
+ - spec/basic_block/single_spec.rb
104
+ - spec/spec_helper.rb
@@ -1,163 +0,0 @@
1
- #include <rbxti.hpp>
2
- #include <rbxti/atomic.hpp>
3
- #include <rbx_config.h>
4
-
5
- #include <iostream>
6
- #ifdef RBX_HAVE_TR1
7
- #include <tr1/unordered_map>
8
- #define std_unordered_map std::tr1::unordered_map
9
- #else
10
- #include <unordered_map>
11
- #define std_unordered_map std::unordered_map
12
- #endif
13
-
14
- using namespace rbxti;
15
-
16
- #if defined(RBX_HAVE_TR1) && !defined(RBX_HAVE_TR1_HASH)
17
- namespace std {
18
- namespace tr1 {
19
- template <>
20
- struct hash<r_mint> {
21
- size_t operator()(const r_mint id) const {
22
- return id;
23
- }
24
- };
25
- }
26
- }
27
- #endif
28
-
29
- namespace coverage {
30
-
31
- typedef std_unordered_map<int, int> InstructionCoverageMap;
32
- typedef std_unordered_map<r_mint, InstructionCoverageMap*> CoverageMap;
33
-
34
- class Coverage {
35
- CoverageMap coverage_map_;
36
- rbxti::SpinLock lock_;
37
-
38
- public:
39
- Coverage() { }
40
- ~Coverage();
41
-
42
- void lock() {
43
- lock_.lock();
44
- }
45
-
46
- void unlock() {
47
- lock_.unlock();
48
- }
49
-
50
- void add(Env* env, r_mint id, int ip);
51
- robject results(Env* env);
52
- };
53
-
54
- Coverage::~Coverage() {
55
- for(CoverageMap::iterator i = coverage_map_.begin();
56
- i != coverage_map_.end();
57
- i++) {
58
- delete i->second;
59
- }
60
- }
61
-
62
- void Coverage::add(Env* env, r_mint id, int ip) {
63
- lock();
64
-
65
- InstructionCoverageMap *map;
66
- CoverageMap::iterator i = coverage_map_.find(id);
67
-
68
- if(i == coverage_map_.end()) {
69
- map = new InstructionCoverageMap;
70
- coverage_map_[id] = map;
71
- } else {
72
- map = i->second;
73
- }
74
-
75
- InstructionCoverageMap::iterator j = map->find(ip);
76
-
77
- if(j == map->end()) {
78
- (*map)[ip] = 1;
79
- } else {
80
- (*map)[ip] += 1;
81
- }
82
-
83
- unlock();
84
- }
85
-
86
- static void ccode_iterator(Env* env, rcompiled_code code, void* data) {
87
- rtable map = (rtable)data;
88
- r_mint id = env->method_id(code);
89
-
90
- bool found = false;
91
- robject obj = env->table_fetch(map, env->integer_new(id), &found);
92
- if(!found) return;
93
-
94
- rtable attr = env->cast_to_rtable(obj);
95
- if(!attr) return;
96
-
97
- env->table_store(attr, env->symbol("code"), code);
98
- }
99
-
100
- robject Coverage::results(Env* env) {
101
- rtable coverage_map = env->table_new();
102
-
103
- for(CoverageMap::iterator i = coverage_map_.begin();
104
- i != coverage_map_.end();
105
- i++) {
106
- InstructionCoverageMap* map = i->second;
107
- rtable method_map = env->table_new();
108
-
109
- for(InstructionCoverageMap::iterator j = map->begin();
110
- j != map->end();
111
- j++) {
112
- env->table_store(method_map,
113
- env->integer_new(j->first),
114
- env->integer_new(j->second));
115
- }
116
-
117
- rtable attr = env->table_new();
118
- env->table_store(attr, env->symbol("counts"), method_map);
119
-
120
- env->table_store(coverage_map, env->integer_new(i->first), attr);
121
- }
122
-
123
- env->find_all_compiled_code(ccode_iterator, (void*)coverage_map);
124
-
125
- return coverage_map;
126
- }
127
-
128
- namespace {
129
- void coverage_enable(Env* env) {
130
- Coverage* coverage = new Coverage;
131
- env->set_global_tool_data(coverage);
132
- }
133
-
134
- robject coverage_results(Env* env) {
135
- Coverage* coverage = reinterpret_cast<Coverage*>(env->global_tool_data());
136
-
137
- env->set_tool_at_ip(NULL);
138
- env->set_global_tool_data(NULL);
139
-
140
- robject results = coverage->results(env);
141
- delete coverage;
142
-
143
- return results;
144
- }
145
-
146
- void coverage_at_ip(Env* env, rmachine_code mcode, int ip) {
147
- Coverage* coverage = reinterpret_cast<Coverage*>(env->global_tool_data());
148
-
149
- if(!coverage) return;
150
-
151
- coverage->add(env, env->machine_code_id(mcode), ip);
152
- }
153
- }
154
-
155
- extern "C" int Tool_Init(Env* env) {
156
- env->set_tool_enable(coverage_enable);
157
- env->set_tool_results(coverage_results);
158
-
159
- env->set_tool_at_ip(coverage_at_ip);
160
-
161
- return 1;
162
- }
163
- }
@@ -1,3 +0,0 @@
1
- require 'mkmf'
2
-
3
- create_makefile 'rubinius/coverage/coverage'