rcov 0.9.11 → 1.0.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.
- data/bin/rcov +26 -3
- data/ext/rcovrt/1.8/callsite.c +38 -53
- data/ext/rcovrt/1.8/rcovrt.c +84 -100
- data/ext/rcovrt/extconf.rb +7 -12
- data/lib/rcov/formatters/html_erb_template.rb +7 -7
- data/lib/rcov/formatters/html_profiling.rb +51 -0
- data/lib/rcov/formatters/ruby_annotation.rb +110 -0
- data/lib/rcov/templates/index.html.erb +18 -14
- data/lib/rcov/version.rb +2 -6
- metadata +35 -75
- data/BLURB +0 -111
- data/LICENSE +0 -53
- data/Rakefile +0 -103
- data/THANKS +0 -110
- data/doc/readme_for_api.markdown +0 -22
- data/doc/readme_for_emacs.markdown +0 -52
- data/doc/readme_for_rake.markdown +0 -51
- data/doc/readme_for_vim.markdown +0 -34
- data/editor-extensions/rcov.el +0 -131
- data/editor-extensions/rcov.vim +0 -38
- data/ext/rcovrt/1.9/callsite.c +0 -234
- data/ext/rcovrt/1.9/rcovrt.c +0 -264
- data/setup.rb +0 -1588
- data/test/assets/sample_01.rb +0 -7
- data/test/assets/sample_02.rb +0 -5
- data/test/assets/sample_03.rb +0 -20
- data/test/assets/sample_04.rb +0 -10
- data/test/assets/sample_05-new.rb +0 -17
- data/test/assets/sample_05-old.rb +0 -13
- data/test/assets/sample_05.rb +0 -17
- data/test/assets/sample_06.rb +0 -8
- data/test/call_site_analyzer_test.rb +0 -171
- data/test/code_coverage_analyzer_test.rb +0 -220
- data/test/expected_coverage/diff-gcc-all.out +0 -7
- data/test/expected_coverage/diff-gcc-diff.out +0 -11
- data/test/expected_coverage/diff-gcc-original.out +0 -5
- data/test/expected_coverage/diff-no-color.out +0 -12
- data/test/expected_coverage/diff.out +0 -12
- data/test/expected_coverage/gcc-text.out +0 -10
- data/test/expected_coverage/sample_03_rb.html +0 -651
- data/test/expected_coverage/sample_03_rb.rb +0 -28
- data/test/expected_coverage/sample_04_rb.html +0 -641
- data/test/file_statistics_test.rb +0 -471
- data/test/functional_test.rb +0 -91
- data/test/test_helper.rb +0 -4
- data/test/turn_off_rcovrt.rb +0 -4
data/bin/rcov
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# -*- coding: iso-8859-1 -*-
|
3
|
+
|
3
4
|
# rcov Copyright (c) 2004-2006 Mauricio Fernandez <mfp@acm.org>
|
4
5
|
#
|
5
6
|
# rcov originally based on
|
@@ -10,6 +11,11 @@
|
|
10
11
|
#
|
11
12
|
# See LEGAL and LICENSE for additional licensing information.
|
12
13
|
#
|
14
|
+
if RUBY_VERSION =~ /1.9/
|
15
|
+
puts "** Ruby 1.9 is not supported. Please switch to simplecov **"
|
16
|
+
exit 1
|
17
|
+
end
|
18
|
+
|
13
19
|
require 'cgi'
|
14
20
|
require 'rbconfig'
|
15
21
|
require 'optparse'
|
@@ -27,6 +33,7 @@ options.profiling = false
|
|
27
33
|
options.destdir = nil
|
28
34
|
options.loadpaths = []
|
29
35
|
options.textmode = false
|
36
|
+
options.custom_formatters = []
|
30
37
|
options.skip = Rcov::BaseFormatter::DEFAULT_OPTS[:ignore]
|
31
38
|
options.include = []
|
32
39
|
options.html = true
|
@@ -178,6 +185,21 @@ EOF
|
|
178
185
|
opts.on("--text-coverage", "Dump coverage info to stdout, using", "ANSI color sequences unless -n.") do
|
179
186
|
options.textmode = :coverage
|
180
187
|
end
|
188
|
+
|
189
|
+
opts.on("--require LIB", "Require an additional lib before running") do |file|
|
190
|
+
require file
|
191
|
+
end
|
192
|
+
|
193
|
+
opts.on("--custom-formatter EXPR", "Generate additional output using a",
|
194
|
+
"custom formatter class. The expression",
|
195
|
+
"is evaluated as Ruby code and should",
|
196
|
+
"return a Class object") do |class_expr|
|
197
|
+
formatter = instance_eval class_expr
|
198
|
+
unless formatter.is_a? Class
|
199
|
+
raise "--custom-formatter expression must return a Class object. Got a #{formatter.class.name}"
|
200
|
+
end
|
201
|
+
options.custom_formatters << formatter
|
202
|
+
end
|
181
203
|
|
182
204
|
opts.on("--gcc", "Dump uncovered line in GCC error format.") do
|
183
205
|
options.gcc_output = true
|
@@ -395,6 +417,10 @@ if options.html
|
|
395
417
|
end
|
396
418
|
end
|
397
419
|
|
420
|
+
options.custom_formatters.each do |formatter|
|
421
|
+
formatters << make_formatter[formatter]
|
422
|
+
end
|
423
|
+
|
398
424
|
textual_formatters = { :counts => Rcov::FullTextReport, :coverage => Rcov::FullTextReport,
|
399
425
|
:gcc => Rcov::FullTextReport, :annotate => Rcov::RubyAnnotation,
|
400
426
|
:summary => Rcov::TextSummary, :report => Rcov::TextReport,
|
@@ -503,9 +529,6 @@ $rcov_code_coverage_analyzer.install_hook
|
|
503
529
|
|
504
530
|
#{{{ Load scripts
|
505
531
|
begin
|
506
|
-
if RUBY_VERSION =~ /1.9/
|
507
|
-
puts "** WARNING: Ruby 1.9 Support is experimental at best. Don't expect correct results! **"
|
508
|
-
end
|
509
532
|
pending_scripts = ARGV.clone
|
510
533
|
ARGV.replace extra_args
|
511
534
|
until pending_scripts.empty?
|
data/ext/rcovrt/1.8/callsite.c
CHANGED
@@ -4,17 +4,15 @@
|
|
4
4
|
#include <st.h>
|
5
5
|
#include <stdlib.h>
|
6
6
|
|
7
|
-
static char callsite_hook_set_p;
|
8
|
-
|
9
7
|
typedef struct {
|
10
8
|
char *sourcefile;
|
11
9
|
unsigned int sourceline;
|
12
10
|
VALUE curr_meth;
|
13
|
-
} type_def_site;
|
11
|
+
} type_def_site;
|
14
12
|
|
13
|
+
static char callsite_hook_set_p;
|
15
14
|
static VALUE caller_info = 0;
|
16
15
|
static VALUE method_def_site_info = 0;
|
17
|
-
|
18
16
|
static caller_stack_len = 1;
|
19
17
|
|
20
18
|
static VALUE record_callsite_info(VALUE args) {
|
@@ -28,23 +26,20 @@ static VALUE record_callsite_info(VALUE args) {
|
|
28
26
|
curr_meth = pargs[1];
|
29
27
|
count_hash = rb_hash_aref(caller_info, curr_meth);
|
30
28
|
|
31
|
-
if(TYPE(count_hash) != T_HASH) {
|
32
|
-
/* Qnil, anything else should be impossible unless somebody's been
|
33
|
-
* messing with ObjectSpace */
|
29
|
+
if (TYPE(count_hash) != T_HASH) {
|
34
30
|
count_hash = rb_hash_new();
|
35
31
|
rb_hash_aset(caller_info, curr_meth, count_hash);
|
36
32
|
}
|
37
33
|
|
38
34
|
count = rb_hash_aref(count_hash, caller_ary);
|
39
35
|
|
40
|
-
if(count == Qnil)
|
41
|
-
count = INT2FIX(0);
|
36
|
+
if (count == Qnil) count = INT2FIX(0);
|
42
37
|
|
43
38
|
count = INT2FIX(FIX2UINT(count) + 1);
|
44
39
|
rb_hash_aset(count_hash, caller_ary, count);
|
45
40
|
/*
|
46
|
-
|
47
|
-
|
41
|
+
printf("CALLSITE: %s -> %s %d\n", RSTRING(rb_inspect(curr_meth))->ptr,
|
42
|
+
RSTRING(rb_inspect(caller_ary))->ptr, FIX2INT(count));
|
48
43
|
*/
|
49
44
|
|
50
45
|
return Qnil;
|
@@ -55,17 +50,16 @@ static VALUE record_method_def_site(VALUE args) {
|
|
55
50
|
VALUE def_site_info;
|
56
51
|
VALUE hash;
|
57
52
|
|
58
|
-
if(RTEST(rb_hash_aref(method_def_site_info, pargs->curr_meth)))
|
59
|
-
return Qnil;
|
53
|
+
if (RTEST(rb_hash_aref(method_def_site_info, pargs->curr_meth))) return Qnil;
|
60
54
|
def_site_info = rb_ary_new();
|
61
55
|
rb_ary_push(def_site_info, rb_str_new2(pargs->sourcefile));
|
62
56
|
rb_ary_push(def_site_info, INT2NUM(pargs->sourceline+1));
|
63
57
|
rb_hash_aset(method_def_site_info, pargs->curr_meth, def_site_info);
|
64
58
|
/*
|
65
|
-
|
66
|
-
|
59
|
+
printf("DEFSITE: %s:%d for %s\n", pargs->sourcefile, pargs->sourceline+1,
|
60
|
+
RSTRING(rb_inspect(pargs->curr_meth))->ptr);
|
67
61
|
*/
|
68
|
-
|
62
|
+
|
69
63
|
return Qnil;
|
70
64
|
}
|
71
65
|
|
@@ -78,18 +72,17 @@ static VALUE callsite_custom_backtrace(int lev) {
|
|
78
72
|
|
79
73
|
ary = rb_ary_new();
|
80
74
|
|
81
|
-
if (frame->last_func == ID_ALLOCATOR)
|
82
|
-
frame = frame->prev;
|
83
|
-
}
|
75
|
+
if (frame->last_func == ID_ALLOCATOR) frame = frame->prev;
|
84
76
|
|
85
77
|
for (; frame && (n = frame->node); frame = frame->prev) {
|
86
78
|
if (frame->prev && frame->prev->last_func) {
|
87
79
|
if (frame->prev->node == n) continue;
|
80
|
+
|
88
81
|
level = rb_ary_new();
|
89
82
|
klass = frame->prev->last_class ? frame->prev->last_class : Qnil;
|
90
|
-
|
91
|
-
|
92
|
-
|
83
|
+
|
84
|
+
if (TYPE(klass) == T_ICLASS) klass = CLASS_OF(klass);
|
85
|
+
|
93
86
|
rb_ary_push(level, klass);
|
94
87
|
rb_ary_push(level, ID2SYM(frame->prev->last_func));
|
95
88
|
rb_ary_push(level, rb_str_new2(n->nd_file));
|
@@ -102,14 +95,14 @@ static VALUE callsite_custom_backtrace(int lev) {
|
|
102
95
|
rb_ary_push(level, rb_str_new2(n->nd_file));
|
103
96
|
rb_ary_push(level, INT2NUM(nd_line(n)));
|
104
97
|
}
|
98
|
+
|
105
99
|
rb_ary_push(ary, level);
|
106
|
-
if(--lev == 0)
|
107
|
-
break;
|
100
|
+
if (--lev == 0) break;
|
108
101
|
}
|
109
|
-
|
102
|
+
|
110
103
|
return ary;
|
111
104
|
}
|
112
|
-
|
105
|
+
|
113
106
|
static void coverage_event_callsite_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass) {
|
114
107
|
VALUE caller_ary;
|
115
108
|
VALUE curr_meth;
|
@@ -117,49 +110,40 @@ static void coverage_event_callsite_hook(rb_event_t event, NODE *node, VALUE sel
|
|
117
110
|
int status;
|
118
111
|
|
119
112
|
caller_ary = callsite_custom_backtrace(caller_stack_len);
|
120
|
-
|
121
|
-
if(TYPE(klass) == T_ICLASS)
|
122
|
-
klass = CLASS_OF(klass);
|
123
|
-
}
|
113
|
+
|
114
|
+
if (TYPE(klass) == T_ICLASS) klass = CLASS_OF(klass);
|
124
115
|
|
125
116
|
curr_meth = rb_ary_new();
|
126
117
|
rb_ary_push(curr_meth, klass);
|
127
118
|
rb_ary_push(curr_meth, ID2SYM(mid));
|
128
|
-
|
129
119
|
args[0] = caller_ary;
|
130
120
|
args[1] = curr_meth;
|
131
121
|
rb_protect(record_callsite_info, (VALUE)args, &status);
|
132
122
|
|
133
|
-
if(!status && node) {
|
134
|
-
type_def_site args;
|
135
|
-
|
123
|
+
if (!status && node) {
|
124
|
+
type_def_site args;
|
136
125
|
args.sourcefile = node->nd_file;
|
137
126
|
args.sourceline = nd_line(node) - 1;
|
138
127
|
args.curr_meth = curr_meth;
|
139
128
|
rb_protect(record_method_def_site, (VALUE)&args, NULL);
|
140
129
|
}
|
141
130
|
|
142
|
-
if(status)
|
143
|
-
rb_gv_set("$!", Qnil);
|
131
|
+
if (status) rb_gv_set("$!", Qnil);
|
144
132
|
}
|
145
133
|
|
146
134
|
static VALUE cov_install_callsite_hook(VALUE self) {
|
147
|
-
if(!callsite_hook_set_p) {
|
148
|
-
if(TYPE(caller_info) != T_HASH)
|
149
|
-
caller_info = rb_hash_new();
|
135
|
+
if (!callsite_hook_set_p) {
|
136
|
+
if (TYPE(caller_info) != T_HASH) caller_info = rb_hash_new();
|
150
137
|
callsite_hook_set_p = 1;
|
151
138
|
rb_add_event_hook(coverage_event_callsite_hook, RUBY_EVENT_CALL);
|
152
|
-
|
153
139
|
return Qtrue;
|
154
|
-
}
|
155
|
-
else
|
156
|
-
return Qfalse;
|
140
|
+
} else return Qfalse;
|
157
141
|
}
|
158
142
|
|
159
143
|
static VALUE cov_remove_callsite_hook(VALUE self) {
|
160
|
-
if(!callsite_hook_set_p)
|
144
|
+
if (!callsite_hook_set_p) {
|
161
145
|
return Qfalse;
|
162
|
-
else {
|
146
|
+
} else {
|
163
147
|
rb_remove_event_hook(coverage_event_callsite_hook);
|
164
148
|
callsite_hook_set_p = 0;
|
165
149
|
return Qtrue;
|
@@ -168,7 +152,6 @@ static VALUE cov_remove_callsite_hook(VALUE self) {
|
|
168
152
|
|
169
153
|
static VALUE cov_generate_callsite_info(VALUE self) {
|
170
154
|
VALUE ret;
|
171
|
-
|
172
155
|
ret = rb_ary_new();
|
173
156
|
rb_ary_push(ret, caller_info);
|
174
157
|
rb_ary_push(ret, method_def_site_info);
|
@@ -176,7 +159,7 @@ static VALUE cov_generate_callsite_info(VALUE self) {
|
|
176
159
|
}
|
177
160
|
|
178
161
|
static VALUE cov_reset_callsite(VALUE self) {
|
179
|
-
if(callsite_hook_set_p) {
|
162
|
+
if (callsite_hook_set_p) {
|
180
163
|
rb_raise(rb_eRuntimeError, "Cannot reset the callsite info in the middle of a traced run.");
|
181
164
|
return Qnil;
|
182
165
|
}
|
@@ -193,22 +176,24 @@ void Init_rcov_callsite() {
|
|
193
176
|
ID id_coverage__ = rb_intern("RCOV__");
|
194
177
|
ID id_script_lines__ = rb_intern("SCRIPT_LINES__");
|
195
178
|
|
196
|
-
if(rb_const_defined(rb_cObject, id_rcov))
|
179
|
+
if (rb_const_defined(rb_cObject, id_rcov)) {
|
197
180
|
mRcov = rb_const_get(rb_cObject, id_rcov);
|
198
|
-
else
|
181
|
+
} else {
|
199
182
|
mRcov = rb_define_module("Rcov");
|
200
|
-
|
201
|
-
|
183
|
+
}
|
184
|
+
|
185
|
+
if(rb_const_defined(mRcov, id_coverage__)) {
|
202
186
|
mRCOV__ = rb_const_get_at(mRcov, id_coverage__);
|
203
|
-
else
|
187
|
+
} else {
|
204
188
|
mRCOV__ = rb_define_module_under(mRcov, "RCOV__");
|
189
|
+
}
|
205
190
|
|
206
191
|
callsite_hook_set_p = 0;
|
207
192
|
caller_info = rb_hash_new();
|
208
193
|
method_def_site_info = rb_hash_new();
|
209
194
|
rb_gc_register_address(&caller_info);
|
210
195
|
rb_gc_register_address(&method_def_site_info);
|
211
|
-
|
196
|
+
|
212
197
|
rb_define_singleton_method(mRCOV__, "install_callsite_hook", cov_install_callsite_hook, 0);
|
213
198
|
rb_define_singleton_method(mRCOV__, "remove_callsite_hook", cov_remove_callsite_hook, 0);
|
214
199
|
rb_define_singleton_method(mRCOV__, "generate_callsite_info", cov_generate_callsite_info, 0);
|
data/ext/rcovrt/1.8/rcovrt.c
CHANGED
@@ -6,7 +6,6 @@
|
|
6
6
|
#include <assert.h>
|
7
7
|
|
8
8
|
#define COVERAGE_DEBUG_EVENTS 0
|
9
|
-
|
10
9
|
#define RCOVRT_VERSION_MAJOR 2
|
11
10
|
#define RCOVRT_VERSION_MINOR 0
|
12
11
|
#define RCOVRT_VERSION_REV 0
|
@@ -24,41 +23,36 @@ struct cov_array {
|
|
24
23
|
};
|
25
24
|
|
26
25
|
static struct cov_array *cached_array = 0;
|
27
|
-
static char *cached_file = 0;
|
26
|
+
static char *cached_file = 0;
|
28
27
|
|
29
28
|
static struct cov_array * coverage_increase_counter_uncached(char *sourcefile, unsigned int sourceline, char mark_only) {
|
30
29
|
struct cov_array *carray = NULL;
|
31
|
-
|
32
|
-
if(sourcefile == NULL) {
|
33
|
-
/* "can't happen", just ignore and avoid segfault */
|
30
|
+
|
31
|
+
if (sourcefile == NULL) {
|
34
32
|
return NULL;
|
35
|
-
}
|
36
|
-
else if(!st_lookup(coverinfo, (st_data_t)sourcefile, (st_data_t*)&carray)) {
|
33
|
+
} else if (!st_lookup(coverinfo, (st_data_t)sourcefile, (st_data_t*)&carray)) {
|
37
34
|
VALUE arr;
|
38
|
-
|
39
35
|
arr = rb_hash_aref(oSCRIPT_LINES__, rb_str_new2(sourcefile));
|
40
|
-
|
41
|
-
|
36
|
+
|
37
|
+
if (NIL_P(arr)) return 0;
|
38
|
+
|
42
39
|
rb_check_type(arr, T_ARRAY);
|
43
40
|
carray = calloc(1, sizeof(struct cov_array));
|
44
41
|
carray->ptr = calloc(RARRAY(arr)->len, sizeof(unsigned int));
|
45
42
|
carray->len = RARRAY(arr)->len;
|
46
43
|
st_insert(coverinfo, (st_data_t)strdup(sourcefile), (st_data_t) carray);
|
47
|
-
}
|
48
|
-
else {
|
49
|
-
/* recovered carray, sanity check */
|
44
|
+
} else {
|
50
45
|
assert(carray && "failed to create valid carray");
|
51
46
|
}
|
52
47
|
|
53
|
-
if(mark_only) {
|
48
|
+
if (mark_only) {
|
54
49
|
if (carray && carray->len > sourceline) {
|
55
|
-
if(!carray->ptr[sourceline])
|
50
|
+
if (!carray->ptr[sourceline])
|
56
51
|
carray->ptr[sourceline] = 1;
|
57
52
|
} else {
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
#endif
|
53
|
+
#if COVERAGE_DEBUG_EVENTS
|
54
|
+
printf("DEBUG: %s carray->len:%d sourceline:%d\n", sourcefile, carray->len, sourceline);
|
55
|
+
#endif
|
62
56
|
}
|
63
57
|
} else {
|
64
58
|
if (carray && carray->len > sourceline) {
|
@@ -73,17 +67,15 @@ static void coverage_mark_caller() {
|
|
73
67
|
struct FRAME *frame = ruby_frame;
|
74
68
|
NODE *n;
|
75
69
|
|
76
|
-
if (frame->last_func == ID_ALLOCATOR)
|
77
|
-
|
78
|
-
}
|
70
|
+
if (frame->last_func == ID_ALLOCATOR) frame = frame->prev;
|
71
|
+
|
79
72
|
for (; frame && (n = frame->node); frame = frame->prev) {
|
80
73
|
if (frame->prev && frame->prev->last_func) {
|
81
74
|
if (frame->prev->node == n) {
|
82
75
|
if (frame->prev->last_func == frame->last_func) continue;
|
83
76
|
}
|
84
77
|
coverage_increase_counter_uncached(n->nd_file, nd_line(n) - 1, 1);
|
85
|
-
}
|
86
|
-
else {
|
78
|
+
} else {
|
87
79
|
coverage_increase_counter_uncached(n->nd_file, nd_line(n) - 1, 1);
|
88
80
|
}
|
89
81
|
break;
|
@@ -91,10 +83,11 @@ static void coverage_mark_caller() {
|
|
91
83
|
}
|
92
84
|
|
93
85
|
static void coverage_increase_counter_cached(char *sourcefile, int sourceline) {
|
94
|
-
if(cached_file == sourcefile && cached_array && cached_array->len > sourceline) {
|
86
|
+
if (cached_file == sourcefile && cached_array && cached_array->len > sourceline) {
|
95
87
|
cached_array->ptr[sourceline]++;
|
96
88
|
return;
|
97
89
|
}
|
90
|
+
|
98
91
|
cached_file = sourcefile;
|
99
92
|
cached_array = coverage_increase_counter_uncached(sourcefile, sourceline, 0);
|
100
93
|
}
|
@@ -103,74 +96,65 @@ static void coverage_event_coverage_hook(rb_event_t event, NODE *node, VALUE sel
|
|
103
96
|
char *sourcefile;
|
104
97
|
unsigned int sourceline;
|
105
98
|
static unsigned int in_hook = 0;
|
106
|
-
|
107
|
-
if(in_hook)
|
108
|
-
return;
|
109
|
-
}
|
99
|
+
|
100
|
+
if (in_hook) return;
|
110
101
|
|
111
102
|
in_hook++;
|
112
103
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
rb_gv_set("$!", old_exception);
|
134
|
-
} while (0);
|
135
|
-
#endif
|
104
|
+
#if COVERAGE_DEBUG_EVENTS
|
105
|
+
do {
|
106
|
+
int status;
|
107
|
+
VALUE old_exception;
|
108
|
+
old_exception = rb_gv_get("$!");
|
109
|
+
rb_protect(rb_inspect, klass, &status);
|
110
|
+
|
111
|
+
if (!status) {
|
112
|
+
printf("EVENT: %d %s %s %s %d\n", event,
|
113
|
+
klass ? RSTRING(rb_inspect(klass))->ptr : "",
|
114
|
+
mid ? (mid == ID_ALLOCATOR ? "ID_ALLOCATOR" : rb_id2name(mid))
|
115
|
+
: "unknown",
|
116
|
+
node ? node->nd_file : "", node ? nd_line(node) : 0);
|
117
|
+
} else {
|
118
|
+
printf("EVENT: %d %s %s %d\n", event,
|
119
|
+
mid ? (mid == ID_ALLOCATOR ? "ID_ALLOCATOR" : rb_id2name(mid))
|
120
|
+
: "unknown",
|
121
|
+
node ? node->nd_file : "", node ? nd_line(node) : 0);
|
122
|
+
}
|
136
123
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
if(event &
|
124
|
+
rb_gv_set("$!", old_exception);
|
125
|
+
} while (0);
|
126
|
+
#endif
|
127
|
+
|
128
|
+
if (event & RUBY_EVENT_C_CALL) coverage_mark_caller();
|
129
|
+
|
130
|
+
if (event & (RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN | RUBY_EVENT_CLASS)) {
|
142
131
|
in_hook--;
|
143
132
|
return;
|
144
133
|
}
|
145
|
-
|
146
|
-
if(node == NULL) {
|
134
|
+
|
135
|
+
if (node == NULL) {
|
147
136
|
in_hook--;
|
148
|
-
|
137
|
+
return;
|
149
138
|
}
|
150
|
-
|
139
|
+
|
151
140
|
sourcefile = node->nd_file;
|
152
141
|
sourceline = nd_line(node) - 1;
|
153
|
-
|
154
142
|
coverage_increase_counter_cached(sourcefile, sourceline);
|
155
|
-
|
156
|
-
if(event & RUBY_EVENT_CALL)
|
157
|
-
coverage_mark_caller();
|
143
|
+
|
144
|
+
if (event & RUBY_EVENT_CALL) coverage_mark_caller();
|
158
145
|
in_hook--;
|
159
146
|
}
|
160
147
|
|
161
148
|
static VALUE cov_install_coverage_hook(VALUE self) {
|
162
|
-
if(!coverage_hook_set_p) {
|
163
|
-
if(!coverinfo)
|
164
|
-
coverinfo = st_init_strtable();
|
149
|
+
if (!coverage_hook_set_p) {
|
150
|
+
if (!coverinfo) coverinfo = st_init_strtable();
|
165
151
|
coverage_hook_set_p = 1;
|
166
152
|
/* TODO: allow C_CALL too, since it's supported already
|
167
153
|
* the overhead is around ~30%, tested on typo */
|
168
154
|
rb_add_event_hook(coverage_event_coverage_hook, RUBY_EVENT_ALL & ~RUBY_EVENT_C_CALL & ~RUBY_EVENT_C_RETURN & ~RUBY_EVENT_CLASS);
|
169
|
-
|
155
|
+
|
170
156
|
return Qtrue;
|
171
|
-
}
|
172
|
-
else
|
173
|
-
return Qfalse;
|
157
|
+
} else return Qfalse;
|
174
158
|
}
|
175
159
|
|
176
160
|
static int populate_cover(st_data_t key, st_data_t value, st_data_t cover) {
|
@@ -179,24 +163,25 @@ static int populate_cover(st_data_t key, st_data_t value, st_data_t cover) {
|
|
179
163
|
VALUE rval;
|
180
164
|
struct cov_array *carray;
|
181
165
|
unsigned int i;
|
182
|
-
|
166
|
+
|
183
167
|
rcover = (VALUE)cover;
|
184
168
|
carray = (struct cov_array *) value;
|
185
169
|
rkey = rb_str_new2((char*) key);
|
186
170
|
rval = rb_ary_new2(carray->len);
|
187
171
|
|
188
|
-
for(i = 0; i < carray->len; i++)
|
172
|
+
for (i = 0; i < carray->len; i++) {
|
189
173
|
RARRAY(rval)->ptr[i] = UINT2NUM(carray->ptr[i]);
|
174
|
+
}
|
190
175
|
|
191
176
|
RARRAY(rval)->len = carray->len;
|
192
177
|
rb_hash_aset(rcover, rkey, rval);
|
193
|
-
|
178
|
+
|
194
179
|
return ST_CONTINUE;
|
195
180
|
}
|
196
181
|
|
197
182
|
static int free_table(st_data_t key, st_data_t value, st_data_t ignored) {
|
198
183
|
struct cov_array *carray;
|
199
|
-
|
184
|
+
|
200
185
|
carray = (struct cov_array *) value;
|
201
186
|
free((char *)key);
|
202
187
|
free(carray->ptr);
|
@@ -206,9 +191,9 @@ static int free_table(st_data_t key, st_data_t value, st_data_t ignored) {
|
|
206
191
|
}
|
207
192
|
|
208
193
|
static VALUE cov_remove_coverage_hook(VALUE self) {
|
209
|
-
if(!coverage_hook_set_p)
|
194
|
+
if (!coverage_hook_set_p) {
|
210
195
|
return Qfalse;
|
211
|
-
else {
|
196
|
+
} else {
|
212
197
|
rb_remove_event_hook(coverage_event_coverage_hook);
|
213
198
|
coverage_hook_set_p = 0;
|
214
199
|
return Qtrue;
|
@@ -218,14 +203,11 @@ static VALUE cov_remove_coverage_hook(VALUE self) {
|
|
218
203
|
static VALUE cov_generate_coverage_info(VALUE self) {
|
219
204
|
VALUE cover;
|
220
205
|
|
221
|
-
if(rb_const_defined_at(mRCOV__, id_cover))
|
222
|
-
rb_mod_remove_const(mRCOV__, ID2SYM(id_cover));
|
223
|
-
}
|
206
|
+
if (rb_const_defined_at(mRCOV__, id_cover)) rb_mod_remove_const(mRCOV__, ID2SYM(id_cover));
|
224
207
|
|
225
208
|
cover = rb_hash_new();
|
226
209
|
|
227
|
-
if(coverinfo)
|
228
|
-
st_foreach(coverinfo, populate_cover, cover);
|
210
|
+
if (coverinfo) st_foreach(coverinfo, populate_cover, cover);
|
229
211
|
|
230
212
|
rb_define_const(mRCOV__, "COVER", cover);
|
231
213
|
|
@@ -233,14 +215,14 @@ static VALUE cov_generate_coverage_info(VALUE self) {
|
|
233
215
|
}
|
234
216
|
|
235
217
|
static VALUE cov_reset_coverage(VALUE self) {
|
236
|
-
if(coverage_hook_set_p) {
|
218
|
+
if (coverage_hook_set_p) {
|
237
219
|
rb_raise(rb_eRuntimeError, "Cannot reset the coverage info in the middle of a traced run.");
|
238
220
|
return Qnil;
|
239
221
|
}
|
240
222
|
|
241
223
|
cached_array = 0;
|
242
224
|
cached_file = 0;
|
243
|
-
st_foreach(coverinfo, free_table, Qnil);
|
225
|
+
st_foreach(coverinfo, free_table, Qnil);
|
244
226
|
st_free_table(coverinfo);
|
245
227
|
coverinfo = 0;
|
246
228
|
|
@@ -249,12 +231,12 @@ static VALUE cov_reset_coverage(VALUE self) {
|
|
249
231
|
|
250
232
|
static VALUE cov_ABI(VALUE self) {
|
251
233
|
VALUE ret;
|
252
|
-
|
234
|
+
|
253
235
|
ret = rb_ary_new();
|
254
236
|
rb_ary_push(ret, INT2FIX(RCOVRT_VERSION_MAJOR));
|
255
237
|
rb_ary_push(ret, INT2FIX(RCOVRT_VERSION_MINOR));
|
256
238
|
rb_ary_push(ret, INT2FIX(RCOVRT_VERSION_REV));
|
257
|
-
|
239
|
+
|
258
240
|
return ret;
|
259
241
|
}
|
260
242
|
|
@@ -262,33 +244,35 @@ void Init_rcovrt() {
|
|
262
244
|
ID id_rcov = rb_intern("Rcov");
|
263
245
|
ID id_coverage__ = rb_intern("RCOV__");
|
264
246
|
ID id_script_lines__ = rb_intern("SCRIPT_LINES__");
|
265
|
-
|
247
|
+
|
266
248
|
id_cover = rb_intern("COVER");
|
267
|
-
|
268
|
-
if(rb_const_defined(rb_cObject, id_rcov))
|
249
|
+
|
250
|
+
if (rb_const_defined(rb_cObject, id_rcov)) {
|
269
251
|
mRcov = rb_const_get(rb_cObject, id_rcov);
|
270
|
-
else
|
252
|
+
} else {
|
271
253
|
mRcov = rb_define_module("Rcov");
|
272
|
-
|
273
|
-
|
254
|
+
}
|
255
|
+
|
256
|
+
if (rb_const_defined(mRcov, id_coverage__)) {
|
274
257
|
mRCOV__ = rb_const_get_at(mRcov, id_coverage__);
|
275
|
-
else
|
258
|
+
} else {
|
276
259
|
mRCOV__ = rb_define_module_under(mRcov, "RCOV__");
|
277
|
-
|
278
|
-
|
260
|
+
}
|
261
|
+
|
262
|
+
if (rb_const_defined(rb_cObject, id_script_lines__)) {
|
279
263
|
oSCRIPT_LINES__ = rb_const_get(rb_cObject, rb_intern("SCRIPT_LINES__"));
|
280
|
-
else {
|
264
|
+
} else {
|
281
265
|
oSCRIPT_LINES__ = rb_hash_new();
|
282
266
|
rb_const_set(rb_cObject, id_script_lines__, oSCRIPT_LINES__);
|
283
267
|
}
|
284
|
-
|
268
|
+
|
285
269
|
coverage_hook_set_p = 0;
|
286
|
-
|
270
|
+
|
287
271
|
rb_define_singleton_method(mRCOV__, "install_coverage_hook", cov_install_coverage_hook, 0);
|
288
272
|
rb_define_singleton_method(mRCOV__, "remove_coverage_hook", cov_remove_coverage_hook, 0);
|
289
273
|
rb_define_singleton_method(mRCOV__, "generate_coverage_info", cov_generate_coverage_info, 0);
|
290
274
|
rb_define_singleton_method(mRCOV__, "reset_coverage", cov_reset_coverage, 0);
|
291
275
|
rb_define_singleton_method(mRCOV__, "ABI", cov_ABI, 0);
|
292
|
-
|
276
|
+
|
293
277
|
Init_rcov_callsite();
|
294
278
|
}
|