summaryrefslogtreecommitdiff
path: root/spec/ruby/core/tracepoint
diff options
context:
space:
mode:
authoreregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-02-07 16:35:33 +0000
committereregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-02-07 16:35:33 +0000
commit75334db3c6479ea3cd7462d36ca5464d386f9c72 (patch)
treec97df2c7aa02f3d0e65524890924f1b294871073 /spec/ruby/core/tracepoint
parent5c7c6763f6cf7b4face107735071c5470e835476 (diff)
Update to ruby/spec@6cf8ebe
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'spec/ruby/core/tracepoint')
-rw-r--r--spec/ruby/core/tracepoint/enable_spec.rb412
1 files changed, 412 insertions, 0 deletions
diff --git a/spec/ruby/core/tracepoint/enable_spec.rb b/spec/ruby/core/tracepoint/enable_spec.rb
index b1a8628896..3b43d3d6b4 100644
--- a/spec/ruby/core/tracepoint/enable_spec.rb
+++ b/spec/ruby/core/tracepoint/enable_spec.rb
@@ -99,4 +99,416 @@ describe 'TracePoint#enable' do
trace.enabled?.should be_false
end
end
+
+ ruby_version_is "2.6" do
+ describe 'target: option' do
+ before :each do
+ ScratchPad.record []
+ end
+
+ it 'enables trace point for specific location' do
+ trace = TracePoint.new(:call) do |tp|
+ ScratchPad << tp.method_id
+ end
+
+ obj = Object.new
+ def obj.foo; end
+ def obj.bar; end
+
+ trace.enable(target: obj.method(:foo)) do
+ obj.foo
+ obj.bar
+ end
+
+ ScratchPad.recorded.should == [:foo]
+ end
+
+ it 'traces all the events triggered in specified location' do
+ trace = TracePoint.new(:line, :call, :return, :b_call, :b_return) do |tp|
+ ScratchPad << tp.event
+ end
+
+ obj = Object.new
+ def obj.foo
+ bar
+ -> {}.call
+ end
+ def obj.bar; end
+
+ trace.enable(target: obj.method(:foo)) do
+ obj.foo
+ end
+
+ ScratchPad.recorded.uniq.sort.should == [:call, :return, :b_call, :b_return, :line].sort
+ end
+
+ it 'does not trace events in nested locations' do
+ trace = TracePoint.new(:call) do |tp|
+ ScratchPad << tp.method_id
+ end
+
+ obj = Object.new
+ def obj.foo
+ bar
+ end
+ def obj.bar
+ baz
+ end
+ def obj.baz
+ end
+
+ trace.enable(target: obj.method(:foo)) do
+ obj.foo
+ end
+
+ ScratchPad.recorded.should == [:foo]
+ end
+
+ it "traces some events in nested blocks" do
+ klass = Class.new do
+ def foo
+ 1.times do
+ 1.times do
+ bar do
+ end
+ end
+ end
+ end
+
+ def bar(&blk)
+ blk.call
+ end
+ end
+
+ trace = TracePoint.new(:b_call) do |tp|
+ ScratchPad << tp.lineno
+ end
+
+ obj = klass.new
+ _, lineno = obj.method(:foo).source_location
+
+ trace.enable(target: obj.method(:foo)) do
+ obj.foo
+ end
+
+ ScratchPad.recorded.should == (lineno+1..lineno+3).to_a
+ end
+
+ describe 'option value' do
+ it 'excepts Method' do
+ trace = TracePoint.new(:call) do |tp|
+ ScratchPad << tp.method_id
+ end
+
+ obj = Object.new
+ def obj.foo; end
+
+ trace.enable(target: obj.method(:foo)) do
+ obj.foo
+ end
+
+ ScratchPad.recorded.should == [:foo]
+ end
+
+ it 'excepts UnboundMethod' do
+ trace = TracePoint.new(:call) do |tp|
+ ScratchPad << tp.method_id
+ end
+
+ klass = Class.new do
+ def foo; end
+ end
+
+ unbound_method = klass.instance_method(:foo)
+ trace.enable(target: unbound_method) do
+ klass.new.foo
+ end
+
+ ScratchPad.recorded.should == [:foo]
+ end
+
+ it 'excepts Proc' do
+ trace = TracePoint.new(:b_call) do |tp|
+ ScratchPad << tp.lineno
+ end
+
+ block = proc {}
+ _, lineno = block.source_location
+
+ trace.enable(target: block) do
+ block.call
+ end
+
+ ScratchPad.recorded.should == [lineno]
+ lineno.should be_kind_of(Integer)
+ end
+
+ it 'excepts RubyVM::InstructionSequence' do
+ trace = TracePoint.new(:call) do |tp|
+ ScratchPad << tp.method_id
+ end
+
+ obj = Object.new
+ def obj.foo; end
+
+ iseq = RubyVM::InstructionSequence.of(obj.method(:foo))
+ trace.enable(target: iseq) do
+ obj.foo
+ end
+
+ ScratchPad.recorded.should == [:foo]
+ end
+ end
+
+ it "raises ArgumentError when passed object isn't consisted of InstructionSequence (iseq)" do
+ trace = TracePoint.new(:call) do |tp|
+ ScratchPad << tp.method_id
+ end
+
+ core_method = 'foo bar'.method(:bytes)
+ RubyVM::InstructionSequence.of(core_method).should == nil
+
+ lambda {
+ trace.enable(target: core_method) do
+ end
+ }.should raise_error(ArgumentError, /specified target is not supported/)
+ end
+
+ it "raises ArgumentError if target object cannot trigger specified event" do
+ trace = TracePoint.new(:call) do |tp|
+ ScratchPad << tp.method_id
+ end
+
+ block = proc {}
+
+ lambda {
+ trace.enable(target: block) do
+ block.call # triggers :b_call and :b_return events
+ end
+ }.should raise_error(ArgumentError, /can not enable any hooks/)
+ end
+
+ it "raises ArgumentError if passed not Method/UnboundMethod/Proc/RubyVM::InstructionSequence" do
+ trace = TracePoint.new(:call) do |tp|
+ end
+
+ lambda {
+ trace.enable(target: Object.new) do
+ end
+ }.should raise_error(ArgumentError, /specified target is not supported/)
+ end
+
+ context "nested enabling and disabling" do
+ it "raises ArgumentError if trace point already enabled with target is re-enabled with target" do
+ trace = TracePoint.new(:b_call) do
+ end
+
+ lambda {
+ trace.enable(target: -> {}) do
+ trace.enable(target: -> {}) do
+ end
+ end
+ }.should raise_error(ArgumentError, /can't nest-enable a targetting TracePoint/)
+ end
+
+ it "raises ArgumentError if trace point already enabled without target is re-enabled with target" do
+ trace = TracePoint.new(:b_call) do
+ end
+
+ lambda {
+ trace.enable do
+ trace.enable(target: -> {}) do
+ end
+ end
+ }.should raise_error(ArgumentError, /can't nest-enable a targetting TracePoint/)
+ end
+
+ it "raises ArgumentError if trace point already enabled with target is re-enabled without target" do
+ trace = TracePoint.new(:b_call) do
+ end
+
+ lambda {
+ trace.enable(target: -> {}) do
+ trace.enable do
+ end
+ end
+ }.should raise_error(ArgumentError, /can't nest-enable a targetting TracePoint/)
+ end
+
+ it "raises ArgumentError if trace point already enabled with target is disabled with block" do
+ trace = TracePoint.new(:b_call) do
+ end
+
+ lambda {
+ trace.enable(target: -> {}) do
+ trace.disable do
+ end
+ end
+ }.should raise_error(ArgumentError, /can't disable a targetting TracePoint in a block/)
+ end
+
+ it "traces events when trace point with target is enabled in another trace point enabled without target" do
+ trace_outer = TracePoint.new(:b_call) do |tp|
+ ScratchPad << :outer
+ end
+
+ trace_inner = TracePoint.new(:b_call) do |tp|
+ ScratchPad << :inner
+ end
+
+ target = -> {}
+
+ trace_outer.enable do
+ trace_inner.enable(target: target) do
+ target.call
+ end
+ end
+
+ ScratchPad.recorded.should == [:outer, :outer, :outer, :inner]
+ end
+
+ it "traces events when trace point with target is enabled in another trace point enabled with target" do
+ trace_outer = TracePoint.new(:b_call) do |tp|
+ ScratchPad << :outer
+ end
+
+ trace_inner = TracePoint.new(:b_call) do |tp|
+ ScratchPad << :inner
+ end
+
+ target = -> {}
+
+ trace_outer.enable(target: target) do
+ trace_inner.enable(target: target) do
+ target.call
+ end
+ end
+
+ ScratchPad.recorded.should == [:inner, :outer]
+ end
+
+ it "traces events when trace point without target is enabled in another trace point enabled with target" do
+ trace_outer = TracePoint.new(:b_call) do |tp|
+ ScratchPad << :outer
+ end
+
+ trace_inner = TracePoint.new(:b_call) do |tp|
+ ScratchPad << :inner
+ end
+
+ target = -> {}
+
+ trace_outer.enable(target: target) do
+ trace_inner.enable do
+ target.call
+ end
+ end
+
+ ScratchPad.recorded.should == [:inner, :inner, :outer]
+ end
+ end
+ end
+
+ describe 'target_line: option' do
+ before :each do
+ ScratchPad.record []
+ end
+
+ it "traces :line events only on specified line of code" do
+ trace = TracePoint.new(:line) do |tp|
+ ScratchPad << tp.lineno
+ end
+
+ target = -> {
+ x = 1
+ y = 2 # <= this line is target
+ z = x + y
+ }
+ _, lineno = target.source_location
+ target_line = lineno + 2
+
+ trace.enable(target_line: target_line, target: target) do
+ target.call
+ end
+
+ ScratchPad.recorded.should == [target_line]
+ end
+
+ it "raises ArgumentError if :target option isn't specified" do
+ trace = TracePoint.new(:line) do |tp|
+ end
+
+ lambda {
+ trace.enable(target_line: 67) do
+ end
+ }.should raise_error(ArgumentError, /only target_line is specified/)
+ end
+
+ it "raises ArgumentError if :line event isn't registered" do
+ trace = TracePoint.new(:call) do |tp|
+ end
+
+ target = -> {
+ x = 1
+ y = 2 # <= this line is target
+ z = x + y
+ }
+ _, lineno = target.source_location
+ target_line = lineno + 2
+
+ lambda {
+ trace.enable(target_line: target_line, target: target) do
+ end
+ }.should raise_error(ArgumentError, /target_line is specified, but line event is not specified/)
+ end
+
+ it "raises ArgumentError if :target_line value is out of target code lines range" do
+ trace = TracePoint.new(:line) do |tp|
+ end
+
+ lambda {
+ trace.enable(target_line: 1, target: -> { }) do
+ end
+ }.should raise_error(ArgumentError, /can not enable any hooks/)
+ end
+
+ it "raises TypeError if :target_line value couldn't be coerced to Integer" do
+ trace = TracePoint.new(:line) do |tp|
+ end
+
+ lambda {
+ trace.enable(target_line: Object.new, target: -> { }) do
+ end
+ }.should raise_error(TypeError, /no implicit conversion of \w+? into Integer/)
+ end
+
+ it "raises ArgumentError if :target_line value is negative" do
+ trace = TracePoint.new(:line) do |tp|
+ end
+
+ lambda {
+ trace.enable(target_line: -2, target: -> { }) do
+ end
+ }.should raise_error(ArgumentError, /can not enable any hooks/)
+ end
+
+ it "excepts value that could be coerced to Integer" do
+ trace = TracePoint.new(:line) do |tp|
+ ScratchPad << tp.lineno
+ end
+
+ target = -> {
+ x = 1 # <= this line is target
+ }
+ _, lineno = target.source_location
+ target_line = lineno + 1
+
+ trace.enable(target_line: target_line.to_r, target: target) do
+ target.call
+ end
+
+ ScratchPad.recorded.should == [target_line]
+ end
+ end
+ end
end