diff options
Diffstat (limited to 'test/ruby/test_proc.rb')
| -rw-r--r-- | test/ruby/test_proc.rb | 604 |
1 files changed, 551 insertions, 53 deletions
diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb index 16efd13d7c..959ea87f25 100644 --- a/test/ruby/test_proc.rb +++ b/test/ruby/test_proc.rb @@ -159,13 +159,65 @@ class TestProc < Test::Unit::TestCase assert_equal(*m_nest{}, "[ruby-core:84583] Feature #14627") end - def test_hash + def test_hash_equal + # iseq backed proc + p1 = proc {} + p2 = p1.dup + + assert_equal p1.hash, p2.hash + + # ifunc backed proc + p1 = {}.to_proc + p2 = p1.dup + + assert_equal p1.hash, p2.hash + + # symbol backed proc + p1 = :hello.to_proc + p2 = :hello.to_proc + + assert_equal p1.hash, p2.hash + end + + def test_hash_uniqueness def self.capture(&block) block end - procs = Array.new(1000){capture{:foo }} - assert_operator(procs.map(&:hash).uniq.size, :>=, 500) + procs = Array.new(1000){capture{:foo }} + assert_operator(procs.map(&:hash).uniq.size, :>=, 500) + + # iseq backed proc + unique_hashes = 1000.times.map { proc {}.hash }.uniq + assert_operator(unique_hashes.size, :>=, 500) + + # ifunc backed proc + unique_hashes = 1000.times.map { {}.to_proc.hash }.uniq + assert_operator(unique_hashes.size, :>=, 500) + + # symbol backed proc + unique_hashes = 1000.times.map { |i| :"test#{i}".to_proc.hash }.uniq + assert_operator(unique_hashes.size, :>=, 500) + end + + def test_hash_does_not_change_after_compaction + omit "compaction is not supported on this platform" unless GC.respond_to?(:compact) + + # [Bug #20853] + [ + "proc {}", # iseq backed proc + "{}.to_proc", # ifunc backed proc + ":hello.to_proc", # symbol backed proc + ].each do |proc| + assert_separately([], <<~RUBY) + p1 = #{proc} + hash = p1.hash + + GC.verify_compaction_references(expand_heap: true, toward: :empty) + + assert_equal(hash, p1.hash, "proc is `#{proc}`") + RUBY + end end def test_block_par @@ -207,18 +259,24 @@ class TestProc < Test::Unit::TestCase end def test_block_given_method + verbose_bak, $VERBOSE = $VERBOSE, nil m = method(:m_block_given?) assert(!m.call, "without block") assert(m.call {}, "with block") assert(!m.call, "without block second") + ensure + $VERBOSE = verbose_bak end def test_block_given_method_to_proc + verbose_bak, $VERBOSE = $VERBOSE, nil bug8341 = '[Bug #8341]' m = method(:m_block_given?).to_proc assert(!m.call, "#{bug8341} without block") assert(m.call {}, "#{bug8341} with block") assert(!m.call, "#{bug8341} without block second") + ensure + $VERBOSE = verbose_bak end def test_block_persist_between_calls @@ -289,7 +347,6 @@ class TestProc < Test::Unit::TestCase assert_equal(false, l.lambda?) assert_equal(false, l.curry.lambda?, '[ruby-core:24127]') assert_equal(false, proc(&l).lambda?) - assert_equal(false, assert_deprecated_warning {lambda(&l)}.lambda?) assert_equal(false, Proc.new(&l).lambda?) l = lambda {} assert_equal(true, l.lambda?) @@ -299,47 +356,21 @@ class TestProc < Test::Unit::TestCase assert_equal(true, Proc.new(&l).lambda?) end - def self.helper_test_warn_lamda_with_passed_block &b + def helper_test_warn_lambda_with_passed_block &b lambda(&b) end - def self.def_lambda_warning name, warn - define_method(name, proc do - prev = Warning[:deprecated] - assert_warn warn do - Warning[:deprecated] = true - yield - end - ensure - Warning[:deprecated] = prev - end) - end - - def_lambda_warning 'test_lambda_warning_normal', '' do - lambda{} - end - - def_lambda_warning 'test_lambda_warning_pass_lambda', '' do - b = lambda{} - lambda(&b) - end - - def_lambda_warning 'test_lambda_warning_pass_symbol_proc', '' do - lambda(&:to_s) - end - - def_lambda_warning 'test_lambda_warning_pass_proc', /deprecated/ do - b = proc{} - lambda(&b) - end - - def_lambda_warning 'test_lambda_warning_pass_block', /deprecated/ do - helper_test_warn_lamda_with_passed_block{} + def test_lambda_warning_pass_proc + assert_raise(ArgumentError) do + b = proc{} + lambda(&b) + end end - def_lambda_warning 'test_lambda_warning_pass_block_symbol_proc', '' do - # Symbol#to_proc returns lambda - helper_test_warn_lamda_with_passed_block(&:to_s) + def test_lambda_warning_pass_block + assert_raise(ArgumentError) do + helper_test_warn_lambda_with_passed_block{} + end end def test_curry_ski_fib @@ -398,6 +429,7 @@ class TestProc < Test::Unit::TestCase end def test_dup_clone + # iseq backed proc b = proc {|x| x + "bar" } class << b; attr_accessor :foo; end @@ -410,6 +442,50 @@ class TestProc < Test::Unit::TestCase assert_equal("foobar", bc.call("foo")) bc.foo = :foo assert_equal(:foo, bc.foo) + + # ifunc backed proc + b = {foo: "bar"}.to_proc + + bd = b.dup + assert_equal("bar", bd.call(:foo)) + + bc = b.clone + assert_equal("bar", bc.call(:foo)) + + # symbol backed proc + b = :to_s.to_proc + + bd = b.dup + assert_equal("testing", bd.call(:testing)) + + bc = b.clone + assert_equal("testing", bc.call(:testing)) + end + + def test_dup_subclass + c1 = Class.new(Proc) + assert_equal c1, c1.new{}.dup.class, '[Bug #17545]' + c1 = Class.new(Proc) {def initialize_dup(*) throw :initialize_dup; end} + assert_throw(:initialize_dup) {c1.new{}.dup} + end + + def test_dup_ifunc_proc_bug_20950 + assert_normal_exit(<<~RUBY, "[Bug #20950]") + p = { a: 1 }.to_proc + 100.times do + p = p.dup + GC.start + p.call + rescue ArgumentError + end + RUBY + end + + def test_clone_subclass + c1 = Class.new(Proc) + assert_equal c1, c1.new{}.clone.class, '[Bug #17545]' + c1 = Class.new(Proc) {def initialize_clone(*) throw :initialize_clone; end} + assert_throw(:initialize_clone) {c1.new{}.clone} end def test_binding @@ -437,7 +513,12 @@ class TestProc < Test::Unit::TestCase file, lineno = method(:source_location_test).to_proc.binding.source_location assert_match(/^#{ Regexp.quote(__FILE__) }$/, file) - assert_equal(@@line_of_source_location_test, lineno, 'Bug #2427') + assert_equal(@@line_of_source_location_test[0], lineno, 'Bug #2427') + end + + def test_binding_error_unless_ruby_frame + define_singleton_method :binding_from_c!, method(:binding).to_proc >> ->(bndg) {bndg} + assert_raise(RuntimeError) { binding_from_c! } end def test_proc_lambda @@ -847,6 +928,88 @@ class TestProc < Test::Unit::TestCase assert_equal [[1, 2], Proc, :x], (pr.call(1, 2){|x| x}) end + def test_proc_args_single_kw_no_autosplat + pr = proc {|c, a: 1| [c, a] } + assert_equal [nil, 1], pr.call() + assert_equal [1, 1], pr.call(1) + assert_equal [[1], 1], pr.call([1]) + assert_equal [1, 1], pr.call(1,2) + assert_equal [[1, 2], 1], pr.call([1,2]) + + assert_equal [nil, 3], pr.call(a: 3) + assert_equal [1, 3], pr.call(1, a: 3) + assert_equal [[1], 3], pr.call([1], a: 3) + assert_equal [1, 3], pr.call(1,2, a: 3) + assert_equal [[1, 2], 3], pr.call([1,2], a: 3) + end + + def test_proc_args_single_kwsplat_no_autosplat + pr = proc {|c, **kw| [c, kw] } + assert_equal [nil, {}], pr.call() + assert_equal [1, {}], pr.call(1) + assert_equal [[1], {}], pr.call([1]) + assert_equal [1, {}], pr.call(1,2) + assert_equal [[1, 2], {}], pr.call([1,2]) + + assert_equal [nil, {a: 3}], pr.call(a: 3) + assert_equal [1, {a: 3}], pr.call(1, a: 3) + assert_equal [[1], {a: 3}], pr.call([1], a: 3) + assert_equal [1, {a: 3}], pr.call(1,2, a: 3) + assert_equal [[1, 2], {a: 3}], pr.call([1,2], a: 3) + end + + def test_proc_args_multiple_kw_autosplat + pr = proc {|c, b, a: 1| [c, b, a] } + assert_equal [1, 2, 1], pr.call([1,2]) + + pr = proc {|c=nil, b=nil, a: 1| [c, b, a] } + assert_equal [nil, nil, 1], pr.call([]) + assert_equal [1, nil, 1], pr.call([1]) + assert_equal [1, 2, 1], pr.call([1,2]) + + pr = proc {|c, b=nil, a: 1| [c, b, a] } + assert_equal [1, nil, 1], pr.call([1]) + assert_equal [1, 2, 1], pr.call([1,2]) + + pr = proc {|c=nil, b, a: 1| [c, b, a] } + assert_equal [nil, 1, 1], pr.call([1]) + assert_equal [1, 2, 1], pr.call([1,2]) + + pr = proc {|c, *b, a: 1| [c, b, a] } + assert_equal [1, [], 1], pr.call([1]) + assert_equal [1, [2], 1], pr.call([1,2]) + + pr = proc {|*c, b, a: 1| [c, b, a] } + assert_equal [[], 1, 1], pr.call([1]) + assert_equal [[1], 2, 1], pr.call([1,2]) + end + + def test_proc_args_multiple_kwsplat_autosplat + pr = proc {|c, b, **kw| [c, b, kw] } + assert_equal [1, 2, {}], pr.call([1,2]) + + pr = proc {|c=nil, b=nil, **kw| [c, b, kw] } + assert_equal [nil, nil, {}], pr.call([]) + assert_equal [1, nil, {}], pr.call([1]) + assert_equal [1, 2, {}], pr.call([1,2]) + + pr = proc {|c, b=nil, **kw| [c, b, kw] } + assert_equal [1, nil, {}], pr.call([1]) + assert_equal [1, 2, {}], pr.call([1,2]) + + pr = proc {|c=nil, b, **kw| [c, b, kw] } + assert_equal [nil, 1, {}], pr.call([1]) + assert_equal [1, 2, {}], pr.call([1,2]) + + pr = proc {|c, *b, **kw| [c, b, kw] } + assert_equal [1, [], {}], pr.call([1]) + assert_equal [1, [2], {}], pr.call([1,2]) + + pr = proc {|*c, b, **kw| [c, b, kw] } + assert_equal [[], 1, {}], pr.call([1]) + assert_equal [[1], 2, {}], pr.call([1,2]) + end + def test_proc_args_only_rest pr = proc {|*c| c } assert_equal [], pr.call() @@ -1219,7 +1382,8 @@ class TestProc < Test::Unit::TestCase assert_equal([[:opt, :a], [:rest, :b], [:opt, :c]], proc {|a, *b, c|}.parameters) assert_equal([[:opt, :a], [:rest, :b], [:opt, :c], [:block, :d]], proc {|a, *b, c, &d|}.parameters) assert_equal([[:opt, :a], [:opt, :b], [:rest, :c], [:opt, :d], [:block, :e]], proc {|a, b=:b, *c, d, &e|}.parameters) - assert_equal([[:opt, nil], [:block, :b]], proc {|(a), &b|a}.parameters) + assert_equal([[:opt], [:block, :b]], proc {|(a), &b|a}.parameters) + assert_equal([[:opt], [:rest, :_], [:opt]], proc {|(a_), *_, (b_)|}.parameters) assert_equal([[:opt, :a], [:opt, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:opt, :f], [:opt, :g], [:block, :h]], proc {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters) assert_equal([[:req]], method(:putc).parameters) @@ -1227,6 +1391,59 @@ class TestProc < Test::Unit::TestCase pr = eval("proc{|"+"(_),"*30+"|}") assert_empty(pr.parameters.map{|_,n|n}.compact) + + assert_equal([[:opt]], proc { it }.parameters) + end + + def test_proc_autosplat_with_multiple_args_with_ruby2_keywords_splat_bug_19759 + def self.yielder_ab(splat) + yield([:a, :b], *splat) + end + + res = yielder_ab([[:aa, :bb], Hash.ruby2_keywords_hash({k: :k})]) do |a, b, k:| + [a, b, k] + end + assert_equal([[:a, :b], [:aa, :bb], :k], res) + + def self.yielder(splat) + yield(*splat) + end + res = yielder([ [:a, :b] ]){|a, b, **| [a, b]} + assert_equal([:a, :b], res) + + res = yielder([ [:a, :b], Hash.ruby2_keywords_hash({}) ]){|a, b, **| [a, b]} + assert_equal([[:a, :b], nil], res) + + res = yielder([ [:a, :b], Hash.ruby2_keywords_hash({c: 1}) ]){|a, b, **| [a, b]} + assert_equal([[:a, :b], nil], res) + + res = yielder([ [:a, :b], Hash.ruby2_keywords_hash({}) ]){|a, b, **nil| [a, b]} + assert_equal([[:a, :b], nil], res) + end + + def test_parameters_lambda + assert_equal([], proc {}.parameters(lambda: true)) + assert_equal([], proc {||}.parameters(lambda: true)) + assert_equal([[:req, :a]], proc {|a|}.parameters(lambda: true)) + assert_equal([[:req, :a], [:req, :b]], proc {|a, b|}.parameters(lambda: true)) + assert_equal([[:opt, :a], [:block, :b]], proc {|a=:a, &b|}.parameters(lambda: true)) + assert_equal([[:req, :a], [:opt, :b]], proc {|a, b=:b|}.parameters(lambda: true)) + assert_equal([[:rest, :a]], proc {|*a|}.parameters(lambda: true)) + assert_equal([[:req, :a], [:rest, :b], [:block, :c]], proc {|a, *b, &c|}.parameters(lambda: true)) + assert_equal([[:req, :a], [:rest, :b], [:req, :c]], proc {|a, *b, c|}.parameters(lambda: true)) + assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], proc {|a, *b, c, &d|}.parameters(lambda: true)) + assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], proc {|a, b=:b, *c, d, &e|}.parameters(lambda: true)) + assert_equal([[:req], [:block, :b]], proc {|(a), &b|a}.parameters(lambda: true)) + assert_equal([[:req, :a], [:req, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:req, :f], [:req, :g], [:block, :h]], proc {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters(lambda: true)) + + pr = eval("proc{|"+"(_),"*30+"|}") + assert_empty(pr.parameters(lambda: true).map{|_,n|n}.compact) + + assert_equal([[:opt, :a]], lambda {|a|}.parameters(lambda: false)) + assert_equal([[:opt, :a], [:opt, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:opt, :f], [:opt, :g], [:block, :h]], lambda {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters(lambda: false)) + + assert_equal([[:req]], proc { it }.parameters(lambda: true)) + assert_equal([[:opt]], lambda { it }.parameters(lambda: false)) end def pm0() end @@ -1261,7 +1478,7 @@ class TestProc < Test::Unit::TestCase assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], method(:pmo6).to_proc.parameters) assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], method(:pmo7).to_proc.parameters) assert_equal([[:req], [:block, :b]], method(:pma1).to_proc.parameters) - assert_equal([[:keyrest]], method(:pmk1).to_proc.parameters) + assert_equal([[:keyrest, :**]], method(:pmk1).to_proc.parameters) assert_equal([[:keyrest, :o]], method(:pmk2).to_proc.parameters) assert_equal([[:req, :a], [:keyrest, :o]], method(:pmk3).to_proc.parameters) assert_equal([[:opt, :a], [:keyrest, :o]], method(:pmk4).to_proc.parameters) @@ -1282,15 +1499,19 @@ class TestProc < Test::Unit::TestCase assert_include(EnvUtil.labeled_class(name, Proc).new {}.to_s, name) end - @@line_of_source_location_test = __LINE__ + 1 + @@line_of_source_location_test = [__LINE__ + 1, 2, __LINE__ + 3, 5] def source_location_test a=1, b=2 end def test_source_location - file, lineno = method(:source_location_test).source_location + file, *loc = method(:source_location_test).source_location assert_match(/^#{ Regexp.quote(__FILE__) }$/, file) - assert_equal(@@line_of_source_location_test, lineno, 'Bug #2427') + assert_equal(@@line_of_source_location_test, loc, 'Bug #2427') + + file, *loc = self.class.instance_method(:source_location_test).source_location + assert_match(/^#{ Regexp.quote(__FILE__) }$/, file) + assert_equal(@@line_of_source_location_test, loc, 'Bug #2427') end @@line_of_attr_reader_source_location_test = __LINE__ + 3 @@ -1323,13 +1544,13 @@ class TestProc < Test::Unit::TestCase end def test_block_source_location - exp_lineno = __LINE__ + 3 - file, lineno = block_source_location_test(1, + exp_loc = [__LINE__ + 3, 49, __LINE__ + 4, 49] + file, *loc = block_source_location_test(1, 2, 3) do end assert_match(/^#{ Regexp.quote(__FILE__) }$/, file) - assert_equal(exp_lineno, lineno) + assert_equal(exp_loc, loc) end def test_splat_without_respond_to @@ -1416,6 +1637,10 @@ class TestProc < Test::Unit::TestCase assert_equal(3, b.local_variable_get(:when)) assert_equal(4, b.local_variable_get(:begin)) assert_equal(5, b.local_variable_get(:end)) + + assert_raise_with_message(NameError, /local variable \Wdefault\W/) { + binding.local_variable_get(:default) + } end def test_local_variable_set @@ -1428,6 +1653,274 @@ class TestProc < Test::Unit::TestCase assert_equal(20, b.eval("b")) end + def test_numparam_is_not_local_variables + "foo".tap do + _9 and flunk + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:_9) } + assert_raise(NameError) { binding.local_variable_set(:_9, 1) } + assert_raise(NameError) { binding.local_variable_defined?(:_9) } + "bar".tap do + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:_9) } + assert_raise(NameError) { binding.local_variable_set(:_9, 1) } + assert_raise(NameError) { binding.local_variable_defined?(:_9) } + end + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:_9) } + assert_raise(NameError) { binding.local_variable_set(:_9, 1) } + assert_raise(NameError) { binding.local_variable_defined?(:_9) } + end + + "foo".tap do + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:_9) } + assert_raise(NameError) { binding.local_variable_set(:_9, 1) } + assert_raise(NameError) { binding.local_variable_defined?(:_9) } + "bar".tap do + _9 and flunk + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:_9) } + assert_raise(NameError) { binding.local_variable_set(:_9, 1) } + assert_raise(NameError) { binding.local_variable_defined?(:_9) } + end + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:_9) } + assert_raise(NameError) { binding.local_variable_set(:_9, 1) } + assert_raise(NameError) { binding.local_variable_defined?(:_9) } + end + end + + def test_implicit_parameters_for_numparams + x = x = 1 + assert_raise(NameError) { binding.implicit_parameter_get(:x) } + assert_raise(NameError) { binding.implicit_parameter_defined?(:x) } + + "foo".tap do + _5 and flunk + assert_equal([:_1, :_2, :_3, :_4, :_5], binding.implicit_parameters) + assert_equal("foo", binding.implicit_parameter_get(:_1)) + assert_equal(nil, binding.implicit_parameter_get(:_5)) + assert_raise(NameError) { binding.implicit_parameter_get(:_6) } + assert_raise(NameError) { binding.implicit_parameter_get(:it) } + assert_equal(true, binding.implicit_parameter_defined?(:_1)) + assert_equal(true, binding.implicit_parameter_defined?(:_5)) + assert_equal(false, binding.implicit_parameter_defined?(:_6)) + assert_equal(false, binding.implicit_parameter_defined?(:it)) + "bar".tap do + assert_equal([], binding.implicit_parameters) + assert_raise(NameError) { binding.implicit_parameter_get(:_1) } + assert_raise(NameError) { binding.implicit_parameter_get(:_6) } + assert_raise(NameError) { binding.implicit_parameter_get(:it) } + assert_equal(false, binding.implicit_parameter_defined?(:_1)) + assert_equal(false, binding.implicit_parameter_defined?(:_6)) + assert_equal(false, binding.implicit_parameter_defined?(:it)) + end + assert_equal([:_1, :_2, :_3, :_4, :_5], binding.implicit_parameters) + assert_equal("foo", binding.implicit_parameter_get(:_1)) + assert_equal(nil, binding.implicit_parameter_get(:_5)) + assert_raise(NameError) { binding.implicit_parameter_get(:_6) } + assert_raise(NameError) { binding.implicit_parameter_get(:it) } + assert_equal(true, binding.implicit_parameter_defined?(:_1)) + assert_equal(true, binding.implicit_parameter_defined?(:_5)) + assert_equal(false, binding.implicit_parameter_defined?(:_6)) + assert_equal(false, binding.implicit_parameter_defined?(:it)) + end + + "foo".tap do + assert_equal([], binding.implicit_parameters) + assert_raise(NameError) { binding.implicit_parameter_get(:_1) } + assert_raise(NameError) { binding.implicit_parameter_get(:_6) } + assert_equal(false, binding.implicit_parameter_defined?(:_1)) + assert_equal(false, binding.implicit_parameter_defined?(:_6)) + assert_equal(false, binding.implicit_parameter_defined?(:it)) + "bar".tap do + _5 and flunk + assert_equal([:_1, :_2, :_3, :_4, :_5], binding.implicit_parameters) + assert_equal("bar", binding.implicit_parameter_get(:_1)) + assert_equal(nil, binding.implicit_parameter_get(:_5)) + assert_raise(NameError) { binding.implicit_parameter_get(:_6) } + assert_raise(NameError) { binding.implicit_parameter_get(:it) } + assert_equal(true, binding.implicit_parameter_defined?(:_1)) + assert_equal(true, binding.implicit_parameter_defined?(:_5)) + assert_equal(false, binding.implicit_parameter_defined?(:_6)) + assert_equal(false, binding.implicit_parameter_defined?(:it)) + end + assert_equal([], binding.implicit_parameters) + assert_raise(NameError) { binding.implicit_parameter_get(:_1) } + assert_raise(NameError) { binding.implicit_parameter_get(:_6) } + assert_equal(false, binding.implicit_parameter_defined?(:_1)) + assert_equal(false, binding.implicit_parameter_defined?(:_6)) + assert_equal(false, binding.implicit_parameter_defined?(:it)) + end + end + + def test_it_is_not_local_variable + "foo".tap do + it + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:it) } + assert_equal(false, binding.local_variable_defined?(:it)) + "bar".tap do + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:it) } + assert_equal(false, binding.local_variable_defined?(:it)) + end + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:it) } + assert_equal(false, binding.local_variable_defined?(:it)) + "bar".tap do + it + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:it) } + assert_equal(false, binding.local_variable_defined?(:it)) + end + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:it) } + assert_equal(false, binding.local_variable_defined?(:it)) + end + + "foo".tap do + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:it) } + assert_equal(false, binding.local_variable_defined?(:it)) + "bar".tap do + it + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:it) } + assert_equal(false, binding.local_variable_defined?(:it)) + end + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:it) } + assert_equal(false, binding.local_variable_defined?(:it)) + end + end + + def test_implicit_parameters_for_it + "foo".tap do + it or flunk + assert_equal([:it], binding.implicit_parameters) + assert_equal("foo", binding.implicit_parameter_get(:it)) + assert_raise(NameError) { binding.implicit_parameter_get(:_1) } + assert_equal(true, binding.implicit_parameter_defined?(:it)) + assert_equal(false, binding.implicit_parameter_defined?(:_1)) + "bar".tap do + assert_equal([], binding.implicit_parameters) + assert_raise(NameError) { binding.implicit_parameter_get(:it) } + assert_raise(NameError) { binding.implicit_parameter_get(:_1) } + assert_equal(false, binding.implicit_parameter_defined?(:it)) + assert_equal(false, binding.implicit_parameter_defined?(:_1)) + end + assert_equal([:it], binding.implicit_parameters) + assert_equal("foo", binding.implicit_parameter_get(:it)) + assert_raise(NameError) { binding.implicit_parameter_get(:_1) } + assert_equal(true, binding.implicit_parameter_defined?(:it)) + assert_equal(false, binding.implicit_parameter_defined?(:_1)) + end + + "foo".tap do + assert_equal([], binding.implicit_parameters) + assert_raise(NameError) { binding.implicit_parameter_get(:it) } + assert_raise(NameError) { binding.implicit_parameter_get(:_1) } + assert_equal(false, binding.implicit_parameter_defined?(:it)) + assert_equal(false, binding.implicit_parameter_defined?(:_1)) + "bar".tap do + it or flunk + assert_equal([:it], binding.implicit_parameters) + assert_equal("bar", binding.implicit_parameter_get(:it)) + assert_raise(NameError) { binding.implicit_parameter_get(:_1) } + assert_equal(true, binding.implicit_parameter_defined?(:it)) + assert_equal(false, binding.implicit_parameter_defined?(:_1)) + end + assert_equal([], binding.implicit_parameters) + assert_raise(NameError) { binding.implicit_parameter_get(:it) } + assert_raise(NameError) { binding.implicit_parameter_get(:_1) } + assert_equal(false, binding.implicit_parameter_defined?(:it)) + assert_equal(false, binding.implicit_parameter_defined?(:_1)) + end + end + + def test_implicit_parameters_for_it_complex + "foo".tap do + it = it = "bar" + + assert_equal([], binding.implicit_parameters) + assert_raise(NameError) { binding.implicit_parameter_get(:it) } + assert_equal(false, binding.implicit_parameter_defined?(:it)) + + assert_equal([:it], binding.local_variables) + assert_equal("bar", binding.local_variable_get(:it)) + assert_equal(true, binding.local_variable_defined?(:it)) + end + + "foo".tap do + it or flunk + + assert_equal([:it], binding.implicit_parameters) + assert_equal("foo", binding.implicit_parameter_get(:it)) + assert_equal(true, binding.implicit_parameter_defined?(:it)) + + assert_equal([], binding.local_variables) + assert_raise(NameError) { binding.local_variable_get(:it) } + assert_equal(false, binding.local_variable_defined?(:it)) + end + + "foo".tap do + it or flunk + it = it = "bar" + + assert_equal([:it], binding.implicit_parameters) + assert_equal("foo", binding.implicit_parameter_get(:it)) + assert_equal(true, binding.implicit_parameter_defined?(:it)) + + assert_equal([:it], binding.local_variables) + assert_equal("bar", binding.local_variable_get(:it)) + assert_equal(true, binding.local_variable_defined?(:it)) + end + end + + def test_implicit_parameters_for_it_and_numparams + "foo".tap do + it or flunk + "bar".tap do + _5 and flunk + assert_equal([:_1, :_2, :_3, :_4, :_5], binding.implicit_parameters) + assert_raise(NameError) { binding.implicit_parameter_get(:it) } + assert_equal("bar", binding.implicit_parameter_get(:_1)) + assert_equal(nil, binding.implicit_parameter_get(:_5)) + assert_raise(NameError) { binding.implicit_parameter_get(:_6) } + assert_equal(false, binding.implicit_parameter_defined?(:it)) + assert_equal(true, binding.implicit_parameter_defined?(:_1)) + assert_equal(true, binding.implicit_parameter_defined?(:_5)) + assert_equal(false, binding.implicit_parameter_defined?(:_6)) + end + end + + "foo".tap do + _5 and flunk + "bar".tap do + it or flunk + assert_equal([:it], binding.implicit_parameters) + assert_equal("bar", binding.implicit_parameter_get(:it)) + assert_raise(NameError) { binding.implicit_parameter_get(:_1) } + assert_raise(NameError) { binding.implicit_parameter_get(:_5) } + assert_raise(NameError) { binding.implicit_parameter_get(:_6) } + assert_equal(true, binding.implicit_parameter_defined?(:it)) + assert_equal(false, binding.implicit_parameter_defined?(:_1)) + assert_equal(false, binding.implicit_parameter_defined?(:_5)) + assert_equal(false, binding.implicit_parameter_defined?(:_6)) + end + end + end + + def test_implicit_parameter_invalid_name + message_pattern = /is not an implicit parameter/ + assert_raise_with_message(NameError, message_pattern) { binding.implicit_parameter_defined?(:foo) } + assert_raise_with_message(NameError, message_pattern) { binding.implicit_parameter_get(:foo) } + assert_raise_with_message(NameError, message_pattern) { binding.implicit_parameter_defined?("wrong_implicit_parameter_name_#{rand(10000)}") } + assert_raise_with_message(NameError, message_pattern) { binding.implicit_parameter_get("wrong_implicit_parameter_name_#{rand(10000)}") } + end + def test_local_variable_set_wb assert_ruby_status([], <<-'end;', '[Bug #13605]', timeout: 30) b = binding @@ -1597,18 +2090,24 @@ class TestProc < Test::Unit::TestCase def test_isolate assert_raise_with_message ArgumentError, /\(a\)/ do a = :a - Proc.new{p a}.isolate.call + Proc.new{p a}.isolate end assert_raise_with_message ArgumentError, /\(a\)/ do a = :a 1.times{ - Proc.new{p a}.isolate.call + Proc.new{p a}.isolate } end assert_raise_with_message ArgumentError, /yield/ do - Proc.new{yield}.isolate.call + Proc.new{yield}.isolate + end + + + name = "\u{2603 26a1}" + assert_raise_with_message(ArgumentError, /\(#{name}\)/) do + eval("#{name} = :#{name}; Proc.new {p #{name}}").isolate end # binding @@ -1718,4 +2217,3 @@ class TestProcKeywords < Test::Unit::TestCase assert_raise(ArgumentError) { (f >> g).call(**{})[:a] } end end - |
