summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authormame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-07-01 16:55:30 +0000
committermame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-07-01 16:55:30 +0000
commit5874de95e8df1d051001cf53614c1d245c1ac5ae (patch)
tree3bd25f3a413a1637a826552181c1568b3bbeb9c0 /lib
parent498324c5d3cd08c2c306a4f91e3a11b7fda22835 (diff)
* Add coverage measurement constant COVERAGE__. This constant is not
for casual use. Usage: (1) assign {} to COVERAGE__, (2) require or load Ruby source file, and (3) COVERAGE__["sourcefilepath"] will return an array whose elements represent number of executions per line of source code. * vm_core.h: add field of coverage array to iseq. * iseq.c (prepare_iseq_build): ditto. * insns.def (trace): update coverage array. * parse.y (coverage): create and initialize coverage array. * compile.h (ADD_TRACE): add trace instruction to update covearge array. * thread.c (clear_coverage): delete coverage array when forking. Otherwise, double count of coverage may occur. * lib/coverage.rb: sample coverage measurement tool. * error.c: distinguish explicitly between parse_in_eval and mild_compile_error. * load.c: ditto. * vm_eval.c: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17781 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r--lib/coverage.rb57
1 files changed, 57 insertions, 0 deletions
diff --git a/lib/coverage.rb b/lib/coverage.rb
new file mode 100644
index 0000000000..f72473ece3
--- /dev/null
+++ b/lib/coverage.rb
@@ -0,0 +1,57 @@
+COVERAGE__ ||= {}
+ext = ENV["COVERUBY_EXT"] || ".cov"
+accum = ENV["COVERUBY_ACCUM"]
+accum = !accum || accum == "" || !(%w(f n 0).include?(accum[0]))
+pwd = Dir.pwd
+
+at_exit do
+ Dir.chdir(pwd) do
+ COVERAGE__.each do |sfile, covs|
+ cfile = sfile + ext
+
+ writable = proc do |f|
+ File.writable?(f) || File.writable?(File.dirname(f))
+ end
+ unless writable[cfile]
+ cfile = cfile.gsub(File.PATH_SEPARATOR, "#")
+ next unless writable[cfile]
+ end
+
+ readlines = proc do |f|
+ File.read(f).force_encoding("ASCII-8BIT").lines.to_a
+ end
+
+ sources = (readlines[sfile] rescue [])
+
+ pcovs = []
+ if accum
+ pcovs = (readlines[cfile] rescue []).map.with_index do |line, idx|
+ if line[/^\s*(?:(#####)|(\d+)|-):\s*\d+:(.*)$/n]
+ cov, line = $1 ? 0 : ($2 ? $2.to_i : nil), $3
+ if !sources[idx] || sources[idx].chomp != line.chomp
+ warn("source file changed, ignoring: `#{ cfile }'")
+ break []
+ end
+ cov
+ else
+ p line
+ warn("coverage file corrupted, ignoring: #{ cfile }")
+ break []
+ end
+ end
+ unless pcovs.empty? || pcovs.size == covs.size
+ warn("coverage file changed, ignoring: `#{ cfile }'")
+ pcovs = []
+ end
+ end
+
+ open(cfile, "w") do |out|
+ covs.zip(sources, pcovs).each_with_index do |(cov, line, pcov), idx|
+ cov += pcov || 0 if cov
+ cov = (cov ? (cov == 0 ? "#####" : cov.to_s) : "-").rjust(9)
+ out.puts("%s:% 5d:%s" % [cov, idx + 1, line])
+ end
+ end
+ end
+ end
+end