edgecase-ocov 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ ocov is a wrapper around gcov for producing rcov-like C0 reports for Objective C projects.
2
+
3
+ ocov is developed at EdgeCase.
@@ -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
+
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- ruby -*-
3
+
4
+ require 'ocov'
5
+
6
+ project = OCov::Project.new(Dir.pwd)
7
+ project.analyze_and_report
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,7 @@
1
+ module OCov
2
+ class Target
3
+ def self.name
4
+ 'Unit Test'
5
+ end
6
+ end
7
+ end
@@ -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
+