spicycode-rcov 0.8.1.5.6 → 0.8.1.5.7

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.
data/Rakefile CHANGED
@@ -17,8 +17,7 @@ require 'rake/clean'
17
17
  ENV["RCOVPATH"] = "bin/rcov"
18
18
 
19
19
  # The following task is largely equivalent to:
20
- # Rcov::RcovTask.new
21
- # (really!)
20
+ # Rcov::RcovTask.new
22
21
  desc "Create a cross-referenced code coverage report."
23
22
  Rcov::RcovTask.new do |t|
24
23
  t.test_files = FileList['test/*_test.rb']
@@ -53,6 +52,7 @@ if RUBY_PLATFORM == 'java'
53
52
  end
54
53
  else
55
54
  Rake::TestTask.new(:test_rcovrt => ["ext/rcovrt/rcovrt.so"]) do |t|
55
+ system("cd ext/rcovrt && make clean && rm Makefile")
56
56
  t.libs << "ext/rcovrt"
57
57
  t.test_files = FileList['test/*_test.rb']
58
58
  t.verbose = true
@@ -73,122 +73,24 @@ end
73
73
 
74
74
  desc "Run the unit tests"
75
75
  task :test => [:test_rcovrt]
76
- #, :test_pure_ruby] disabled since 1.8.5 broke them
76
+
77
+ desc "install by setup.rb"
78
+ task :install do
79
+ sh "sudo ruby setup.rb install"
80
+ end
81
+
82
+ task :default => :test
77
83
 
78
84
  desc "Generate rdoc documentation for the rcov library"
79
85
  Rake::RDocTask.new("rdoc") { |rdoc|
80
86
  rdoc.rdoc_dir = 'doc'
81
87
  rdoc.title = "rcov"
82
88
  rdoc.options << "--line-numbers" << "--inline-source"
83
- rdoc.rdoc_files.include('readme_for_api')
84
- rdoc.rdoc_files.include('readme_for_rake')
85
- rdoc.rdoc_files.include('readme_for_rant')
86
- rdoc.rdoc_files.include('readme_for_vim')
89
+ rdoc.rdoc_files.include('doc/readme_for_api')
90
+ rdoc.rdoc_files.include('doc/readme_for_rake')
91
+ rdoc.rdoc_files.include('doc/readme_for_rant')
92
+ rdoc.rdoc_files.include('doc/readme_for_vim')
87
93
  rdoc.rdoc_files.include('lib/**/*.rb')
88
94
  }
89
95
 
90
- task :default => :test
91
-
92
- desc "install by setup.rb"
93
- task :install do
94
- sh "sudo ruby setup.rb install"
95
- end
96
-
97
-
98
- PKG_FILES = ["bin/rcov", "lib/rcov.rb", "lib/rcov/lowlevel.rb", "lib/rcov/xx.rb", "lib/rcov/version.rb", "lib/rcov/rant.rb", "lib/rcov/report.rb", "lib/rcov/rcovtask.rb", "ext/rcovrt/extconf.rb", "ext/rcovrt/rcovrt.c", "ext/rcovrt/callsite.c", "LEGAL", "LICENSE", "Rakefile", "Rantfile", "readme_for_rake", "readme_for_rant", "readme_for_vim", "readme_for_emacs", "readme_for_vim", "readme_for_api", "THANKS", "test/functional_test.rb", "test/file_statistics_test.rb", "test/assets/sample_03.rb", "test/assets/sample_05-new.rb", "test/code_coverage_analyzer_test.rb", "test/assets/sample_04.rb", "test/assets/sample_02.rb", "test/assets/sample_05-old.rb", "test/assets/sample_01.rb", "test/turn_off_rcovrt.rb", "test/call_site_analyzer_test.rb", "test/assets/sample_05.rb", "rcov.vim", "rcov.el", "setup.rb", "BLURB", "CHANGES"]
99
-
100
- # gem management tasks Use these to build the java code before creating the gem package
101
- # this code can also be used to generate the MRI gem. But I left the gemspec file in too.
102
- spec = Gem::Specification.new do |s|
103
- s.name = %q{rcov}
104
- s.version = Rcov::VERSION
105
-
106
- s.required_rubygems_version = nil if s.respond_to? :required_rubygems_version=
107
- s.authors = ["Mauricio Fernandez"]
108
- s.cert_chain = nil
109
- s.date = %q{2007-11-21}
110
- s.default_executable = %q{rcov}
111
- s.description = %q{rcov is a code coverage tool for Ruby. It is commonly used for viewing overall test unit coverage of target code. It features fast execution (20-300 times faster than previous tools), multiple analysis modes, XHTML and several kinds of text reports, easy automation with Rake via a RcovTask, fairly accurate coverage information through code linkage inference using simple heuristics, colorblind-friendliness...}
112
- s.email = %q{mfp@acm.org}
113
- s.executables = ["rcov"]
114
- s.extensions = ["ext/rcovrt/extconf.rb"]
115
- s.platform = Gem::Platform::RUBY
116
- s.extra_rdoc_files = ["readme_for_api", "readme_for_rake", "readme_for_rant", "readme_for_vim"]
117
- s.files = PKG_FILES
118
- s.has_rdoc = true
119
- s.homepage = %q{http://eigenclass.org/hiki.rb?rcov}
120
- s.rdoc_options = ["--main", "readme_for_api", "--title", "rcov code coverage tool"]
121
- s.require_paths = ["lib"]
122
- s.required_ruby_version = Gem::Requirement.new("> 0.0.0")
123
- s.rubygems_version = %q{1.2.0}
124
- s.summary = %q{Code coverage analysis tool for Ruby}
125
- s.test_files = ["test/functional_test.rb", "test/file_statistics_test.rb", "test/code_coverage_analyzer_test.rb", "test/call_site_analyzer_test.rb"]
126
-
127
- if s.respond_to? :specification_version then
128
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
129
- s.specification_version = 1
130
-
131
- if current_version >= 3 then
132
- else
133
- end
134
- else
135
- end
136
- end
137
-
138
- # tasks added in to support generating the JRuby gem.
139
- if RUBY_PLATFORM == 'java'
140
- spec.platform = "jruby"
141
- spec.extensions = []
142
- # add the jruby extension to the file list
143
- PKG_FILES << "lib/rcovrt.jar"
144
-
145
- def java_classpath_arg
146
- begin
147
- require 'java'
148
- classpath = java.lang.System.getProperty('java.class.path')
149
- rescue LoadError
150
- end
151
-
152
- if classpath.empty?
153
- classpath = FileList["#{ENV['JRUBY_HOME']}/lib/*.jar"].join(File::PATH_SEPARATOR)
154
- end
155
-
156
- classpath ? "-cp #{classpath}" : ""
157
- end
158
-
159
-
160
- CLEAN.include ["ext/java/classes", "lib/rcovrt.jar", "pkg"]
161
-
162
- def compile_java
163
- mkdir_p "ext/java/classes"
164
- sh "javac -g -target 1.5 -source 1.5 -d ext/java/classes #{java_classpath_arg} #{FileList['ext/java/src/**/*.java'].join(' ')}"
165
- end
166
-
167
- def make_jar
168
- require 'fileutils'
169
- lib = File.join(File.dirname(__FILE__), 'lib')
170
- FileUtils.mkdir(lib) unless File.exists? lib
171
- sh "jar cf lib/rcovrt.jar -C ext/java/classes/ ."
172
- end
173
-
174
- file 'lib/rcovrt.jar' => FileList["ext/java/src/*.java"] do
175
- compile_java
176
- make_jar
177
- end
178
-
179
- desc "compile the java extension and put it into the lib directory"
180
- task :java_compile => ["lib/rcovrt.jar"]
181
-
182
- end
183
-
184
- Rake::GemPackageTask.new(spec) do |p|
185
- p.need_tar = true
186
- p.gem_spec = spec
187
- end
188
-
189
- # extend the gem task to include the java_compile
190
- if RUBY_PLATFORM == 'java'
191
- Rake::Task["pkg"].enhance(["java_compile"])
192
- end
193
-
194
96
  # vim: set sw=2 ft=ruby:
data/bin/rcov CHANGED
@@ -265,7 +265,7 @@ EOF
265
265
  "method specified by SELECTOR",
266
266
  "(format: Foo::Bar#method, A::B.method)") do |selector|
267
267
  case selector
268
- when /([^.]+)(#|\.)(.*)/: options.report_cov_bug_for = selector
268
+ when /([^.]+)(#|\.)(.*)/ then options.report_cov_bug_for = selector
269
269
  else
270
270
  raise OptionParser::InvalidArgument, selector
271
271
  end
File without changes
@@ -0,0 +1,64 @@
1
+
2
+ <tt>rcov.el</tt> allows you to use rcov from Emacs conveniently.
3
+ * Run unit tests and jump to uncovered code by <tt>C-x `</tt>.
4
+ * Run unit tests and save the current coverage status.
5
+ * Run unit tests and jump to uncovered code introduced since the last run.
6
+ * View cross-reference annotated code.
7
+
8
+ == Installation
9
+
10
+ Copy <tt>rcov.el</tt> to the appropriate directory, which is in load-path.
11
+ Then require it.
12
+ (require 'rcov)
13
+
14
+
15
+ == Usage
16
+
17
+ There are some commands to run rcov in Emacs.
18
+ All of them displays +rcov+ window, whose major-mode is compilation-mode.
19
+ Therefore you can jump to uncovered code by <tt>C-x `</tt>.
20
+
21
+ +rcov-command-line+, +rcovsave-command-line+, and +rcovdiff-command-line+ define
22
+ command line to run rcov.
23
+ If you do not use +rcov+ from Rake, you must modify them.
24
+
25
+ === Finding uncovered code
26
+
27
+ Type the following while editing your program:
28
+ M-x rcov
29
+
30
+ === Setting the reference point
31
+
32
+ +rcov+'s <tt>--text-coverage-diff</tt> mode compares the current coverage status against
33
+ the saved one. It therefore needs that information to be recorded
34
+ before you write new code (typically right after you perform a commit) in
35
+ order to have something to compare against.
36
+
37
+ You can save the current status with the <tt>--save</tt> option.
38
+
39
+ Type the following to save the current status in Emacs:
40
+ M-x rcovsave
41
+ If you do not use +rcov+ from Rake, you must modify +rcovsave-command-line+ variable.
42
+
43
+ === Finding new uncovered code
44
+
45
+ Type the following to save the current status in Emacs:
46
+ M-x rcovdiff
47
+
48
+ === Viewing cross-reference annotated code
49
+
50
+ If you read cross-reference annotated code, issue
51
+ rake rcov RCOVOPTS='-a'
52
+ at the beginning.
53
+ This command creates +coverage+ directory and many *.rb files in it.
54
+ Filenames of these Ruby scripts are converted from original path.
55
+ You can browse them by normally <tt>C-x C-f</tt>.
56
+ You can think of <tt>-a</tt> option as <tt>--xrefs</tt> option and output format is Ruby script.
57
+
58
+ After find-file-ed annotated script, the major-mode is rcov-xref-mode,
59
+ which is derived from ruby-mode and specializes navigation.
60
+
61
+ <tt>Tab</tt> and <tt>M-Tab</tt> goes forward/backward links.
62
+ <tt>Ret</tt> follows selected link.
63
+
64
+ This feature is useful to read third-party code or to follow control flow.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,258 @@
1
+ #include <ruby.h>
2
+ #include <ruby/st.h>
3
+ #include <stdlib.h>
4
+
5
+ static char callsite_hook_set_p;
6
+
7
+ typedef struct {
8
+ const char *sourcefile;
9
+ unsigned int sourceline;
10
+ VALUE curr_meth;
11
+ } type_def_site;
12
+ static VALUE caller_info = 0;
13
+ static VALUE method_def_site_info = 0;
14
+
15
+ static int caller_stack_len = 1;
16
+
17
+ /*
18
+ *
19
+ * callsite hook and associated functions
20
+ *
21
+ * */
22
+
23
+ static VALUE
24
+ record_callsite_info(VALUE args)
25
+ {
26
+ VALUE caller_ary;
27
+ VALUE curr_meth;
28
+ VALUE count_hash;
29
+ VALUE count;
30
+ VALUE *pargs = (VALUE *)args;
31
+
32
+ caller_ary = pargs[0];
33
+ curr_meth = pargs[1];
34
+ count_hash = rb_hash_aref(caller_info, curr_meth);
35
+ if(TYPE(count_hash) != T_HASH) {
36
+ /* Qnil, anything else should be impossible unless somebody's been
37
+ * messing with ObjectSpace */
38
+ count_hash = rb_hash_new();
39
+ rb_hash_aset(caller_info, curr_meth, count_hash);
40
+ }
41
+ count = rb_hash_aref(count_hash, caller_ary);
42
+ if(count == Qnil)
43
+ count = INT2FIX(0);
44
+ count = INT2FIX(FIX2UINT(count) + 1);
45
+ rb_hash_aset(count_hash, caller_ary, count);
46
+ /* * /
47
+ printf("CALLSITE: %s -> %s %d\n", RSTRING_PTR(rb_inspect(curr_meth)),
48
+ RSTRING_PTR(rb_inspect(caller_ary)), FIX2INT(count));
49
+ / * */
50
+
51
+ return Qnil;
52
+ }
53
+
54
+
55
+ static VALUE
56
+ record_method_def_site(VALUE args)
57
+ {
58
+ type_def_site *pargs = (type_def_site *)args;
59
+ VALUE def_site_info;
60
+ // VALUE hash;
61
+
62
+ if( RTEST(rb_hash_aref(method_def_site_info, pargs->curr_meth)) )
63
+ return Qnil;
64
+ def_site_info = rb_ary_new();
65
+ rb_ary_push(def_site_info, rb_str_new2(pargs->sourcefile));
66
+ rb_ary_push(def_site_info, INT2NUM(pargs->sourceline+1));
67
+ rb_hash_aset(method_def_site_info, pargs->curr_meth, def_site_info);
68
+ /* * /
69
+ printf("DEFSITE: %s:%d for %s\n", pargs->sourcefile, pargs->sourceline+1,
70
+ RSTRING_PTR(rb_inspect(pargs->curr_meth)));
71
+ / * */
72
+
73
+ return Qnil;
74
+ }
75
+
76
+ static VALUE
77
+ callsite_custom_backtrace(int lev)
78
+ {
79
+ ID id;
80
+ VALUE klass;
81
+ VALUE klass_path;
82
+ VALUE eval_string;
83
+
84
+ rb_frame_method_id_and_class(&id, &klass);
85
+ if (id == ID_ALLOCATOR)
86
+ return Qnil;
87
+ if (klass) {
88
+ if (TYPE(klass) == T_ICLASS) {
89
+ klass = RBASIC(klass)->klass;
90
+ }
91
+ else if (FL_TEST(klass, FL_SINGLETON)) {
92
+ klass = rb_iv_get(klass, "__attached__");
93
+ }
94
+ }
95
+ // rb_sprintf("\"#<Class:%s>\"", RSTRING_PTR(klass_path))
96
+
97
+ /*
98
+ klass = class << klass; self end unless klass === eval("self", binding)
99
+ */
100
+
101
+ klass_path = rb_class_path(klass);
102
+ VALUE reciever = rb_funcall(rb_binding_new(), rb_intern("eval"), 1, rb_str_new2("self"));
103
+ if (rb_funcall(klass, rb_intern("=="), 1, reciever) == Qtrue) {
104
+ klass_path = rb_sprintf("\"#<Class:%s>\"", RSTRING_PTR(klass_path));
105
+ OBJ_FREEZE(klass_path);
106
+ }
107
+
108
+ eval_string = rb_sprintf("caller[%d, 1].map do |line|\nmd = /^([^:]*)(?::(\\d+)(?::in `(?:block in )?(.*)'))?/.match(line)\nraise \"Bad backtrace format\" unless md\n[%s, md[3] ? md[3].to_sym : nil, md[1], (md[2] || '').to_i]\nend", lev, RSTRING_PTR(klass_path));
109
+ return rb_eval_string(RSTRING_PTR(eval_string));
110
+ }
111
+
112
+ static void
113
+ coverage_event_callsite_hook(rb_event_flag_t event, VALUE node,
114
+ VALUE self, ID mid, VALUE klass)
115
+ {
116
+ VALUE caller_ary;
117
+ VALUE curr_meth;
118
+ VALUE args[2];
119
+ int status;
120
+
121
+ caller_ary = callsite_custom_backtrace(caller_stack_len);
122
+
123
+ VALUE klass_path;
124
+ curr_meth = rb_ary_new();
125
+
126
+ rb_frame_method_id_and_class(&mid, &klass);
127
+
128
+ if (mid == ID_ALLOCATOR)
129
+ return; //Qnil;
130
+ if (klass) {
131
+ if (TYPE(klass) == T_ICLASS) {
132
+ klass = RBASIC(klass)->klass;
133
+ }
134
+ else if (FL_TEST(klass, FL_SINGLETON)) {
135
+ klass = rb_iv_get(klass, "__attached__");
136
+ }
137
+ }
138
+
139
+ /*
140
+ klass = class << klass; self end unless klass === eval("self", binding)
141
+ */
142
+
143
+ klass_path = rb_class_path(klass);
144
+ VALUE reciever = rb_funcall(rb_binding_new(), rb_intern("eval"), 1, rb_str_new2("self"));
145
+ if (rb_funcall(klass, rb_intern("=="), 1, reciever) == Qtrue) {
146
+ klass_path = rb_sprintf("#<Class:%s>", RSTRING_PTR(klass_path));
147
+ OBJ_FREEZE(klass_path);
148
+ }
149
+
150
+ rb_ary_push(curr_meth, klass_path);
151
+ rb_ary_push(curr_meth, ID2SYM(mid));
152
+
153
+ args[0] = caller_ary;
154
+ args[1] = curr_meth;
155
+ rb_protect(record_callsite_info, (VALUE)args, &status);
156
+
157
+ if(!status) {
158
+ type_def_site args;
159
+
160
+ args.sourcefile = rb_sourcefile();
161
+ args.sourceline = rb_sourceline();
162
+ args.curr_meth = curr_meth;
163
+ rb_protect(record_method_def_site, (VALUE)&args, NULL);
164
+ }
165
+ if(status)
166
+ rb_gv_set("$!", Qnil);
167
+ }
168
+
169
+
170
+ static VALUE
171
+ cov_install_callsite_hook(VALUE self)
172
+ {
173
+ if(!callsite_hook_set_p) {
174
+ if(TYPE(caller_info) != T_HASH)
175
+ caller_info = rb_hash_new();
176
+ callsite_hook_set_p = 1;
177
+ VALUE something = 0;
178
+ rb_add_event_hook(coverage_event_callsite_hook,
179
+ RUBY_EVENT_CALL, something);
180
+ return Qtrue;
181
+ } else
182
+ return Qfalse;
183
+ }
184
+
185
+
186
+ static VALUE
187
+ cov_remove_callsite_hook(VALUE self)
188
+ {
189
+ if(!callsite_hook_set_p)
190
+ return Qfalse;
191
+ else {
192
+ rb_remove_event_hook(coverage_event_callsite_hook);
193
+ callsite_hook_set_p = 0;
194
+ return Qtrue;
195
+ }
196
+ }
197
+
198
+
199
+ static VALUE
200
+ cov_generate_callsite_info(VALUE self)
201
+ {
202
+ VALUE ret;
203
+
204
+ ret = rb_ary_new();
205
+ rb_ary_push(ret, caller_info);
206
+ rb_ary_push(ret, method_def_site_info);
207
+ return ret;
208
+ }
209
+
210
+
211
+ static VALUE
212
+ cov_reset_callsite(VALUE self)
213
+ {
214
+ if(callsite_hook_set_p) {
215
+ rb_raise(rb_eRuntimeError,
216
+ "Cannot reset the callsite info in the middle of a traced run.");
217
+ return Qnil;
218
+ }
219
+
220
+ caller_info = rb_hash_new();
221
+ method_def_site_info = rb_hash_new();
222
+ return Qnil;
223
+ }
224
+
225
+ void
226
+ Init_rcov_callsite()
227
+ {
228
+ VALUE mRcov;
229
+ VALUE mRCOV__;
230
+ ID id_rcov = rb_intern("Rcov");
231
+ ID id_coverage__ = rb_intern("RCOV__");
232
+ // ID id_script_lines__ = rb_intern("SCRIPT_LINES__");
233
+
234
+ if(rb_const_defined(rb_cObject, id_rcov))
235
+ mRcov = rb_const_get(rb_cObject, id_rcov);
236
+ else
237
+ mRcov = rb_define_module("Rcov");
238
+
239
+ if(rb_const_defined(mRcov, id_coverage__))
240
+ mRCOV__ = rb_const_get_at(mRcov, id_coverage__);
241
+ else
242
+ mRCOV__ = rb_define_module_under(mRcov, "RCOV__");
243
+
244
+ callsite_hook_set_p = 0;
245
+ caller_info = rb_hash_new();
246
+ method_def_site_info = rb_hash_new();
247
+ rb_gc_register_address(&caller_info);
248
+ rb_gc_register_address(&method_def_site_info);
249
+
250
+ rb_define_singleton_method(mRCOV__, "install_callsite_hook",
251
+ cov_install_callsite_hook, 0);
252
+ rb_define_singleton_method(mRCOV__, "remove_callsite_hook",
253
+ cov_remove_callsite_hook, 0);
254
+ rb_define_singleton_method(mRCOV__, "generate_callsite_info",
255
+ cov_generate_callsite_info, 0);
256
+ rb_define_singleton_method(mRCOV__, "reset_callsite", cov_reset_callsite, 0);
257
+ }
258
+ /* vim: set sw=8 expandtab: */
@@ -0,0 +1,315 @@
1
+ #include <ruby.h>
2
+ #include <ruby/st.h>
3
+ #include <stdlib.h>
4
+ #include <assert.h>
5
+
6
+ #define COVERAGE_DEBUG_EVENTS 0
7
+
8
+ #define RCOVRT_VERSION_MAJOR 2
9
+ #define RCOVRT_VERSION_MINOR 0
10
+ #define RCOVRT_VERSION_REV 0
11
+
12
+ static VALUE mRcov;
13
+ static VALUE mRCOV__;
14
+ static VALUE oSCRIPT_LINES__;
15
+ static ID id_cover;
16
+ static st_table* coverinfo = 0;
17
+ static char coverage_hook_set_p;
18
+
19
+ struct cov_array {
20
+ unsigned int len;
21
+ unsigned int *ptr;
22
+ };
23
+
24
+ static struct cov_array *cached_array = 0;
25
+ static char *cached_file = 0;
26
+
27
+ /*
28
+ *
29
+ * coverage hook and associated functions
30
+ *
31
+ * */
32
+ static struct cov_array *
33
+ coverage_increase_counter_uncached(char *sourcefile, unsigned int sourceline,
34
+ char mark_only)
35
+ {
36
+ struct cov_array *carray = NULL;
37
+
38
+ if(sourcefile == NULL) {
39
+ /* "can't happen", just ignore and avoid segfault */
40
+ return NULL;
41
+ } else if(!st_lookup(coverinfo, (st_data_t)sourcefile, (st_data_t*)&carray)) {
42
+ VALUE arr;
43
+
44
+ arr = rb_hash_aref(oSCRIPT_LINES__, rb_str_new2(sourcefile));
45
+ if(NIL_P(arr))
46
+ return 0;
47
+ rb_check_type(arr, T_ARRAY);
48
+ carray = calloc(1, sizeof(struct cov_array));
49
+ carray->ptr = calloc(RARRAY_LEN(arr), sizeof(unsigned int));
50
+ carray->len = RARRAY_LEN(arr);
51
+ st_insert(coverinfo, (st_data_t)strdup(sourcefile),
52
+ (st_data_t) carray);
53
+ } else {
54
+ /* recovered carray, sanity check */
55
+ assert(carray && "failed to create valid carray");
56
+ }
57
+
58
+ if(mark_only) {
59
+ if(!carray->ptr[sourceline])
60
+ carray->ptr[sourceline] = 1;
61
+ } else {
62
+ if (carray && carray->len > sourceline) {
63
+ carray->ptr[sourceline]++;
64
+ }
65
+ }
66
+
67
+ return carray;
68
+ }
69
+
70
+
71
+ static void
72
+ coverage_mark_caller()
73
+ {
74
+ // if @coverage_hook_activated
75
+ // COVER[file] ||= Array.new(SCRIPT_LINES__[file].size, 0)
76
+ // COVER[file][line - 1] ||= 0
77
+ // COVER[file][line - 1] += 1
78
+ // end
79
+
80
+ coverage_increase_counter_uncached(rb_sourcefile(), rb_sourceline(), 1);
81
+ }
82
+
83
+
84
+ static void
85
+ coverage_increase_counter_cached(char *sourcefile, int sourceline)
86
+ {
87
+ if(cached_file == sourcefile && cached_array && cached_array->len > sourceline) {
88
+ cached_array->ptr[sourceline]++;
89
+ return;
90
+ }
91
+ cached_file = sourcefile;
92
+ cached_array = coverage_increase_counter_uncached(sourcefile, sourceline, 0);
93
+ }
94
+
95
+ static void
96
+ coverage_event_coverage_hook(rb_event_flag_t event, VALUE node,
97
+ VALUE self, ID mid, VALUE klass)
98
+ {
99
+ char *sourcefile;
100
+ unsigned int sourceline;
101
+ static unsigned int in_hook = 0;
102
+
103
+ if(in_hook) {
104
+ return;
105
+ }
106
+
107
+ in_hook++;
108
+
109
+ #if COVERAGE_DEBUG_EVENTS
110
+ do {
111
+ int status;
112
+ VALUE old_exception;
113
+ old_exception = rb_gv_get("$!");
114
+ rb_protect(rb_inspect, klass, &status);
115
+ if(!status) {
116
+ printf("EVENT: %d %s %s %s %d\n", event,
117
+ klass ? RSTRING(rb_inspect(klass))->ptr : "",
118
+ mid ? (mid == ID_ALLOCATOR ? "ID_ALLOCATOR" : rb_id2name(mid))
119
+ : "unknown",
120
+ node ? node->nd_file : "", node ? nd_line(node) : 0);
121
+ } else {
122
+ printf("EVENT: %d %s %s %d\n", event,
123
+ mid ? (mid == ID_ALLOCATOR ? "ID_ALLOCATOR" : rb_id2name(mid))
124
+ : "unknown",
125
+ node ? node->nd_file : "", node ? nd_line(node) : 0);
126
+ }
127
+ rb_gv_set("$!", old_exception);
128
+ } while (0);
129
+ #endif
130
+
131
+ if(event & RUBY_EVENT_C_CALL) {
132
+ coverage_mark_caller();
133
+ }
134
+ if(event & (RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN | RUBY_EVENT_CLASS)) {
135
+ in_hook--;
136
+ return;
137
+ }
138
+
139
+ // printf("NODE? %s , %s\n", rb_id2name(rb_frame_this_func()), RSTRING_PTR(rb_inspect(node)));
140
+
141
+ sourcefile = rb_sourcefile();
142
+ sourceline = rb_sourceline();
143
+
144
+ if (0 == sourceline || 0 == sourcefile) {
145
+ in_hook--;
146
+ return;
147
+ }
148
+
149
+ coverage_increase_counter_cached(sourcefile, sourceline);
150
+ if(event & RUBY_EVENT_CALL)
151
+ coverage_mark_caller();
152
+ in_hook--;
153
+ }
154
+
155
+
156
+ static VALUE
157
+ cov_install_coverage_hook(VALUE self)
158
+ {
159
+ if(!coverage_hook_set_p) {
160
+ if(!coverinfo)
161
+ coverinfo = st_init_strtable();
162
+ coverage_hook_set_p = 1;
163
+ /* TODO: allow C_CALL too, since it's supported already
164
+ * the overhead is around ~30%, tested on typo */
165
+ VALUE holder = 0;
166
+ rb_add_event_hook(coverage_event_coverage_hook,
167
+ RUBY_EVENT_ALL & ~RUBY_EVENT_C_CALL &
168
+ ~RUBY_EVENT_C_RETURN & ~RUBY_EVENT_CLASS, holder);
169
+ return Qtrue;
170
+ }
171
+ else
172
+ return Qfalse;
173
+ }
174
+
175
+
176
+ static int
177
+ populate_cover(st_data_t key, st_data_t value, st_data_t cover)
178
+ {
179
+ VALUE rcover;
180
+ VALUE rkey;
181
+ VALUE rval;
182
+ struct cov_array *carray;
183
+ unsigned int i;
184
+
185
+ rcover = (VALUE)cover;
186
+ carray = (struct cov_array *) value;
187
+ rkey = rb_str_new2((char*) key);
188
+ rval = rb_ary_new2(carray->len);
189
+ for(i = 0; i < carray->len; i++)
190
+ rb_ary_push(rval, UINT2NUM(carray->ptr[i]));
191
+
192
+ rb_hash_aset(rcover, rkey, rval);
193
+
194
+ return ST_CONTINUE;
195
+ }
196
+
197
+
198
+ static int
199
+ free_table(st_data_t key, st_data_t value, st_data_t ignored)
200
+ {
201
+ struct cov_array *carray;
202
+
203
+ carray = (struct cov_array *) value;
204
+ free((char *)key);
205
+ free(carray->ptr);
206
+ free(carray);
207
+
208
+ return ST_CONTINUE;
209
+ }
210
+
211
+
212
+ static VALUE
213
+ cov_remove_coverage_hook(VALUE self)
214
+ {
215
+ if(!coverage_hook_set_p)
216
+ return Qfalse;
217
+ else {
218
+ rb_remove_event_hook(coverage_event_coverage_hook);
219
+ coverage_hook_set_p = 0;
220
+ return Qtrue;
221
+ }
222
+ }
223
+
224
+
225
+ static VALUE
226
+ cov_generate_coverage_info(VALUE self)
227
+ {
228
+ VALUE cover;
229
+
230
+ if(rb_const_defined_at(mRCOV__, id_cover)) {
231
+ rb_mod_remove_const(mRCOV__, ID2SYM(id_cover));
232
+ }
233
+
234
+ cover = rb_hash_new();
235
+ if(coverinfo)
236
+ st_foreach(coverinfo, populate_cover, cover);
237
+ rb_define_const(mRCOV__, "COVER", cover);
238
+
239
+ return cover;
240
+ }
241
+
242
+
243
+ static VALUE
244
+ cov_reset_coverage(VALUE self)
245
+ {
246
+ if(coverage_hook_set_p) {
247
+ rb_raise(rb_eRuntimeError,
248
+ "Cannot reset the coverage info in the middle of a traced run.");
249
+ return Qnil;
250
+ }
251
+
252
+ cached_array = 0;
253
+ cached_file = 0;
254
+ st_foreach(coverinfo, free_table, Qnil);
255
+ st_free_table(coverinfo);
256
+ coverinfo = 0;
257
+
258
+ return Qnil;
259
+ }
260
+
261
+
262
+ static VALUE
263
+ cov_ABI(VALUE self)
264
+ {
265
+ VALUE ret;
266
+
267
+ ret = rb_ary_new();
268
+ rb_ary_push(ret, INT2FIX(RCOVRT_VERSION_MAJOR));
269
+ rb_ary_push(ret, INT2FIX(RCOVRT_VERSION_MINOR));
270
+ rb_ary_push(ret, INT2FIX(RCOVRT_VERSION_REV));
271
+
272
+ return ret;
273
+ }
274
+
275
+
276
+ void
277
+ Init_rcovrt()
278
+ {
279
+ ID id_rcov = rb_intern("Rcov");
280
+ ID id_coverage__ = rb_intern("RCOV__");
281
+ ID id_script_lines__ = rb_intern("SCRIPT_LINES__");
282
+
283
+ id_cover = rb_intern("COVER");
284
+
285
+ if(rb_const_defined(rb_cObject, id_rcov))
286
+ mRcov = rb_const_get(rb_cObject, id_rcov);
287
+ else
288
+ mRcov = rb_define_module("Rcov");
289
+
290
+ if(rb_const_defined(mRcov, id_coverage__))
291
+ mRCOV__ = rb_const_get_at(mRcov, id_coverage__);
292
+ else
293
+ mRCOV__ = rb_define_module_under(mRcov, "RCOV__");
294
+
295
+ if(rb_const_defined(rb_cObject, id_script_lines__))
296
+ oSCRIPT_LINES__ = rb_const_get(rb_cObject, rb_intern("SCRIPT_LINES__"));
297
+ else {
298
+ oSCRIPT_LINES__ = rb_hash_new();
299
+ rb_const_set(rb_cObject, id_script_lines__, oSCRIPT_LINES__);
300
+ }
301
+
302
+ coverage_hook_set_p = 0;
303
+
304
+ rb_define_singleton_method(mRCOV__, "install_coverage_hook",
305
+ cov_install_coverage_hook, 0);
306
+ rb_define_singleton_method(mRCOV__, "remove_coverage_hook",
307
+ cov_remove_coverage_hook, 0);
308
+ rb_define_singleton_method(mRCOV__, "generate_coverage_info",
309
+ cov_generate_coverage_info, 0);
310
+ rb_define_singleton_method(mRCOV__, "reset_coverage", cov_reset_coverage, 0);
311
+ rb_define_singleton_method(mRCOV__, "ABI", cov_ABI, 0);
312
+
313
+ Init_rcov_callsite();
314
+ }
315
+ /* vim: set sw=8 expandtab: */
@@ -6,8 +6,18 @@ unless RUBY_PLATFORM == 'java' then
6
6
  have_library("gcov", "__gcov_open")
7
7
 
8
8
  $CFLAGS << " -fprofile-arcs -ftest-coverage"
9
- create_makefile("rcovrt")
9
+ if RUBY_VERSION =~ /1.9/
10
+ $CFLAGS << ' -DRUBY_19_COMPATIBILITY'
11
+ create_makefile("rcovrt", "1.9/")
12
+ else
13
+ create_makefile("rcovrt", "1.8/")
14
+ end
10
15
  else
11
- create_makefile("rcovrt")
16
+ if RUBY_VERSION =~ /1.9/
17
+ $CFLAGS << ' -DRUBY_19_COMPATIBILITY'
18
+ create_makefile("rcovrt", "1.9/")
19
+ else
20
+ create_makefile("rcovrt", "1.8/")
21
+ end
12
22
  end
13
23
  end
@@ -917,8 +917,8 @@ class CallSiteAnalyzer < DifferentialAnalyzer
917
917
  def expand_name(classname_or_fullname, methodname = nil)
918
918
  if methodname.nil?
919
919
  case classname_or_fullname
920
- when /(.*)#(.*)/: classname, methodname = $1, $2
921
- when /(.*)\.(.*)/: classname, methodname = "#<Class:#{$1}>", $2
920
+ when /(.*)#(.*)/ then classname, methodname = $1, $2
921
+ when /(.*)\.(.*)/ then classname, methodname = "#<Class:#{$1}>", $2
922
922
  else
923
923
  raise ArgumentError, "Incorrect method name"
924
924
  end
@@ -99,8 +99,8 @@ class Formatter # :nodoc:
99
99
  @ignore_files = options[:ignore]
100
100
  @dont_ignore_files = options[:dont_ignore]
101
101
  @sort_criterium = case options[:sort]
102
- when :loc : lambda{|fname, finfo| finfo.num_code_lines}
103
- when :coverage : lambda{|fname, finfo| finfo.code_coverage}
102
+ when :loc then lambda{|fname, finfo| finfo.num_code_lines}
103
+ when :coverage then lambda{|fname, finfo| finfo.code_coverage}
104
104
  else lambda{|fname, finfo| fname}
105
105
  end
106
106
  @sort_reverse = options[:sort_reverse]
@@ -773,7 +773,7 @@ EOS
773
773
  tr_(:class => color_classes[color_class_index]) {
774
774
  td_ {
775
775
  case f.name
776
- when "TOTAL":
776
+ when "TOTAL" then
777
777
  t_ { "TOTAL" }
778
778
  else
779
779
  a_(:href => mangle_filename(f.name)){ t_ { f.name } }
@@ -73,37 +73,25 @@ class TestCallSiteAnalyzer < Test::Unit::TestCase
73
73
 
74
74
  def test_basic_defsite_recording
75
75
  @a.run_hooked{ @o.f1 }
76
- verify_defsite_equal(["./test/assets/sample_03.rb", 3],
77
- @a.defsite("Rcov::Test::Temporary::Sample03", "f1"))
78
- verify_defsite_equal(["./test/assets/sample_03.rb", 7],
79
- @a.defsite("Rcov::Test::Temporary::Sample03", "f2"))
80
- verify_defsite_equal(["./test/assets/sample_03.rb", 7],
81
- @a.defsite("Rcov::Test::Temporary::Sample03#f2"))
76
+ verify_defsite_equal(["./test/assets/sample_03.rb", 3], @a.defsite("Rcov::Test::Temporary::Sample03", "f1"))
77
+ verify_defsite_equal(["./test/assets/sample_03.rb", 7], @a.defsite("Rcov::Test::Temporary::Sample03", "f2"))
78
+ verify_defsite_equal(["./test/assets/sample_03.rb", 7], @a.defsite("Rcov::Test::Temporary::Sample03#f2"))
82
79
  end
83
80
 
84
81
  def test_basic_callsite_recording
85
82
  @a.run_hooked{ @o.f1 }
86
83
  assert(@a.analyzed_classes.include?("Rcov::Test::Temporary::Sample03"))
87
84
  assert_equal(%w[f1 f2], @a.analyzed_methods("Rcov::Test::Temporary::Sample03"))
88
- verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 10},
89
- @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
90
- verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 10},
91
- @a.callsites("Rcov::Test::Temporary::Sample03#f2"))
92
- #verify_callsites_equal({["./test/sample_03.rb:4:in `f1'"] => 10},
93
- # @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
94
- #verify_callsites_equal({["./test/sample_03.rb:4:in `f1'"] => 10},
95
- # @a.callsites("Rcov::Test::Temporary::Sample03#f2"))
85
+ verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 10}, @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
86
+ verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 10}, @a.callsites("Rcov::Test::Temporary::Sample03#f2"))
96
87
  end
97
88
 
98
89
  def test_basic_callsite_recording_API
99
90
  @a.run_hooked{ @o.f1 }
100
91
  assert(@a.analyzed_classes.include?("Rcov::Test::Temporary::Sample03"))
101
92
  assert_equal(%w[f1 f2], @a.analyzed_methods("Rcov::Test::Temporary::Sample03"))
102
- verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1,
103
- "./test/assets/sample_03.rb", 4]] => 10},
104
- @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
105
- verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 10},
106
- @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
93
+ verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 10}, @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
94
+ verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 10}, @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
107
95
  callsites = @a.callsites("Rcov::Test::Temporary::Sample03", "f2")
108
96
  callsite = callsites.keys[0]
109
97
  #expand path is used here to compensate for differences between JRuby and MRI
@@ -117,12 +105,8 @@ class TestCallSiteAnalyzer < Test::Unit::TestCase
117
105
  @a.run_hooked{ @o.class.g1 }
118
106
  assert(@a.analyzed_classes.include?("#<Class:Rcov::Test::Temporary::Sample03>"))
119
107
  assert_equal(%w[g1 g2], @a.analyzed_methods("#<Class:Rcov::Test::Temporary::Sample03>"))
120
- verify_callsites_equal({[[class << Rcov::Test::Temporary::Sample03; self end,
121
- :g1, "./test/assets/sample_03.rb", 15]] => 10},
122
- @a.callsites("Rcov::Test::Temporary::Sample03.g2"))
123
- verify_callsites_equal({[[class << Rcov::Test::Temporary::Sample03; self end,
124
- :g1, "./test/assets/sample_03.rb", 15]] => 10},
125
- @a.callsites("#<Class:Rcov::Test::Temporary::Sample03>","g2"))
108
+ verify_callsites_equal({[[class << Rcov::Test::Temporary::Sample03; self end, :g1, "./test/assets/sample_03.rb", 15]] => 10}, @a.callsites("Rcov::Test::Temporary::Sample03.g2"))
109
+ verify_callsites_equal({[[class << Rcov::Test::Temporary::Sample03; self end, :g1, "./test/assets/sample_03.rb", 15]] => 10}, @a.callsites("#<Class:Rcov::Test::Temporary::Sample03>","g2"))
126
110
  end
127
111
 
128
112
 
@@ -130,24 +114,17 @@ class TestCallSiteAnalyzer < Test::Unit::TestCase
130
114
  @a.run_hooked{ @o.f1 }
131
115
  assert(@a.analyzed_classes.include?("Rcov::Test::Temporary::Sample03"))
132
116
  assert_equal(%w[f1 f2], @a.analyzed_methods("Rcov::Test::Temporary::Sample03"))
133
- verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1,
134
- "./test/assets/sample_03.rb", 4]] => 10},
135
- @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
117
+ verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 10}, @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
136
118
 
137
119
  @a.run_hooked{ @o.f1 }
138
120
  assert(@a.analyzed_classes.include?("Rcov::Test::Temporary::Sample03"))
139
121
  assert_equal(%w[f1 f2], @a.analyzed_methods("Rcov::Test::Temporary::Sample03"))
140
- verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1,
141
- "./test/assets/sample_03.rb", 4]] => 20},
142
- @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
122
+ verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 20}, @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
143
123
 
144
124
  @a.run_hooked{ @o.f3 }
145
125
  assert_equal(%w[f1 f2 f3], @a.analyzed_methods("Rcov::Test::Temporary::Sample03"))
146
- verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1,
147
- "./test/assets/sample_03.rb", 4]] => 120,
148
- [[Rcov::Test::Temporary::Sample03, :f3,
149
- "./test/assets/sample_03.rb", 11]]=>100 },
150
- @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
126
+ verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 120,
127
+ [[Rcov::Test::Temporary::Sample03, :f3, "./test/assets/sample_03.rb", 11]] => 100 }, @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
151
128
  end
152
129
 
153
130
  def test_reset
@@ -158,10 +135,7 @@ class TestCallSiteAnalyzer < Test::Unit::TestCase
158
135
  end
159
136
  assert(@a.analyzed_classes.include?("Rcov::Test::Temporary::Sample03"))
160
137
  assert_equal(%w[f1 f2], @a.analyzed_methods("Rcov::Test::Temporary::Sample03"))
161
- verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1,
162
- "./test/assets/sample_03.rb", 4]] => 10},
163
- @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
164
-
138
+ verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 10}, @a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
165
139
  end
166
140
 
167
141
  def test_nested_callsite_recording
@@ -171,37 +145,27 @@ class TestCallSiteAnalyzer < Test::Unit::TestCase
171
145
  b.run_hooked { @o.f1 }
172
146
  assert(b.analyzed_classes.include?("Rcov::Test::Temporary::Sample03"))
173
147
  assert_equal(%w[f1 f2], b.analyzed_methods("Rcov::Test::Temporary::Sample03"))
174
- verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1,
175
- "./test/assets/sample_03.rb", 4]] => 10},
176
- b.callsites("Rcov::Test::Temporary::Sample03", "f2"))
148
+ verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 10}, b.callsites("Rcov::Test::Temporary::Sample03", "f2"))
177
149
 
178
150
  @o.f1
179
151
  assert_equal(%w[f1 f2], b.analyzed_methods("Rcov::Test::Temporary::Sample03"))
180
- verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1,
181
- "./test/assets/sample_03.rb", 4]] => 10},
182
- b.callsites("Rcov::Test::Temporary::Sample03", "f2"))
152
+ verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 10}, b.callsites("Rcov::Test::Temporary::Sample03", "f2"))
183
153
 
184
154
  assert(a.analyzed_classes.include?("Rcov::Test::Temporary::Sample03"))
185
155
  assert_equal(%w[f1 f2], a.analyzed_methods("Rcov::Test::Temporary::Sample03"))
186
- verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1,
187
- "./test/assets/sample_03.rb", 4]] => 20},
188
- a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
156
+ verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 20}, a.callsites("Rcov::Test::Temporary::Sample03", "f2"))
189
157
  end
158
+
190
159
  b.run_hooked{ @o.f3 }
191
160
  assert_equal(%w[f1 f2 f3], b.analyzed_methods("Rcov::Test::Temporary::Sample03"))
192
- verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1,
193
- "./test/assets/sample_03.rb", 4]] => 110,
194
- [[Rcov::Test::Temporary::Sample03, :f3,
195
- "./test/assets/sample_03.rb", 11]]=>100 },
196
- b.callsites("Rcov::Test::Temporary::Sample03", "f2"))
161
+ verify_callsites_equal({[[Rcov::Test::Temporary::Sample03, :f1, "./test/assets/sample_03.rb", 4]] => 110,
162
+ [[Rcov::Test::Temporary::Sample03, :f3, "./test/assets/sample_03.rb", 11]]=>100 }, b.callsites("Rcov::Test::Temporary::Sample03", "f2"))
197
163
  end
198
164
 
199
165
  def test_expand_name
200
166
  assert_equal(["Foo", "foo"], @a.instance_eval{ expand_name("Foo#foo") })
201
167
  assert_equal(["Foo", "foo"], @a.instance_eval{ expand_name("Foo", "foo") })
202
- assert_equal(["#<Class:Foo>", "foo"],
203
- @a.instance_eval{ expand_name("Foo.foo") })
204
- assert_equal(["#<Class:Foo>", "foo"],
205
- @a.instance_eval{ expand_name("#<Class:Foo>", "foo") })
168
+ assert_equal(["#<Class:Foo>", "foo"], @a.instance_eval{ expand_name("Foo.foo") })
169
+ assert_equal(["#<Class:Foo>", "foo"], @a.instance_eval{ expand_name("#<Class:Foo>", "foo") })
206
170
  end
207
171
  end
@@ -1,7 +1,7 @@
1
1
  require File.dirname(__FILE__) + '/test_helper'
2
2
 
3
3
  class TestCodeCoverageAnalyzer < Test::Unit::TestCase
4
- LINES = <<-EOF.to_a
4
+ LINES = <<-EOF.split "\n"
5
5
  puts 1
6
6
  if foo
7
7
  bar
@@ -88,9 +88,9 @@ EOF
88
88
  analyzer = Rcov::CodeCoverageAnalyzer.new
89
89
  analyzer.run_hooked{ load sample_file }
90
90
  line_info, cov_info, count_info = analyzer.data(sample_file)
91
- assert_equal([1, 2, 0, 0, 1, 0, 11], count_info) unless PLATFORM =~ /java/
91
+ assert_equal([1, 2, 0, 0, 1, 0, 11], count_info) unless (defined? PLATFORM && PLATFORM =~ /java/) || RUBY_VERSION =~ /1.9/
92
92
  # JRUBY reports an if x==blah as hitting this type of line once, JRUBY also optimizes this stuff so you'd have to run with --debug to get "extra" information. MRI hits it twice.
93
- assert_equal([1, 1, 0, 0, 1, 0, 11], count_info) if PLATFORM =~ /java/
93
+ assert_equal([1, 2, 0, 0, 1, 0, 11], count_info) if RUBY_VERSION =~ /1.9/
94
94
 
95
95
  analyzer.reset
96
96
  #set_trace_func proc { |event, file, line, id, binding, classname| printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname if (file =~ /sample_02.rb/) }
@@ -98,13 +98,15 @@ EOF
98
98
  sample_file = File.join(File.dirname(__FILE__), "assets/sample_02.rb")
99
99
  analyzer.run_hooked{ load sample_file }
100
100
  line_info, cov_info, count_info = analyzer.data(sample_file)
101
- assert_equal([8, 1, 0, 0, 0], count_info)
101
+ assert_equal([8, 1, 0, 0, 0], count_info) unless RUBY_VERSION =~ /1.9/
102
+ assert_equal([4, 1, 0, 0, 4], count_info) if RUBY_VERSION =~ /1.9/
102
103
 
103
104
  analyzer.reset
104
105
  assert_equal([], analyzer.analyzed_files)
105
106
  analyzer.run_hooked{ Rcov::Test::Temporary::Sample02.foo(1, 1) }
106
107
  line_info, cov_info, count_info = analyzer.data(sample_file)
107
- assert_equal([0, 1, 1, 1, 0], count_info)
108
+ assert_equal([0, 1, 1, 1, 0], count_info) unless RUBY_VERSION =~ /1.9/
109
+ assert_equal([0, 2, 1, 0, 0], count_info) if RUBY_VERSION =~ /1.9/
108
110
  analyzer.run_hooked do
109
111
  10.times{ Rcov::Test::Temporary::Sample02.foo(1, 1) }
110
112
  end
metadata CHANGED
@@ -1,14 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spicycode-rcov
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1.5.6
4
+ version: 0.8.1.5.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mauricio Fernandez
8
+ - Chad Humphries
9
+ - Aaron Bedra
8
10
  autorequire:
9
11
  bindir: bin
10
12
  cert_chain:
11
- date: 2008-08-29 00:00:00 -07:00
13
+ date: 2009-03-17 00:00:00 -07:00
12
14
  default_executable: rcov
13
15
  dependencies: []
14
16
 
@@ -19,10 +21,10 @@ executables:
19
21
  extensions:
20
22
  - ext/rcovrt/extconf.rb
21
23
  extra_rdoc_files:
22
- - readme_for_api
23
- - readme_for_rake
24
- - readme_for_rant
25
- - readme_for_vim
24
+ - doc/readme_for_api
25
+ - doc/readme_for_rake
26
+ - doc/readme_for_rant
27
+ - doc/readme_for_vim
26
28
  files:
27
29
  - bin/rcov
28
30
  - lib/rcov.rb
@@ -31,19 +33,21 @@ files:
31
33
  - lib/rcov/version.rb
32
34
  - lib/rcov/rant.rb
33
35
  - lib/rcov/report.rb
34
- - lib/rcov/rexml_extensions.rb
35
36
  - lib/rcov/rcovtask.rb
36
37
  - ext/rcovrt/extconf.rb
37
- - ext/rcovrt/rcovrt.c
38
- - ext/rcovrt/callsite.c
38
+ - ext/rcovrt/1.8/rcovrt.c
39
+ - ext/rcovrt/1.9/rcovrt.c
40
+ - ext/rcovrt/1.8/callsite.c
41
+ - ext/rcovrt/1.9/callsite.c
39
42
  - LEGAL
40
43
  - LICENSE
41
44
  - Rakefile
42
45
  - Rantfile
43
- - readme_for_rake
44
- - readme_for_rant
45
- - readme_for_vim
46
- - readme_for_api
46
+ - doc/readme_for_rake
47
+ - doc/readme_for_rant
48
+ - doc/readme_for_vim
49
+ - doc/readme_for_emacs
50
+ - doc/readme_for_api
47
51
  - THANKS
48
52
  - test/functional_test.rb
49
53
  - test/file_statistics_test.rb
@@ -57,14 +61,13 @@ files:
57
61
  - test/turn_off_rcovrt.rb
58
62
  - test/call_site_analyzer_test.rb
59
63
  - test/assets/sample_05.rb
60
- - test/rexml_test.rb
61
- - rcov.vim
62
- - rcov.el
64
+ - editor-extensions/rcov.vim
65
+ - editor-extensions/rcov.el
63
66
  - setup.rb
64
67
  - BLURB
65
68
  - CHANGES
66
69
  has_rdoc: true
67
- homepage: http://eigenclass.org/hiki.rb?rcov
70
+ homepage: http://github.com/spicycode/rcov
68
71
  post_install_message:
69
72
  rdoc_options:
70
73
  - --main
@@ -1,44 +0,0 @@
1
- require 'rexml/document'
2
- require 'rexml/formatters/pretty'
3
-
4
- module Rcov
5
- module REXMLExtensions
6
-
7
- def self.fix_pretty_formatter_wrap
8
- REXML::Formatters::Pretty.class_eval do
9
- include PrettyFormatterWrapFix
10
- end
11
- end
12
-
13
- # Fix for this bug: http://clint-hill.com/2008/10/02/a-bug-in-ruby-did-i-just-find-that/
14
- # Also known from this fun exception:
15
- #
16
- # /usr/local/ruby/lib/ruby/1.8/rexml/formatters/pretty.rb:131:in
17
- # `[]': no implicit conversion from nil to integer (TypeError)
18
- #
19
- # This bug was fixed in Ruby with this changeset http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=19487
20
- # ...which should mean that this bug only affects Ruby 1.8.6. The latest stable version of 1.8.7 (and up) should be fine.
21
- module PrettyFormatterWrapFix
22
-
23
- def self.included(base)
24
- base.class_eval do
25
- def wrap(string, width)
26
- # Recursively wrap string at width.
27
- return string if string.length <= width
28
- place = string.rindex(' ', width) # Position in string with last ' ' before cutoff
29
- return string if place.nil?
30
- return string[0,place] + "\n" + wrap(string[place+1..-1], width)
31
- end
32
- end
33
- end
34
-
35
- end
36
-
37
- def self.init!
38
- if RUBY_VERSION == "1.8.6"
39
- fix_pretty_formatter_wrap
40
- end
41
- end
42
- end
43
-
44
- end
@@ -1,23 +0,0 @@
1
- require File.dirname(__FILE__) + '/test_helper'
2
- require 'rcov/rexml_extensions'
3
-
4
- class TestRexml < Test::Unit::TestCase
5
-
6
- def test_wrap_with_long_lines_without_spaces_should_not_break_wrap
7
- Rcov::REXMLExtensions.fix_pretty_formatter_wrap
8
- pretty_formatter = ::REXML::Formatters::Pretty.new
9
- long_string = "this-is-a-long-string-without-any-spaces-to-try-to-break-rexml-formatter-and-it-is-over-100-characters-long"
10
- pretty_formatter.instance_eval { wrap(long_string, 100) } # avoid send, it can't bypass private methods in ruby19
11
- end
12
-
13
- def test_wrap_original_behavior_should_be_preserved
14
- pretty_formatter = REXML::Formatters::Pretty.new
15
- str = "This string should be wrapped at 40 characters"
16
- pretty_formatter.instance_eval do
17
- str = wrap(str, 40)
18
- end # avoid send, it can't bypass private methods in ruby19
19
- assert_equal("This string should be wrapped at 40\ncharacters", str)
20
-
21
- end
22
-
23
- end