coverage.so如何运作?

时间:2016-07-14 05:03:17

标签: ruby

我试图了解ruby的内部库coverage.so是如何工作的。通过“工作”,我不是指它的用法。我的意思是如何计算线的执行计数。我查看了源代码,但看起来像是在某种方法调用之后,这超出了我的理解范围。

以下是我的经历:

1 个答案:

答案 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;
}