summaryrefslogtreecommitdiff
path: root/test/ruby/test_refinement.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_refinement.rb')
-rw-r--r--test/ruby/test_refinement.rb950
1 files changed, 949 insertions, 1 deletions
diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb
index 6ce434790b..dce09c2dd8 100644
--- a/test/ruby/test_refinement.rb
+++ b/test/ruby/test_refinement.rb
@@ -1035,6 +1035,43 @@ class TestRefinement < Test::Unit::TestCase
RUBY
end
+ def test_prohibit_super_in_refined_module_method
+ assert_separately([], <<-"end;")
+ bug22071 = '[ruby-core:125511] [Bug #22071]'
+ class BasicObject
+ def a; "B" end
+ end
+
+ module G
+ def a; "G" + super end
+ end
+
+ module F
+ include G
+ def a; "F" + super end
+ end
+
+ class A
+ def a; "A" + super end
+ end
+
+ class B < A
+ include F
+ end
+
+ module R
+ refine F do
+ def a; "R"+super end
+ end
+ end
+ using R
+
+ msg = "super in a method in a module that has been refined and that is called via super" +
+ " from a refinement method is not supported."
+ assert_raise(NoMethodError, msg, bug22071) { B.new.a }
+ end;
+ end
+
def test_refine_after_using
assert_separately([], <<-"end;")
bug8880 = '[ruby-core:57079] [Bug #8880]'
@@ -1058,6 +1095,613 @@ class TestRefinement < Test::Unit::TestCase
end;
end
+ {
+ zsuper: "public :a",
+ super: "def a = super"
+ }.each do |desc, method_def|
+ define_method :"test_modify_#{desc}_refinement_method_in_superclass" do
+ assert_separately([], <<-"end;")
+ class A
+ private def a = :a
+ alias a a
+ end
+
+ class B < A
+ end
+
+ module R
+ refine B do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:a, B.new.a)
+
+ class A
+ def a = :b
+ end
+ assert_equal(:b, B.new.a)
+ end;
+ end
+
+ define_method :"test_modify_#{desc}_refinement_method_in_module_prepended_to_superclass" do
+ assert_separately([], <<-"end;")
+ module M
+ private def a = :a
+ alias a a
+ end
+
+ class A
+ prepend M
+ end
+
+ class B < A
+ end
+
+ module R
+ refine B do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:a, B.new.a)
+
+ module M
+ def a = :b
+ end
+ assert_equal(:b, B.new.a)
+ end;
+ end
+
+ define_method :"test_modify_#{desc}_refinement_method_in_module_included_in_superclass" do
+ assert_separately([], <<-"end;")
+ module M
+ private def a = :a
+ alias a a
+ end
+
+ class A
+ include M
+ end
+
+ class B < A
+ end
+
+ module R
+ refine B do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:a, B.new.a)
+
+ module M
+ def a = :b
+ end
+ assert_equal(:b, B.new.a)
+ end;
+ end
+
+ define_method :"test_remove_#{desc}_refinement_method_from_superclass" do
+ assert_separately([], <<-"end;")
+ class A
+ private def a = :a
+ end
+
+ class B < A
+ private def a = :b
+ end
+
+ class C < B
+ end
+
+ module R
+ refine C do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:b, C.new.a)
+
+ class B
+ remove_method(:a)
+ end
+ assert_equal(:a, C.new.a)
+ end;
+ end
+
+ define_method :"test_remove_#{desc}_refinement_method_from_module_prepended_to_superclass" do
+ assert_separately([], <<-"end;")
+ module M
+ private def a = :b
+ end
+
+ class A
+ prepend M
+ private def a = :a
+ end
+
+ class B < A
+ end
+
+ module R
+ refine B do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:b, B.new.a)
+
+ module M
+ remove_method(:a)
+ end
+ assert_equal(:a, B.new.a)
+ end;
+ end
+
+ define_method :"test_remove_#{desc}_refinement_method_from_module_prepended_to_class" do
+ assert_separately([], <<-"end;")
+ module M
+ private def a = :b
+ end
+
+ class A
+ prepend M
+ private def a = :a
+ end
+
+ module R
+ refine A do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:b, A.new.a)
+
+ module M
+ remove_method(:a)
+ end
+ assert_equal(:a, A.new.a)
+ end;
+ end
+
+ define_method :"test_remove_#{desc}_refinement_method_from_module_included_in_superclass" do
+ assert_separately([], <<-"end;")
+ module M
+ private def a = :b
+ end
+
+ class A
+ private def a = :a
+ end
+
+ class B < A
+ include M
+ end
+
+ class C < B
+ end
+
+ module R
+ refine C do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:b, C.new.a)
+
+ module M
+ remove_method(:a)
+ end
+ assert_equal(:a, C.new.a)
+ end;
+ end
+
+ define_method :"test_remove_#{desc}_refinement_method_from_module_included_in_class" do
+ assert_separately([], <<-"end;")
+ module M
+ private def a = :b
+ end
+
+ class A
+ private def a = :a
+ end
+
+ class B < A
+ include M
+ end
+
+ module R
+ refine B do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:b, B.new.a)
+
+ module M
+ remove_method(:a)
+ end
+ assert_equal(:a, B.new.a)
+ end;
+ end
+
+ define_method :"test_undef_#{desc}_refinement_method_in_superclass" do
+ assert_separately([], <<-"end;")
+ class A
+ private def a = :a
+ end
+
+ class B < A
+ private def a = :b
+ end
+
+ class C < B
+ end
+
+ module R
+ refine C do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:b, C.new.a)
+
+ class B
+ undef_method(:a)
+ end
+ assert_raise(NoMethodError) { C.new.a }
+ end;
+ end
+
+ define_method :"test_undef_#{desc}_refinement_method_in_module_prepended_to_superclass" do
+ assert_separately([], <<-"end;")
+ module M
+ private def a = :b
+ end
+
+ class A
+ prepend M
+ private def a = :a
+ end
+
+ class B < A
+ end
+
+ module R
+ refine B do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:b, B.new.a)
+
+ module M
+ undef_method(:a)
+ end
+ assert_raise(NoMethodError) { B.new.a }
+ end;
+ end
+
+ define_method :"test_undef_#{desc}_refinement_method_in_module_prepended_to_class" do
+ assert_separately([], <<-"end;")
+ module M
+ private def a = :b
+ end
+
+ class A
+ prepend M
+ private def a = :a
+ end
+
+ module R
+ refine A do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:b, A.new.a)
+
+ module M
+ undef_method(:a)
+ end
+ assert_raise(NoMethodError) { A.new.a }
+ end;
+ end
+
+ define_method :"test_undef_#{desc}_refinement_method_in_module_included_in_superclass" do
+ assert_separately([], <<-"end;")
+ module M
+ private def a = :b
+ end
+
+ class A
+ private def a = :a
+ end
+
+ class B < A
+ include M
+ end
+
+ class C < B
+ end
+
+ module R
+ refine C do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:b, C.new.a)
+
+ module M
+ undef_method(:a)
+ end
+ assert_raise(NoMethodError) { C.new.a }
+ end;
+ end
+
+ define_method :"test_undef_#{desc}_refinement_method_in_module_included_in_class" do
+ assert_separately([], <<-"end;")
+ module M
+ private def a = :b
+ end
+
+ class A
+ private def a = :a
+ end
+
+ class B < A
+ include M
+ end
+
+ module R
+ refine B do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:b, B.new.a)
+
+ module M
+ undef_method(:a)
+ end
+ assert_raise(NoMethodError) { B.new.a }
+ end;
+ end
+
+ define_method :"test_override_#{desc}_refinement_method_by_prepending_to_class" do
+ assert_separately([], <<-"end;")
+ class A
+ private def a = :a
+ end
+
+ module R
+ refine A do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:a, A.new.a)
+
+ module M
+ def a = :b
+ end
+ A.prepend M
+ assert_equal(:b, A.new.a)
+ end;
+ end
+
+ define_method :"test_override_#{desc}_refinement_method_by_prepending_to_superclass" do
+ assert_separately([], <<-"end;")
+ class A
+ private def a = :a
+ end
+
+ class B < A
+ end
+
+ module R
+ refine B do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:a, B.new.a)
+
+ module M
+ def a = :b
+ end
+ A.prepend M
+ assert_equal(:b, B.new.a)
+ end;
+ end
+
+ define_method :"test_override_#{desc}_refinement_method_by_including_in_class" do
+ assert_separately([], <<-"end;")
+ class A
+ private def a = :a
+ end
+
+ class B < A
+ end
+
+ module R
+ refine B do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:a, B.new.a)
+
+ module M
+ def a = :b
+ end
+ B.include M
+ assert_equal(:b, B.new.a)
+ end;
+ end
+
+ define_method :"test_override_#{desc}_refinement_method_by_including_in_superclass" do
+ assert_separately([], <<-"end;")
+ class A
+ private def a = :a
+ end
+
+ class B < A
+ end
+
+ class C < B
+ end
+
+ module R
+ refine C do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:a, C.new.a)
+
+ module M
+ def a = :b
+ end
+ B.include M
+ assert_equal(:b, C.new.a)
+ end;
+ end
+
+ define_method :"test_override_#{desc}_refinement_method_by_prepending_undef_to_class" do
+ assert_separately([], <<-"end;")
+ class A
+ private def a = :a
+ end
+
+ module R
+ refine A do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:a, A.new.a)
+
+ module M
+ def a = :b
+ undef_method :a
+ end
+ A.prepend M
+ assert_raise(NoMethodError) { A.new.a }
+ end;
+ end
+
+ define_method :"test_override_#{desc}_refinement_method_by_prepending_undef_to_superclass" do
+ assert_separately([], <<-"end;")
+ class A
+ private def a = :a
+ end
+
+ class B < A
+ end
+
+ module R
+ refine B do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:a, B.new.a)
+
+ module M
+ def a = :b
+ undef_method :a
+ end
+ A.prepend M
+ assert_raise(NoMethodError) { B.new.a }
+ end;
+ end
+
+ define_method :"test_override_#{desc}_refinement_method_by_including_undef_in_class" do
+ assert_separately([], <<-"end;")
+ class A
+ private def a = :a
+ end
+
+ class B < A
+ end
+
+ module R
+ refine B do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:a, B.new.a)
+
+ module M
+ def a = :b
+ undef_method :a
+ end
+ B.include M
+ assert_raise(NoMethodError) { B.new.a }
+ end;
+ end
+
+ define_method :"test_override_#{desc}_refinement_method_by_including_undef_in_superclass" do
+ assert_separately([], <<-"end;")
+ class A
+ private def a = :a
+ end
+
+ class B < A
+ end
+
+ class C < B
+ end
+
+ module R
+ refine C do
+ #{method_def}
+ end
+ end
+ using R
+ assert_equal(:a, C.new.a)
+
+ module M
+ def a = :b
+ undef_method :a
+ end
+ B.include M
+ assert_raise(NoMethodError) { C.new.a }
+ end;
+ end
+ end
+
+ def test_zsuper_refinement_method_arity_and_parameters
+ assert_separately([], <<-"end;")
+ class A
+ private def a(b) = b
+ end
+
+ class B < A
+ public :a
+ end
+
+ module R
+ refine A do
+ public :a
+ end
+ end
+ using R
+
+ m = B.instance_method(:a)
+ assert_equal(1, m.arity)
+ assert_equal([[:req, :b]], m.parameters)
+
+ m = A.instance_method(:a)
+ assert_equal(1, m.arity)
+ assert_equal([[:req, :b]], m.parameters)
+ end;
+ end
+
def test_instance_methods
bug8881 = '[ruby-core:57080] [Bug #8881]'
assert_not_include(Foo.instance_methods(false), :z, bug8881)
@@ -1933,6 +2577,29 @@ class TestRefinement < Test::Unit::TestCase
end;
end
+ def test_public_in_refine_for_method_in_superclass
+ assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
+ begin;
+ bug21446 = '[ruby-core:122558] [Bug #21446]'
+
+ class CowSuper
+ private
+ def moo() "Moo"; end
+ end
+ class Cow < CowSuper
+ end
+
+ module PublicCows
+ refine(Cow) {
+ public :moo
+ }
+ end
+
+ using PublicCows
+ assert_equal("Moo", Cow.new.moo, bug21446)
+ end;
+ end
+
module SuperToModule
class Parent
end
@@ -2232,7 +2899,7 @@ class TestRefinement < Test::Unit::TestCase
def test_refining_module_repeatedly
bug14070 = '[ruby-core:83617] [Bug #14070]'
- assert_in_out_err([], <<-INPUT, ["ok"], [], bug14070)
+ assert_in_out_err([], <<-INPUT, ["ok"], [], bug14070, timeout: 30)
1000.times do
Class.new do
include Enumerable
@@ -2712,6 +3379,287 @@ class TestRefinement < Test::Unit::TestCase
INPUT
end
+ def test_refined_module_method
+ m = Module.new {
+ x = Module.new {def qux;end}
+ refine(x) {def qux;end}
+ break x
+ }
+ extend m
+ meth = method(:qux)
+ assert_equal m, meth.owner
+ assert_equal :qux, meth.name
+ end
+
+ def test_symbol_proc_from_using_scope
+ # assert_separately to contain the side effects of refining Kernel
+ assert_separately([], <<~RUBY)
+ class RefinedScope
+ using(Module.new { refine(Kernel) { def itself = 0 } })
+ ITSELF = :itself.to_proc
+ end
+
+ assert_equal(1, RefinedScope::ITSELF[1], "[Bug #21265]")
+ RUBY
+ end
+
+ def test_method_super_method_single_refinements
+ assert_separately([], <<~RUBY)
+ class A
+ def b = "A"
+ end
+ module M
+ R = refine(A) { def b; "M" + super; end }
+ end
+ using M
+ a = A.new
+ m = a.method(:b)
+ assert_equal("MA", a.b)
+ assert_equal("MA", m.call)
+ assert_equal(M::R, m.owner)
+ assert_equal(A, m.owner.target)
+
+ m = m.super_method
+ assert_equal(A, m.owner)
+ assert_nil(m.super_method)
+ RUBY
+ end
+
+ def test_method_super_method_multiple_refinements_with_activated_refinements_during_super
+ assert_separately([], <<~RUBY)
+ class A
+ def b = "A"
+ end
+ module M
+ R = refine(A) { def b; "M" + super; end }
+ end
+ module N
+ using M
+ R = refine(A) { def b; "N" + super; end }
+ end
+ using M
+ using N
+ a = A.new
+ m = a.method(:b)
+ assert_equal("NMA", a.b)
+ assert_equal("NMA", m.call)
+ assert_equal(N::R, m.owner)
+ assert_equal(A, m.owner.target)
+
+ m = m.super_method
+ assert_equal(M::R, m.owner)
+ assert_equal(A, m.owner.target)
+
+ m = m.super_method
+ assert_equal(A, m.owner)
+ assert_nil(m.super_method)
+ RUBY
+ end
+
+ def test_method_super_method_multiple_refinements_without_activated_refinements_during_super
+ assert_separately([], <<~RUBY)
+ class A
+ def b = "A"
+ end
+ module M
+ R = refine(A) { def b; "M" + super; end }
+ end
+ module N
+ R = refine(A) { def b; "N" + super; end }
+ end
+ using M
+ using N
+ a = A.new
+ m = a.method(:b)
+ assert_equal("NA", a.b)
+ assert_equal("NA", m.call)
+ assert_equal(N::R, m.owner)
+ assert_equal(A, m.owner.target)
+
+ m = m.super_method
+ assert_equal(A, m.owner)
+ assert_nil(m.super_method)
+ RUBY
+ end
+
+ def test_unbound_method_super_method_single_refinements
+ assert_separately([], <<~RUBY)
+ class A
+ def b = "A"
+ end
+ module M
+ R = refine(A) { def b; "M" + super; end }
+ end
+ using M
+ m = A.instance_method(:b)
+ assert_equal(M::R, m.owner)
+ assert_equal(A, m.owner.target)
+
+ m = m.super_method
+ assert_equal(A, m.owner)
+ assert_nil(m.super_method)
+ RUBY
+ end
+
+ def test_method_super_method_nonrefined_finds_refined_super
+ assert_separately([], <<~RUBY)
+ class A
+ def b = "A"
+ end
+ module M
+ R = refine(A) { def b; "M" + super; end }
+ end
+ using M
+ class B < A
+ def b = "B" + super
+ end
+ b = B.new
+ m = b.method(:b)
+ assert_equal("BMA", b.b)
+ assert_equal("BMA", m.call)
+ assert_equal(B, m.owner)
+ m = m.super_method
+ assert_equal(M::R, m.owner)
+ assert_equal(A, m.owner.target)
+
+ m = m.super_method
+ assert_equal(A, m.owner)
+ assert_nil(m.super_method)
+ RUBY
+ end
+
+ def test_method_super_method_refined_finds_refined_method_in_superclass
+ assert_separately([], <<~RUBY)
+ class A
+ def b = "A"
+ end
+ class B < A
+ end
+ module M
+ R = refine(A) { def b; "M" + super; end }
+ end
+ using M
+ module N
+ R = refine(B) { def b; "N" + super; end }
+ end
+ using N
+
+ b = B.new
+ m = b.method(:b)
+ assert_equal("NMA", b.b)
+ assert_equal("NMA", m.call)
+ assert_equal(N::R, m.owner)
+ assert_equal(B, m.owner.target)
+
+ m = m.super_method
+ assert_equal(M::R, m.owner)
+ assert_equal(A, m.owner.target)
+
+ m = m.super_method
+ assert_equal(A, m.owner)
+ assert_nil(m.super_method)
+ RUBY
+ end
+
+ def test_method_super_method_uses_cref_of_method_not_cref_of_caller
+ assert_separately([], <<~RUBY)
+ class A
+ def b = "A"
+ end
+ class B < A
+ end
+ module M
+ R = refine(A) { def b; "M" + super; end }
+ end
+ module N
+ R = refine(B) do
+ using M
+ def b; "N" + super; end
+ end
+ end
+ using N
+
+ b = B.new
+ m = b.method(:b)
+ assert_equal("NMA", b.b)
+ assert_equal("NMA", m.call)
+ assert_equal(N::R, m.owner)
+ assert_equal(B, m.owner.target)
+
+ m = m.super_method
+ assert_equal(M::R, m.owner)
+ assert_equal(A, m.owner.target)
+
+ m = m.super_method
+ assert_equal(A, m.owner)
+ assert_nil(m.super_method)
+ RUBY
+ end
+
+ def test_method_super_method_only_considers_activated_refinements
+ assert_separately([], <<~RUBY)
+ class A
+ def b = "A"
+ end
+ class B < A
+ def b = "B" + super
+ end
+ module M
+ R = refine(A){def b = "M" + super}
+ end
+ module N
+ R = refine(B){def b = "N" + super}
+ end
+
+ module O
+ using M
+ using N
+
+ b = B.new
+ m = b.method(:b)
+ assert_equal("NBA", b.b)
+ assert_equal("NBA", m.call)
+ assert_equal(N::R, m.owner)
+ assert_equal(B, m.owner.target)
+
+ m = m.super_method
+ assert_equal(B, m.owner)
+ m = m.super_method
+ assert_equal(A, m.owner)
+ assert_nil(m.super_method)
+ end
+ RUBY
+ end
+
+ def test_method_super_method_bmethod_finds_refinements
+ assert_separately([], <<~RUBY)
+ class A
+ def b = "A"
+ end
+ module M
+ R = refine(A) { def b; "M" + super; end }
+ end
+ using M
+ class B < A
+ define_method(:b) { "B" + super() }
+ end
+
+ b = B.new
+ m = b.method(:b)
+ assert_equal("BMA", b.b)
+ assert_equal("BMA", m.call)
+ assert_equal(B, m.owner)
+
+ m = m.super_method
+ assert_equal(M::R, m.owner)
+ assert_equal(A, m.owner.target)
+
+ m = m.super_method
+ assert_equal(A, m.owner)
+ assert_nil(m.super_method)
+ RUBY
+ end
+
private
def eval_using(mod, s)