summaryrefslogtreecommitdiff
path: root/test/ruby
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2021-12-27 09:39:15 -0800
committerBenoit Daloze <eregontp@gmail.com>2022-08-20 13:44:00 +0200
commit8212aab81a77a2a91fb7c1681b4968171193b48f (patch)
tree05894efbb106ad56f06a25b9bbfd9432440c7ad9 /test/ruby
parentb32a3f1275a8c7748f2134492ce3c532f277d261 (diff)
Make Object#method and Module#instance_method not skip ZSUPER methods
Based on https://github.com/jeremyevans/ruby/commit/c95e7e5329140f640b6497905485761f3336d967 Among other things, this fixes calling visibility methods (public?, protected?, and private?) on them. It also fixes #owner to show the class the zsuper method entry is defined in, instead of the original class it references. For some backwards compatibility, adjust #parameters and #source_location, to show the parameters and source location of the method originally defined. Also have the parameters and source location still be shown by #inspect. Clarify documentation of {Method,UnboundMethod}#owner. Add tests based on the description of https://bugs.ruby-lang.org/issues/18435 and based on https://github.com/ruby/ruby/pull/5356#issuecomment-1005298809 Fixes [Bug #18435] [Bug #18729] Co-authored-by: Benoit Daloze <eregontp@gmail.com>
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/6242
Diffstat (limited to 'test/ruby')
-rw-r--r--test/ruby/test_method.rb59
1 files changed, 54 insertions, 5 deletions
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index 56e94493d9..5f689c3d4f 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -1056,20 +1056,28 @@ class TestMethod < Test::Unit::TestCase
assert_equal(sm, im.clone.bind(o).super_method)
end
- def test_super_method_removed
+ def test_super_method_removed_public
c1 = Class.new {private def foo; end}
c2 = Class.new(c1) {public :foo}
c3 = Class.new(c2) {def foo; end}
c1.class_eval {undef foo}
m = c3.instance_method(:foo)
m = assert_nothing_raised(NameError, Feature9781) {break m.super_method}
- assert_nil(m, Feature9781)
+ assert_equal c2, m.owner
+ end
+
+ def test_super_method_removed_regular
+ c1 = Class.new { def foo; end }
+ c2 = Class.new(c1) { def foo; end }
+ assert_equal c1.instance_method(:foo), c2.instance_method(:foo).super_method
+ c1.remove_method :foo
+ assert_equal nil, c2.instance_method(:foo).super_method
end
def test_prepended_public_zsuper
mod = EnvUtil.labeled_module("Mod") {private def foo; :ok end}
- mods = [mod]
obj = Object.new.extend(mod)
+ mods = [obj.singleton_class]
class << obj
public :foo
end
@@ -1079,7 +1087,7 @@ class TestMethod < Test::Unit::TestCase
end
m = obj.method(:foo)
assert_equal(mods, mods.map {m.owner.tap {m = m.super_method}})
- assert_nil(m)
+ assert_nil(m.super_method)
end
def test_super_method_with_prepended_module
@@ -1192,6 +1200,47 @@ class TestMethod < Test::Unit::TestCase
assert_nil(super_method)
end
+ # Bug 18435
+ def test_instance_methods_owner_consistency
+ a = Module.new { def method1; end }
+
+ b = Class.new do
+ include a
+ protected :method1
+ end
+
+ assert_equal [:method1], b.instance_methods(false)
+ assert_equal b, b.instance_method(:method1).owner
+ end
+
+ def test_zsuper_method_removed
+ a = EnvUtil.labeled_class('A') do
+ private
+ def foo(arg = nil)
+ 1
+ end
+ end
+ line = __LINE__ - 4
+
+ b = EnvUtil.labeled_class('B', a) do
+ public :foo
+ end
+
+ unbound = b.instance_method(:foo)
+
+ assert_equal unbound, b.public_instance_method(:foo)
+ assert_equal "#<UnboundMethod: B(A)#foo(arg=...) #{__FILE__}:#{line}>", unbound.inspect
+ assert_equal [[:opt, :arg]], unbound.parameters
+
+ a.remove_method(:foo)
+
+ assert_equal [[:rest]], unbound.parameters
+ assert_equal "#<UnboundMethod: B#foo(*)>", unbound.inspect
+
+ obj = b.new
+ assert_raise_with_message(NoMethodError, /super: no superclass method `foo'/) { unbound.bind_call(obj) }
+ end
+
def rest_parameter(*rest)
rest
end
@@ -1310,7 +1359,7 @@ class TestMethod < Test::Unit::TestCase
::Object.prepend(M2)
m = Object.instance_method(:x)
- assert_equal M, m.owner
+ assert_equal M2, m.owner
end;
end