* test/lib/tracepointchecker.rb: add to check TracePoint healthiness.
* test/runner.rb: use it. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46479 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
7d9b37cc53
commit
2aa6f9c2b7
@ -1,3 +1,9 @@
|
|||||||
|
Fri Jun 20 17:15:43 2014 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
|
* test/lib/tracepointchecker.rb: add to check TracePoint healthiness.
|
||||||
|
|
||||||
|
* test/runner.rb: use it.
|
||||||
|
|
||||||
Fri Jun 20 07:26:44 2014 Koichi Sasada <ko1@atdot.net>
|
Fri Jun 20 07:26:44 2014 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
* test/ruby/test_settracefunc.rb: rewrite tests with
|
* test/ruby/test_settracefunc.rb: rewrite tests with
|
||||||
|
118
test/lib/tracepointchecker.rb
Normal file
118
test/lib/tracepointchecker.rb
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
module TracePointChecker
|
||||||
|
STATE = {
|
||||||
|
count: 0,
|
||||||
|
running: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
module ZombieTraceHunter
|
||||||
|
def before_setup
|
||||||
|
@tracepoint_captured_stat = TracePoint.stat.map{|k, (activated, deleted)| [k, activated]}
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def after_teardown
|
||||||
|
super
|
||||||
|
|
||||||
|
# detect zombie traces.
|
||||||
|
assert_equal(
|
||||||
|
@tracepoint_captured_stat,
|
||||||
|
TracePoint.stat.map{|k, (activated, deleted)| [k, activated]},
|
||||||
|
"The number of active trace events was changed"
|
||||||
|
)
|
||||||
|
# puts "TracePoint - deleted: #{deleted}" if deleted > 0
|
||||||
|
|
||||||
|
TracePointChecker.check if STATE[:running]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
MAIN_THREAD = Thread.current
|
||||||
|
TRACES = []
|
||||||
|
|
||||||
|
def self.prefix event
|
||||||
|
case event
|
||||||
|
when :call, :return
|
||||||
|
:n
|
||||||
|
when :c_call, :c_return
|
||||||
|
:c
|
||||||
|
when :b_call, :b_return
|
||||||
|
:b
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.clear_call_stack
|
||||||
|
Thread.current[:call_stack] = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.call_stack
|
||||||
|
stack = Thread.current[:call_stack]
|
||||||
|
stack = clear_call_stack unless stack
|
||||||
|
stack
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.verbose_out label, method
|
||||||
|
puts label => call_stack, :count => STATE[:count], :method => method
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.method_label tp
|
||||||
|
"#{prefix(tp.event)}##{tp.method_id}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.start verbose: false, stop_at_failure: false
|
||||||
|
call_events = %i(a_call)
|
||||||
|
return_events = %i(a_return)
|
||||||
|
clear_call_stack
|
||||||
|
|
||||||
|
STATE[:running] = true
|
||||||
|
|
||||||
|
TRACES << TracePoint.new(*call_events){|tp|
|
||||||
|
next if Thread.current != MAIN_THREAD
|
||||||
|
|
||||||
|
method = method_label(tp)
|
||||||
|
call_stack.push method
|
||||||
|
STATE[:count] += 1
|
||||||
|
|
||||||
|
verbose_out :psuh, method if verbose
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACES << TracePoint.new(*return_events){|tp|
|
||||||
|
next if Thread.current != MAIN_THREAD
|
||||||
|
STATE[:count] += 1
|
||||||
|
|
||||||
|
method = "#{prefix(tp.event)}##{tp.method_id}"
|
||||||
|
verbose_out :pop1, method if verbose
|
||||||
|
|
||||||
|
stored_method = call_stack.pop
|
||||||
|
next if stored_method.nil?
|
||||||
|
|
||||||
|
verbose_out :pop2, method if verbose
|
||||||
|
|
||||||
|
if stored_method != method
|
||||||
|
stop if stop_at_failure
|
||||||
|
RubyVM::SDR() if defined? RubyVM::SDR()
|
||||||
|
call_stack.clear
|
||||||
|
raise "#{stored_method} is expected, but #{method} (count: #{STATE[:count]})"
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACES.each{|trace| trace.enable}
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.stop
|
||||||
|
STATE[:running] = true
|
||||||
|
TRACES.each{|trace| trace.disable}
|
||||||
|
TRACES.clear
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.check
|
||||||
|
TRACES.each{|trace|
|
||||||
|
raise "trace #{trace} should not be deactivated" unless trace.enabled?
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class ::Test::Unit::TestCase
|
||||||
|
include TracePointChecker::ZombieTraceHunter
|
||||||
|
end
|
||||||
|
|
||||||
|
# TracePointChecker.start verbose: false
|
@ -16,27 +16,16 @@ end
|
|||||||
ENV["GEM_SKIP"] = ENV["GEM_HOME"] = ENV["GEM_PATH"] = "".freeze
|
ENV["GEM_SKIP"] = ENV["GEM_HOME"] = ENV["GEM_PATH"] = "".freeze
|
||||||
|
|
||||||
require_relative 'profile_test_all' if ENV.has_key?('RUBY_TEST_ALL_PROFILE')
|
require_relative 'profile_test_all' if ENV.has_key?('RUBY_TEST_ALL_PROFILE')
|
||||||
|
require_relative 'lib/tracepointchecker'
|
||||||
|
|
||||||
module Test::Unit
|
module Test::Unit
|
||||||
module ZombieHunter
|
module ZombieHunter
|
||||||
|
|
||||||
def before_setup
|
|
||||||
@tracepoint_captured_stat = TracePoint.stat.map{|k, (activated, deleted)| [k, activated]}
|
|
||||||
end
|
|
||||||
|
|
||||||
def after_teardown
|
def after_teardown
|
||||||
super
|
super
|
||||||
assert_empty(Process.waitall)
|
assert_empty(Process.waitall)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# detect zombie traces.
|
|
||||||
assert_equal(
|
|
||||||
@tracepoint_captured_stat,
|
|
||||||
TracePoint.stat.map{|k, (activated, deleted)| [k, activated]},
|
|
||||||
"The number of active trace events was changed"
|
|
||||||
)
|
|
||||||
# puts "TracePoint - deleted: #{deleted}" if deleted > 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
class TestCase
|
class TestCase
|
||||||
include ZombieHunter
|
include ZombieHunter
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user