Feature #9508 » pull-request-511.patch
compile.c | ||
---|---|---|
iseq->compile_data->last_coverable_line = (line); \
|
||
ADD_INSN1((seq), (line), trace, INT2FIX(RUBY_EVENT_COVERAGE)); \
|
||
} \
|
||
if ((event) == RUBY_EVENT_DEFN && iseq->method_coverage) { \
|
||
/*iseq->compile_data->last_coverable_line = (line); \
|
||
VALUE info = rb_hash_new(); \
|
||
rb_hash_aset(info, ID2SYM(rb_intern("count")), INT2FIX(0));*/ \
|
||
rb_hash_aset(iseq->method_coverage, LONG2FIX(line), Qnil); \
|
||
} \
|
||
if ((event) == RUBY_EVENT_CALL && iseq->method_coverage && \
|
||
(line) != iseq->compile_data->last_coverable_line) { \
|
||
iseq->compile_data->last_coverable_line = (line); \
|
||
ADD_INSN1((seq), (line), trace, INT2FIX(RUBY_EVENT_MCOVERAGE)); \
|
||
} \
|
||
if (iseq->compile_data->option->trace_instruction) { \
|
||
ADD_INSN1((seq), (line), trace, INT2FIX(event)); \
|
||
} \
|
||
... | ... | |
debugp_param("defn/iseq", iseqval);
|
||
ADD_TRACE(ret, nd_line(node), RUBY_EVENT_DEFN);
|
||
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
|
||
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
|
||
ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid));
|
ext/coverage/coverage.c | ||
---|---|---|
VALUE path = (VALUE)key;
|
||
VALUE coverage = (VALUE)val;
|
||
VALUE coverages = (VALUE)h;
|
||
coverage = rb_ary_dup(coverage);
|
||
rb_ary_clear((VALUE)val);
|
||
VALUE line_coverage = rb_hash_lookup(coverage, ID2SYM(rb_intern("lines")));
|
||
line_coverage = rb_ary_dup(line_coverage);
|
||
coverage = rb_hash_dup(coverage);
|
||
rb_hash_clear((VALUE)val);
|
||
rb_hash_freeze(line_coverage);
|
||
rb_hash_aset(coverage, ID2SYM(rb_intern("lines")), line_coverage);
|
||
rb_ary_freeze(coverage);
|
||
rb_hash_aset(coverages, path, coverage);
|
||
return ST_CONTINUE;
|
include/ruby/ruby.h | ||
---|---|---|
#define RUBY_EVENT_C_CALL 0x0020
|
||
#define RUBY_EVENT_C_RETURN 0x0040
|
||
#define RUBY_EVENT_RAISE 0x0080
|
||
#define RUBY_EVENT_DEFN 0x0090
|
||
#define RUBY_EVENT_ALL 0x00ff
|
||
/* for TracePoint extended events */
|
||
... | ... | |
/* special events */
|
||
#define RUBY_EVENT_SPECIFIED_LINE 0x010000
|
||
#define RUBY_EVENT_COVERAGE 0x020000
|
||
#define RUBY_EVENT_MCOVERAGE 0x040000
|
||
/* internal events */
|
||
#define RUBY_INTERNAL_EVENT_SWITCH 0x040000
|
iseq.c | ||
---|---|---|
RUBY_MARK_UNLESS_NULL((VALUE)iseq->cref_stack);
|
||
RUBY_MARK_UNLESS_NULL(iseq->klass);
|
||
RUBY_MARK_UNLESS_NULL(iseq->coverage);
|
||
RUBY_MARK_UNLESS_NULL(iseq->method_coverage);
|
||
RUBY_MARK_UNLESS_NULL(iseq->orig);
|
||
if (iseq->compile_data != 0) {
|
||
... | ... | |
iseq->compile_data->last_coverable_line = -1;
|
||
RB_OBJ_WRITE(iseq->self, &iseq->coverage, Qfalse);
|
||
RB_OBJ_WRITE(iseq->self, &iseq->method_coverage, Qfalse);
|
||
if (!GET_THREAD()->parse_in_eval) {
|
||
VALUE coverages = rb_get_coverages();
|
||
if (RTEST(coverages)) {
|
||
RB_OBJ_WRITE(iseq->self, &iseq->coverage, rb_hash_lookup(coverages, path));
|
||
RB_OBJ_WRITE(iseq->self, &iseq->coverage,
|
||
rb_hash_lookup(rb_hash_lookup(coverages, path), ID2SYM(rb_intern("lines"))));
|
||
RB_OBJ_WRITE(iseq->self, &iseq->method_coverage,
|
||
rb_hash_lookup(rb_hash_lookup(coverages, path), ID2SYM(rb_intern("methods"))));
|
||
if (NIL_P(iseq->coverage)) RB_OBJ_WRITE(iseq->self, &iseq->coverage, Qfalse);
|
||
if (NIL_P(iseq->method_coverage)) RB_OBJ_WRITE(iseq->self, &iseq->method_coverage, Qfalse);
|
||
}
|
||
}
|
||
parse.y | ||
---|---|---|
VALUE coverages = rb_get_coverages();
|
||
if (RTEST(coverages) && RBASIC(coverages)->klass == 0) {
|
||
VALUE lines = rb_ary_new2(n);
|
||
VALUE rb_file_coverage = rb_hash_new();
|
||
VALUE methods = rb_hash_new();
|
||
int i;
|
||
RBASIC_CLEAR_CLASS(lines);
|
||
for (i = 0; i < n; i++) RARRAY_ASET(lines, i, Qnil);
|
||
RARRAY(lines)->as.heap.len = n;
|
||
rb_hash_aset(coverages, fname, lines);
|
||
rb_hash_aset(rb_file_coverage, ID2SYM(rb_intern("lines")), lines);
|
||
rb_hash_aset(rb_file_coverage, ID2SYM(rb_intern("methods")), methods);
|
||
rb_hash_aset(coverages, fname, rb_file_coverage);
|
||
return lines;
|
||
}
|
||
return 0;
|
thread.c | ||
---|---|---|
clear_coverage_i(st_data_t key, st_data_t val, st_data_t dummy)
|
||
{
|
||
int i;
|
||
VALUE lines = (VALUE)val;
|
||
VALUE lines = rb_hash_lookup(val, ID2SYM(rb_intern("lines")));
|
||
for (i = 0; i < RARRAY_LEN(lines); i++) {
|
||
if (RARRAY_AREF(lines, i) != Qnil) {
|
||
... | ... | |
}
|
||
}
|
||
static void
|
||
update_method_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
|
||
{
|
||
VALUE method_coverage = GET_THREAD()->cfp->iseq->method_coverage;
|
||
if (method_coverage) {
|
||
long line = rb_sourceline();
|
||
VALUE info = rb_hash_lookup(method_coverage, LONG2FIX(line));
|
||
if (info == Qnil) {
|
||
VALUE info = rb_hash_new();
|
||
rb_hash_aset(info, ID2SYM(rb_intern("count")), INT2FIX(1));
|
||
rb_hash_aset(method_coverage, LONG2FIX(line), info);
|
||
} else {
|
||
long count = FIX2LONG(rb_hash_lookup(info, ID2SYM(rb_intern("count")))) + 1;
|
||
rb_hash_aset(info, ID2SYM(rb_intern("count")), LONG2FIX(count));
|
||
}
|
||
}
|
||
}
|
||
VALUE
|
||
rb_get_coverages(void)
|
||
{
|
||
... | ... | |
{
|
||
GET_VM()->coverages = coverages;
|
||
rb_add_event_hook(update_coverage, RUBY_EVENT_COVERAGE, Qnil);
|
||
rb_add_event_hook(update_method_coverage, RUBY_EVENT_MCOVERAGE, Qnil);
|
||
}
|
||
void
|
vm_core.h | ||
---|---|---|
VALUE *iseq_encoded; /* encoded iseq */
|
||
unsigned long iseq_size;
|
||
const VALUE mark_ary; /* Array: includes operands which should be GC marked */
|
||
const VALUE coverage; /* coverage array */
|
||
const VALUE coverage; /* coverage array */
|
||
const VALUE method_coverage; /* method coverage array */
|
||
/* insn info, must be freed */
|
||
struct iseq_line_info_entry *line_info_table;
|
||
-
|
compile.c | ||
---|---|---|
iseq->compile_data->last_coverable_line = (line); \
|
||
ADD_INSN1((seq), (line), trace, INT2FIX(RUBY_EVENT_COVERAGE)); \
|
||
} \
|
||
if ((event) == RUBY_EVENT_DEFN && iseq->method_coverage) { \
|
||
/*iseq->compile_data->last_coverable_line = (line); \
|
||
VALUE info = rb_hash_new(); \
|
||
rb_hash_aset(info, ID2SYM(rb_intern("count")), INT2FIX(0));*/ \
|
||
rb_hash_aset(iseq->method_coverage, LONG2FIX(line), Qnil); \
|
||
} \
|
||
if ((event) == RUBY_EVENT_CALL && iseq->method_coverage && \
|
||
(line) != iseq->compile_data->last_coverable_line) { \
|
||
iseq->compile_data->last_coverable_line = (line); \
|
||
... | ... | |
} \
|
||
} while (0)
|
||
#define ADD_COVERAGE_TRACE(seq, line, event) \
|
||
do { \
|
||
if ((event) == RUBY_EVENT_DEFN && iseq->method_coverage) { \
|
||
rb_hash_aset(iseq->method_coverage, LONG2FIX(line), INT2FIX(0)); \
|
||
} \
|
||
} while (0)
|
||
/* add label */
|
||
#define ADD_LABEL(seq, label) \
|
||
ADD_ELEM((seq), (LINK_ELEMENT *) (label))
|
||
... | ... | |
debugp_param("defn/iseq", iseqval);
|
||
ADD_TRACE(ret, nd_line(node), RUBY_EVENT_DEFN);
|
||
ADD_COVERAGE_TRACE(ret, nd_line(node), RUBY_EVENT_DEFN);
|
||
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
|
||
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
|
||
ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid));
|
thread.c | ||
---|---|---|
long line = rb_sourceline();
|
||
VALUE info = rb_hash_lookup(method_coverage, LONG2FIX(line));
|
||
if (info == Qnil) {
|
||
VALUE info = rb_hash_new();
|
||
rb_hash_aset(info, ID2SYM(rb_intern("count")), INT2FIX(1));
|
||
rb_hash_aset(method_coverage, LONG2FIX(line), info);
|
||
} else {
|
||
long count = FIX2LONG(rb_hash_lookup(info, ID2SYM(rb_intern("count")))) + 1;
|
||
rb_hash_aset(info, ID2SYM(rb_intern("count")), LONG2FIX(count));
|
||
}
|
||
long count = FIX2LONG(info) + 1;
|
||
rb_hash_aset(method_coverage, LONG2FIX(line), LONG2FIX(count));
|
||
}
|
||
}
|
||
-
|
compile.c | ||
---|---|---|
if ((event) == RUBY_EVENT_DEFN && iseq->method_coverage) { \
|
||
rb_hash_aset(iseq->method_coverage, LONG2FIX(line), INT2FIX(0)); \
|
||
} \
|
||
if ((event) == RUBY_EVENT_BRANCH && iseq->branch_coverage) { \
|
||
rb_hash_aset(iseq->branch_coverage, LONG2FIX(line), INT2FIX(0)); \
|
||
ADD_INSN1((seq), (line), trace, INT2FIX(RUBY_EVENT_BCOVERAGE)); \
|
||
} \
|
||
} while (0)
|
||
/* add label */
|
||
... | ... | |
ADD_SEQ(ret, cond_seq);
|
||
ADD_LABEL(ret, then_label);
|
||
if (node->nd_body)
|
||
ADD_COVERAGE_TRACE(ret, nd_line(node->nd_body), RUBY_EVENT_BRANCH);
|
||
ADD_SEQ(ret, then_seq);
|
||
ADD_INSNL(ret, line, jump, end_label);
|
||
ADD_LABEL(ret, else_label);
|
||
if (node->nd_else)
|
||
ADD_COVERAGE_TRACE(ret, nd_line(node->nd_else), RUBY_EVENT_BRANCH);
|
||
ADD_SEQ(ret, else_seq);
|
||
ADD_LABEL(ret, end_label);
|
include/ruby/ruby.h | ||
---|---|---|
#define RUBY_EVENT_C_RETURN 0x0040
|
||
#define RUBY_EVENT_RAISE 0x0080
|
||
#define RUBY_EVENT_DEFN 0x0090
|
||
#define RUBY_EVENT_BRANCH 0x00a0
|
||
#define RUBY_EVENT_ALL 0x00ff
|
||
/* for TracePoint extended events */
|
||
... | ... | |
#define RUBY_EVENT_SPECIFIED_LINE 0x010000
|
||
#define RUBY_EVENT_COVERAGE 0x020000
|
||
#define RUBY_EVENT_MCOVERAGE 0x040000
|
||
#define RUBY_EVENT_BCOVERAGE 0x080000
|
||
/* internal events */
|
||
#define RUBY_INTERNAL_EVENT_SWITCH 0x040000
|
iseq.c | ||
---|---|---|
RUBY_MARK_UNLESS_NULL(iseq->klass);
|
||
RUBY_MARK_UNLESS_NULL(iseq->coverage);
|
||
RUBY_MARK_UNLESS_NULL(iseq->method_coverage);
|
||
RUBY_MARK_UNLESS_NULL(iseq->branch_coverage);
|
||
RUBY_MARK_UNLESS_NULL(iseq->orig);
|
||
if (iseq->compile_data != 0) {
|
||
... | ... | |
RB_OBJ_WRITE(iseq->self, &iseq->coverage, Qfalse);
|
||
RB_OBJ_WRITE(iseq->self, &iseq->method_coverage, Qfalse);
|
||
RB_OBJ_WRITE(iseq->self, &iseq->branch_coverage, Qfalse);
|
||
if (!GET_THREAD()->parse_in_eval) {
|
||
VALUE coverages = rb_get_coverages();
|
||
if (RTEST(coverages)) {
|
||
... | ... | |
rb_hash_lookup(rb_hash_lookup(coverages, path), ID2SYM(rb_intern("lines"))));
|
||
RB_OBJ_WRITE(iseq->self, &iseq->method_coverage,
|
||
rb_hash_lookup(rb_hash_lookup(coverages, path), ID2SYM(rb_intern("methods"))));
|
||
RB_OBJ_WRITE(iseq->self, &iseq->branch_coverage,
|
||
rb_hash_lookup(rb_hash_lookup(coverages, path), ID2SYM(rb_intern("branches"))));
|
||
if (NIL_P(iseq->coverage)) RB_OBJ_WRITE(iseq->self, &iseq->coverage, Qfalse);
|
||
if (NIL_P(iseq->method_coverage)) RB_OBJ_WRITE(iseq->self, &iseq->method_coverage, Qfalse);
|
||
}
|
parse.y | ||
---|---|---|
VALUE lines = rb_ary_new2(n);
|
||
VALUE rb_file_coverage = rb_hash_new();
|
||
VALUE methods = rb_hash_new();
|
||
VALUE branches = rb_hash_new();
|
||
int i;
|
||
RBASIC_CLEAR_CLASS(lines);
|
||
for (i = 0; i < n; i++) RARRAY_ASET(lines, i, Qnil);
|
||
RARRAY(lines)->as.heap.len = n;
|
||
rb_hash_aset(rb_file_coverage, ID2SYM(rb_intern("lines")), lines);
|
||
rb_hash_aset(rb_file_coverage, ID2SYM(rb_intern("methods")), methods);
|
||
rb_hash_aset(rb_file_coverage, ID2SYM(rb_intern("branches")), branches);
|
||
rb_hash_aset(coverages, fname, rb_file_coverage);
|
||
return lines;
|
||
}
|
thread.c | ||
---|---|---|
}
|
||
static void
|
||
update_method_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
|
||
update_detailed_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
|
||
{
|
||
VALUE method_coverage = GET_THREAD()->cfp->iseq->method_coverage;
|
||
if (method_coverage) {
|
||
long line = rb_sourceline();
|
||
VALUE info = rb_hash_lookup(method_coverage, LONG2FIX(line));
|
||
VALUE coverage;
|
||
if (event == RUBY_EVENT_MCOVERAGE) {
|
||
coverage = GET_THREAD()->cfp->iseq->method_coverage;
|
||
} else if (event == RUBY_EVENT_BCOVERAGE) {
|
||
coverage = GET_THREAD()->cfp->iseq->branch_coverage;
|
||
} else {
|
||
rb_raise(rb_eArgError, "unknown detailed coverage event");
|
||
}
|
||
if (coverage) {
|
||
VALUE line = LONG2FIX(rb_sourceline());
|
||
VALUE count = rb_hash_lookup(coverage, line);
|
||
if (count == Qnil) {
|
||
return;
|
||
}
|
||
long count = FIX2LONG(info) + 1;
|
||
rb_hash_aset(method_coverage, LONG2FIX(line), LONG2FIX(count));
|
||
rb_hash_aset(coverage, line, LONG2FIX(FIX2LONG(count) + 1));
|
||
}
|
||
}
|
||
... | ... | |
{
|
||
GET_VM()->coverages = coverages;
|
||
rb_add_event_hook(update_coverage, RUBY_EVENT_COVERAGE, Qnil);
|
||
rb_add_event_hook(update_method_coverage, RUBY_EVENT_MCOVERAGE, Qnil);
|
||
rb_add_event_hook(update_detailed_coverage, RUBY_EVENT_MCOVERAGE, Qnil);
|
||
rb_add_event_hook(update_detailed_coverage, RUBY_EVENT_BCOVERAGE, Qnil);
|
||
}
|
||
void
|
vm_core.h | ||
---|---|---|
const VALUE mark_ary; /* Array: includes operands which should be GC marked */
|
||
const VALUE coverage; /* coverage array */
|
||
const VALUE method_coverage; /* method coverage array */
|
||
const VALUE branch_coverage; /* branch coverage array */
|
||
/* insn info, must be freed */
|
||
struct iseq_line_info_entry *line_info_table;
|
||
-
|
compile.c | ||
---|---|---|
ADD_INSNL(ret, line, jump, end_label);
|
||
ADD_LABEL(ret, else_label);
|
||
if (node->nd_else)
|
||
/* do not trace elsif node */
|
||
if (node->nd_else && nd_type(node->nd_else) != NODE_IF)
|
||
ADD_COVERAGE_TRACE(ret, nd_line(node->nd_else), RUBY_EVENT_BRANCH);
|
||
ADD_SEQ(ret, else_seq);
|
||
ext/coverage/coverage.c | ||
---|---|---|
VALUE path = (VALUE)key;
|
||
VALUE coverage = (VALUE)val;
|
||
VALUE coverages = (VALUE)h;
|
||
VALUE line_coverage = rb_hash_lookup(coverage, ID2SYM(rb_intern("lines")));
|
||
VALUE method_coverage = rb_hash_lookup(coverage, ID2SYM(rb_intern("methods")));
|
||
VALUE branch_coverage = rb_hash_lookup(coverage, ID2SYM(rb_intern("branches")));
|
||
line_coverage = rb_ary_dup(line_coverage);
|
||
method_coverage = rb_hash_dup(method_coverage);
|
||
branch_coverage = rb_hash_dup(branch_coverage);
|
||
rb_ary_clear(rb_hash_lookup(coverage, ID2SYM(rb_intern("lines"))));
|
||
rb_hash_clear(rb_hash_lookup(coverage, ID2SYM(rb_intern("methods"))));
|
||
rb_hash_clear(rb_hash_lookup(coverage, ID2SYM(rb_intern("branches"))));
|
||
coverage = rb_hash_dup(coverage);
|
||
rb_hash_clear((VALUE)val);
|
||
rb_hash_freeze(line_coverage);
|
||
rb_ary_freeze(line_coverage);
|
||
rb_hash_freeze(method_coverage);
|
||
rb_hash_freeze(branch_coverage);
|
||
rb_hash_aset(coverage, ID2SYM(rb_intern("lines")), line_coverage);
|
||
rb_hash_aset(coverage, ID2SYM(rb_intern("methods")), method_coverage);
|
||
rb_hash_aset(coverage, ID2SYM(rb_intern("branches")), branch_coverage);
|
||
rb_ary_freeze(coverage);
|
||
rb_hash_aset(coverages, path, coverage);
|
||
return ST_CONTINUE;
|
iseq.c | ||
---|---|---|
rb_hash_lookup(rb_hash_lookup(coverages, path), ID2SYM(rb_intern("branches"))));
|
||
if (NIL_P(iseq->coverage)) RB_OBJ_WRITE(iseq->self, &iseq->coverage, Qfalse);
|
||
if (NIL_P(iseq->method_coverage)) RB_OBJ_WRITE(iseq->self, &iseq->method_coverage, Qfalse);
|
||
if (NIL_P(iseq->branch_coverage)) RB_OBJ_WRITE(iseq->self, &iseq->branch_coverage, Qfalse);
|
||
}
|
||
}
|
||
test/coverage/test_branch_coverage.rb | ||
---|---|---|
require "test/unit"
|
||
require "coverage"
|
||
require "tmpdir"
|
||
class TestBranchCoverage < Test::Unit::TestCase
|
||
def test_branch_coverage
|
||
loaded_features = $".dup
|
||
Dir.mktmpdir {|tmp|
|
||
Dir.chdir(tmp) {
|
||
File.open("test.rb", "w") do |f|
|
||
f.puts <<-EOS
|
||
if 2+2 == 4
|
||
:ok
|
||
end
|
||
:ok unless [].size > 0
|
||
:bad unless [].size == 0
|
||
ary = [1,2,3]
|
||
if ary.include? 4
|
||
:bad
|
||
elsif ary.include? 5
|
||
:also_bad
|
||
else
|
||
:good
|
||
end
|
||
EOS
|
||
end
|
||
Coverage.start
|
||
require tmp + '/test.rb'
|
||
branch_coverage = Coverage.result[tmp + '/test.rb'][:branches]
|
||
assert_equal 6, branch_coverage.size
|
||
assert_equal 1, branch_coverage[2]
|
||
assert_equal 1, branch_coverage[5]
|
||
assert_equal 0, branch_coverage[6]
|
||
assert_equal 0, branch_coverage[10]
|
||
assert_equal 0, branch_coverage[12]
|
||
assert_equal 1, branch_coverage[14]
|
||
}
|
||
}
|
||
ensure
|
||
$".replace loaded_features
|
||
end
|
||
end
|
test/coverage/test_coverage.rb | ||
---|---|---|
def test_result_without_start
|
||
assert_raise(RuntimeError) {Coverage.result}
|
||
end
|
||
def test_result_with_nothing
|
||
Coverage.start
|
||
result = Coverage.result
|
||
assert_kind_of(Hash, result)
|
||
assert(! result.empty?)
|
||
result.each do |key, val|
|
||
assert_kind_of(String, key)
|
||
assert_kind_of(Array, val)
|
||
assert_kind_of(Hash, val)
|
||
assert_kind_of(Array, val[:lines])
|
||
assert_kind_of(Hash, val[:methods])
|
||
assert_kind_of(Hash, val[:branches])
|
||
end
|
||
end
|
||
... | ... | |
Coverage.start
|
||
require tmp + '/test.rb'
|
||
assert_equal 3, Coverage.result[tmp + '/test.rb'].size
|
||
assert_equal 3, Coverage.result[tmp + '/test.rb'][:lines].size
|
||
Coverage.start
|
||
coverage_test_method
|
||
assert_equal 0, Coverage.result[tmp + '/test.rb'].size
|
||
assert_equal 0, Coverage.result[tmp + '/test.rb'][:lines].size
|
||
}
|
||
}
|
||
ensure
|
||
... | ... | |
Coverage.start
|
||
require tmp + '/test.rb'
|
||
assert_equal 10003, Coverage.result[tmp + '/test.rb'].size
|
||
assert_equal 10003, Coverage.result[tmp + '/test.rb'][:lines].size
|
||
}
|
||
}
|
||
ensure
|
test/coverage/test_method_coverage.rb | ||
---|---|---|
require "test/unit"
|
||
require "coverage"
|
||
require "tmpdir"
|
||
class TestMethodCoverage < Test::Unit::TestCase
|
||
def test_method_coverage
|
||
loaded_features = $".dup
|
||
Dir.mktmpdir {|tmp|
|
||
Dir.chdir(tmp) {
|
||
File.open("test.rb", "w") do |f|
|
||
f.puts <<-EOS
|
||
def method_one
|
||
:one
|
||
end
|
||
def method_two
|
||
:two
|
||
end
|
||
method_two; method_two
|
||
EOS
|
||
end
|
||
Coverage.start
|
||
require tmp + '/test.rb'
|
||
method_coverage = Coverage.result[tmp + '/test.rb'][:methods]
|
||
assert_equal 2, method_coverage.size
|
||
assert_equal 0, method_coverage[1]
|
||
assert_equal 2, method_coverage[5]
|
||
}
|
||
}
|
||
ensure
|
||
$".replace loaded_features
|
||
end
|
||
end
|
thread.c | ||
---|---|---|
{
|
||
GET_VM()->coverages = Qfalse;
|
||
rb_remove_event_hook(update_coverage);
|
||
rb_remove_event_hook(update_detailed_coverage);
|
||
}
|
||
VALUE
|
||
-
|
compile.c | ||
---|---|---|
l1 = NEW_LABEL(line);
|
||
ADD_LABEL(body_seq, l1);
|
||
if (node->nd_body)
|
||
ADD_COVERAGE_TRACE(body_seq, nd_line(node->nd_body), RUBY_EVENT_BRANCH);
|
||
ADD_INSN(body_seq, line, pop);
|
||
COMPILE_(body_seq, "when body", node->nd_body, poped);
|
||
ADD_INSNL(body_seq, line, jump, endlabel);
|
||
... | ... | |
/* else */
|
||
if (node) {
|
||
ADD_LABEL(cond_seq, elselabel);
|
||
ADD_COVERAGE_TRACE(cond_seq, nd_line(node), RUBY_EVENT_BRANCH);
|
||
ADD_INSN(cond_seq, line, pop);
|
||
COMPILE_(cond_seq, "else", node, poped);
|
||
ADD_INSNL(cond_seq, line, jump, endlabel);
|
||
... | ... | |
while (node && nd_type(node) == NODE_WHEN) {
|
||
LABEL *l1 = NEW_LABEL(line = nd_line(node));
|
||
ADD_LABEL(body_seq, l1);
|
||
if (node->nd_body)
|
||
ADD_COVERAGE_TRACE(body_seq, nd_line(node->nd_body), RUBY_EVENT_BRANCH);
|
||
COMPILE_(body_seq, "when", node->nd_body, poped);
|
||
ADD_INSNL(body_seq, line, jump, endlabel);
|
||
... | ... | |
node = node->nd_next;
|
||
}
|
||
/* else */
|
||
ADD_COVERAGE_TRACE(ret, nd_line(node), RUBY_EVENT_BRANCH);
|
||
COMPILE_(ret, "else", node, poped);
|
||
ADD_INSNL(ret, nd_line(orig_node), jump, endlabel);
|
||
... | ... | |
debugp_param("defs/iseq", iseqval);
|
||
ADD_COVERAGE_TRACE(ret, nd_line(node), RUBY_EVENT_DEFN);
|
||
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
|
||
COMPILE(ret, "defs: recv", node->nd_recv);
|
||
ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid));
|
test/coverage/test_branch_coverage.rb | ||
---|---|---|
require "tmpdir"
|
||
class TestBranchCoverage < Test::Unit::TestCase
|
||
def test_branch_coverage
|
||
def test_if_else_coverage
|
||
loaded_features = $".dup
|
||
Dir.mktmpdir {|tmp|
|
||
... | ... | |
ensure
|
||
$".replace loaded_features
|
||
end
|
||
def test_when_coverage
|
||
loaded_features = $".dup
|
||
Dir.mktmpdir {|tmp|
|
||
Dir.chdir(tmp) {
|
||
File.open("test.rb", "w") do |f|
|
||
f.puts <<-EOS
|
||
case
|
||
when 2 + 2 == 5
|
||
x = :bad
|
||
x = :math
|
||
when 2 + 2 == 4
|
||
x = :good
|
||
else
|
||
x = :also_bad
|
||
end
|
||
case [1,2,3]
|
||
when String
|
||
:string?
|
||
else
|
||
:else
|
||
end
|
||
EOS
|
||
end
|
||
Coverage.start
|
||
require tmp + '/test.rb'
|
||
branch_coverage = Coverage.result[tmp + '/test.rb'][:branches]
|
||
assert_equal 5, branch_coverage.size
|
||
assert_equal 0, branch_coverage[3]
|
||
assert_equal 1, branch_coverage[6]
|
||
assert_equal 0, branch_coverage[8]
|
||
assert_equal 0, branch_coverage[13]
|
||
assert_equal 1, branch_coverage[15]
|
||
}
|
||
}
|
||
ensure
|
||
$".replace loaded_features
|
||
end
|
||
end
|