summaryrefslogtreecommitdiff
path: root/test/ruby/test_super.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_super.rb')
-rw-r--r--test/ruby/test_super.rb653
1 files changed, 648 insertions, 5 deletions
diff --git a/test/ruby/test_super.rb b/test/ruby/test_super.rb
index 900fe997e6..25bad2242a 100644
--- a/test/ruby/test_super.rb
+++ b/test/ruby/test_super.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
require 'test/unit'
class TestSuper < Test::Unit::TestCase
@@ -6,6 +7,8 @@ class TestSuper < Test::Unit::TestCase
def double(a, b) [a,b] end
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
@@ -49,6 +52,28 @@ class TestSuper < Test::Unit::TestCase
class Optional5 < Base
def array(a = 1, b = 2, *) super end
end
+ class Keyword1 < Base
+ def keyword(foo: "keyword1") super end
+ end
+ class Keyword2 < Base
+ def keyword(foo: "keyword2")
+ foo = "changed1"
+ x = super
+ foo = "changed2"
+ y = super
+ [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))
@@ -88,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
@@ -111,6 +136,19 @@ class TestSuper < Test::Unit::TestCase
assert_equal([9, 8], Optional5.new.array(9, 8))
assert_equal([9, 8, 7], Optional5.new.array(9, 8, 7))
end
+ def test_keyword1
+ assert_equal({foo: "keyword1"}, Keyword1.new.keyword)
+ bug8008 = '[ruby-core:53114] [Bug #8008]'
+ assert_equal({foo: bug8008}, Keyword1.new.keyword(foo: bug8008))
+ end
+ 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)
@@ -120,15 +158,620 @@ class TestSuper < Test::Unit::TestCase
def uu(a)
class << self
define_method(:tt) do |sym|
- super
+ super(sym)
end
end
end
end
- def test_define_method # [ruby-core:03856]
+ def test_define_method
a = A.new
a.uu(12)
- assert_equal("A#tt", a.tt(12))
+ assert_equal("A#tt", a.tt(12), "[ruby-core:3856]")
+ 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
+ }
+ end
+
+ class SubSeq
+ def initialize
+ @first=11
+ @first or fail
+ end
+
+ def subseq
+ @first or fail
+ end
+ end
+
+ class Indexed
+ def subseq
+ SubSeq.new
+ end
+ end
+
+ Overlaid = proc do
+ class << self
+ def subseq
+ super.instance_eval(& Overlaid)
+ end
+ end
+ end
+
+ def test_overlaid
+ assert_nothing_raised('[ruby-dev:40959]') do
+ overlaid = proc do |obj|
+ def obj.reverse
+ super
+ end
+ end
+ overlaid.call(str = "123")
+ overlaid.call([1,2,3])
+ str.reverse
+ end
+
+ assert_nothing_raised('[ruby-core:27230]') do
+ mid=Indexed.new
+ mid.instance_eval(&Overlaid)
+ mid.subseq
+ mid.subseq
+ end
+ end
+
+ module DoubleInclude
+ class Base
+ def foo
+ [:Base]
+ end
+ end
+
+ module Override
+ def foo
+ super << :Override
+ end
+ end
+
+ class A < Base
+ end
+
+ class B < A
+ end
+
+ B.send(:include, Override)
+ A.send(:include, Override)
+ end
+
+ def test_double_include
+ assert_equal([:Base, :Override, :Override], DoubleInclude::B.new.foo, "[Bug #3351]")
+ end
+
+ module DoubleInclude2
+ class Base
+ def foo
+ [:Base]
+ end
+ end
+
+ module Override
+ def foo
+ super << :Override
+ end
+ end
+
+ class A < Base
+ def foo
+ super << :A
+ end
+ end
+
+ class B < A
+ def foo
+ super << :B
+ end
+ end
+
+ B.send(:include, Override)
+ A.send(:include, Override)
+ end
+
+ def test_double_include2
+ assert_equal([:Base, :Override, :A, :Override, :B],
+ DoubleInclude2::B.new.foo)
+ end
+
+ def test_super_in_instance_eval
+ 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
+ x = Object.new
+ x.instance_eval do
+ super()
+ end
+ end
+ }
+ obj = sub_class.new
+ 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 = 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) {
+ define_method(:foo) do
+ x = Object.new
+ x.instance_eval do
+ super()
+ end
+ end
+ }
+ obj = sub_class.new
+ assert_raise_with_message(TypeError, /Sub\u{30af 30e9 30b9}/) do
+ obj.foo
+ end
+ end
+
+ def test_super_in_instance_eval_in_module
+ super_class = EnvUtil.labeled_class("Super\u{30af 30e9 30b9}") {
+ def foo
+ return [:super, self]
+ end
+ }
+ 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
+ }
+ obj = sub_class.new
+ assert_equal([:super, obj], obj.foo.call)
+ end
+
+ def test_super_in_orphan_block_with_instance_eval
+ 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
+ x = Object.new
+ x.instance_eval do
+ lambda { super() }
+ end
+ end
+ }
+ obj = sub_class.new
+ assert_raise_with_message(TypeError, /Sub\u{30af 30e9 30b9}/) do
+ obj.foo.call
+ end
+ end
+
+ def test_yielding_super
+ a = Class.new { def yielder; yield; end }
+ x = Class.new { define_singleton_method(:hello) { 'hi' } }
+ y = Class.new(x) {
+ define_singleton_method(:hello) {
+ m = a.new
+ m.yielder { super() }
+ }
+ }
+ assert_equal 'hi', y.hello
+ end
+
+ def test_super_in_thread
+ hoge = Class.new {
+ def bar; 'hoge'; end
+ }
+ foo = Class.new(hoge) {
+ def bar; Thread.new { super }.join.value; end
+ }
+
+ assert_equal 'hoge', foo.new.bar
+ end
+
+ def assert_super_in_block(type)
+ bug7064 = '[ruby-core:47680]'
+ assert_normal_exit "#{type} {super}", bug7064
+ end
+
+ def test_super_in_at_exit
+ assert_super_in_block("at_exit")
+ end
+ def test_super_in_END
+ assert_super_in_block("END")
+ end
+
+ 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