diff options
Diffstat (limited to 'test/ruby/test_lambda.rb')
| -rw-r--r-- | test/ruby/test_lambda.rb | 189 |
1 files changed, 158 insertions, 31 deletions
diff --git a/test/ruby/test_lambda.rb b/test/ruby/test_lambda.rb index c47351886a..c1858a36dd 100644 --- a/test/ruby/test_lambda.rb +++ b/test/ruby/test_lambda.rb @@ -31,8 +31,10 @@ class TestLambdaParameters < Test::Unit::TestCase bug9605 = '[ruby-core:61468] [Bug #9605]' assert_nothing_raised(ArgumentError, bug9605) {1.times(&->(n){ a += 1 })} assert_equal(3, a, bug9605) - assert_nothing_raised(ArgumentError, bug9605) {a = [[1, 2]].map(&->(x, y) {x+y})} - assert_equal([3], a, bug9605) + assert_nothing_raised(ArgumentError, bug9605) { + a = %w(Hi there how are you).each_with_index.detect(&->(w, i) {w.length == 3}) + } + assert_equal(["how", 2], a, bug9605) end def test_call_rest_args @@ -72,6 +74,109 @@ class TestLambdaParameters < Test::Unit::TestCase assert_raise(ArgumentError, bug9605) {proc(&plus).call [1,2]} end + def test_proc_inside_lambda_inside_method_return_inside_lambda_inside_method + def self.a + -> do + p = Proc.new{return :a} + p.call + end.call + end + assert_equal(:a, a) + + def self.b + lambda do + p = Proc.new{return :b} + p.call + end.call + end + assert_equal(:b, b) + end + + def test_proc_inside_lambda_inside_method_return_inside_lambda_outside_method + def self.a + -> do + p = Proc.new{return :a} + p.call + end + end + assert_equal(:a, a.call) + + def self.b + lambda do + p = Proc.new{return :b} + p.call + end + end + assert_equal(:b, b.call) + end + + def test_proc_inside_lambda_inside_method_return_outside_lambda_inside_method + def self.a + -> do + Proc.new{return :a} + end.call.call + end + assert_raise(LocalJumpError) {a} + + def self.b + lambda do + Proc.new{return :b} + end.call.call + end + assert_raise(LocalJumpError) {b} + end + + def test_proc_inside_lambda_inside_method_return_outside_lambda_outside_method + def self.a + -> do + Proc.new{return :a} + end + end + assert_raise(LocalJumpError) {a.call.call} + + def self.b + lambda do + Proc.new{return :b} + end + end + assert_raise(LocalJumpError) {b.call.call} + end + + def test_proc_inside_lambda2_inside_method_return_outside_lambda1_inside_method + def self.a + -> do + -> do + Proc.new{return :a} + end.call.call + end.call + end + assert_raise(LocalJumpError) {a} + + def self.b + lambda do + lambda do + Proc.new{return :a} + end.call.call + end.call + end + assert_raise(LocalJumpError) {b} + end + + def test_proc_inside_lambda_toplevel + assert_ruby_status [], <<~RUBY + lambda{ + $g = proc{ return :pr } + }.call + begin + $g.call + rescue LocalJumpError + # OK! + else + raise + end + RUBY + end + def test_instance_exec bug12568 = '[ruby-core:76300] [Bug #12568]' assert_nothing_raised(ArgumentError, bug12568) do @@ -99,29 +204,9 @@ class TestLambdaParameters < Test::Unit::TestCase assert_equal(:ok, x, bug13090) end - def yield_1(arg) - yield arg - end - - tap do |;bug9605, expected, result| - bug9605 = '[ruby-core:65887] [Bug #9605] arity check should be relaxed' - expected = [1,2,3] - - [ - ["array", expected], - ["to_ary", Struct.new(:to_ary).new(expected)], - ].product \ - [ - ["proc", proc {|a, b, c| [a, b, c]}], - ["lambda", lambda {|a, b, c| [a, b, c]}], - ] do - |(vtype, val), (btype, block)| - define_method("test_yield_relaxed(#{vtype},&#{btype})") do - result = assert_nothing_raised(ArgumentError, bug9605) { - break yield_1(val, &block) - } - assert_equal(expected, result, bug9605) - end + def test_arity_error + assert_raise(ArgumentError, '[Bug #12705]') do + [1, 2].tap(&lambda {|a, b|}) end end @@ -175,27 +260,69 @@ class TestLambdaParameters < Test::Unit::TestCase assert_equal(42, return_in_callee(42), feature8693) end + def break_in_current(val) + 1.tap(&->(*) {break 0}) + val + end + + def break_in_callee(val) + yield_block(&->(*) {break 0}) + val + end + + def test_break + assert_equal(42, break_in_current(42)) + assert_equal(42, break_in_callee(42)) + end + def test_do_lambda_source_location - exp_lineno = __LINE__ + 3 + exp = [__LINE__ + 1, 10, __LINE__ + 5, 7] lmd = ->(x, y, z) do # end - file, lineno = lmd.source_location + file, *loc = lmd.source_location assert_match(/^#{ Regexp.quote(__FILE__) }$/, file) - assert_equal(exp_lineno, lineno, "must be at the beginning of the block") + assert_equal(exp, loc) end def test_brace_lambda_source_location - exp_lineno = __LINE__ + 3 + exp = [__LINE__ + 1, 10, __LINE__ + 5, 5] lmd = ->(x, y, z) { # } - file, lineno = lmd.source_location + file, *loc = lmd.source_location assert_match(/^#{ Regexp.quote(__FILE__) }$/, file) - assert_equal(exp_lineno, lineno, "must be at the beginning of the block") + assert_equal(exp, loc) + end + + def test_not_orphan_return + assert_equal(42, Module.new { extend self + def m1(&b) b.call end; def m2(); m1(&-> { return 42 }) end }.m2) + assert_equal(42, Module.new { extend self + def m1(&b) b end; def m2(); m1(&-> { return 42 }).call end }.m2) + assert_equal(42, Module.new { extend self + def m1(&b) b end; def m2(); m1(&-> { return 42 }) end }.m2.call) + end + + def test_not_orphan_break + assert_equal(42, Module.new { extend self + def m1(&b) b.call end; def m2(); m1(&-> { break 42 }) end }.m2) + assert_equal(42, Module.new { extend self + def m1(&b) b end; def m2(); m1(&-> { break 42 }).call end }.m2) + assert_equal(42, Module.new { extend self + def m1(&b) b end; def m2(); m1(&-> { break 42 }) end }.m2.call) + end + + def test_not_orphan_next + assert_equal(42, Module.new { extend self + def m1(&b) b.call end; def m2(); m1(&-> { next 42 }) end }.m2) + assert_equal(42, Module.new { extend self + def m1(&b) b end; def m2(); m1(&-> { next 42 }).call end }.m2) + assert_equal(42, Module.new { extend self + def m1(&b) b end; def m2(); m1(&-> { next 42 }) end }.m2.call) end end |
