summaryrefslogtreecommitdiff
path: root/test/lib/tracepointchecker.rb
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-06-20 08:22:09 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-06-20 08:22:09 +0000
commit2aa6f9c2b7149e37d8610154cfd5ead3c0fdd994 (patch)
treef7b789c5b61a250397071f1de731c55bd759ffb7 /test/lib/tracepointchecker.rb
parent7d9b37cc53b259ccbd9e8e5d4b9b068b7b1d5e2c (diff)
* 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
Diffstat (limited to 'test/lib/tracepointchecker.rb')
-rw-r--r--test/lib/tracepointchecker.rb118
1 files changed, 118 insertions, 0 deletions
diff --git a/test/lib/tracepointchecker.rb b/test/lib/tracepointchecker.rb
new file mode 100644
index 0000000..f90611b
--- /dev/null
+++ b/test/lib/tracepointchecker.rb
@@ -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