valo-rcov 0.8.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/BLURB +111 -0
  2. data/LICENSE +53 -0
  3. data/Rakefile +88 -0
  4. data/THANKS +96 -0
  5. data/bin/rcov +500 -0
  6. data/doc/readme_for_api +41 -0
  7. data/doc/readme_for_emacs +64 -0
  8. data/doc/readme_for_rake +62 -0
  9. data/doc/readme_for_vim +47 -0
  10. data/editor-extensions/rcov.el +131 -0
  11. data/editor-extensions/rcov.vim +38 -0
  12. data/ext/rcovrt/1.8/callsite.c +216 -0
  13. data/ext/rcovrt/1.8/rcovrt.c +287 -0
  14. data/ext/rcovrt/1.9/callsite.c +234 -0
  15. data/ext/rcovrt/1.9/rcovrt.c +264 -0
  16. data/ext/rcovrt/extconf.rb +21 -0
  17. data/lib/rcov.rb +1009 -0
  18. data/lib/rcov/formatters.rb +15 -0
  19. data/lib/rcov/formatters/base_formatter.rb +168 -0
  20. data/lib/rcov/formatters/full_text_report.rb +55 -0
  21. data/lib/rcov/formatters/html_coverage.rb +255 -0
  22. data/lib/rcov/formatters/html_erb_template.rb +128 -0
  23. data/lib/rcov/formatters/text_coverage_diff.rb +199 -0
  24. data/lib/rcov/formatters/text_report.rb +36 -0
  25. data/lib/rcov/formatters/text_summary.rb +15 -0
  26. data/lib/rcov/lowlevel.rb +145 -0
  27. data/lib/rcov/rcovtask.rb +156 -0
  28. data/lib/rcov/templates/detail.html.erb +78 -0
  29. data/lib/rcov/templates/index.html.erb +76 -0
  30. data/lib/rcov/templates/screen.css +165 -0
  31. data/lib/rcov/version.rb +10 -0
  32. data/setup.rb +1588 -0
  33. data/test/assets/sample_01.rb +7 -0
  34. data/test/assets/sample_02.rb +5 -0
  35. data/test/assets/sample_03.rb +20 -0
  36. data/test/assets/sample_04.rb +10 -0
  37. data/test/assets/sample_05-new.rb +17 -0
  38. data/test/assets/sample_05-old.rb +13 -0
  39. data/test/assets/sample_05.rb +17 -0
  40. data/test/call_site_analyzer_test.rb +171 -0
  41. data/test/code_coverage_analyzer_test.rb +184 -0
  42. data/test/file_statistics_test.rb +471 -0
  43. data/test/functional_test.rb +89 -0
  44. data/test/turn_off_rcovrt.rb +4 -0
  45. metadata +107 -0
data/BLURB ADDED
@@ -0,0 +1,111 @@
1
+ Overview
2
+ ========
3
+ rcov is a code coverage tool for Ruby. It is commonly used for viewing overall
4
+ test coverage of target code. It features:
5
+ * fast execution: 20-300 times faster than previous tools
6
+ * multiple analysis modes: standard, bogo-profile, "intentional testing",
7
+ dependency analysis...
8
+ * detection of uncovered code introduced since the last run ("differential
9
+ code coverage")
10
+ * fairly accurate coverage information through code linkage inference using
11
+ simple heuristics
12
+ * cross-referenced XHTML and several kinds of text reports
13
+ * support for easy automation with Rake
14
+ * colorblind-friendliness
15
+
16
+ How do I use it?
17
+ ================
18
+
19
+ In the common scenario, your tests are under test/ and the target code
20
+ (whose coverage you want) is in lib/. In that case, all you have to do is
21
+ use rcov to run the tests (instead of testrb), and a number of XHTML files
22
+ with the code coverage information will be generated, e.g.
23
+
24
+ rcov -Ilib test/*.rb
25
+
26
+ will execute all the .rb files under test/ and generate the code coverage
27
+ report for the target code (i.e. for the files in lib/) under coverage/. The
28
+ target code needs not be under lib/; rcov will detect is as long as it is
29
+ require()d by the tests. rcov is smart enough to ignore "uninteresting"
30
+ files: the tests themselves, files installed in Ruby's standard locations,
31
+ etc. See rcov --help for the list of regexps rcov matches filenames
32
+ against.
33
+
34
+ rcov can also be used from Rake; see readme_for_rake or the RDoc documentation
35
+ for more information.
36
+
37
+ rcov can output information in several formats, and perform different kinds
38
+ of analyses in addition to plain code coverage. See rcov --help for a
39
+ description of the available options.
40
+
41
+ Sample output
42
+ =============
43
+
44
+ The text report (also used by default in RcovTasks) resembles
45
+
46
+
47
+ +-----------------------------------------------------+-------+-------+--------+
48
+ | File | Lines | LOC | COV |
49
+ +-----------------------------------------------------+-------+-------+--------+
50
+ |lib/rcov.rb | 572 | 358 | 91.3% |
51
+ +-----------------------------------------------------+-------+-------+--------+
52
+ |Total | 572 | 358 | 91.3% |
53
+ +-----------------------------------------------------+-------+-------+--------+
54
+ 91.3% 1 file(s) 572 Lines 358 LOC
55
+
56
+
57
+
58
+ The (undecorated) textual output with execution count information looks like this:
59
+
60
+ $ rcov --no-html --text-counts b.rb
61
+ ================================================================================
62
+ ./b.rb
63
+ ================================================================================
64
+ | 2
65
+ a, b, c = (1..3).to_a | 2
66
+ 10.times do | 1
67
+ a += 1 | 10
68
+ 20.times do |i| | 10
69
+ b += i | 200
70
+ b.times do | 200
71
+ c += (j = (b-a).abs) > 0 ? j : 0 | 738800
72
+ end | 0
73
+ end | 0
74
+ end | 0
75
+
76
+
77
+ rcov can detect when you've added code that was not covered by your unit
78
+ tests:
79
+
80
+ $ rcov --text-coverage-diff --no-color test/*.rb
81
+ Started
82
+ .......................................
83
+ Finished in 1.163085 seconds.
84
+
85
+ 39 tests, 415 assertions, 0 failures, 0 errors
86
+
87
+ ================================================================================
88
+ !!!!! Uncovered code introduced in lib/rcov.rb
89
+
90
+ ### lib/rcov.rb:207
91
+
92
+ def precompute_coverage(comments_run_by_default = true)
93
+ changed = false
94
+ lastidx = lines.size - 1
95
+ if (!is_code?(lastidx) || /^__END__$/ =~ @lines[-1]) && !@coverage[lastidx]
96
+ !! # mark the last block of comments
97
+ !! @coverage[lastidx] ||= :inferred
98
+ !! (lastidx-1).downto(0) do |i|
99
+ !! break if is_code?(i)
100
+ !! @coverage[i] ||= :inferred
101
+ !! end
102
+ !! end
103
+ (0...lines.size).each do |i|
104
+ next if @coverage[i]
105
+ line = @lines[i]
106
+
107
+
108
+
109
+ License
110
+ -------
111
+ rcov is released under the terms of Ruby's license.
data/LICENSE ADDED
@@ -0,0 +1,53 @@
1
+ rcov is copyrighted free software by Mauricio Fernandez <mfp@acm.org>.
2
+ You can redistribute it and/or modify it under either the terms of the GPL,
3
+ or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) give non-standard binaries non-standard names, with
21
+ instructions on where to get the original software distribution.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or binary form,
26
+ provided that you do at least ONE of the following:
27
+
28
+ a) distribute the binaries and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under these terms.
43
+
44
+ 5. The scripts and library files supplied as input to or produced as
45
+ output from the software do not automatically fall under the
46
+ copyright of the software, but belong to whomever generated them,
47
+ and may be sold commercially, and may be aggregated with this
48
+ software.
49
+
50
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
51
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
52
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53
+ PURPOSE.
@@ -0,0 +1,88 @@
1
+ # This Rakefile serves as an example of how to use Rcov::RcovTask.
2
+ # Take a look at the RDoc documentation (or readme_for_rake) for further
3
+ # information.
4
+
5
+ $:.unshift "lib" if File.directory? "lib"
6
+ require 'rcov/rcovtask'
7
+ require 'rcov/version'
8
+ require 'rake/testtask'
9
+ require 'rake/rdoctask'
10
+ require 'rake/gempackagetask'
11
+ require 'rake/clean'
12
+
13
+ puts "************\n#{ENV["PATH"]}\n************\n"
14
+ puts "************\n#{RUBY_VERSION}\n************"
15
+
16
+ # Use the specified rcov executable instead of the one in $PATH
17
+ # (this way we get a sort of informal functional test).
18
+ # This could also be specified from the command like, e.g.
19
+ # rake rcov RCOVPATH=/path/to/myrcov
20
+ ENV["RCOVPATH"] = "bin/rcov"
21
+
22
+ # The following task is largely equivalent to:
23
+ # Rcov::RcovTask.new
24
+ desc "Create a cross-referenced code coverage report."
25
+ Rcov::RcovTask.new do |t|
26
+ t.test_files = FileList['test/*_test.rb']
27
+ t.ruby_opts << "-Ilib:ext/rcovrt" # in order to use this rcov
28
+ t.rcov_opts << "--xrefs" # comment to disable cross-references
29
+ t.verbose = true
30
+ end
31
+
32
+ desc "Analyze code coverage for the FileStatistics class."
33
+ Rcov::RcovTask.new(:rcov_sourcefile) do |t|
34
+ t.test_files = FileList['test/file_statistics_test.rb']
35
+ t.verbose = true
36
+ t.rcov_opts << "--test-unit-only"
37
+ t.ruby_opts << "-Ilib:ext/rcovrt" # in order to use this rcov
38
+ t.output_dir = "coverage.sourcefile"
39
+ end
40
+
41
+ Rcov::RcovTask.new(:rcov_ccanalyzer) do |t|
42
+ t.test_files = FileList['test/code_coverage_analyzer_test.rb']
43
+ t.verbose = true
44
+ t.rcov_opts << "--test-unit-only"
45
+ t.ruby_opts << "-Ilib:ext/rcovrt" # in order to use this rcov
46
+ t.output_dir = "coverage.ccanalyzer"
47
+ end
48
+
49
+ desc "Run the unit tests with rcovrt."
50
+ Rake::TestTask.new(:test_rcovrt => ["ext/rcovrt/rcovrt.so"]) do |t|
51
+ system("cd ext/rcovrt && make clean && rm Makefile")
52
+ t.libs << "ext/rcovrt"
53
+ t.test_files = FileList['test/*_test.rb']
54
+ t.verbose = true
55
+ end
56
+
57
+ file "ext/rcovrt/rcovrt.so" => FileList["ext/rcovrt/*.c"] do
58
+ ruby "setup.rb config"
59
+ ruby "setup.rb setup"
60
+ end
61
+
62
+ desc "Run the unit tests in pure-Ruby mode ."
63
+ Rake::TestTask.new(:test_pure_ruby) do |t|
64
+ t.libs << "ext/rcovrt"
65
+ t.test_files = FileList['test/turn_off_rcovrt.rb', 'test/*_test.rb']
66
+ t.verbose = true
67
+ end
68
+
69
+ desc "Run the unit tests"
70
+ task :test => [:test_rcovrt]
71
+
72
+ desc "install by setup.rb"
73
+ task :install do
74
+ sh "sudo ruby setup.rb install"
75
+ end
76
+
77
+ task :default => :test
78
+
79
+ desc "Generate rdoc documentation for the rcov library"
80
+ Rake::RDocTask.new("rdoc") { |rdoc|
81
+ rdoc.rdoc_dir = 'doc'
82
+ rdoc.title = "rcov"
83
+ rdoc.options << "--line-numbers" << "--inline-source"
84
+ rdoc.rdoc_files.include('doc/readme_for_api')
85
+ rdoc.rdoc_files.include('doc/readme_for_rake')
86
+ rdoc.rdoc_files.include('doc/readme_for_vim')
87
+ rdoc.rdoc_files.include('lib/**/*.rb')
88
+ }
data/THANKS ADDED
@@ -0,0 +1,96 @@
1
+
2
+ Tom Dolbilin:
3
+ * identified and fixed backslash problem on win32 for generated filenames
4
+
5
+ Andrew Kreiling:
6
+ * made the index XHTML compliant
7
+ * consolidate multiple references to the same underlying .rb file
8
+
9
+ Robert Feldt:
10
+ * pointed me to dynamic uses of the tracing hooks, provided the inspiration
11
+ for RCOV__.run_hooked
12
+ * helped to refine the color scheme
13
+
14
+ Andre Nathan:
15
+ * identified a bug in the heuristics: missing propagation for lines
16
+ with only }, ), ]
17
+
18
+ David Roberts:
19
+ * reported confusing behavior when all files are ignored because they match
20
+ a regexp in the reject list
21
+ * tested the RubyGems package for win32
22
+
23
+ John-Mason Shackelford:
24
+ * reported an important bug in the pure-Ruby tracer module, which broke it
25
+ altogether in 0.4.0
26
+ * suggested a change in the CSS to make XHTML reports more readable under IE
27
+
28
+ Dave Burt:
29
+ * reported an issue with text reports under cmd.exe (should use < 80 cols)
30
+
31
+ Alex Wayne:
32
+ * reported problem with heredocs: they were not being marked as a whole if
33
+ the "header" wasn't reported by Ruby.
34
+ * reported problem with the last line of literal data structs not being
35
+ covered if there was stuff after the end delimiter
36
+
37
+ Coda Hale:
38
+ * reported problem with blocks were the first line is not being marked
39
+ and ditto for the last line when end/} is followed by more stuff
40
+
41
+ Tim Shadel:
42
+ * reported that the last comment block was not being marked even when
43
+ it was the last thing in the file
44
+
45
+ Thomas Leitner:
46
+ * reported that the SCRIPT_LINES__ workaround did not always work
47
+ * fixed the bug which broke differential reports for filenames with
48
+ special characters
49
+
50
+ Assaph Mehr:
51
+ * beta-tested 0.7.0 and found a bug in --aggregate (missing files)
52
+
53
+ Ryan Kinderman:
54
+ * suggested that -Ipath be passed to ruby instead of rcov in RcovTasks
55
+
56
+ Jan Svitok:
57
+ * reported typo in rcovtask.rb's RDoc
58
+
59
+ rubikitch:
60
+ * implemented --annotate mode
61
+ * implemented --gcc option
62
+ * superior emacs support
63
+ * testing, refactoring...
64
+ * many other things, see darcs changes
65
+
66
+ Zed A. Shaw:
67
+ * reported and fixed segfault triggered by rspec
68
+
69
+ Lee Marlow:
70
+ * patch allowing to run rcov against a data file with no input code
71
+
72
+ Kurt Stephens:
73
+ * patch to rethrow any exceptions generated by the traced scripts after
74
+ report generation; notably SystemExit, allowing to use the exit code from
75
+ test runners under rake.
76
+
77
+ Brian Candler:
78
+ * found compatibility issues with the REXML lib included in ruby-1.8.6-p110
79
+ and provided a workaround
80
+
81
+ Mat Schaffer:
82
+ * reported missing line colorization on Safari and probably other browsers,
83
+ owing to self-closing <a> not being handled properly despite being valid
84
+ XHTML 1.0.
85
+
86
+ Sam Granieri:
87
+ * tested workaround for REXML bug
88
+
89
+ Kosmas Schütz, Daniel Berger, François Beausoleil, Bil Kleb:
90
+ * provided information about the ruby-1.8.6-p11[01] REXML problems
91
+
92
+ Chad Humphries:
93
+ * indicated that Spec::DSL::Example has changed in RSpec trunk
94
+
95
+ Jeremy Hinegardner:
96
+ * more info about REXML's bugs in 1.8.6-p11[01]
@@ -0,0 +1,500 @@
1
+ #!/usr/bin/env ruby
2
+ # rcov Copyright (c) 2004-2006 Mauricio Fernandez <mfp@acm.org>
3
+ #
4
+ # rcov originally based on
5
+ # module COVERAGE__ originally (c) NAKAMURA Hiroshi
6
+ # module PrettyCoverage originally (c) Simon Strandgaard
7
+ #
8
+ # rewritten & extended by Mauricio Fern�ndez <mfp@acm.org>
9
+ #
10
+ # See LEGAL and LICENSE for additional licensing information.
11
+ #
12
+ require 'cgi'
13
+ require 'rbconfig'
14
+ require 'optparse'
15
+ require 'ostruct'
16
+
17
+ SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
18
+ require 'rcov/version'
19
+ require 'rcov/formatters'
20
+
21
+ #{{{ "main" code
22
+ options = OpenStruct.new
23
+ options.color = true
24
+ options.range = 30.0
25
+ options.profiling = false
26
+ options.destdir = nil
27
+ options.loadpaths = []
28
+ options.textmode = false
29
+ options.skip = Rcov::BaseFormatter::DEFAULT_OPTS[:ignore]
30
+ options.include = []
31
+ options.html = true
32
+ options.comments_run_by_default = false
33
+ options.test_unit_only = false
34
+ options.spec_only = false
35
+ options.sort = :name
36
+ options.sort_reverse = false
37
+ options.output_threshold = 101
38
+ options.replace_prog_name = false
39
+ options.callsites = false
40
+ options.crossrefs = false
41
+ options.coverage_diff_file = "coverage.info"
42
+ options.coverage_diff_mode = :compare
43
+ options.coverage_diff_save = false
44
+ options.diff_cmd = "diff"
45
+ options.report_cov_bug_for = nil
46
+ options.aggregate_file = nil
47
+ options.gcc_output = false
48
+ options.charset = nil
49
+
50
+ EXTRA_HELP = <<-EOF
51
+
52
+ You can run several programs at once:
53
+ rcov something.rb somethingelse.rb
54
+
55
+ The parameters to be passed to the program under inspection can be specified
56
+ after --:
57
+
58
+ rcov -Ilib -t something.rb -- --theseopts --are --given --to --something.rb
59
+
60
+ ARGV will be set to the specified parameters after --.
61
+ Keep in mind that all the programs are run under the same process
62
+ (i.e. they just get Kernel#load()'ed in sequence).
63
+
64
+ $PROGRAM_NAME (aka. $0) will be set before each file is load()ed if
65
+ --replace-progname is used.
66
+ EOF
67
+
68
+ def deprecated(opt)
69
+ puts "#{opt} is now depricated. Please remove it from you Rakefile or scripts. It will be removed in the next release."
70
+ end
71
+
72
+ #{{{ OptionParser
73
+ opts = OptionParser.new do |opts|
74
+ opts.banner = <<-EOF
75
+ rcov #{Rcov::VERSION} #{Rcov::RELEASE_DATE}
76
+ Usage: rcov [options] <script1.rb> [script2.rb] [-- --extra-options]
77
+ EOF
78
+ opts.separator ""
79
+ opts.separator "Options:"
80
+
81
+ opts.on("-o", "--output PATH", "Destination directory.") do |dir|
82
+ options.destdir = dir
83
+ end
84
+
85
+ opts.on("-I", "--include PATHS", "Prepend PATHS to $: (colon separated list)") do |paths|
86
+ options.loadpaths = paths.split(/:/)
87
+ end
88
+
89
+ opts.on("--[no-]comments", "Mark all comments by default.", "(default: --no-comments)") do |comments_run_p|
90
+ options.comments_run_by_default = comments_run_p
91
+ end
92
+
93
+ opts.on("--test-unit-only", "Only trace code executed inside TestCases.") do
94
+ deprecated("--test-unit-only")
95
+ end
96
+
97
+ opts.on("--spec-only", "Only trace code executed inside RSpec specs.") do
98
+ deprecated("--spec-only")
99
+ end
100
+
101
+ opts.on("-n", "--no-color", "Create colorblind-safe output.") do
102
+ options.color = false
103
+ end
104
+
105
+ opts.on("-i", "--include-file PATTERNS",
106
+ "Generate info for files matching a",
107
+ "pattern (comma-separated regexp list)") do |list|
108
+ begin
109
+ regexps = list.split(/,/).map{|x| Regexp.new(x) }
110
+ options.include += regexps
111
+ rescue RegexpError => e
112
+ raise OptionParser::InvalidArgument, e.message
113
+ end
114
+ end
115
+
116
+ opts.on("-x", "--exclude PATTERNS", "Don't generate info for files matching a","pattern (comma-separated regexp list)") do |list|
117
+ begin
118
+ regexps = list.split(/,/).map{|x| Regexp.new x}
119
+ options.skip += regexps
120
+ rescue RegexpError => e
121
+ raise OptionParser::InvalidArgument, e.message
122
+ end
123
+ end
124
+
125
+ opts.on("--exclude-only PATTERNS", "Skip info only for files matching the", "given patterns.") do |list|
126
+ begin
127
+ options.skip = list.split(/,/).map{|x| Regexp.new(x) }
128
+ rescue RegexpError => e
129
+ raise OptionParser::InvalidArgument, e.message
130
+ end
131
+ end
132
+
133
+ opts.on("--rails", "Skip config/, environment/ and vendor/.") do
134
+ options.skip.concat [%r{\bvendor/},%r{\bconfig/},%r{\benvironment/}]
135
+ end
136
+
137
+ opts.on("--[no-]callsites", "Show callsites in generated XHTML report.", "(somewhat slower; disabled by default)") do |val|
138
+ options.callsites = val
139
+ end
140
+
141
+ opts.on("--[no-]xrefs", "Generate fully cross-referenced report.", "(includes --callsites)") do |val|
142
+ options.crossrefs = val
143
+ options.callsites ||= val
144
+ end
145
+
146
+ opts.on("-p", "--profile", "Generate bogo-profiling info.") do
147
+ options.profiling = true
148
+ options.destdir ||= "profiling"
149
+ end
150
+
151
+ opts.on("-r", "--range RANGE", Float, "Color scale range for profiling info (dB).") do |val|
152
+ options.range = val
153
+ end
154
+
155
+ opts.on("-a", "--annotate", "Generate annotated source code.") do
156
+ options.html = false
157
+ options.textmode = :annotate
158
+ options.crossrefs = true
159
+ options.callsites = true
160
+ options.skip = [ %r!/test/unit/! ]
161
+ end
162
+
163
+ opts.on("-T", "--text-report", "Dump detailed plain-text report to stdout.", "(filename, LoC, total lines, coverage)") do
164
+ options.textmode = :report
165
+ end
166
+
167
+ opts.on("-t", "--text-summary", "Dump plain-text summary to stdout.") do
168
+ options.textmode = :summary
169
+ end
170
+
171
+ opts.on("--text-counts", "Dump execution counts in plaintext.") do
172
+ options.textmode = :counts
173
+ end
174
+
175
+ opts.on("--text-coverage", "Dump coverage info to stdout, using", "ANSI color sequences unless -n.") do
176
+ options.textmode = :coverage
177
+ end
178
+
179
+ opts.on("--gcc", "Dump uncovered line in GCC error format.") do
180
+ options.gcc_output = true
181
+ end
182
+
183
+ opts.on("--aggregate FILE", "Aggregate data from previous runs",
184
+ "in FILE. Overwrites FILE with the",
185
+ "merged data. FILE is created if",
186
+ "necessary.") do |file|
187
+ options.aggregate_file = file
188
+ end
189
+
190
+ opts.on("-D [FILE]", "--text-coverage-diff [FILE]",
191
+ "Compare code coverage with saved state",
192
+ "in FILE, defaults to coverage.info.",
193
+ "Implies --comments.") do |file|
194
+ options.textmode = :coverage_diff
195
+ options.comments_run_by_default = true
196
+ if options.coverage_diff_save
197
+ raise "You shouldn't use --save and --text-coverage-diff at a time."
198
+ end
199
+ options.coverage_diff_mode = :compare
200
+ options.coverage_diff_file = file if file && !file.empty?
201
+ end
202
+
203
+ opts.on("--save [FILE]", "Save coverage data to FILE,", "for later use with rcov -D.", "(default: coverage.info)") do |file|
204
+ options.coverage_diff_save = true
205
+ options.coverage_diff_mode = :record
206
+ if options.textmode == :coverage_diff
207
+ raise "You shouldn't use --save and --text-coverage-diff at a time."
208
+ end
209
+ options.coverage_diff_file = file if file && !file.empty?
210
+ end
211
+
212
+ opts.on("--[no-]html", "Generate HTML output.", "(default: --html)") do |val|
213
+ options.html = val
214
+ end
215
+
216
+ opts.on("--sort CRITERION", [:name, :loc, :coverage], "Sort files in the output by the specified", "field (name, loc, coverage)") do |criterion|
217
+ options.sort = criterion
218
+ end
219
+
220
+ opts.on("--sort-reverse", "Reverse files in the output.") do
221
+ options.sort_reverse = true
222
+ end
223
+
224
+ opts.on("--threshold INT", "Only list files with coverage < INT %.", "(default: 101)") do |threshold|
225
+ begin
226
+ threshold = Integer(threshold)
227
+ raise if threshold <= 0 || threshold > 101
228
+ rescue Exception
229
+ raise OptionParser::InvalidArgument, threshold
230
+ end
231
+ options.output_threshold = threshold
232
+ end
233
+
234
+ opts.on("--charset CHARSET", "Charset used in Content-Type declaration of HTML reports.") do |c|
235
+ options.charset = c
236
+ end
237
+
238
+ opts.on("--only-uncovered", "Same as --threshold 100") do
239
+ options.output_threshold = 100
240
+ end
241
+
242
+ opts.on("--replace-progname", "Replace $0 when loading the .rb files.") do
243
+ options.replace_prog_name = true
244
+ end
245
+
246
+ opts.on("-w", "Turn warnings on (like ruby).") do
247
+ $VERBOSE = true
248
+ end
249
+
250
+ opts.on("--no-rcovrt", "Do not use the optimized C runtime.", "(will run 30-300 times slower)") do
251
+ $rcov_do_not_use_rcovrt = true
252
+ end
253
+
254
+ opts.on("--diff-cmd PROGNAME", "Use PROGNAME for --text-coverage-diff.",
255
+ "(default: diff)") do |cmd|
256
+ options.diff_cmd = cmd
257
+ end
258
+
259
+ opts.separator ""
260
+
261
+ opts.on_tail("-h", "--help", "Show extended help message") do
262
+ require 'pp'
263
+ puts opts
264
+ puts <<EOF
265
+
266
+ Files matching any of the following regexps will be omitted in the report(s):
267
+ #{PP.pp(options.skip, "").chomp}
268
+ EOF
269
+ puts EXTRA_HELP
270
+ exit
271
+ end
272
+
273
+ opts.on_tail("--report-cov-bug SELECTOR", "Report coverage analysis bug for the",
274
+ "method specified by SELECTOR", "(format: Foo::Bar#method, A::B.method)") do |selector|
275
+ case selector
276
+ when /([^.]+)(#|\.)(.*)/ then options.report_cov_bug_for = selector
277
+ else
278
+ raise OptionParser::InvalidArgument, selector
279
+ end
280
+ options.textmode = nil
281
+ options.html = false
282
+ options.callsites = true
283
+ end
284
+ opts.on_tail("--version", "Show version") do
285
+ puts "rcov " + Rcov::VERSION + " " + Rcov::RELEASE_DATE
286
+ exit
287
+ end
288
+ end
289
+
290
+ $ORIGINAL_ARGV = ARGV.clone
291
+ if (idx = ARGV.index("--"))
292
+ extra_args = ARGV[idx+1..-1]
293
+ ARGV.replace(ARGV[0,idx])
294
+ else
295
+ extra_args = []
296
+ end
297
+
298
+ begin
299
+ opts.parse! ARGV
300
+ rescue OptionParser::InvalidOption, OptionParser::InvalidArgument, OptionParser::MissingArgument => e
301
+ puts opts
302
+ puts
303
+ puts e.message
304
+ exit(-1)
305
+ end
306
+
307
+ options.destdir ||= "coverage"
308
+ unless ARGV[0] or options.aggregate_file && File.file?(options.aggregate_file)
309
+ puts opts
310
+ exit
311
+ end
312
+
313
+ # {{{ set loadpath
314
+ options.loadpaths.reverse_each{|x| $:.unshift x}
315
+
316
+ #{{{ require 'rcov': do it only now in order to be able to run rcov on itself
317
+ # since we need to set $: before.
318
+
319
+ require 'rcov'
320
+
321
+ options.callsites = true if options.report_cov_bug_for
322
+ options.textmode = :gcc if !options.textmode and options.gcc_output
323
+
324
+ def rcov_load_aggregate_data(file)
325
+ require 'zlib'
326
+ begin
327
+ old_data = nil
328
+ Zlib::GzipReader.open(file){|gz| old_data = Marshal.load(gz) }
329
+ rescue
330
+ old_data = {}
331
+ end
332
+ old_data || {}
333
+ end
334
+
335
+ def rcov_save_aggregate_data(file)
336
+ require 'zlib'
337
+ Zlib::GzipWriter.open(file) do |f|
338
+ Marshal.dump({:callsites => $rcov_callsite_analyzer, :coverage => $rcov_code_coverage_analyzer}, f)
339
+ end
340
+ end
341
+
342
+ if options.callsites
343
+ if options.aggregate_file
344
+ saved_aggregate_data = rcov_load_aggregate_data(options.aggregate_file)
345
+ if saved_aggregate_data[:callsites]
346
+ $rcov_callsite_analyzer = saved_aggregate_data[:callsites]
347
+ end
348
+ end
349
+ $rcov_callsite_analyzer ||= Rcov::CallSiteAnalyzer.new
350
+ $rcov_callsite_analyzer.install_hook
351
+ else
352
+ $rcov_callsite_analyzer = nil
353
+ end
354
+
355
+ # {{{ create formatters
356
+ formatters = []
357
+ make_formatter = lambda do |klass|
358
+ klass.new(:destdir => options.destdir, :color => options.color,
359
+ :fsr => options.range, :textmode => options.textmode,
360
+ :ignore => options.skip, :dont_ignore => options.include,
361
+ :sort => options.sort,
362
+ :sort_reverse => options.sort_reverse,
363
+ :output_threshold => options.output_threshold,
364
+ :callsite_analyzer => $rcov_callsite_analyzer,
365
+ :coverage_diff_mode => options.coverage_diff_mode,
366
+ :coverage_diff_file => options.coverage_diff_file,
367
+ :callsites => options.callsites,
368
+ :cross_references => options.crossrefs,
369
+ :diff_cmd => options.diff_cmd,
370
+ :comments_run_by_default => options.comments_run_by_default,
371
+ :gcc_output => options.gcc_output,
372
+ :charset => options.charset
373
+ )
374
+ end
375
+
376
+ if options.html
377
+ if options.profiling
378
+ formatters << make_formatter[Rcov::HTMLProfiling]
379
+ else
380
+ formatters << make_formatter[Rcov::HTMLCoverage]
381
+ end
382
+ end
383
+
384
+ textual_formatters = { :counts => Rcov::FullTextReport, :coverage => Rcov::FullTextReport,
385
+ :gcc => Rcov::FullTextReport, :annotate => Rcov::RubyAnnotation,
386
+ :summary => Rcov::TextSummary, :report => Rcov::TextReport,
387
+ :coverage_diff => Rcov::TextCoverageDiff }
388
+
389
+ if textual_formatters[options.textmode]
390
+ formatters << make_formatter[textual_formatters[options.textmode]]
391
+ end
392
+
393
+ formatters << make_formatter[Rcov::TextCoverageDiff] if options.coverage_diff_save
394
+
395
+ if options.aggregate_file
396
+ saved_aggregate_data ||= rcov_load_aggregate_data(options.aggregate_file)
397
+ if saved_aggregate_data[:coverage]
398
+ $rcov_code_coverage_analyzer = saved_aggregate_data[:coverage]
399
+ end
400
+ end
401
+
402
+ $rcov_code_coverage_analyzer ||= Rcov::CodeCoverageAnalyzer.new
403
+
404
+ # must be registered before test/unit puts its own
405
+
406
+
407
+ # The exception to rethrow after reporting has been handled.
408
+ $__rcov_exit_exception = nil
409
+
410
+ END {
411
+ $rcov_code_coverage_analyzer.remove_hook
412
+ $rcov_callsite_analyzer.remove_hook if $rcov_callsite_analyzer
413
+ rcov_save_aggregate_data(options.aggregate_file) if options.aggregate_file
414
+ $rcov_code_coverage_analyzer.dump_coverage_info(formatters)
415
+ if options.report_cov_bug_for
416
+ defsite = $rcov_callsite_analyzer.defsite(options.report_cov_bug_for)
417
+ if !defsite
418
+ $stderr.puts <<-EOF
419
+ Couldn't find definition site of #{options.report_cov_bug_for}.
420
+ Was it executed at all?
421
+ EOF
422
+ exit(-1)
423
+ end
424
+ lines, mark_info, count_info = $rcov_code_coverage_analyzer.data(defsite.file)
425
+ puts <<EOF
426
+
427
+ Please fill in the blanks in the following report.
428
+
429
+
430
+ You can post bugs to
431
+ http://github.com/relevance/rcov/issues
432
+
433
+ Thank you!
434
+
435
+ =============================================================================
436
+ Bug report generated on #{Time.new}
437
+
438
+ Ruby version: #{RUBY_VERSION} (#{RUBY_RELEASE_DATE})
439
+ Platform: #{RUBY_PLATFORM}
440
+ rcov version: #{Rcov::VERSION}
441
+ rcovrt loaded? #{$".any?{|x| /\brcovrt\b/ =~ x} }
442
+ using RubyGems? #{$".any?{|x| /\brubygems\b/ =~ x} }
443
+ Command-line arguments: #{$ORIGINAL_ARGV.inspect}
444
+ Coverage analysis bug in: #{options.report_cov_bug_for}
445
+
446
+ Line(s) ____________ should be ______ (red/green).
447
+
448
+ Raw coverage information (feel free to remove useless data, but please leave
449
+ some context around the faulty lines):
450
+
451
+ EOF
452
+ defsite.line.upto(SCRIPT_LINES__[defsite.file].size) do |i|
453
+ puts "%7d:%5d:%s" % [count_info[i-1], i, lines[i-1]]
454
+ end
455
+ exit
456
+ end
457
+ if !formatters.empty? and formatters.all?{|formatter| formatter.sorted_file_pairs.empty? }
458
+ require 'pp'
459
+ $stderr.puts <<-EOF
460
+
461
+ No file to analyze was found. All the files loaded by rcov matched one of the
462
+ following expressions, and were thus ignored:
463
+ #{PP.pp(options.skip, "").chomp}
464
+
465
+ You can solve this by doing one or more of the following:
466
+ * rename the files not to be ignored so they don't match the above regexps
467
+ * use --include-file to give a list of patterns for files not to be ignored
468
+ * use --exclude-only to give the new list of regexps to match against
469
+ * structure your code as follows:
470
+ test/test_*.rb for the test cases
471
+ lib/**/*.rb for the target source code whose coverage you want
472
+ making sure that the test/test_*.rb files are loading from lib/, e.g. by
473
+ using the -Ilib command-line argument, adding
474
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
475
+ to test/test_*.rb, or running rcov via a Rakefile (read the RDoc
476
+ documentation or README.rake in the source distribution).
477
+ EOF
478
+ end
479
+
480
+ raise $__rcov_exit_exception if $__rcov_exit_exception
481
+ }
482
+
483
+ $rcov_code_coverage_analyzer.install_hook
484
+
485
+ #{{{ Load scripts
486
+ begin
487
+ pending_scripts = ARGV.clone
488
+ ARGV.replace extra_args
489
+ until pending_scripts.empty?
490
+ prog = pending_scripts.shift
491
+ if options.replace_prog_name
492
+ $0 = File.basename(File.expand_path(prog))
493
+ end
494
+ load prog
495
+ end
496
+ rescue Object => err
497
+ $__rcov_exit_exception = err
498
+ end
499
+
500
+ __END__