summaryrefslogtreecommitdiff
path: root/test/coverage
diff options
context:
space:
mode:
authormame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-05 07:16:42 +0000
committermame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-05 07:16:42 +0000
commit0a6816ecd79fac5dfb32eb237f4c31bb45c9460d (patch)
tree63c3def6ba4957dace4d3fba56f1da964b9750de /test/coverage
parentaa87ae7a04b9c4845ef4326b63150027ed1036a9 (diff)
downloadruby-0a6816ecd79fac5dfb32eb237f4c31bb45c9460d.tar.gz
Revamp method coverage to support define_method
Traditionally, method coverage measurement was implemented by inserting `trace2` instruction to the head of method iseq. So, it just measured methods defined by `def` keyword. This commit drastically changes the measuring mechanism of method coverage; at `RUBY_EVENT_CALL`, it keeps a hash from rb_method_entry_t* to runs (i.e., it counts the runs per method entry), and at `Coverage.result`, it creates the result hash by enumerating all `rb_method_entry_t*` objects (by `ObjectSpace.each_object`). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61023 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'test/coverage')
-rw-r--r--test/coverage/test_coverage.rb113
1 files changed, 109 insertions, 4 deletions
diff --git a/test/coverage/test_coverage.rb b/test/coverage/test_coverage.rb
index 14e58ee64c..b361d8bcde 100644
--- a/test/coverage/test_coverage.rb
+++ b/test/coverage/test_coverage.rb
@@ -188,7 +188,15 @@ class TestCoverage < Test::Unit::TestCase
Coverage.start(#{ opt })
tmp = Dir.pwd
require tmp + '/test.rb'
- p Coverage.result[tmp + "/test.rb"]
+ r = Coverage.result[tmp + "/test.rb"]
+ if r[:methods]
+ h = {}
+ r[:methods].keys.sort_by {|key| key.drop(1) }.each do |key|
+ h[key] = r[:methods][key]
+ end
+ r[:methods].replace h
+ end
+ p r
end;
}
}
@@ -332,9 +340,9 @@ class TestCoverage < Test::Unit::TestCase
def test_method_coverage
result = {
:methods => {
- [:foo, 0, 1] => 2,
- [:bar, 1, 2] => 1,
- [:baz, 2, 4] => 0,
+ [Object, :bar, 2] => 1,
+ [Object, :baz, 4] => 0,
+ [Object, :foo, 1] => 2,
}
}
assert_coverage(<<-"end;", { methods: true }, result)
@@ -348,4 +356,101 @@ class TestCoverage < Test::Unit::TestCase
bar
end;
end
+
+ def test_method_coverage_for_define_method
+ result = {
+ :methods => {
+ [Object, :bar, 2] => 1,
+ [Object, :baz, 4] => 0,
+ [Object, :foo, 1] => 2,
+ }
+ }
+ assert_coverage(<<-"end;", { methods: true }, result)
+ define_method(:foo) {}
+ define_method(:bar) {
+ }
+ f = proc {}
+ define_method(:baz, &f)
+
+ foo
+ foo
+ bar
+ end;
+ end
+
+ class DummyConstant < String
+ def inspect
+ self
+ end
+ end
+
+ def test_method_coverage_for_alias
+ _C = DummyConstant.new("C")
+ _M = DummyConstant.new("M")
+ code = <<-"end;"
+ module M
+ def foo
+ end
+ alias bar foo
+ end
+ class C
+ include M
+ def baz
+ end
+ alias qux baz
+ end
+ end;
+
+ result = {
+ :methods => {
+ [_C, :baz, 8] => 0,
+ [_M, :foo, 2] => 0,
+ }
+ }
+ assert_coverage(code, { methods: true }, result)
+
+ result = {
+ :methods => {
+ [_C, :baz, 8] => 12,
+ [_M, :foo, 2] => 3,
+ }
+ }
+ assert_coverage(code + <<-"end;", { methods: true }, result)
+ obj = C.new
+ 1.times { obj.foo }
+ 2.times { obj.bar }
+ 4.times { obj.baz }
+ 8.times { obj.qux }
+ end;
+ end
+
+ def test_method_coverage_for_singleton_class
+ _singleton_Foo = DummyConstant.new("#<Class:Foo>")
+ _Foo = DummyConstant.new("Foo")
+ code = <<-"end;"
+ class Foo
+ def foo
+ end
+ alias bar foo
+ def self.baz
+ end
+ class << self
+ alias qux baz
+ end
+ end
+
+ 1.times { Foo.new.foo }
+ 2.times { Foo.new.bar }
+ 4.times { Foo.baz }
+ 8.times { Foo.qux }
+ end;
+
+ result = {
+ :methods => {
+ [_singleton_Foo, :baz, 5] => 12,
+ [_Foo, :foo, 2] => 3,
+ }
+ }
+ assert_coverage(code, { methods: true }, result)
+ end
end