From fcbf63e62c627deae76c1b8cb8c0876c536ed811 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Mon, 16 Mar 2020 18:49:26 +0900 Subject: Fresh start --- jni/ruby/test/dtrace/dummy.rb | 1 + jni/ruby/test/dtrace/helper.rb | 50 ++++++++++++++ jni/ruby/test/dtrace/test_array_create.rb | 35 ++++++++++ jni/ruby/test/dtrace/test_cmethod.rb | 49 +++++++++++++ jni/ruby/test/dtrace/test_function_entry.rb | 87 ++++++++++++++++++++++++ jni/ruby/test/dtrace/test_gc.rb | 26 +++++++ jni/ruby/test/dtrace/test_hash_create.rb | 52 ++++++++++++++ jni/ruby/test/dtrace/test_load.rb | 52 ++++++++++++++ jni/ruby/test/dtrace/test_method_cache.rb | 28 ++++++++ jni/ruby/test/dtrace/test_object_create_start.rb | 35 ++++++++++ jni/ruby/test/dtrace/test_raise.rb | 29 ++++++++ jni/ruby/test/dtrace/test_require.rb | 34 +++++++++ jni/ruby/test/dtrace/test_singleton_function.rb | 55 +++++++++++++++ jni/ruby/test/dtrace/test_string.rb | 27 ++++++++ 14 files changed, 560 insertions(+) create mode 100644 jni/ruby/test/dtrace/dummy.rb create mode 100644 jni/ruby/test/dtrace/helper.rb create mode 100644 jni/ruby/test/dtrace/test_array_create.rb create mode 100644 jni/ruby/test/dtrace/test_cmethod.rb create mode 100644 jni/ruby/test/dtrace/test_function_entry.rb create mode 100644 jni/ruby/test/dtrace/test_gc.rb create mode 100644 jni/ruby/test/dtrace/test_hash_create.rb create mode 100644 jni/ruby/test/dtrace/test_load.rb create mode 100644 jni/ruby/test/dtrace/test_method_cache.rb create mode 100644 jni/ruby/test/dtrace/test_object_create_start.rb create mode 100644 jni/ruby/test/dtrace/test_raise.rb create mode 100644 jni/ruby/test/dtrace/test_require.rb create mode 100644 jni/ruby/test/dtrace/test_singleton_function.rb create mode 100644 jni/ruby/test/dtrace/test_string.rb (limited to 'jni/ruby/test/dtrace') diff --git a/jni/ruby/test/dtrace/dummy.rb b/jni/ruby/test/dtrace/dummy.rb new file mode 100644 index 0000000..e856142 --- /dev/null +++ b/jni/ruby/test/dtrace/dummy.rb @@ -0,0 +1 @@ +# this is a dummy file used by test/dtrace/test_require.rb diff --git a/jni/ruby/test/dtrace/helper.rb b/jni/ruby/test/dtrace/helper.rb new file mode 100644 index 0000000..ccc7081 --- /dev/null +++ b/jni/ruby/test/dtrace/helper.rb @@ -0,0 +1,50 @@ +# -*- coding: us-ascii -*- +require 'test/unit' +require 'tempfile' + +if Process.euid == 0 + ok = true +elsif (sudo = ENV["SUDO"]) and !sudo.empty? and (`#{sudo} echo ok` rescue false) + ok = true +else + ok = false +end +ok &= (`dtrace -V` rescue false) +module DTrace + class TestCase < Test::Unit::TestCase + INCLUDE = File.expand_path('..', File.dirname(__FILE__)) + + def trap_probe d_program, ruby_program + d = Tempfile.new(%w'probe .d') + d.write d_program + d.flush + + rb = Tempfile.new(%w'probed .rb') + rb.write ruby_program + rb.flush + + d_path = d.path + rb_path = rb.path + + cmd = ["dtrace", "-q", "-s", d_path, "-c", "#{EnvUtil.rubybin} -I#{INCLUDE} #{rb_path}"] + if sudo = @@sudo + [RbConfig::CONFIG["LIBPATHENV"], "RUBY", "RUBYOPT"].each do |name| + if name and val = ENV[name] + cmd.unshift("#{name}=#{val}") + end + end + cmd.unshift(sudo) + end + probes = IO.popen(cmd, err: [:child, :out]) do |io| + io.readlines + end + d.close(true) + rb.close(true) + yield(d_path, rb_path, probes) + end + end +end if ok + +if ok + DTrace::TestCase.class_variable_set(:@@sudo, sudo) +end diff --git a/jni/ruby/test/dtrace/test_array_create.rb b/jni/ruby/test/dtrace/test_array_create.rb new file mode 100644 index 0000000..d849bcc --- /dev/null +++ b/jni/ruby/test/dtrace/test_array_create.rb @@ -0,0 +1,35 @@ +require_relative '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 if defined?(DTrace::TestCase) diff --git a/jni/ruby/test/dtrace/test_cmethod.rb b/jni/ruby/test/dtrace/test_cmethod.rb new file mode 100644 index 0000000..0a9107f --- /dev/null +++ b/jni/ruby/test/dtrace/test_cmethod.rb @@ -0,0 +1,49 @@ +require_relative 'helper' + +module DTrace + class TestCMethod < TestCase + def test_entry + probe = <<-eoprobe +ruby$target:::cmethod-entry +{ + 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[1] == 'times' + } + + assert_equal 1, foo_calls.length + } + end + + def test_exit + probe = <<-eoprobe +ruby$target:::cmethod-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[1] == 'times' + } + + assert_equal 1, foo_calls.length + } + end + + def ruby_program + <<-eoruby + class Foo + def self.foo; end + end + 10.times { Foo.foo } + eoruby + end + end +end if defined?(DTrace::TestCase) + diff --git a/jni/ruby/test/dtrace/test_function_entry.rb b/jni/ruby/test/dtrace/test_function_entry.rb new file mode 100644 index 0000000..74aee64 --- /dev/null +++ b/jni/ruby/test/dtrace/test_function_entry.rb @@ -0,0 +1,87 @@ +require_relative 'helper' + +module DTrace + class TestFunctionEntry < TestCase + def test_function_entry + probe = <<-eoprobe +ruby$target:::method-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:::method-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 + + def test_return_from_raise + program = <<-eoruby + class Foo + def bar; raise; end + def baz + bar + rescue + end + end + + Foo.new.baz + eoruby + + probe = <<-eoprobe +ruby$target:::method-return +/arg0 && arg1 && arg2/ +{ + printf("%s %s %s %d\\n", copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3); +} + eoprobe + + trap_probe(probe, program) { |d_file, rb_file, probes| + foo_calls = probes.map { |line| line.split }.find_all { |row| + row.first == 'Foo' && row[1] == 'bar' + } + assert foo_calls.any? + } + end + + private + def ruby_program + <<-eoruby + class Foo + def foo; end + end + x = Foo.new + 10.times { x.foo } + eoruby + end + end +end if defined?(DTrace::TestCase) diff --git a/jni/ruby/test/dtrace/test_gc.rb b/jni/ruby/test/dtrace/test_gc.rb new file mode 100644 index 0000000..2f58a11 --- /dev/null +++ b/jni/ruby/test/dtrace/test_gc.rb @@ -0,0 +1,26 @@ +require_relative '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 if defined?(DTrace::TestCase) diff --git a/jni/ruby/test/dtrace/test_hash_create.rb b/jni/ruby/test/dtrace/test_hash_create.rb new file mode 100644 index 0000000..2cceded --- /dev/null +++ b/jni/ruby/test/dtrace/test_hash_create.rb @@ -0,0 +1,52 @@ +require_relative '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 if defined?(DTrace::TestCase) diff --git a/jni/ruby/test/dtrace/test_load.rb b/jni/ruby/test/dtrace/test_load.rb new file mode 100644 index 0000000..cceb0c2 --- /dev/null +++ b/jni/ruby/test/dtrace/test_load.rb @@ -0,0 +1,52 @@ +require_relative '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 if defined?(DTrace::TestCase) diff --git a/jni/ruby/test/dtrace/test_method_cache.rb b/jni/ruby/test/dtrace/test_method_cache.rb new file mode 100644 index 0000000..d8ddf45 --- /dev/null +++ b/jni/ruby/test/dtrace/test_method_cache.rb @@ -0,0 +1,28 @@ +require_relative 'helper' + +module DTrace + class TestMethodCacheClear < TestCase + def test_method_cache_clear + trap_probe(probe, <<-code) do |_,rbfile,lines| + class String; end + class String; def abc() end end + class Object; def abc() end end + code + assert_not_includes lines, "String #{rbfile} 1\n" + assert_includes lines, "String #{rbfile} 2\n" + assert_includes lines, "global #{rbfile} 3\n" + end + end + + private + def probe + <<-eoprobe +ruby$target:::method-cache-clear +/arg1/ +{ + printf("%s %s %d\\n", copyinstr(arg0), copyinstr(arg1), arg2); +} + eoprobe + end + end +end if defined?(DTrace::TestCase) diff --git a/jni/ruby/test/dtrace/test_object_create_start.rb b/jni/ruby/test/dtrace/test_object_create_start.rb new file mode 100644 index 0000000..2be9611 --- /dev/null +++ b/jni/ruby/test/dtrace/test_object_create_start.rb @@ -0,0 +1,35 @@ +require_relative '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 if defined?(DTrace::TestCase) diff --git a/jni/ruby/test/dtrace/test_raise.rb b/jni/ruby/test/dtrace/test_raise.rb new file mode 100644 index 0000000..48fdbf1 --- /dev/null +++ b/jni/ruby/test/dtrace/test_raise.rb @@ -0,0 +1,29 @@ +require_relative '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 if defined?(DTrace::TestCase) diff --git a/jni/ruby/test/dtrace/test_require.rb b/jni/ruby/test/dtrace/test_require.rb new file mode 100644 index 0000000..46a1d76 --- /dev/null +++ b/jni/ruby/test/dtrace/test_require.rb @@ -0,0 +1,34 @@ +require_relative '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 if defined?(DTrace::TestCase) diff --git a/jni/ruby/test/dtrace/test_singleton_function.rb b/jni/ruby/test/dtrace/test_singleton_function.rb new file mode 100644 index 0000000..9e118f6 --- /dev/null +++ b/jni/ruby/test/dtrace/test_singleton_function.rb @@ -0,0 +1,55 @@ +require_relative 'helper' + +module DTrace + class TestSingletonFunctionEntry < TestCase + def test_entry + probe = <<-eoprobe +ruby$target:::method-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 == '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:::method-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 == '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 if defined?(DTrace::TestCase) diff --git a/jni/ruby/test/dtrace/test_string.rb b/jni/ruby/test/dtrace/test_string.rb new file mode 100644 index 0000000..873d5ac --- /dev/null +++ b/jni/ruby/test/dtrace/test_string.rb @@ -0,0 +1,27 @@ +require_relative '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 if defined?(DTrace::TestCase) -- cgit v1.2.3