summaryrefslogtreecommitdiff
path: root/test/ruby/test_call.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_call.rb')
-rw-r--r--test/ruby/test_call.rb163
1 files changed, 160 insertions, 3 deletions
diff --git a/test/ruby/test_call.rb b/test/ruby/test_call.rb
index ced1eaf5e9..dd1936c4e2 100644
--- a/test/ruby/test_call.rb
+++ b/test/ruby/test_call.rb
@@ -3,7 +3,24 @@ require 'test/unit'
require '-test-/iter'
class TestCall < Test::Unit::TestCase
- def aaa(a, b=100, *rest)
+ # These dummy method definitions prevent warnings "the block passed to 'a'..."
+ def a(&) = nil
+ def b(&) = nil
+ def c(&) = nil
+ def d(&) = nil
+ def e(&) = nil
+ def f(&) = nil
+ def g(&) = nil
+ def h(&) = nil
+ def i(&) = nil
+ def j(&) = nil
+ def k(&) = nil
+ def l(&) = nil
+ def m(&) = nil
+ def n(&) = nil
+ def o(&) = nil
+
+ def aaa(a, b=100, *rest, &)
res = [a, b]
res += rest if rest
return res
@@ -106,6 +123,25 @@ class TestCall < Test::Unit::TestCase
assert_equal([1, 2, {kw: 3}], f(*a, kw: 3))
end
+ def test_forward_argument_init
+ o = Object.new
+ def o.simple_forward_argument_init(a=eval('b'), b=1)
+ [a, b]
+ end
+
+ def o.complex_forward_argument_init(a=eval('b'), b=eval('kw'), kw: eval('kw2'), kw2: 3)
+ [a, b, kw, kw2]
+ end
+
+ def o.keyword_forward_argument_init(a: eval('b'), b: eval('kw'), kw: eval('kw2'), kw2: 3)
+ [a, b, kw, kw2]
+ end
+
+ assert_equal [nil, 1], o.simple_forward_argument_init
+ assert_equal [nil, nil, 3, 3], o.complex_forward_argument_init
+ assert_equal [nil, nil, 3, 3], o.keyword_forward_argument_init
+ end
+
def test_call_bmethod_proc
pr = proc{|sym| sym}
define_singleton_method(:a, &pr)
@@ -303,7 +339,7 @@ class TestCall < Test::Unit::TestCase
assert_syntax_error(%q{h[*a, 2, b: 5, **kw] += 1}, message)
end
- def test_call_splat_order
+ def test_call_splat_post_order
bug12860 = '[ruby-core:77701] [Bug# 12860]'
ary = [1, 2]
assert_equal([1, 2, 1], aaa(*ary, ary.shift), bug12860)
@@ -311,7 +347,7 @@ class TestCall < Test::Unit::TestCase
assert_equal([0, 1, 2, 1], aaa(0, *ary, ary.shift), bug12860)
end
- def test_call_block_order
+ def test_call_splat_block_order
bug16504 = '[ruby-core:96769] [Bug# 16504]'
b = proc{}
ary = [1, 2, b]
@@ -320,6 +356,22 @@ class TestCall < Test::Unit::TestCase
assert_equal([0, 1, 2, b], aaa(0, *ary, &ary.pop), bug16504)
end
+ def test_call_splat_kw_order
+ b = {}
+ ary = [1, 2, b]
+ assert_equal([1, 2, b, {a: b}], aaa(*ary, a: ary.pop))
+ ary = [1, 2, b]
+ assert_equal([0, 1, 2, b, {a: b}], aaa(0, *ary, a: ary.pop))
+ end
+
+ def test_call_splat_kw_splat_order
+ b = {}
+ ary = [1, 2, b]
+ assert_equal([1, 2, b], aaa(*ary, **ary.pop))
+ ary = [1, 2, b]
+ assert_equal([0, 1, 2, b], aaa(0, *ary, **ary.pop))
+ end
+
def test_call_args_splat_with_nonhash_keyword_splat
o = Object.new
def o.to_hash; {a: 1} end
@@ -329,6 +381,111 @@ class TestCall < Test::Unit::TestCase
assert_equal Hash, f(*[], **o).class
end
+ def test_call_args_splat_with_pos_arg_kw_splat_is_not_mutable
+ o = Object.new
+ def o.foo(a, **h)= h[:splat_modified] = true
+
+ a = []
+ b = {splat_modified: false}
+
+ o.foo(*a, :x, **b)
+
+ assert_equal({splat_modified: false}, b)
+ end
+
+ def test_anon_splat
+ r2kh = Hash.ruby2_keywords_hash(kw: 2)
+ r2kea = [r2kh]
+ r2ka = [1, r2kh]
+
+ def self.s(*) ->(*a){a}.call(*) end
+ assert_equal([], s)
+ assert_equal([1], s(1))
+ assert_equal([{kw: 2}], s(kw: 2))
+ assert_equal([{kw: 2}], s(**{kw: 2}))
+ assert_equal([1, {kw: 2}], s(1, kw: 2))
+ assert_equal([1, {kw: 2}], s(1, **{kw: 2}))
+ assert_equal([{kw: 2}], s(*r2kea))
+ assert_equal([1, {kw: 2}], s(*r2ka))
+
+ singleton_class.remove_method(:s)
+ def self.s(*, kw: 0) [*->(*a){a}.call(*), kw] end
+ assert_equal([0], s)
+ assert_equal([1, 0], s(1))
+ assert_equal([2], s(kw: 2))
+ assert_equal([2], s(**{kw: 2}))
+ assert_equal([1, 2], s(1, kw: 2))
+ assert_equal([1, 2], s(1, **{kw: 2}))
+ assert_equal([2], s(*r2kea))
+ assert_equal([1, 2], s(*r2ka))
+
+ singleton_class.remove_method(:s)
+ def self.s(*, **kw) [*->(*a){a}.call(*), kw] end
+ assert_equal([{}], s)
+ assert_equal([1, {}], s(1))
+ assert_equal([{kw: 2}], s(kw: 2))
+ assert_equal([{kw: 2}], s(**{kw: 2}))
+ assert_equal([1, {kw: 2}], s(1, kw: 2))
+ assert_equal([1, {kw: 2}], s(1, **{kw: 2}))
+ assert_equal([{kw: 2}], s(*r2kea))
+ assert_equal([1, {kw: 2}], s(*r2ka))
+
+ singleton_class.remove_method(:s)
+ def self.s(*, kw: 0, **kws) [*->(*a){a}.call(*), kw, kws] end
+ assert_equal([0, {}], s)
+ assert_equal([1, 0, {}], s(1))
+ assert_equal([2, {}], s(kw: 2))
+ assert_equal([2, {}], s(**{kw: 2}))
+ assert_equal([1, 2, {}], s(1, kw: 2))
+ assert_equal([1, 2, {}], s(1, **{kw: 2}))
+ assert_equal([2, {}], s(*r2kea))
+ assert_equal([1, 2, {}], s(*r2ka))
+ end
+
+ def test_anon_splat_mutated_bug_21757
+ args = [1, 2]
+ kw = {bug: true}
+
+ def self.m(*); end
+ m(*args, bug: true)
+ assert_equal(2, args.length)
+
+ proc = ->(*) { }
+ proc.(*args, bug: true)
+ assert_equal(2, args.length)
+
+ def self.m2(*); end
+ m2(*args, **kw)
+ assert_equal(2, args.length)
+
+ proc = ->(*) { }
+ proc.(*args, **kw)
+ assert_equal(2, args.length)
+
+ def self.m3(*, **nil); end
+ assert_raise(ArgumentError) { m3(*args, bug: true) }
+ assert_equal(2, args.length)
+
+ proc = ->(*, **nil) { }
+ assert_raise(ArgumentError) { proc.(*args, bug: true) }
+ assert_equal(2, args.length)
+ end
+
+ def test_kwsplat_block_eval_order
+ def self.t(**kw, &b) [kw, b] end
+
+ pr = ->{}
+ h = {a: pr}
+ a = []
+
+ ary = t(**h, &h.delete(:a))
+ assert_equal([{a: pr}, pr], ary)
+
+ h = {a: pr}
+ ary = t(*a, **h, &h.delete(:a))
+ assert_equal([{a: pr}, pr], ary)
+ end
+
def test_kwsplat_block_order
o = Object.new
ary = []