diff options
Diffstat (limited to 'test/ruby/test_yield.rb')
| -rw-r--r-- | test/ruby/test_yield.rb | 113 |
1 files changed, 100 insertions, 13 deletions
diff --git a/test/ruby/test_yield.rb b/test/ruby/test_yield.rb index 3ae6881b87..e7e65fce9e 100644 --- a/test/ruby/test_yield.rb +++ b/test/ruby/test_yield.rb @@ -1,4 +1,6 @@ +# frozen_string_literal: false require 'test/unit' +require 'stringio' class TestRubyYield < Test::Unit::TestCase @@ -64,9 +66,28 @@ class TestRubyYield < Test::Unit::TestCase } end + def test_with_enum + obj = Object.new + def obj.each + yield(*[]) + end + obj.each{|*v| assert_equal([], [], '[ruby-dev:32392]')} + obj.to_enum.each{|*v| assert_equal([], [], '[ruby-dev:32392]')} + end + + def block_args_unleashed + yield(1,2,3,4,5) + end + + def test_block_args_unleashed + r = block_args_unleashed {|a,b=1,*c,d,e| + [a,b,c,d,e] + } + assert_equal([1,2,[3],4,5], r, "[ruby-core:19485]") + end end -require 'sentence' +require_relative 'sentence' class TestRubyYieldGen < Test::Unit::TestCase Syntax = { :exp => [["0"], @@ -155,7 +176,8 @@ class TestRubyYieldGen < Test::Unit::TestCase :block_arg => [['&', :arg]], #:test => [['def m() yield', :command_args_noblock, ' end; r = m {', :block_param_def, 'vars', '}; undef m; r']] :test_proc => [['def m() yield', :command_args_noblock, ' end; r = m {', :block_param_def, 'vars', '}; undef m; r']], - :test_lambda => [['def m() yield', :command_args_noblock, ' end; r = m(&lambda {', :block_param_def, 'vars', '}); undef m; r']] + :test_lambda => [['def m() yield', :command_args_noblock, ' end; r = m(&lambda {', :block_param_def, 'vars', '}); undef m; r']], + :test_enum => [['o = Object.new; def o.each() yield', :command_args_noblock, ' end; r1 = r2 = nil; o.each {|*x| r1 = x }; o.to_enum.each {|*x| r2 = x }; [r1, r2]']] } def rename_var(obj) @@ -189,8 +211,8 @@ class TestRubyYieldGen < Test::Unit::TestCase if args.last == [] args = args[0...-1] end - code = "emu_return_args #{args.map {|a| a.join('') }.join(",")}" - eval code + code = "emu_return_args(#{args.map {|a| a.join('') }.join(",")})" + eval code, nil, 'generated_code_in_emu_eval_args' end def emu_bind_single(arg, param, result_binding) @@ -304,35 +326,100 @@ class TestRubyYieldGen < Test::Unit::TestCase } end + def disable_stderr + begin + save_stderr = $stderr + $stderr = StringIO.new + yield + ensure + $stderr = save_stderr + end + end + def check_nofork(t, islambda=false) t, vars = rename_var(t) t = t.subst('vars') { " [#{vars.join(",")}]" } emu_values = emu(t, vars, islambda) s = t.to_s + o = Object.new #print "#{s}\t\t" #STDOUT.flush - begin - eval_values = eval(s) - rescue ArgumentError - eval_values = ArgumentError - end + eval_values = disable_stderr { + begin + o.instance_eval(s, 'generated_code_in_check_nofork') + rescue ArgumentError + ArgumentError + end + } #success = emu_values == eval_values ? 'succ' : 'fail' #puts "eval:#{vs_ev.inspect[1...-1].delete(' ')}\temu:#{vs_emu.inspect[1...-1].delete(' ')}\t#{success}" assert_equal(emu_values, eval_values, s) end + def assert_all_sentences(syntax, *args) + syntax = Sentence.expand_syntax(syntax) + all_assertions do |a| + Sentence.each(syntax, *args) {|t| + a.for(t) {yield t} + } + end + end + def test_yield - syntax = Sentence.expand_syntax(Syntax) - Sentence.each(syntax, :test_proc, 4) {|t| + assert_all_sentences(Syntax, :test_proc, 4) {|t| check_nofork(t) } end def test_yield_lambda - syntax = Sentence.expand_syntax(Syntax) - Sentence.each(syntax, :test_lambda, 4) {|t| + assert_all_sentences(Syntax, :test_lambda, 4) {|t| check_nofork(t, true) } end + def test_yield_enum + assert_all_sentences(Syntax, :test_enum, 4) {|t| + code = t.to_s + r1, r2 = disable_stderr { + eval(code, nil, 'generated_code_in_test_yield_enum') + } + assert_equal(r1, r2, "#{t}") + } + end + + def test_block_with_mock + y = Object.new + def y.s(a) + yield(a) + end + m = Object.new + def m.method_missing(*a) + super + end + assert_equal [m, nil], y.s(m){|a,b|[a,b]} + end + + def test_block_cached_argc + # [Bug #11451] + assert_ruby_status([], <<-"end;") + class Yielder + def each + yield :x, :y, :z + end + end + class Getter1 + include Enumerable + def each(&block) + Yielder.new.each(&block) + end + end + class Getter2 + include Enumerable + def each + Yielder.new.each { |a, b, c, d| yield(a) } + end + end + Getter1.new.map{Getter2.new.each{|x|}} + end; + end end |
