Skip to content

Commit 3c823aa

Browse files
committed
Add specs for Kernel#warn's edge case when redefining Warning#warn
* See #2109 and ruby/ruby@8a2a882e53
1 parent 5e5b7b9 commit 3c823aa

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

spec/ruby/core/kernel/warn_spec.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,4 +197,35 @@ def o.to_sym; :deprecated; end
197197
-> { warn(**h) }.should_not complain(verbose: true)
198198
-> { warn('foo', **h) }.should complain("foo\n")
199199
end
200+
201+
it "does not call Warning.warn if self is the Warning module" do
202+
# RubyGems redefines Kernel#warn so we need to use a subprocess and disable RubyGems here
203+
code = <<-RUBY
204+
def Warning.warn(*args, **kwargs)
205+
raise 'should not be called'
206+
end
207+
Kernel.instance_method(:warn).bind(Warning).call('Kernel#warn spec edge case')
208+
RUBY
209+
out = ruby_exe(code, args: "2>&1", options: "--disable-gems")
210+
out.should == "Kernel#warn spec edge case\n"
211+
$?.should.success?
212+
end
213+
214+
it "avoids recursion if Warning#warn is redefined and calls super" do
215+
# This works because of the spec above, which is the workaround for it.
216+
# Note that redefining Warning#warn is a mistake which would naturally end in infinite recursion,
217+
# Warning.extend Module.new { def warn } should be used instead.
218+
# RubyGems redefines Kernel#warn so we need to use a subprocess and disable RubyGems here
219+
code = <<-RUBY
220+
module Warning
221+
def warn(*args)
222+
super
223+
end
224+
end
225+
warn "avoid infinite recursion"
226+
RUBY
227+
out = ruby_exe(code, args: "2>&1", options: "--disable-gems")
228+
out.should == "avoid infinite recursion\n"
229+
$?.should.success?
230+
end
200231
end

spec/tags/core/kernel/warn_tags.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
slow:Kernel#warn :uplevel keyword argument shows the caller of #require and not #require itself without RubyGems
22
slow:Kernel#warn :uplevel keyword argument shows the caller of #require and not #require itself with RubyGems loaded
3+
slow:Kernel#warn does not call Warning.warn if self is the Warning module
4+
slow:Kernel#warn avoids recursion if Warning#warn is redefined and calls super

0 commit comments

Comments
 (0)