spicycode-rcov 0.8.1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,147 @@
1
+ # rcov Copyright (c) 2004-2006 Mauricio Fernandez <mfp@acm.org>
2
+ #
3
+ # See LEGAL and LICENSE for licensing information.
4
+
5
+ require 'rcov/version'
6
+
7
+ module Rcov
8
+
9
+ # RCOV__ performs the low-level tracing of the execution, gathering code
10
+ # coverage information in the process. The C core made available through the
11
+ # rcovrt extension will be used if possible. Otherwise the functionality
12
+ # will be emulated using set_trace_func, but this is very expensive and
13
+ # will fail if other libraries (e.g. breakpoint) change the trace_func.
14
+ #
15
+ # Do not use this module; it is very low-level and subject to frequent
16
+ # changes. Rcov::CodeCoverageAnalyzer offers a much more convenient and
17
+ # stable interface.
18
+ module RCOV__
19
+ COVER = {}
20
+ CALLSITES = {}
21
+ DEFSITES = {}
22
+ pure_ruby_impl_needed = true
23
+ unless defined? $rcov_do_not_use_rcovrt
24
+ begin
25
+ require 'rcovrt'
26
+ abi = [0,0,0]
27
+ begin
28
+ abi = RCOV__.ABI
29
+ raise if abi[0] != RCOVRT_ABI[0] || abi[1] < RCOVRT_ABI[1]
30
+ pure_ruby_impl_needed = false
31
+ rescue
32
+ $stderr.puts <<-EOF
33
+ The rcovrt extension I found was built for a different version of rcov.
34
+ The required ABI is: #{RCOVRT_ABI.join(".")}
35
+ Your current rcovrt extension is: #{abi.join(".")}
36
+
37
+ Please delete rcovrt.{so,bundle,dll,...} and install the required one.
38
+ EOF
39
+ raise LoadError
40
+ end
41
+ rescue LoadError
42
+ $stderr.puts <<-EOF
43
+
44
+ Since the rcovrt extension couldn't be loaded, rcov will run in pure-Ruby
45
+ mode, which is about two orders of magnitude slower.
46
+
47
+ If you're on win32, you can find a pre-built extension (usable with recent
48
+ One Click Installer and mswin32 builds) at http://eigenclass.org/hiki.rb?rcov .
49
+
50
+ EOF
51
+ end
52
+ end
53
+
54
+ if pure_ruby_impl_needed
55
+ methods = %w[install_coverage_hook remove_coverage_hook reset_coverage
56
+ install_callsite_hook remove_callsite_hook reset_callsite
57
+ generate_coverage_info generate_callsite_info]
58
+ sklass = class << self; self end
59
+ (methods & sklass.instance_methods).each do |meth|
60
+ sklass.class_eval{ remove_method meth }
61
+ end
62
+
63
+ @coverage_hook_activated = @callsite_hook_activated = false
64
+
65
+ def self.install_coverage_hook # :nodoc:
66
+ install_common_hook
67
+ @coverage_hook_activated = true
68
+ end
69
+
70
+ def self.install_callsite_hook # :nodoc:
71
+ install_common_hook
72
+ @callsite_hook_activated = true
73
+ end
74
+
75
+ def self.install_common_hook # :nodoc:
76
+ set_trace_func lambda {|event, file, line, id, binding, klass|
77
+ next unless SCRIPT_LINES__.has_key? file
78
+ case event
79
+ when 'call'
80
+ if @callsite_hook_activated
81
+ receiver = eval("self", binding)
82
+ klass = class << klass; self end unless klass === receiver
83
+ begin
84
+ DEFSITES[[klass.to_s, id.to_s]] = [file, line]
85
+ rescue Exception
86
+ end
87
+ caller_arr = self.format_backtrace_array(caller[1,1])
88
+ begin
89
+ hash = CALLSITES[[klass.to_s, id.to_s]] ||= {}
90
+ hash[caller_arr] ||= 0
91
+ hash[caller_arr] += 1
92
+ #puts "#{event} #{file} #{line} #{klass.inspect} " +
93
+ # "#{klass.object_id} #{id} #{eval('self', binding)}"
94
+ rescue Exception
95
+ end
96
+ end
97
+ when 'c-call', 'c-return', 'class'
98
+ return
99
+ end
100
+ if @coverage_hook_activated
101
+ COVER[file] ||= Array.new(SCRIPT_LINES__[file].size, 0)
102
+ COVER[file][line - 1] ||= 0
103
+ COVER[file][line - 1] += 1
104
+ end
105
+ }
106
+ end
107
+
108
+ def self.remove_coverage_hook # :nodoc:
109
+ @coverage_hook_activated = false
110
+ set_trace_func(nil) if !@callsite_hook_activated
111
+ end
112
+
113
+ def self.remove_callsite_hook # :nodoc:
114
+ @callsite_hook_activated = false
115
+ set_trace_func(nil) if !@coverage_hook_activated
116
+ end
117
+
118
+ def self.reset_coverage # :nodoc:
119
+ COVER.replace({})
120
+ end
121
+
122
+ def self.reset_callsite # :nodoc:
123
+ CALLSITES.replace({})
124
+ DEFSITES.replace({})
125
+ end
126
+
127
+ def self.generate_coverage_info # :nodoc:
128
+ Marshal.load(Marshal.dump(COVER))
129
+ end
130
+
131
+ def self.generate_callsite_info # :nodoc:
132
+ [CALLSITES, DEFSITES]
133
+ end
134
+
135
+ def self.format_backtrace_array(backtrace)
136
+ backtrace.map do |line|
137
+ md = /^([^:]*)(?::(\d+)(?::in `(.*)'))?/.match(line)
138
+ raise "Bad backtrace format" unless md
139
+ [nil, md[3] ? md[3].to_sym : nil, md[1], (md[2] || '').to_i]
140
+ end
141
+ end
142
+ end
143
+ end # RCOV__
144
+
145
+ end # Rcov
146
+
147
+ # vi: set sw=2:
data/lib/rcov/rant.rb ADDED
@@ -0,0 +1,87 @@
1
+
2
+ require 'rant/rantlib'
3
+
4
+ module Rant # :nodoc:
5
+ module Generators # :nodoc:
6
+ class Rcov # :nodoc:
7
+ def self.rant_gen(app, ch, args, &block)
8
+ if !args || args.empty?
9
+ self.new(app, ch, &block)
10
+ elsif args.size == 1
11
+ name, pre = app.normalize_task_arg(args.first, ch)
12
+ self.new(app, ch, name, pre, &block)
13
+ else
14
+ app.abort_at(ch,
15
+ "Rcov takes only one additional argument, " +
16
+ "which should be like one given to the `task' command.")
17
+ end
18
+ end
19
+
20
+ attr_accessor :verbose
21
+ attr_accessor :libs
22
+ attr_accessor :test_dirs
23
+ attr_accessor :pattern
24
+ attr_accessor :test_files
25
+ attr_accessor :rcov_opts
26
+ # Directory where to put the generated XHTML reports
27
+ attr_accessor :output_dir
28
+
29
+ def initialize(app, cinf, name = :rcov, prerequisites = [], &block)
30
+ @rac = app
31
+ @name = name
32
+ @pre = prerequisites
33
+ #@block = block
34
+ @verbose = nil
35
+ cf = cinf[:file]
36
+ @libs = []
37
+ libdir = File.join(File.dirname(File.expand_path(cf)), 'lib')
38
+ @libs << libdir if test(?d, libdir)
39
+ @rcov_opts = ["--text-report"]
40
+ @test_dirs = []
41
+ @pattern = nil
42
+ @test_files = nil
43
+ yield self if block_given?
44
+ @pattern = "test*.rb" if @pattern.nil? && @test_files.nil?
45
+ @output_dir ||= "coverage"
46
+
47
+ @pre ||= []
48
+ # define the task
49
+ app.task(:__caller__ => cinf, @name => @pre) { |t|
50
+ args = []
51
+ if @libs && !@libs.empty?
52
+ args << "-I#{@libs.join File::PATH_SEPARATOR}"
53
+ end
54
+ if rcov_path = ENV['RCOVPATH']
55
+ args << rcov_path
56
+ else
57
+ args << "-S" << "rcov"
58
+ end
59
+ args.concat rcov_opts
60
+ args << "-o" << @output_dir
61
+ if test(?d, "test")
62
+ @test_dirs << "test"
63
+ elsif test(?d, "tests")
64
+ @test_dirs << "tests"
65
+ end
66
+ args.concat filelist
67
+ app.context.sys.ruby args
68
+ }
69
+ end
70
+
71
+ def filelist
72
+ return @rac.sys[@rac.var['TEST']] if @rac.var['TEST']
73
+ filelist = @test_files || []
74
+ if filelist.empty?
75
+ if @test_dirs && !@test_dirs.empty?
76
+ @test_dirs.each { |dir|
77
+ filelist.concat(@rac.sys[File.join(dir, @pattern)])
78
+ }
79
+ else
80
+ filelist.concat(@rac.sys[@pattern]) if @pattern
81
+ end
82
+ end
83
+ filelist
84
+ end
85
+ end # class Rcov
86
+ end # module Generators
87
+ end # module Rant
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Define a task library for performing code coverage analysis of unit tests
4
+ # using rcov.
5
+
6
+ require 'rake'
7
+ require 'rake/tasklib'
8
+
9
+ module Rcov
10
+
11
+ # Create a task that runs a set of tests through rcov, generating code
12
+ # coverage reports.
13
+ #
14
+ # Example:
15
+ #
16
+ # require 'rcov/rcovtask'
17
+ #
18
+ # Rcov::RcovTask.new do |t|
19
+ # t.libs << "test"
20
+ # t.test_files = FileList['test/test*.rb']
21
+ # t.verbose = true
22
+ # end
23
+ #
24
+ # If rake is invoked with a "TEST=filename" command line option,
25
+ # then the list of test files will be overridden to include only the
26
+ # filename specified on the command line. This provides an easy way
27
+ # to run just one test.
28
+ #
29
+ # If rake is invoked with a "RCOVOPTS=options" command line option,
30
+ # then the given options are passed to rcov.
31
+ #
32
+ # If rake is invoked with a "RCOVPATH=path/to/rcov" command line option,
33
+ # then the given rcov executable will be used; otherwise the one in your
34
+ # PATH will be used.
35
+ #
36
+ # Examples:
37
+ #
38
+ # rake rcov # run tests normally
39
+ # rake rcov TEST=just_one_file.rb # run just one test file.
40
+ # rake rcov RCOVOPTS="-p" # run in profile mode
41
+ # rake rcov RCOVOPTS="-T" # generate text report
42
+ #
43
+ class RcovTask < Rake::TaskLib
44
+
45
+ # Name of test task. (default is :rcov)
46
+ attr_accessor :name
47
+
48
+ # List of directories to added to $LOAD_PATH before running the
49
+ # tests. (default is 'lib')
50
+ attr_accessor :libs
51
+
52
+ # True if verbose test output desired. (default is false)
53
+ attr_accessor :verbose
54
+
55
+ # Request that the tests be run with the warning flag set.
56
+ # E.g. warning=true implies "ruby -w" used to run the tests.
57
+ attr_accessor :warning
58
+
59
+ # Glob pattern to match test files. (default is 'test/test*.rb')
60
+ attr_accessor :pattern
61
+
62
+ # Array of commandline options to pass to ruby when running the rcov loader.
63
+ attr_accessor :ruby_opts
64
+
65
+ # Array of commandline options to pass to rcov. An explicit
66
+ # RCOVOPTS=opts on the command line will override this. (default
67
+ # is <tt>["--text-report"]</tt>)
68
+ attr_accessor :rcov_opts
69
+
70
+ # Output directory for the XHTML report.
71
+ attr_accessor :output_dir
72
+
73
+ # Explicitly define the list of test files to be included in a
74
+ # test. +list+ is expected to be an array of file names (a
75
+ # FileList is acceptable). If both +pattern+ and +test_files+ are
76
+ # used, then the list of test files is the union of the two.
77
+ def test_files=(list)
78
+ @test_files = list
79
+ end
80
+
81
+ # Create a testing task.
82
+ def initialize(name=:rcov)
83
+ @name = name
84
+ @libs = ["lib"]
85
+ @pattern = nil
86
+ @test_files = nil
87
+ @verbose = false
88
+ @warning = false
89
+ @rcov_opts = ["--text-report"]
90
+ @ruby_opts = []
91
+ @output_dir = "coverage"
92
+ yield self if block_given?
93
+ @pattern = 'test/test*.rb' if @pattern.nil? && @test_files.nil?
94
+ define
95
+ end
96
+
97
+ # Create the tasks defined by this task lib.
98
+ def define
99
+ lib_path = @libs.join(File::PATH_SEPARATOR)
100
+ actual_name = Hash === name ? name.keys.first : name
101
+ unless Rake.application.last_comment
102
+ desc "Analyze code coverage with tests" +
103
+ (@name==:rcov ? "" : " for #{actual_name}")
104
+ end
105
+ task @name do
106
+ run_code = ''
107
+ RakeFileUtils.verbose(@verbose) do
108
+ run_code =
109
+ case rcov_path
110
+ when nil, ''
111
+ "-S rcov"
112
+ else %!"#{rcov_path}"!
113
+ end
114
+ ruby_opts = @ruby_opts.clone
115
+ ruby_opts.push( "-I#{lib_path}" )
116
+ ruby_opts.push run_code
117
+ ruby_opts.push( "-w" ) if @warning
118
+ ruby ruby_opts.join(" ") + " " + option_list +
119
+ %[ -o "#{@output_dir}" ] +
120
+ file_list.collect { |fn| %["#{fn}"] }.join(' ')
121
+ end
122
+ end
123
+
124
+ desc "Remove rcov products for #{actual_name}"
125
+ task paste("clobber_", actual_name) do
126
+ rm_r @output_dir rescue nil
127
+ end
128
+
129
+ clobber_task = paste("clobber_", actual_name)
130
+ task :clobber => [clobber_task]
131
+
132
+ task actual_name => clobber_task
133
+ self
134
+ end
135
+
136
+ def rcov_path # :nodoc:
137
+ ENV['RCOVPATH']
138
+ end
139
+
140
+ def option_list # :nodoc:
141
+ ENV['RCOVOPTS'] || @rcov_opts.join(" ") || ""
142
+ end
143
+
144
+ def file_list # :nodoc:
145
+ if ENV['TEST']
146
+ FileList[ ENV['TEST'] ]
147
+ else
148
+ result = []
149
+ result += @test_files.to_a if @test_files
150
+ result += FileList[ @pattern ].to_a if @pattern
151
+ FileList[result]
152
+ end
153
+ end
154
+ end
155
+ end
156
+