зеркало из https://github.com/github/ruby.git
test/dtrace/helper.rb: support systemtap in dtrace tests
For the current cases, a few string substitions is enough to make dtrace(1) scripts work with stap(1). For more complex scripts (maybe in the future), we may pass a hash with implementation-specific scripts. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63581 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
bd80fc5315
Коммит
750f1a3988
|
@ -10,6 +10,22 @@ elsif (sudo = ENV["SUDO"]) and !sudo.empty? and (`#{sudo} echo ok` rescue false)
|
|||
else
|
||||
ok = false
|
||||
end
|
||||
|
||||
impl = :dtrace
|
||||
|
||||
# GNU/Linux distros with Systemtap support allows unprivileged users
|
||||
# in the stapusr and statdev groups to work.
|
||||
if RUBY_PLATFORM =~ /linux/
|
||||
impl = :stap
|
||||
begin
|
||||
require 'etc'
|
||||
login = Etc.getlogin
|
||||
ok = Etc.getgrnam('stapusr').mem.include?(login) &&
|
||||
Etc.getgrnam('stapdev').mem.include?(login)
|
||||
rescue LoadError, ArgumentError
|
||||
end unless ok
|
||||
end
|
||||
|
||||
if ok
|
||||
case RUBY_PLATFORM
|
||||
when /darwin/i
|
||||
|
@ -20,7 +36,24 @@ if ok
|
|||
end
|
||||
end
|
||||
end
|
||||
ok &= (`dtrace -V` rescue false)
|
||||
|
||||
# use miniruby to reduce the amount of trace data we don't care about
|
||||
rubybin = "miniruby#{RbConfig::CONFIG["EXEEXT"]}"
|
||||
rubybin = File.join(File.dirname(EnvUtil.rubybin), rubybin)
|
||||
rubybin = EnvUtil.rubybin unless File.executable?(rubybin)
|
||||
|
||||
# make sure ruby was built with --enable-dtrace and we can run
|
||||
# dtrace(1) or stap(1):
|
||||
cmd = "#{rubybin} --disable=gems -eexit"
|
||||
case impl
|
||||
when :dtrace; cmd = %W(dtrace -l -n ruby$target:::gc-sweep-end -c #{cmd})
|
||||
when :stap; cmd = %W(stap -l process.mark("gc__sweep__end") -c #{cmd})
|
||||
else
|
||||
warn "don't know how to check if built with #{impl} support"
|
||||
cmd = false
|
||||
end
|
||||
ok &= system(*cmd, err: IO::NULL, out: IO::NULL) if cmd
|
||||
|
||||
module DTrace
|
||||
class TestCase < Test::Unit::TestCase
|
||||
INCLUDE = File.expand_path('..', File.dirname(__FILE__))
|
||||
|
@ -40,17 +73,52 @@ module DTrace
|
|||
end
|
||||
end
|
||||
|
||||
# only handles simple cases, use a Hash for d_program
|
||||
# if there are more complex cases
|
||||
def dtrace2systemtap(d_program)
|
||||
translate = lambda do |str|
|
||||
# dtrace starts args with '0', systemtap with '1' and prefixes '$'
|
||||
str = str.gsub(/\barg(\d+)/) { "$arg#{$1.to_i + 1}" }
|
||||
# simple function mappings:
|
||||
str.gsub!(/\bcopyinstr\b/, 'user_string')
|
||||
str.gsub!(/\bstrstr\b/, 'isinstr')
|
||||
str
|
||||
end
|
||||
out = ''
|
||||
cond = nil
|
||||
d_program.split(/^/).each do |l|
|
||||
case l
|
||||
when /\bruby\$target:::([a-z-]+)/
|
||||
name = $1.gsub(/-/, '__')
|
||||
out << %Q{probe process.mark("#{name}")\n}
|
||||
when %r{/(.+)/}
|
||||
cond = translate.call($1)
|
||||
when "{\n"
|
||||
out << l
|
||||
out << "if (#{cond}) {\n" if cond
|
||||
when "}\n"
|
||||
out << "}\n" if cond
|
||||
out << l
|
||||
else
|
||||
out << translate.call(l)
|
||||
end
|
||||
end
|
||||
out
|
||||
end
|
||||
|
||||
DTRACE_CMD ||= %w[dtrace]
|
||||
|
||||
READ_PROBES ||= proc do |cmd|
|
||||
IO.popen(cmd, err: [:child, :out], &:readlines)
|
||||
end
|
||||
|
||||
miniruby = "miniruby#{RbConfig::CONFIG["EXEEXT"]}"
|
||||
miniruby = File.join(File.dirname(EnvUtil.rubybin), miniruby)
|
||||
RUBYBIN = File.exist?(miniruby) ? miniruby : EnvUtil.rubybin
|
||||
|
||||
def trap_probe d_program, ruby_program
|
||||
if Hash === d_program
|
||||
d_program = d_program[IMPL] or
|
||||
skip "#{d_program} not implemented for #{IMPL}"
|
||||
elsif String === d_program && IMPL == :stap
|
||||
d_program = dtrace2systemtap(d_program)
|
||||
end
|
||||
d = Tempfile.new(%w'probe .d')
|
||||
d.write d_program
|
||||
d.flush
|
||||
|
@ -62,7 +130,11 @@ module DTrace
|
|||
d_path = d.path
|
||||
rb_path = rb.path
|
||||
cmd = "#{RUBYBIN} --disable=gems -I#{INCLUDE} #{rb_path}"
|
||||
cmd = [*DTRACE_CMD, "-q", "-s", d_path, "-c", cmd ]
|
||||
if IMPL == :stap
|
||||
cmd = %W(stap #{d_path} -c #{cmd})
|
||||
else
|
||||
cmd = [*DTRACE_CMD, "-q", "-s", d_path, "-c", cmd ]
|
||||
end
|
||||
if sudo = @@sudo
|
||||
[RbConfig::CONFIG["LIBPATHENV"], "RUBY", "RUBYOPT"].each do |name|
|
||||
if name and val = ENV[name]
|
||||
|
@ -81,4 +153,6 @@ end if ok
|
|||
|
||||
if ok
|
||||
DTrace::TestCase.class_variable_set(:@@sudo, sudo)
|
||||
DTrace::TestCase.const_set(:IMPL, impl)
|
||||
DTrace::TestCase.const_set(:RUBYBIN, rubybin)
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче