rcov 0.9.11 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|