Skip to content

Commit

Permalink
optimized version of ddcov
Browse files Browse the repository at this point in the history
  • Loading branch information
anmarchenko committed Feb 23, 2024
1 parent 7516168 commit 522f590
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 25 deletions.
107 changes: 90 additions & 17 deletions ext/ddcov/ddcov.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,99 @@
#include <ruby/debug.h>
#include <stdio.h>

VALUE DDCovClass = Qnil;
// Utils
static bool prefix(const char *pre, const char *str)
{
return strncmp(pre, str, strlen(pre)) == 0;
}

VALUE dd_cov_initialize(VALUE self)
// Data structure
struct dd_cov_data
{
rb_iv_set(self, "@var", rb_hash_new());
return self;
char *root;
VALUE coverage;
};

static void dd_cov_mark(void *ptr)
{
// printf("MARK\n");
struct dd_cov_data *dd_cov_data = ptr;
rb_gc_mark_movable(dd_cov_data->coverage);
}

static void dd_cov_free(void *ptr)
{
// printf("FREE\n");
struct dd_cov_data *dd_cov_data = ptr;

xfree(dd_cov_data);
}

static void dd_cov_compact(void *ptr)
{
// printf("COMPACT\n");
struct dd_cov_data *dd_cov_data = ptr;
dd_cov_data->coverage = rb_gc_location(dd_cov_data->coverage);
}

const rb_data_type_t dd_cov_data_type = {
.wrap_struct_name = "dd_cov",
.function = {
.dmark = dd_cov_mark,
.dfree = dd_cov_free,
.dsize = NULL,
.dcompact = dd_cov_compact},
.flags = RUBY_TYPED_FREE_IMMEDIATELY};

static VALUE dd_cov_allocate(VALUE klass)
{
// printf("ALLOCATE\n");
struct dd_cov_data *dd_cov_data;
VALUE obj = TypedData_Make_Struct(klass, struct dd_cov_data, &dd_cov_data_type, dd_cov_data);
dd_cov_data->coverage = rb_hash_new();
return obj;
}

// DDCov methods
static VALUE dd_cov_initialize(VALUE self, VALUE rb_root)
{
// printf("INITIALIZE\n");
struct dd_cov_data *dd_cov_data;
TypedData_Get_Struct(self, struct dd_cov_data, &dd_cov_data_type, dd_cov_data);

// printf("struct got\n");
dd_cov_data->root = StringValueCStr(rb_root);
// printf("root set\n");

return Qnil;
}

void dd_cov_update_line_coverage(rb_event_flag_t event, VALUE data, VALUE self, ID id, VALUE klass)
static void dd_cov_update_line_coverage(rb_event_flag_t event, VALUE data, VALUE self, ID id, VALUE klass)
{
// printf("EVENT HOOK FIRED\n");
// printf("FILE: %s\n", rb_sourcefile());
// printf("LINE: %d\n", rb_sourceline());
struct dd_cov_data *dd_cov_data;
TypedData_Get_Struct(data, struct dd_cov_data, &dd_cov_data_type, dd_cov_data);

const char *filename = rb_sourcefile();
if (filename == 0)
{
return;
}

unsigned long filename_length = strlen(filename);
if (!prefix(dd_cov_data->root, filename))
{
return;
}

unsigned long len_filename = strlen(filename);

VALUE rb_str_source_file = rb_str_new(filename, filename_length);
rb_hash_aset(rb_iv_get(data, "@var"), rb_str_source_file, Qtrue);
VALUE rb_str_source_file = rb_str_new(filename, len_filename);
rb_hash_aset(dd_cov_data->coverage, rb_str_source_file, Qtrue);
}

VALUE dd_cov_start(VALUE self)
static VALUE dd_cov_start(VALUE self)
{
// get current thread
VALUE thval = rb_thread_current();
Expand All @@ -39,23 +105,30 @@ VALUE dd_cov_start(VALUE self)
return self;
}

VALUE dd_cov_stop(VALUE self)
static VALUE dd_cov_stop(VALUE self)
{
// get current thread
VALUE thval = rb_thread_current();

// remove event hook
rb_thread_remove_event_hook(thval, dd_cov_update_line_coverage);

return rb_iv_get(self, "@var");
struct dd_cov_data *dd_cov_data;
TypedData_Get_Struct(self, struct dd_cov_data, &dd_cov_data_type, dd_cov_data);

VALUE cov = dd_cov_data->coverage;

dd_cov_data->coverage = rb_hash_new();

return cov;
}

void Init_ddcov(void)
{
id_puts = rb_intern("puts");
VALUE cDDCov = rb_define_class("DDCov", rb_cObject);

rb_define_alloc_func(cDDCov, dd_cov_allocate);

DDCovClass = rb_define_class("DDCov", rb_cObject);
rb_define_method(DDCovClass, "initialize", dd_cov_initialize, 0);
rb_define_method(DDCovClass, "start", dd_cov_start, 0);
rb_define_method(DDCovClass, "stop", dd_cov_stop, 0);
rb_define_method(cDDCov, "initialize", dd_cov_initialize, 1);
rb_define_method(cDDCov, "start", dd_cov_start, 0);
rb_define_method(cDDCov, "stop", dd_cov_stop, 0);
}
14 changes: 6 additions & 8 deletions lib/datadog/ci/itr/coverage/collector.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# frozen_string_literal: true

require "coverage"

require_relative "filter"
require_relative "../../utils/git"
require_relative "../../../../ddcov/ddcov"

module Datadog
Expand All @@ -11,22 +9,22 @@ module Itr
module Coverage
class Collector
def initialize
@ddcov = DDCov.new
# TODO: make this thread local
end

def setup
p "RUNNING WITH CODE COVERAGE ENABLED"
end

def start
@ddcov = DDCov.new(Utils::Git.root)
@ddcov.start
end

def stop
result = @ddcov.stop
@ddcov.instance_variable_set(:@var, {})

Filter.call(result)
@ddcov.stop
# p "RAW"
# p result.count
end
end
end
Expand Down

0 comments on commit 522f590

Please sign in to comment.