edgecase-ocov 1.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.
@@ -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
+