summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authortenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-11-12 21:52:12 +0000
committertenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-11-12 21:52:12 +0000
commit4c740bae97f31e16cc6d15753868b6bd49e330d0 (patch)
treee2f0d5e04d7b0743d20491ebcb430eee972744dd /test
parent25f64fc62cfcd4ae1c1e95a5c5448102edccdf8a (diff)
* probes.d: add DTrace probe declarations. [ruby-core:27448]
* array.c (empty_ary_alloc, ary_new): added array create DTrace probe. * compile.c (rb_insns_name): allowing DTrace probes to access instruction sequence name. * Makefile.in: translate probes.d file to appropriate header file. * common.mk: declare dependencies on the DTrace header. * configure.in: add a test for existence of DTrace. * eval.c (setup_exception): add a probe for when an exception is raised. * gc.c: Add DTrace probes for mark begin and end, and sweep begin and end. * hash.c (empty_hash_alloc): Add a probe for hash allocation. * insns.def: Add probes for function entry and return. * internal.h: function declaration for compile.c change. * load.c (rb_f_load): add probes for `load` entry and exit, require entry and exit, and wrapping search_required for load path search. * object.c (rb_obj_alloc): added a probe for general object creation. * parse.y (yycompile0): added a probe around parse and compile phase. * string.c (empty_str_alloc, str_new): DTrace probes for string allocation. * test/dtrace/*: tests for DTrace probes. * vm.c (vm_invoke_proc): add probes for function return on exception raise, hash create, and instruction sequence execution. * vm_core.h: add probe declarations for function entry and exit. * vm_dump.c: add probes header file. * vm_eval.c (vm_call0_cfunc, vm_call0_cfunc_with_frame): add probe on function entry and return. * vm_exec.c: expose instruction number to instruction name function. * vm_insnshelper.c: add function entry and exit probes for cfunc methods. * vm_insnhelper.h: vm usage information is always collected, so uncomment the functions. 12 19:14:50 2012 Akinori MUSHA <knu@iDaemons.org> * configure.in (isinf, isnan): isinf() and isnan() are macros on DragonFly which cannot be found by AC_REPLACE_FUNCS(). This workaround enforces the fact that they exist on DragonFly. 12 15:59:38 2012 Shugo Maeda <shugo@ruby-lang.org> * vm_core.h (rb_call_info_t::refinements), compile.c (new_callinfo), vm_insnhelper.c (vm_search_method): revert r37616 because it's too slow. [ruby-dev:46477] * test/ruby/test_refinement.rb (test_inline_method_cache): skip the test until the bug is fixed efficiently. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37631 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'test')
-rw-r--r--test/dtrace/dummy.rb1
-rw-r--r--test/dtrace/helper.rb33
-rw-r--r--test/dtrace/test_array_create.rb35
-rw-r--r--test/dtrace/test_function_entry.rb58
-rw-r--r--test/dtrace/test_gc.rb26
-rw-r--r--test/dtrace/test_hash_create.rb52
-rw-r--r--test/dtrace/test_load.rb52
-rw-r--r--test/dtrace/test_object_create_start.rb35
-rw-r--r--test/dtrace/test_raise.rb29
-rw-r--r--test/dtrace/test_require.rb34
-rw-r--r--test/dtrace/test_singleton_function.rb55
-rw-r--r--test/dtrace/test_string.rb27
12 files changed, 437 insertions, 0 deletions
diff --git a/test/dtrace/dummy.rb b/test/dtrace/dummy.rb
new file mode 100644
index 0000000000..e85614228c
--- /dev/null
+++ b/test/dtrace/dummy.rb
@@ -0,0 +1 @@
+# this is a dummy file used by test/dtrace/test_require.rb
diff --git a/test/dtrace/helper.rb b/test/dtrace/helper.rb
new file mode 100644
index 0000000000..ef691b5e32
--- /dev/null
+++ b/test/dtrace/helper.rb
@@ -0,0 +1,33 @@
+require 'minitest/autorun'
+require 'tempfile'
+
+module DTrace
+ class TestCase < MiniTest::Unit::TestCase
+ INCLUDE = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+
+ def setup
+ skip "must be setuid 0 to run dtrace tests" unless Process.euid == 0
+ end
+
+ def trap_probe d_program, ruby_program
+ d = Tempfile.new('probe.d')
+ d.write d_program
+ d.flush
+
+ rb = Tempfile.new('probed.rb')
+ rb.write ruby_program
+ rb.flush
+
+ d_path = d.path
+ rb_path = rb.path
+
+ cmd = "dtrace -q -s #{d_path} -c '#{Gem.ruby} -I#{INCLUDE} #{rb_path}'"
+ probes = IO.popen(cmd) do |io|
+ io.readlines
+ end
+ d.close(true)
+ rb.close(true)
+ yield(d_path, rb_path, probes)
+ end
+ end
+end
diff --git a/test/dtrace/test_array_create.rb b/test/dtrace/test_array_create.rb
new file mode 100644
index 0000000000..22d52d4393
--- /dev/null
+++ b/test/dtrace/test_array_create.rb
@@ -0,0 +1,35 @@
+require 'dtrace/helper'
+
+module DTrace
+ class TestArrayCreate < TestCase
+ def test_lit
+ trap_probe(probe, '[]') { |_,rbfile,saw|
+ saw = saw.map(&:split).find_all { |num, file, line|
+ file == rbfile && num == '0'
+ }
+ assert_equal([rbfile], saw.map { |line| line[1] })
+ assert_equal(['1'], saw.map { |line| line[2] })
+ }
+ end
+
+ def test_many_lit
+ trap_probe(probe, '[1,2,3,4]') { |_,rbfile,saw|
+ saw = saw.map(&:split).find_all { |num, file, line|
+ file == rbfile && num == '4' && line == '1'
+ }
+ assert_operator saw.length, :>, 0
+ }
+ end
+
+ private
+ def probe type = 'array'
+ <<-eoprobe
+ruby$target:::#{type}-create
+/arg1/
+{
+ printf("%d %s %d\\n", arg0, copyinstr(arg1), arg2);
+}
+ eoprobe
+ end
+ end
+end
diff --git a/test/dtrace/test_function_entry.rb b/test/dtrace/test_function_entry.rb
new file mode 100644
index 0000000000..b9ba0477f7
--- /dev/null
+++ b/test/dtrace/test_function_entry.rb
@@ -0,0 +1,58 @@
+require 'dtrace/helper'
+
+module DTrace
+ class TestFunctionEntry < TestCase
+ def test_function_entry
+ probe = <<-eoprobe
+ruby$target:::function-entry
+/arg0 && arg1 && arg2/
+{
+ printf("%s %s %s %d\\n", copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
+}
+ eoprobe
+
+ trap_probe(probe, ruby_program) { |d_file, rb_file, probes|
+ foo_calls = probes.map { |line| line.split }.find_all { |row|
+ row.first == 'Foo' && row[1] == 'foo'
+ }
+
+ assert_equal 10, foo_calls.length
+ line = '2'
+ foo_calls.each { |f| assert_equal line, f[3] }
+ foo_calls.each { |f| assert_equal rb_file, f[2] }
+ }
+ end
+
+ def test_function_return
+ probe = <<-eoprobe
+ruby$target:::function-return
+/arg0 && arg1 && arg2/
+{
+ printf("%s %s %s %d\\n", copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
+}
+ eoprobe
+
+ trap_probe(probe, ruby_program) { |d_file, rb_file, probes|
+ foo_calls = probes.map { |line| line.split }.find_all { |row|
+ row.first == 'Foo' && row[1] == 'foo'
+ }
+
+ assert_equal 10, foo_calls.length
+ line = '2'
+ foo_calls.each { |f| assert_equal line, f[3] }
+ foo_calls.each { |f| assert_equal rb_file, f[2] }
+ }
+ end
+
+ private
+ def ruby_program
+ <<-eoruby
+ class Foo
+ def foo; end
+ end
+ x = Foo.new
+ 10.times { x.foo }
+ eoruby
+ end
+ end
+end
diff --git a/test/dtrace/test_gc.rb b/test/dtrace/test_gc.rb
new file mode 100644
index 0000000000..24251c1a68
--- /dev/null
+++ b/test/dtrace/test_gc.rb
@@ -0,0 +1,26 @@
+require 'dtrace/helper'
+
+module DTrace
+ class TestGC < TestCase
+ %w{
+ gc-mark-begin
+ gc-mark-end
+ gc-sweep-begin
+ gc-sweep-end
+ }.each do |probe_name|
+ define_method(:"test_#{probe_name.gsub(/-/, '_')}") do
+ probe = "ruby$target:::#{probe_name} { printf(\"#{probe_name}\\n\"); }"
+
+ trap_probe(probe, ruby_program) { |_, _, saw|
+ assert_operator saw.length, :>, 0
+ }
+
+ end
+ end
+
+ private
+ def ruby_program
+ "100000.times { Object.new }"
+ end
+ end
+end
diff --git a/test/dtrace/test_hash_create.rb b/test/dtrace/test_hash_create.rb
new file mode 100644
index 0000000000..6f6738195a
--- /dev/null
+++ b/test/dtrace/test_hash_create.rb
@@ -0,0 +1,52 @@
+require 'dtrace/helper'
+
+module DTrace
+ class TestHashCreate < TestCase
+ def test_hash_new
+ trap_probe(probe, 'Hash.new') { |_,rbfile,saw|
+ saw = saw.map(&:split).find_all { |num, file, line|
+ file == rbfile && num == '0'
+ }
+ assert_operator saw.length, :>, 0
+ }
+ end
+
+ def test_hash_lit
+ trap_probe(probe, '{}') { |_,rbfile,saw|
+ saw = saw.map(&:split).find_all { |num, file, line|
+ file == rbfile && num == '0'
+ }
+ assert_operator saw.length, :>, 0
+ }
+ end
+
+ def test_hash_lit_elements
+ trap_probe(probe, '{ :foo => :bar }') { |_,rbfile,saw|
+ saw = saw.map(&:split).find_all { |num, file, line|
+ file == rbfile && num == '2'
+ }
+ assert_operator saw.length, :>, 0
+ }
+ end
+
+ def test_hash_lit_elements_string
+ trap_probe(probe, '{ :foo => :bar, :bar => "baz" }') { |_,rbfile,saw|
+ saw = saw.map(&:split).find_all { |num, file, line|
+ file == rbfile && num == '4'
+ }
+ assert_operator saw.length, :>, 0
+ }
+ end
+
+ private
+ def probe
+ <<-eoprobe
+ruby$target:::hash-create
+/arg1/
+{
+ printf("%d %s %d\\n", arg0, copyinstr(arg1), arg2);
+}
+ eoprobe
+ end
+ end
+end
diff --git a/test/dtrace/test_load.rb b/test/dtrace/test_load.rb
new file mode 100644
index 0000000000..8ac7e39119
--- /dev/null
+++ b/test/dtrace/test_load.rb
@@ -0,0 +1,52 @@
+require 'dtrace/helper'
+require 'tempfile'
+
+module DTrace
+ class TestLoad < TestCase
+ def setup
+ super
+ @rbfile = Tempfile.new(['omg', 'rb'])
+ @rbfile.write 'x = 10'
+ end
+
+ def teardown
+ super
+ @rbfile.close(true) if @rbfile
+ end
+
+ def test_load_entry
+ probe = <<-eoprobe
+ruby$target:::load-entry
+{
+ printf("%s %s %d\\n", copyinstr(arg0), copyinstr(arg1), arg2);
+}
+ eoprobe
+ trap_probe(probe, program) { |dpath, rbpath, saw|
+ saw = saw.map(&:split).find_all { |loaded, _, _|
+ loaded == @rbfile.path
+ }
+ assert_equal 10, saw.length
+ }
+ end
+
+ def test_load_return
+ probe = <<-eoprobe
+ruby$target:::load-return
+{
+ printf("%s\\n", copyinstr(arg0));
+}
+ eoprobe
+ trap_probe(probe, program) { |dpath, rbpath, saw|
+ saw = saw.map(&:split).find_all { |loaded, _, _|
+ loaded == @rbfile.path
+ }
+ assert_equal 10, saw.length
+ }
+ end
+
+ private
+ def program
+ "10.times { load '#{@rbfile.path}' }"
+ end
+ end
+end
diff --git a/test/dtrace/test_object_create_start.rb b/test/dtrace/test_object_create_start.rb
new file mode 100644
index 0000000000..756b3b3545
--- /dev/null
+++ b/test/dtrace/test_object_create_start.rb
@@ -0,0 +1,35 @@
+require 'dtrace/helper'
+
+module DTrace
+ class TestObjectCreateStart < TestCase
+ def test_object_create_start
+ trap_probe(probe, '10.times { Object.new }') { |_,rbfile,saw|
+ saw = saw.map(&:split).find_all { |_, file, _|
+ file == rbfile
+ }
+ assert_equal 10, saw.length
+ }
+ end
+
+ def test_object_create_start_name
+ trap_probe(probe, 'Hash.new') { |_,rbfile,saw|
+ saw = saw.map(&:split).find_all { |klass, file, line|
+ file == rbfile
+ }
+ assert_equal(%w{ Hash }, saw.map(&:first))
+ assert_equal([rbfile], saw.map { |line| line[1] })
+ assert_equal(['1'], saw.map { |line| line[2] })
+ }
+ end
+
+ private
+ def probe
+ <<-eoprobe
+ruby$target:::object-create
+{
+ printf("%s %s %d\\n", copyinstr(arg0), copyinstr(arg1), arg2);
+}
+ eoprobe
+ end
+ end
+end
diff --git a/test/dtrace/test_raise.rb b/test/dtrace/test_raise.rb
new file mode 100644
index 0000000000..fedae8e1a7
--- /dev/null
+++ b/test/dtrace/test_raise.rb
@@ -0,0 +1,29 @@
+require 'dtrace/helper'
+
+module DTrace
+ class TestRaise < TestCase
+ def test_raise
+ probe = <<-eoprobe
+ruby$target:::raise
+{
+ printf("%s %s %d\\n", copyinstr(arg0), copyinstr(arg1), arg2);
+}
+ eoprobe
+ trap_probe(probe, program) { |dpath, rbpath, saw|
+ saw = saw.map(&:split).find_all { |_, source_file, _|
+ source_file == rbpath
+ }
+ assert_equal 10, saw.length
+ saw.each do |klass, _, source_line|
+ assert_equal 'RuntimeError', klass
+ assert_equal '1', source_line
+ end
+ }
+ end
+
+ private
+ def program
+ '10.times { raise rescue nil }'
+ end
+ end
+end
diff --git a/test/dtrace/test_require.rb b/test/dtrace/test_require.rb
new file mode 100644
index 0000000000..c50037e334
--- /dev/null
+++ b/test/dtrace/test_require.rb
@@ -0,0 +1,34 @@
+require 'dtrace/helper'
+
+module DTrace
+ class TestRequire < TestCase
+ def test_require_entry
+ probe = <<-eoprobe
+ruby$target:::require-entry
+{
+ printf("%s %s %d\\n", copyinstr(arg0), copyinstr(arg1), arg2);
+}
+ eoprobe
+ trap_probe(probe, ruby_program) { |d_file, rb_file, saw|
+ required = saw.map { |s| s.split }.find_all do |(required, _)|
+ required == 'dtrace/dummy'
+ end
+ assert_equal 10, required.length
+ }
+ end
+
+ def test_require_return
+ probe = <<-eoprobe
+ruby$target:::require-return
+{
+ printf("%s\\n", copyinstr(arg0));
+}
+ eoprobe
+ end
+
+ private
+ def ruby_program
+ "10.times { require 'dtrace/dummy' }"
+ end
+ end
+end
diff --git a/test/dtrace/test_singleton_function.rb b/test/dtrace/test_singleton_function.rb
new file mode 100644
index 0000000000..98fe7d3a77
--- /dev/null
+++ b/test/dtrace/test_singleton_function.rb
@@ -0,0 +1,55 @@
+require 'dtrace/helper'
+
+module DTrace
+ class TestSingletonFunctionEntry < TestCase
+ def test_entry
+ probe = <<-eoprobe
+ruby$target:::function-entry
+/strstr(copyinstr(arg0), "Foo") != NULL/
+{
+ printf("%s %s %s %d\\n", copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
+}
+ eoprobe
+
+ trap_probe(probe, ruby_program) { |d_file, rb_file, probes|
+ foo_calls = probes.map { |line| line.split }.find_all { |row|
+ row.first == '#<Class:Foo>' && row[1] == 'foo'
+ }
+
+ assert_equal 10, foo_calls.length
+ line = '2'
+ foo_calls.each { |f| assert_equal line, f[3] }
+ foo_calls.each { |f| assert_equal rb_file, f[2] }
+ }
+ end
+
+ def test_exit
+ probe = <<-eoprobe
+ruby$target:::function-return
+{
+ printf("%s %s %s %d\\n", copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
+}
+ eoprobe
+
+ trap_probe(probe, ruby_program) { |d_file, rb_file, probes|
+ foo_calls = probes.map { |line| line.split }.find_all { |row|
+ row.first == '#<Class:Foo>' && row[1] == 'foo'
+ }
+
+ assert_equal 10, foo_calls.length
+ line = '2'
+ foo_calls.each { |f| assert_equal line, f[3] }
+ foo_calls.each { |f| assert_equal rb_file, f[2] }
+ }
+ end
+
+ def ruby_program
+ <<-eoruby
+ class Foo
+ def self.foo; end
+ end
+ 10.times { Foo.foo }
+ eoruby
+ end
+ end
+end
diff --git a/test/dtrace/test_string.rb b/test/dtrace/test_string.rb
new file mode 100644
index 0000000000..ca8453d38d
--- /dev/null
+++ b/test/dtrace/test_string.rb
@@ -0,0 +1,27 @@
+require 'dtrace/helper'
+
+module DTrace
+ class TestStringProbes < TestCase
+ def test_object_create_start_string_lit
+ trap_probe(probe, '"omglolwutbbq"') { |_,rbfile,saw|
+ saw = saw.map(&:split).find_all { |klass, file, line, len|
+ file == rbfile && len == '12' && line == '1'
+ }
+ assert_equal(%w{ String }, saw.map(&:first))
+ assert_equal([rbfile], saw.map { |line| line[1] })
+ assert_equal(['1'], saw.map { |line| line[2] })
+ }
+ end
+
+ private
+ def probe
+ <<-eoprobe
+ruby$target:::string-create
+/arg1/
+{
+ printf("String %s %d %d\\n", copyinstr(arg1), arg2, arg0);
+}
+ eoprobe
+ end
+ end
+end