edgecase-ocov 1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +3 -0
- data/Rakefile +68 -0
- data/bin/ocov +7 -0
- data/lib/ocov.rb +12 -0
- data/lib/ocov/gcov.rb +49 -0
- data/lib/ocov/project.rb +95 -0
- data/lib/ocov/source_line.rb +23 -0
- data/lib/ocov/target.rb +7 -0
- data/lib/ocov/templates/file.html.erb +24 -0
- data/lib/ocov/templates/index.html.erb +72 -0
- metadata +67 -0
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Rakefile for ocov -*- ruby -*-
|
2
|
+
begin
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'rake/testtask'
|
6
|
+
require 'rake/rdoctask'
|
7
|
+
rescue Exception
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
|
11
|
+
if `ruby -Ilib -rocov -e "print OCov.version"` =~ /([0-9.]+)$/
|
12
|
+
CURRENT_VERSION = $1
|
13
|
+
else
|
14
|
+
CURRENT_VERSION = '0.0.0'
|
15
|
+
end
|
16
|
+
|
17
|
+
PKG_FILES = FileList['[A-Z]*',
|
18
|
+
'README.rdoc',
|
19
|
+
'bin/*',
|
20
|
+
'lib/**/*.rb',
|
21
|
+
'lib/ocov/templates/*.erb',
|
22
|
+
'doc/**/*'
|
23
|
+
]
|
24
|
+
|
25
|
+
desc 'Generate documentation for magic bus'
|
26
|
+
rd = Rake::RDocTask.new(:rdoc) do |rdoc|
|
27
|
+
rdoc.rdoc_dir = 'html'
|
28
|
+
rdoc.template = 'doc/jamis.rb'
|
29
|
+
rdoc.rdoc_dir = 'rdoc'
|
30
|
+
rdoc.title = 'ocov'
|
31
|
+
rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README.rdoc' << '--title' << 'Magic Bus'
|
32
|
+
rdoc.rdoc_files.include('README.rdoc', 'lib/**/*.rb', 'doc/**/*.rdoc')
|
33
|
+
end
|
34
|
+
|
35
|
+
if !defined?(Gem)
|
36
|
+
puts "Package target requires RubyGEMs"
|
37
|
+
else
|
38
|
+
spec = Gem::Specification.new do |s|
|
39
|
+
s.name = 'ocov'
|
40
|
+
s.version = CURRENT_VERSION
|
41
|
+
s.summary = 'C0 coverage report tool for Objective-C'
|
42
|
+
s.executables = ['ocov']
|
43
|
+
s.files = PKG_FILES.to_a
|
44
|
+
s.require_path = 'lib'
|
45
|
+
s.has_rdoc = true
|
46
|
+
s.extra_rdoc_files = rd.rdoc_files.reject {|fn| fn =~ /\.rb$/}.to_a
|
47
|
+
s.rdoc_options = rd.options
|
48
|
+
|
49
|
+
s.author = "EdgeCase, LLC"
|
50
|
+
s.email = "scott@edgecase.com"
|
51
|
+
s.homepage = "http://github.com/edgecase/ocov/tree/master"
|
52
|
+
end
|
53
|
+
|
54
|
+
package_task = Rake::GemPackageTask.new(spec) do |pkg|
|
55
|
+
pkg.need_zip = true
|
56
|
+
pkg.need_tar = true
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "Run all tests"
|
61
|
+
task :default => [:test]
|
62
|
+
|
63
|
+
Rake::TestTask.new(:test) do |t|
|
64
|
+
t.test_files = FileList['test/test*.rb']
|
65
|
+
t.warning = true
|
66
|
+
t.verbose = false
|
67
|
+
end
|
68
|
+
|
data/bin/ocov
ADDED
data/lib/ocov.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'ocov', 'project')
|
2
|
+
require File.join(File.dirname(__FILE__), 'ocov', 'gcov')
|
3
|
+
require File.join(File.dirname(__FILE__), 'ocov', 'source_line')
|
4
|
+
require File.join(File.dirname(__FILE__), 'ocov', 'target')
|
5
|
+
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
module OCov
|
9
|
+
def self.version
|
10
|
+
"1.0"
|
11
|
+
end
|
12
|
+
end
|
data/lib/ocov/gcov.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
module OCov
|
2
|
+
class GCov
|
3
|
+
attr_reader :name
|
4
|
+
attr_reader :lines
|
5
|
+
attr_reader :lines_of_code
|
6
|
+
attr_reader :coverage
|
7
|
+
|
8
|
+
def initialize(build_path, class_file)
|
9
|
+
@class_file = class_file
|
10
|
+
@build_path = build_path
|
11
|
+
@name = File.basename(class_file)
|
12
|
+
@lines = []
|
13
|
+
@coverage = 100.00
|
14
|
+
@lines_of_code = 0
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
run_gcov
|
19
|
+
parse_gcov_output
|
20
|
+
cleanup
|
21
|
+
end
|
22
|
+
|
23
|
+
def total_lines
|
24
|
+
lines.size
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def run_gcov
|
29
|
+
results = `gcov -o "#{@build_path}" "#{@class_file}"`
|
30
|
+
if results =~ /Lines executed:(\d+\.\d+)% of (\d+)/
|
31
|
+
@lines_of_code = $2.to_i
|
32
|
+
@coverage = $1.to_f
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse_gcov_output
|
37
|
+
gcov_file = File.open("#{File.basename(@class_file)}.gcov")
|
38
|
+
gcov_file.readlines.each do |line|
|
39
|
+
if OCov::SourceLine.parsable?(line)
|
40
|
+
@lines << OCov::SourceLine.new(line)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def cleanup
|
46
|
+
FileUtils.rm_f("#{File.basename(@class_file)}.gcov")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/ocov/project.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module OCov
|
4
|
+
class Project
|
5
|
+
attr_reader :name
|
6
|
+
attr_reader :files
|
7
|
+
|
8
|
+
def initialize(project_path)
|
9
|
+
@project_path = project_path
|
10
|
+
@files = []
|
11
|
+
|
12
|
+
determine_name_from_xcode_file
|
13
|
+
end
|
14
|
+
|
15
|
+
def analyze_and_report
|
16
|
+
analyze
|
17
|
+
|
18
|
+
FileUtils.rm_rf('coverage')
|
19
|
+
FileUtils.mkdir('coverage')
|
20
|
+
|
21
|
+
template = ERB.new(open(File.join(File.dirname(__FILE__), 'templates', 'index.html.erb')).read)
|
22
|
+
f = open('coverage/index.html', 'w')
|
23
|
+
f.write(template.result(binding))
|
24
|
+
f.close
|
25
|
+
|
26
|
+
files.each do |file|
|
27
|
+
template = ERB.new(open(File.join(File.dirname(__FILE__), 'templates', 'file.html.erb')).read)
|
28
|
+
f = open("coverage/#{file.name.gsub('.', '_')}.html", 'w')
|
29
|
+
f.write(template.result(file.send(:binding)))
|
30
|
+
f.close
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def analyze
|
35
|
+
class_files.each do |file|
|
36
|
+
gcov = OCov::GCov.new(build_path, file)
|
37
|
+
gcov.run
|
38
|
+
@files << gcov
|
39
|
+
end
|
40
|
+
@files.sort! { |a, b| b.coverage <=> a.coverage }
|
41
|
+
end
|
42
|
+
|
43
|
+
def total_coverage
|
44
|
+
(total_lines_covered.to_f / total_lines_of_code) * 100
|
45
|
+
end
|
46
|
+
|
47
|
+
def total_lines_covered
|
48
|
+
files.inject(0) { |sum, file| sum + ((file.coverage / 100.0) * file.lines_of_code).to_i }
|
49
|
+
end
|
50
|
+
|
51
|
+
def total_lines
|
52
|
+
files.inject(0) { |sum, file| sum + file.total_lines }
|
53
|
+
end
|
54
|
+
|
55
|
+
def total_lines_of_code
|
56
|
+
files.inject(0) { |sum, file| sum + file.lines_of_code }
|
57
|
+
end
|
58
|
+
|
59
|
+
def classes_path
|
60
|
+
File.join(@project_path, 'Classes')
|
61
|
+
end
|
62
|
+
|
63
|
+
def build_path
|
64
|
+
File.join(@project_path, 'build', "#{@name}.build", 'Debug-iphonesimulator', "#{OCov::Target.name}.build", 'Objects-normal', 'i386')
|
65
|
+
end
|
66
|
+
|
67
|
+
def class_files
|
68
|
+
Dir.glob(File.join(classes_path, '*.m')).inject([]) do |arr, file|
|
69
|
+
arr << file if File.basename(file) !~ /(AppDelegate|ViewController)\.m$/
|
70
|
+
arr
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def gcda_files
|
75
|
+
Dir.glob(File.join(build_path, '*.gcda')).inject([]) do |arr, file|
|
76
|
+
arr << file if File.basename(file) !~ /^(GTM|Test)/
|
77
|
+
arr
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
private
|
86
|
+
def determine_name_from_xcode_file
|
87
|
+
xcode_file = Dir.glob(File.join(@project_path, '*.xcodeproj')).first
|
88
|
+
if xcode_file
|
89
|
+
@name = File.basename(xcode_file, '.xcodeproj')
|
90
|
+
else
|
91
|
+
raise "Unable to determine project name"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module OCov
|
2
|
+
class SourceLine
|
3
|
+
def self.parsable?(line)
|
4
|
+
!(line =~ / -: 0:/)
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(line)
|
8
|
+
@line = line
|
9
|
+
end
|
10
|
+
|
11
|
+
def covered?
|
12
|
+
!(@line =~ /^ #####:/)
|
13
|
+
end
|
14
|
+
|
15
|
+
def source_line
|
16
|
+
@line.strip.split(':')[2..-1].join(':')
|
17
|
+
end
|
18
|
+
|
19
|
+
def line_number
|
20
|
+
@line.split(':')[1].to_i
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/ocov/target.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title><%= file.name %> - C0 code coverage</title>
|
4
|
+
<style type="text/css">
|
5
|
+
span { width: 100%; display: block;}
|
6
|
+
|
7
|
+
span.covered {
|
8
|
+
background-color: rgb(185, 210, 200);
|
9
|
+
}
|
10
|
+
|
11
|
+
span.uncovered {
|
12
|
+
background-color: rgb(225, 110, 110);
|
13
|
+
}
|
14
|
+
</style>
|
15
|
+
</head>
|
16
|
+
<body>
|
17
|
+
<h1>C0 code coverage information for <%= name %></h1>
|
18
|
+
<p>Generated on <%= Time.now %> with <a href="http://github.com/edgecase/ocov/tree/master">ocov <%= OCov.version %></a></p>
|
19
|
+
<hr />
|
20
|
+
<pre>
|
21
|
+
<% file.lines.each do |line| %><span class="<%= line.covered? ? 'covered' : 'uncovered' %>"><%= '% 3d' % line.line_number %>: <%= line.source_line %></span><% end %>
|
22
|
+
</pre>
|
23
|
+
</body>
|
24
|
+
</html>
|
@@ -0,0 +1,72 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title><%= name %> C0 code coverage</title>
|
4
|
+
<style type="text/css">
|
5
|
+
.graph_outer {
|
6
|
+
height: 12px;
|
7
|
+
background: red;
|
8
|
+
width: 100px;
|
9
|
+
border: 1px solid #808080;
|
10
|
+
float:right;
|
11
|
+
}
|
12
|
+
.graph_inner {
|
13
|
+
height: 12px;
|
14
|
+
background: #00F000;
|
15
|
+
}
|
16
|
+
table.report { border-collapse: collapse; width: 100%; }
|
17
|
+
th {
|
18
|
+
background: #dcecff;
|
19
|
+
border: #d0d0d0 1px solid;
|
20
|
+
font-weight: bold;
|
21
|
+
text-align: center;
|
22
|
+
}
|
23
|
+
table.report td { border: #d0d0d0 1px solid; }
|
24
|
+
td.value { text-align: right; }
|
25
|
+
th.filename { width: 55%; }
|
26
|
+
</style>
|
27
|
+
</head>
|
28
|
+
<body>
|
29
|
+
<h1>C0 code coverage information for <%= name %></h1>
|
30
|
+
<p>Generated on <%= Time.now %> with <a href="http://github.com/edgecase/ocov/tree/master">ocov <%= OCov.version %></a></p>
|
31
|
+
<hr />
|
32
|
+
<table class="report">
|
33
|
+
<thead>
|
34
|
+
<th class="filename">Name</th>
|
35
|
+
<th>Total Lines</th>
|
36
|
+
<th>Lines of Code</th>
|
37
|
+
<th>Coverage</th>
|
38
|
+
</thead>
|
39
|
+
<tbody>
|
40
|
+
<tr>
|
41
|
+
<td>TOTAL</td>
|
42
|
+
<td class="value"><%= total_lines %></td>
|
43
|
+
<td class="value"><%= total_lines_of_code %></td>
|
44
|
+
<td>
|
45
|
+
<table>
|
46
|
+
<tr>
|
47
|
+
<td class="value" style="border: 0px; width: 50px;"><%= '%.1f' % total_coverage %>%</td>
|
48
|
+
<td style="border: 0px;"><div class="graph_outer"><div class="graph_inner" style="width: <%= '%d' % total_coverage %>%;"></div></div></td>
|
49
|
+
</tr>
|
50
|
+
</table>
|
51
|
+
</td>
|
52
|
+
</tr>
|
53
|
+
|
54
|
+
<% files.each do |file| %>
|
55
|
+
<tr>
|
56
|
+
<td><a href="<%= file.name.gsub('.', '_') %>.html"><%= file.name %></a></td>
|
57
|
+
<td class="value"><%= file.total_lines %></td>
|
58
|
+
<td class="value"><%= file.lines_of_code %></td>
|
59
|
+
<td>
|
60
|
+
<table>
|
61
|
+
<tr>
|
62
|
+
<td class="value" style="border: 0px; width: 50px;"><%= '%.1f' % file.coverage %>%</td>
|
63
|
+
<td style="border: 0px;"><div class="graph_outer"><div class="graph_inner" style="width: <%= '%d' % file.coverage %>%;"></div></div></td>
|
64
|
+
</tr>
|
65
|
+
</table>
|
66
|
+
</td>
|
67
|
+
</tr>
|
68
|
+
<% end %>
|
69
|
+
</tbody>
|
70
|
+
</table>
|
71
|
+
</body>
|
72
|
+
</html>
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: edgecase-ocov
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "1.0"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- EdgeCase, LLC
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-01-11 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: scott@edgecase.com
|
18
|
+
executables:
|
19
|
+
- ocov
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
files:
|
25
|
+
- Rakefile
|
26
|
+
- README.rdoc
|
27
|
+
- bin/ocov
|
28
|
+
- lib/ocov/gcov.rb
|
29
|
+
- lib/ocov/project.rb
|
30
|
+
- lib/ocov/source_line.rb
|
31
|
+
- lib/ocov/target.rb
|
32
|
+
- lib/ocov.rb
|
33
|
+
- lib/ocov/templates/file.html.erb
|
34
|
+
- lib/ocov/templates/index.html.erb
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://github.com/edgecase/ocov/tree/master
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options:
|
39
|
+
- --line-numbers
|
40
|
+
- --inline-source
|
41
|
+
- --main
|
42
|
+
- README.rdoc
|
43
|
+
- --title
|
44
|
+
- Magic Bus
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.2.0
|
63
|
+
signing_key:
|
64
|
+
specification_version: 2
|
65
|
+
summary: C0 coverage report tool for Objective-C
|
66
|
+
test_files: []
|
67
|
+
|