diff options
Diffstat (limited to 'spec/ruby/core/kernel/warn_spec.rb')
| -rw-r--r-- | spec/ruby/core/kernel/warn_spec.rb | 161 |
1 files changed, 152 insertions, 9 deletions
diff --git a/spec/ruby/core/kernel/warn_spec.rb b/spec/ruby/core/kernel/warn_spec.rb index 84cfa78672..189129dd31 100644 --- a/spec/ruby/core/kernel/warn_spec.rb +++ b/spec/ruby/core/kernel/warn_spec.rb @@ -14,10 +14,10 @@ describe "Kernel#warn" do end it "is a private method" do - Kernel.should have_private_instance_method(:warn) + Kernel.private_instance_methods(false).should.include?(:warn) end - it "requires multiple arguments" do + it "accepts multiple arguments" do Kernel.method(:warn).arity.should < 0 end @@ -101,6 +101,69 @@ describe "Kernel#warn" do -> { w.f4("foo", 3) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f3_call_lineno}: warning: foo|) end + # Test both explicitly without and with RubyGems as RubyGems overrides Kernel#warn + it "shows the caller of #require and not #require itself without RubyGems" do + file = fixture(__FILE__ , "warn_require_caller.rb") + ruby_exe(file, options: "--disable-gems", args: "2>&1").should == "#{file}:2: warning: warn-require-warning\n" + end + + it "shows the caller of #require and not #require itself with RubyGems loaded" do + file = fixture(__FILE__ , "warn_require_caller.rb") + ruby_exe(file, options: "-rrubygems", args: "2>&1").should == "#{file}:2: warning: warn-require-warning\n" + end + + it "doesn't show the caller when the uplevel is `nil`" do + w = KernelSpecs::WarnInNestedCall.new + + -> { w.f4("foo", nil) }.should output(nil, "foo\n") + end + + guard -> { Kernel.instance_method(:tap).source_location } do + it "skips <internal: core library methods defined in Ruby" do + file, line = Kernel.instance_method(:tap).source_location + file.should.start_with?('<internal:') + + file = fixture(__FILE__ , "warn_core_method.rb") + n = 9 + ruby_exe(file, options: "--disable-gems", args: "2>&1").lines.should == [ + "#{file}:#{n+0}: warning: use X instead\n", + "#{file}:#{n+1}: warning: use X instead\n", + "#{file}:#{n+2}: warning: use X instead\n", + "#{file}:#{n+4}: warning: use X instead\n", + ] + end + end + + it "accepts :category keyword with a symbol" do + -> { + $VERBOSE = true + warn("message", category: :deprecated) + }.should output(nil, "message\n") + end + + it "accepts :category keyword with nil" do + -> { + $VERBOSE = true + warn("message", category: nil) + }.should output(nil, "message\n") + end + + it "accepts :category keyword with object convertible to symbol" do + o = Object.new + def o.to_sym; :deprecated; end + -> { + $VERBOSE = true + warn("message", category: o) + }.should output(nil, "message\n") + end + + it "raises if :category keyword is not nil and not convertible to symbol" do + -> { + $VERBOSE = true + warn("message", category: Object.new) + }.should.raise(TypeError) + end + it "converts first arg using to_s" do w = KernelSpecs::WarnInNestedCall.new @@ -131,19 +194,19 @@ describe "Kernel#warn" do end it "raises ArgumentError if passed negative value" do - -> { warn "", uplevel: -2 }.should raise_error(ArgumentError) - -> { warn "", uplevel: -100 }.should raise_error(ArgumentError) + -> { warn "", uplevel: -2 }.should.raise(ArgumentError) + -> { warn "", uplevel: -100 }.should.raise(ArgumentError) end it "raises ArgumentError if passed -1" do - -> { warn "", uplevel: -1 }.should raise_error(ArgumentError) + -> { warn "", uplevel: -1 }.should.raise(ArgumentError) end it "raises TypeError if passed not Integer" do - -> { warn "", uplevel: "" }.should raise_error(TypeError) - -> { warn "", uplevel: [] }.should raise_error(TypeError) - -> { warn "", uplevel: {} }.should raise_error(TypeError) - -> { warn "", uplevel: Object.new }.should raise_error(TypeError) + -> { warn "", uplevel: "" }.should.raise(TypeError) + -> { warn "", uplevel: [] }.should.raise(TypeError) + -> { warn "", uplevel: {} }.should.raise(TypeError) + -> { warn "", uplevel: Object.new }.should.raise(TypeError) end end @@ -152,4 +215,84 @@ describe "Kernel#warn" do -> { warn(**h) }.should_not complain(verbose: true) -> { warn('foo', **h) }.should complain("foo\n") end + + it "calls Warning.warn without keyword arguments if Warning.warn does not accept keyword arguments" do + verbose = $VERBOSE + $VERBOSE = false + class << Warning + alias_method :_warn, :warn + def warn(message) + ScratchPad.record(message) + end + end + + begin + ScratchPad.clear + Kernel.warn("Chunky bacon!") + ScratchPad.recorded.should == "Chunky bacon!\n" + + Kernel.warn("Deprecated bacon!", category: :deprecated) + ScratchPad.recorded.should == "Deprecated bacon!\n" + ensure + class << Warning + remove_method :warn + alias_method :warn, :_warn + remove_method :_warn + end + $VERBOSE = verbose + end + end + + it "calls Warning.warn with category: nil if Warning.warn accepts keyword arguments" do + Warning.should_receive(:warn).with("Chunky bacon!\n", category: nil) + verbose = $VERBOSE + $VERBOSE = false + begin + Kernel.warn("Chunky bacon!") + ensure + $VERBOSE = verbose + end + end + + it "calls Warning.warn with given category keyword converted to a symbol" do + Warning.should_receive(:warn).with("Chunky bacon!\n", category: :deprecated) + verbose = $VERBOSE + $VERBOSE = false + begin + Kernel.warn("Chunky bacon!", category: 'deprecated') + ensure + $VERBOSE = verbose + end + end + + it "does not call Warning.warn if self is the Warning module" do + # RubyGems redefines Kernel#warn so we need to use a subprocess and disable RubyGems here + code = <<-RUBY + def Warning.warn(*args, **kwargs) + raise 'should not be called' + end + Kernel.instance_method(:warn).bind(Warning).call('Kernel#warn spec edge case') + RUBY + out = ruby_exe(code, args: "2>&1", options: "--disable-gems") + out.should == "Kernel#warn spec edge case\n" + $?.should.success? + end + + it "avoids recursion if Warning#warn is redefined and calls super" do + # This works because of the spec above, which is the workaround for it. + # Note that redefining Warning#warn is a mistake which would naturally end in infinite recursion, + # Warning.extend Module.new { def warn } should be used instead. + # RubyGems redefines Kernel#warn so we need to use a subprocess and disable RubyGems here + code = <<-RUBY + module Warning + def warn(*args, **kwargs) + super + end + end + warn "avoid infinite recursion" + RUBY + out = ruby_exe(code, args: "2>&1", options: "--disable-gems") + out.should == "avoid infinite recursion\n" + $?.should.success? + end end |
