diff options
author | Stan Lo <stan001212@gmail.com> | 2023-02-27 19:07:14 +0800 |
---|---|---|
committer | git <svn-admin@ruby-lang.org> | 2023-02-27 11:07:19 +0000 |
commit | 0aa50a03b1ea8d37069ae57c469f43860abbcf05 (patch) | |
tree | e489108876b1dd857eb888f9679f89196c443dcb /test | |
parent | 4f611df3f7f61fbdf83b02121dd1edea0b7c68ec (diff) |
[ruby/irb] Provide more useful message when
`IRB::Inspector#inspect_value` errors
(https://github.com/ruby/irb/pull/511)
**Before**
```
irb(main):001:0> c = Cat.new "foo"
(Object doesn't support #inspect)
=>
```
**After**
```
irb(main):001:0> c = Cat.new "foo"
An error occurred when inspecting the object: #<NoMethodError: undefined method `is_a?' for foo:Cat
if obj.is_a?(String)
^^^^^^>
Result of Kernel#inspect: #<Cat:0x0000000109090d80 @name="foo">
=>
```
Diffstat (limited to 'test')
-rw-r--r-- | test/irb/test_context.rb | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/test/irb/test_context.rb b/test/irb/test_context.rb index c0a5164a32..55f258de88 100644 --- a/test/irb/test_context.rb +++ b/test/irb/test_context.rb @@ -125,11 +125,11 @@ module TestIRB [:marshal, "123", Marshal.dump(123)], ], failed: [ - [false, "BasicObject.new", /\(Object doesn't support #inspect\)\n(=> )?\n/], - [:p, "class Foo; undef inspect ;end; Foo.new", /\(Object doesn't support #inspect\)\n(=> )?\n/], - [true, "BasicObject.new", /\(Object doesn't support #inspect\)\n(=> )?\n/], - [:yaml, "BasicObject.new", /\(Object doesn't support #inspect\)\n(=> )?\n/], - [:marshal, "[Object.new, Class.new]", /\(Object doesn't support #inspect\)\n(=> )?\n/] + [false, "BasicObject.new", /#<NoMethodError: undefined method `to_s' for/], + [:p, "class Foo; undef inspect ;end; Foo.new", /#<NoMethodError: undefined method `inspect' for/], + [true, "BasicObject.new", /#<NoMethodError: undefined method `is_a\?' for/], + [:yaml, "BasicObject.new", /#<NoMethodError: undefined method `inspect' for/], + [:marshal, "[Object.new, Class.new]", /#<TypeError: can't dump anonymous class #<Class:/] ] }.each do |scenario, cases| cases.each do |inspect_mode, input, expected| @@ -149,6 +149,58 @@ module TestIRB end end + def test_object_inspection_falls_back_to_kernel_inspect_when_errored + omit if RUBY_ENGINE == "truffleruby" + verbose, $VERBOSE = $VERBOSE, nil + main = Object.new + main.singleton_class.module_eval <<~RUBY + class Foo + def inspect + raise "foo" + end + end + RUBY + + irb = IRB::Irb.new(IRB::WorkSpace.new(main), TestInputMethod.new(["Foo.new"])) + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_match(/An error occurred when inspecting the object: #<RuntimeError: foo>/, out) + assert_match(/Result of Kernel#inspect: #<#<Class:.*>::Foo:/, out) + ensure + $VERBOSE = verbose + end + + def test_object_inspection_prints_useful_info_when_kernel_inspect_also_errored + omit if RUBY_VERSION < '2.7' || RUBY_ENGINE == "truffleruby" + verbose, $VERBOSE = $VERBOSE, nil + main = Object.new + main.singleton_class.module_eval <<~RUBY + class Foo + def initialize + # Kernel#inspect goes through instance variables with #inspect + # So this will cause Kernel#inspect to fail + @foo = BasicObject.new + end + + def inspect + raise "foo" + end + end + RUBY + + irb = IRB::Irb.new(IRB::WorkSpace.new(main), TestInputMethod.new(["Foo.new"])) + out, err = capture_output do + irb.eval_input + end + assert_empty err + assert_match(/An error occurred when inspecting the object: #<RuntimeError: foo>/, out) + assert_match(/An error occurred when running Kernel#inspect: #<NoMethodError: undefined method `inspect' for/, out) + ensure + $VERBOSE = verbose + end + def test_default_config assert_equal(true, @context.use_autocomplete?) end |