我试图了解ruby的内部库coverage.so是如何工作的。通过“工作”,我不是指它的用法。我的意思是如何计算线的执行计数。我查看了源代码,但看起来像是在某种方法调用之后,这超出了我的理解范围。
以下是我的经历:
答案 0 :(得分:0)
coverage.so
模块只是连接到ruby核心以获取信息,搜索rb_get_coverages()
函数以获取此信息https://github.com/ruby/ruby/blob/38ea561319864fecf92bc61af0d9b9b1f49df6a0/thread.c
VALUE
rb_get_coverages(void)
{
return GET_VM()->coverages;
}
void
rb_set_coverages(VALUE coverages)
{
GET_VM()->coverages = coverages;
rb_add_event_hook(update_coverage, RUBY_EVENT_COVERAGE, Qnil);
}
此文件的增量(count = old_count +1
):
static void
update_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
{
VALUE coverage = rb_iseq_coverage(GET_THREAD()->cfp->iseq);
if (RB_TYPE_P(coverage, T_ARRAY) && !RBASIC_CLASS(coverage)) {
long line = rb_sourceline() - 1;
long count;
if (line >= RARRAY_LEN(coverage)) { /* no longer tracked */
return;
}
count = FIX2LONG(RARRAY_AREF(coverage, line)) + 1;
if (POSFIXABLE(count)) {
RARRAY_ASET(coverage, line, LONG2FIX(count));
}
}
}
在parse.y https://github.com/ruby/ruby/blob/4c4f809e932417137d06e334d79065a4849dda0b/parse.y#L5491
中创建的实际哈希static VALUE
coverage(VALUE fname, int n)
{
VALUE coverages = rb_get_coverages();
if (RTEST(coverages) && RBASIC(coverages)->klass == 0) {
VALUE lines = n > 0 ? rb_ary_tmp_new_fill(n) : rb_ary_tmp_new(0);
rb_hash_aset(coverages, fname, lines);
return lines;
}
return 0;
}