[前][次][番号順一覧][スレッド一覧]

ruby-changes:47770

From: mame <ko1@a...>
Date: Thu, 14 Sep 2017 14:12:41 +0900 (JST)
Subject: [ruby-changes:47770] mame:r59888 (trunk): Add method coverage

mame	2017-09-14 14:12:34 +0900 (Thu, 14 Sep 2017)

  New Revision: 59888

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=59888

  Log:
    Add method coverage

  Modified files:
    trunk/compile.c
    trunk/ext/coverage/coverage.c
    trunk/test/coverage/test_coverage.rb
    trunk/thread.c
Index: ext/coverage/coverage.c
===================================================================
--- ext/coverage/coverage.c	(revision 59887)
+++ ext/coverage/coverage.c	(revision 59888)
@@ -92,6 +92,22 @@ branch_coverage(VALUE branches) https://github.com/ruby/ruby/blob/trunk/ext/coverage/coverage.c#L92
     return ret;
 }
 
+static VALUE
+method_coverage(VALUE methods)
+{
+    VALUE ret = rb_hash_new();
+    int i, id;
+
+    for (i = 0; i < RARRAY_LEN(methods); ) {
+	VALUE method_name = RARRAY_AREF(methods, i++);
+	VALUE lineno = RARRAY_AREF(methods, i++);
+	VALUE counter = RARRAY_AREF(methods, i++);
+	rb_hash_aset(ret, rb_ary_new_from_args(3, method_name, INT2FIX(id++), lineno), counter);
+    }
+
+    return ret;
+}
+
 static int
 coverage_peek_result_i(st_data_t key, st_data_t val, st_data_t h)
 {
@@ -121,7 +137,7 @@ coverage_peek_result_i(st_data_t key, st https://github.com/ruby/ruby/blob/trunk/ext/coverage/coverage.c#L137
 	}
 
 	if (methods) {
-	    rb_hash_aset(h, ID2SYM(rb_intern("methods")), methods);
+	    rb_hash_aset(h, ID2SYM(rb_intern("methods")), method_coverage(methods));
 	}
 
 	rb_hash_freeze(h);
Index: compile.c
===================================================================
--- compile.c	(revision 59887)
+++ compile.c	(revision 59888)
@@ -277,6 +277,19 @@ struct iseq_compile_data_ensure_node_sta https://github.com/ruby/ruby/blob/trunk/compile.c#L277
 	  ADD_INSN2((seq), (line), trace2, INT2FIX(RUBY_EVENT_COVERAGE), INT2FIX(counter_idx * 16 + COVERAGE_INDEX_BRANCHES)); \
       } \
   } while (0)
+#define ADD_TRACE_METHOD_COVERAGE(seq, line, method_name) \
+  do { \
+      if (ISEQ_COVERAGE(iseq) && \
+	  ISEQ_METHOD_COVERAGE(iseq) && \
+	  (line) > 0) { \
+	  VALUE methods = ISEQ_METHOD_COVERAGE(iseq); \
+	  long counter_idx = RARRAY_LEN(methods) / 3; \
+	  rb_ary_push(methods, ID2SYM(method_name)); \
+	  rb_ary_push(methods, INT2FIX(line)); \
+	  rb_ary_push(methods, INT2FIX(0)); \
+	  ADD_INSN2((seq), (line), trace2, INT2FIX(RUBY_EVENT_COVERAGE), INT2FIX(counter_idx * 16 + COVERAGE_INDEX_METHODS)); \
+      } \
+  } while (0)
 
 #define ADD_TRACE(seq, line, event) \
   do { \
@@ -637,6 +650,7 @@ rb_iseq_compile_node(rb_iseq_t *iseq, NO https://github.com/ruby/ruby/blob/trunk/compile.c#L650
 	  case ISEQ_TYPE_METHOD:
 	    {
 		ADD_TRACE(ret, FIX2INT(iseq->body->location.first_lineno), RUBY_EVENT_CALL);
+		ADD_TRACE_METHOD_COVERAGE(ret, FIX2INT(iseq->body->location.first_lineno), rb_intern_str(iseq->body->location.label));
 		CHECK(COMPILE(ret, "scoped node", node->nd_body));
 		ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN);
 		break;
Index: test/coverage/test_coverage.rb
===================================================================
--- test/coverage/test_coverage.rb	(revision 59887)
+++ test/coverage/test_coverage.rb	(revision 59888)
@@ -280,4 +280,29 @@ class TestCoverage < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/coverage/test_coverage.rb#L280
       }
     }
   end
+
+  def test_method_coverage
+    Dir.mktmpdir {|tmp|
+      Dir.chdir(tmp) {
+        File.open("test.rb", "w") do |f|
+          f.puts 'def foo; end'
+          f.puts 'def bar'
+          f.puts 'end'
+          f.puts 'def baz; end'
+          f.puts ''
+          f.puts 'foo'
+          f.puts 'foo'
+          f.puts 'bar'
+        end
+
+        assert_in_out_err(%w[-W0 -rcoverage], <<-"end;", ["{:methods=>{[:foo, 0, 1]=>2, [:bar, 1, 2]=>1, [:baz, 2, 4]=>0}}"], [])
+          ENV["COVERAGE_EXPERIMENTAL_MODE"] = "true"
+          Coverage.start(methods: true)
+          tmp = Dir.pwd
+          require tmp + '/test.rb'
+          p Coverage.result[tmp + "/test.rb"]
+        end;
+      }
+    }
+  end
 end
Index: thread.c
===================================================================
--- thread.c	(revision 59887)
+++ thread.c	(revision 59888)
@@ -4094,6 +4094,7 @@ clear_coverage_i(st_data_t key, st_data_ https://github.com/ruby/ruby/blob/trunk/thread.c#L4094
     VALUE coverage = (VALUE)val;
     VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
     VALUE branches = RARRAY_AREF(coverage, COVERAGE_INDEX_BRANCHES);
+    VALUE methods = RARRAY_AREF(coverage, COVERAGE_INDEX_METHODS);
 
     if (lines) {
 	for (i = 0; i < RARRAY_LEN(lines); i++) {
@@ -4108,6 +4109,11 @@ clear_coverage_i(st_data_t key, st_data_ https://github.com/ruby/ruby/blob/trunk/thread.c#L4109
 	    RARRAY_ASET(counters, i, INT2FIX(0));
 	}
     }
+    if (methods) {
+	for (i = 2; i < RARRAY_LEN(methods); i += 3) {
+	    RARRAY_ASET(methods, i, INT2FIX(0));
+	}
+    }
 
     return ST_CONTINUE;
 }
@@ -5016,6 +5022,19 @@ update_coverage(VALUE data, const rb_tra https://github.com/ruby/ruby/blob/trunk/thread.c#L5022
 	    }
 	    break;
 	  }
+	  case COVERAGE_INDEX_METHODS: {
+	    VALUE methods = RARRAY_AREF(coverage, COVERAGE_INDEX_METHODS);
+	    if (methods) {
+		long count;
+		long idx = arg / 16 * 3 + 2;
+		VALUE num = RARRAY_AREF(methods, idx);
+		count = FIX2LONG(num) + 1;
+		if (POSFIXABLE(count)) {
+		    RARRAY_ASET(methods, idx, LONG2FIX(count));
+		}
+	    }
+	    break;
+	  }
 	}
     }
 }
@@ -5088,7 +5107,14 @@ rb_default_coverage(int n) https://github.com/ruby/ruby/blob/trunk/thread.c#L5107
     RARRAY_ASET(coverage, COVERAGE_INDEX_BRANCHES, branches);
 
     if (mode & COVERAGE_TARGET_METHODS) {
-	/* not implemented yet */
+	methods = rb_ary_tmp_new(0);
+	/* internal data structures for method coverage:
+	 *
+	 * [symbol_of_method_name, lineno_of_method_head, counter,
+	 *  ...]
+	 *
+	 * Example: [:foobar, 1, 0, ...]
+	 */
     }
     RARRAY_ASET(coverage, COVERAGE_INDEX_METHODS, methods);
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]