diff options
Diffstat (limited to 'test/ruby/test_super.rb')
| -rw-r--r-- | test/ruby/test_super.rb | 433 |
1 files changed, 411 insertions, 22 deletions
diff --git a/test/ruby/test_super.rb b/test/ruby/test_super.rb index 98cf43b7a1..25bad2242a 100644 --- a/test/ruby/test_super.rb +++ b/test/ruby/test_super.rb @@ -1,5 +1,5 @@ +# frozen_string_literal: false require 'test/unit' -require_relative 'envutil' class TestSuper < Test::Unit::TestCase class Base @@ -8,6 +8,7 @@ class TestSuper < Test::Unit::TestCase def array(*a) a end def optional(a = 0) a end def keyword(**a) a end + def forward(*a) a end end class Single1 < Base def single(*) super end @@ -63,6 +64,16 @@ class TestSuper < Test::Unit::TestCase [x, y] end end + class Forward < Base + def forward(...) + w = super() + x = super + y = super(...) + a = 1 + z = super(a, ...) + [w, x, y, z] + end + end def test_single1 assert_equal(1, Single1.new.single(1)) @@ -102,11 +113,11 @@ class TestSuper < Test::Unit::TestCase def test_optional2 assert_raise(ArgumentError) do # call Base#optional with 2 arguments; the 2nd arg is supplied - assert_equal(9, Optional2.new.optional(9)) + Optional2.new.optional(9) end assert_raise(ArgumentError) do # call Base#optional with 2 arguments - assert_equal(9, Optional2.new.optional(9, 2)) + Optional2.new.optional(9, 2) end end def test_optional3 @@ -133,6 +144,11 @@ class TestSuper < Test::Unit::TestCase def test_keyword2 assert_equal([{foo: "changed1"}, {foo: "changed2"}], Keyword2.new.keyword) end + def test_forwardable(...) + assert_equal([[],[],[],[1]], Forward.new.forward()) + assert_equal([[],[1,2],[1,2],[1,1,2]], Forward.new.forward(1,2)) + assert_equal([[],[:test],[:test],[1,:test]], Forward.new.forward(:test, ...)) + end class A def tt(aa) @@ -152,14 +168,13 @@ class TestSuper < Test::Unit::TestCase a = A.new a.uu(12) assert_equal("A#tt", a.tt(12), "[ruby-core:3856]") - e = assert_raise(RuntimeError, "[ruby-core:24244]") { + assert_raise_with_message(RuntimeError, /implicit argument passing of super from method defined by define_method/, "[ruby-core:24244]") { lambda { Class.new { define_method(:a) {super} }.new.a }.call } - assert_match(/implicit argument passing of super from method defined by define_method/, e.message) end class SubSeq @@ -195,7 +210,7 @@ class TestSuper < Test::Unit::TestCase end end overlaid.call(str = "123") - overlaid.call(ary = [1,2,3]) + overlaid.call([1,2,3]) str.reverse end @@ -230,11 +245,8 @@ class TestSuper < Test::Unit::TestCase A.send(:include, Override) end - # [Bug #3351] def test_double_include - assert_equal([:Base, :Override], DoubleInclude::B.new.foo) - # should be changed as follows? - # assert_equal([:Base, :Override, :Override], DoubleInclude::B.new.foo) + assert_equal([:Base, :Override, :Override], DoubleInclude::B.new.foo, "[Bug #3351]") end module DoubleInclude2 @@ -272,12 +284,12 @@ class TestSuper < Test::Unit::TestCase end def test_super_in_instance_eval - super_class = Class.new { + super_class = EnvUtil.labeled_class("Super\u{30af 30e9 30b9}") { def foo return [:super, self] end } - sub_class = Class.new(super_class) { + sub_class = EnvUtil.labeled_class("Sub\u{30af 30e9 30b9}", super_class) { def foo x = Object.new x.instance_eval do @@ -286,18 +298,18 @@ class TestSuper < Test::Unit::TestCase end } obj = sub_class.new - assert_raise(TypeError) do + assert_raise_with_message(TypeError, /Sub\u{30af 30e9 30b9}/) do obj.foo end end def test_super_in_instance_eval_with_define_method - super_class = Class.new { + super_class = EnvUtil.labeled_class("Super\u{30af 30e9 30b9}") { def foo return [:super, self] end } - sub_class = Class.new(super_class) { + sub_class = EnvUtil.labeled_class("Sub\u{30af 30e9 30b9}", super_class) { define_method(:foo) do x = Object.new x.instance_eval do @@ -306,20 +318,42 @@ class TestSuper < Test::Unit::TestCase end } obj = sub_class.new - assert_raise(TypeError) do + assert_raise_with_message(TypeError, /Sub\u{30af 30e9 30b9}/) do obj.foo end end - def test_super_in_orphan_block - super_class = Class.new { + def test_super_in_instance_eval_in_module + super_class = EnvUtil.labeled_class("Super\u{30af 30e9 30b9}") { def foo return [:super, self] end } - sub_class = Class.new(super_class) { + mod = EnvUtil.labeled_module("Mod\u{30af 30e9 30b9}") { def foo x = Object.new + x.instance_eval do + super() + end + end + } + sub_class = EnvUtil.labeled_class("Sub\u{30af 30e9 30b9}", super_class) { + include mod + } + obj = sub_class.new + assert_raise_with_message(TypeError, /Sub\u{30af 30e9 30b9}/) do + obj.foo + end + end + + def test_super_in_orphan_block + super_class = EnvUtil.labeled_class("Super\u{30af 30e9 30b9}") { + def foo + return [:super, self] + end + } + sub_class = EnvUtil.labeled_class("Sub\u{30af 30e9 30b9}", super_class) { + def foo lambda { super() } end } @@ -328,12 +362,12 @@ class TestSuper < Test::Unit::TestCase end def test_super_in_orphan_block_with_instance_eval - super_class = Class.new { + super_class = EnvUtil.labeled_class("Super\u{30af 30e9 30b9}") { def foo return [:super, self] end } - sub_class = Class.new(super_class) { + sub_class = EnvUtil.labeled_class("Sub\u{30af 30e9 30b9}", super_class) { def foo x = Object.new x.instance_eval do @@ -342,7 +376,7 @@ class TestSuper < Test::Unit::TestCase end } obj = sub_class.new - assert_raise(TypeError) do + assert_raise_with_message(TypeError, /Sub\u{30af 30e9 30b9}/) do obj.foo.call end end @@ -385,4 +419,359 @@ class TestSuper < Test::Unit::TestCase def test_super_in_BEGIN assert_super_in_block("BEGIN") end + + class X + def foo(*args) + args + end + end + + class Y < X + define_method(:foo) do |*args| + super(*args) + end + end + + def test_super_splat + # [ruby-list:49575] + y = Y.new + assert_equal([1, 2], y.foo(1, 2)) + assert_equal([1, false], y.foo(1, false)) + assert_equal([1, 2, 3, 4, 5], y.foo(1, 2, 3, 4, 5)) + assert_equal([false, true], y.foo(false, true)) + assert_equal([false, false], y.foo(false, false)) + assert_equal([1, 2, 3, false, 5], y.foo(1, 2, 3, false, 5)) + end + + def test_missing_super + o = Class.new {def foo; super; end}.new + e = assert_raise(NoMethodError) {o.foo} + assert_same(o, e.receiver) + assert_equal(:foo, e.name) + end + + def test_missing_super_in_method_module + bug9315 = '[ruby-core:59358] [Bug #9315]' + a = Module.new do + def foo + super + end + end + b = Class.new do + include a + end + assert_raise(NoMethodError, bug9315) do + b.new.method(:foo).call + end + end + + def test_module_super_in_method_module + bug9315 = '[ruby-core:59589] [Bug #9315]' + a = Module.new do + def foo + super + end + end + c = Class.new do + def foo + :ok + end + end + o = c.new.extend(a) + assert_nothing_raised(NoMethodError, bug9315) do + assert_equal(:ok, o.method(:foo).call, bug9315) + end + end + + def test_missing_super_in_module_unbound_method + bug9377 = '[ruby-core:59619] [Bug #9377]' + + a = Module.new do + def foo; super end + end + + m = a.instance_method(:foo).bind(Object.new) + assert_raise(NoMethodError, bug9377) do + m.call + end + end + + def test_super_in_module_unbound_method + bug9721 = '[ruby-core:61936] [Bug #9721]' + + a = Module.new do + def foo(result) + result << "A" + end + end + + b = Module.new do + def foo(result) + result << "B" + super + end + end + + um = b.instance_method(:foo) + + m = um.bind(Object.new.extend(a)) + result = [] + assert_nothing_raised(NoMethodError, bug9721) do + m.call(result) + end + assert_equal(%w[B A], result, bug9721) + + bug9740 = '[ruby-core:62017] [Bug #9740]' + + b.module_eval do + define_method(:foo) do |res| + um.bind(self).call(res) + end + end + + result.clear + o = Object.new.extend(a).extend(b) + assert_nothing_raised(NoMethodError, SystemStackError, bug9740) do + o.foo(result) + end + assert_equal(%w[B A], result, bug9721) + end + + # [Bug #18329] + def test_super_missing_prepended_module + a = Module.new do + def probe(*methods) + prepend(probing_module(methods)) + end + + def probing_module(methods) + Module.new do + methods.each do |method| + define_method(method) do |*args, **kwargs, &block| + super(*args, **kwargs, &block) + end + end + end + end + end + + b = Class.new do + extend a + + probe :danger!, :missing + + def danger!; end + end + + o = b.new + o.danger! + begin + original_gc_stress = GC.stress + GC.stress = true + 2.times { o.missing rescue NoMethodError } + ensure + GC.stress = original_gc_stress + end + end + + def test_zsuper_kw_splat_not_mutable + extend(Module.new{def a(**k) k[:a] = 1 end}) + extend(Module.new do + def a(**k) + before = k.dup + super + [before, k] + end + end) + assert_equal(*a) + end + + def test_from_eval + bug10263 = '[ruby-core:65122] [Bug #10263a]' + a = Class.new do + def foo + "A" + end + end + b = Class.new(a) do + def foo + binding.eval("super") + end + end + assert_equal("A", b.new.foo, bug10263) + end + + def test_super_with_block + a = Class.new do + def foo + yield + end + end + + b = Class.new(a) do + def foo + super{ + "b" + } + end + end + + assert_equal "b", b.new.foo{"c"} + end + + def test_public_zsuper_with_prepend + bug12876 = '[ruby-core:77784] [Bug #12876]' + m = EnvUtil.labeled_module("M") + c = EnvUtil.labeled_class("C") {prepend m; public :initialize} + o = assert_nothing_raised(Timeout::Error, bug12876) { + Timeout.timeout(3) {c.new} + } + assert_instance_of(c, o) + m.module_eval {def initialize; raise "exception in M"; end} + assert_raise_with_message(RuntimeError, "exception in M") { + c.new + } + end + + def test_super_with_included_prepended_module_method_caching_bug_20716 + a = Module.new do + def test(*args) + super + end + end + + b = Module.new do + def test(a) + a + end + end + + c = Class.new + + b.prepend(a) + c.include(b) + + assert_equal(1, c.new.test(1)) + + b.class_eval do + begin + verbose_bak, $VERBOSE = $VERBOSE, nil + def test + :test + end + ensure + $VERBOSE = verbose_bak + end + end + + assert_equal(:test, c.new.test) + end + + class TestFor_super_with_modified_rest_parameter_base + def foo *args + args + end + end + + class TestFor_super_with_modified_rest_parameter < TestFor_super_with_modified_rest_parameter_base + def foo *args + args = 13 + super + end + end + def test_super_with_modified_rest_parameter + assert_equal [13], TestFor_super_with_modified_rest_parameter.new.foo + end + + def test_super_with_define_method + superklass1 = Class.new do + def foo; :foo; end + def bar; :bar; end + def boo; :boo; end + end + superklass2 = Class.new(superklass1) do + alias baz boo + def boo; :boo2; end + end + subklass = Class.new(superklass2) + [:foo, :bar, :baz, :boo].each do |sym| + subklass.define_method(sym){ super() } + end + assert_equal :foo, subklass.new.foo + assert_equal :bar, subklass.new.bar + assert_equal :boo, subklass.new.baz + assert_equal :boo2, subklass.new.boo + end + + def test_super_attr_writer # [Bug #16785] + writer_class = Class.new do + attr_writer :test + end + superwriter_class = Class.new(writer_class) do + def initialize + @test = 1 # index: 1 + end + + def test=(test) + super(test) + end + end + inherited_class = Class.new(superwriter_class) do + def initialize + @a = nil + @test = 2 # index: 2 + end + end + + superwriter = superwriter_class.new + superwriter.test = 3 # set ic->index of superwriter_class#test= to 1 + + inherited = inherited_class.new + inherited.test = 4 # it may set 4 to index=1 while it should be index=2 + + assert_equal 3, superwriter.instance_variable_get(:@test) + assert_equal 4, inherited.instance_variable_get(:@test) + end + + def test_super_attr_reader + reader_class = Class.new do + attr_reader :test + end + superreader_class = Class.new(reader_class) do + def initialize + @test = 1 # index: 1 + end + + def test + super + end + end + inherited_class = Class.new(superreader_class) do + def initialize + @a = nil + @test = 2 # index: 2 + end + end + + superreader = superreader_class.new + assert_equal 1, superreader.test # set ic->index of superreader_class#test to 1 + + inherited = inherited_class.new + assert_equal 2, inherited.test # it may read index=1 while it should be index=2 + end + + def test_super_in_basic_object + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + class ::BasicObject + def no_super + super() + rescue ::NameError + :ok + end + end + + assert_equal :ok, "[Bug #21694]".no_super + end; + end end |
