diff options
Diffstat (limited to 'test/ruby/test_beginendblock.rb')
| -rw-r--r-- | test/ruby/test_beginendblock.rb | 239 |
1 files changed, 131 insertions, 108 deletions
diff --git a/test/ruby/test_beginendblock.rb b/test/ruby/test_beginendblock.rb index 85b2afb139..3706efab52 100644 --- a/test/ruby/test_beginendblock.rb +++ b/test/ruby/test_beginendblock.rb @@ -1,152 +1,121 @@ +# frozen_string_literal: false require 'test/unit' -require 'tempfile' -require 'timeout' -require_relative 'envutil' +EnvUtil.suppress_warning {require 'continuation'} class TestBeginEndBlock < Test::Unit::TestCase DIR = File.dirname(File.expand_path(__FILE__)) - def q(content) - "\"#{content}\"" - end - def test_beginendblock - ruby = EnvUtil.rubybin target = File.join(DIR, 'beginmainend.rb') - result = IO.popen([ruby, target]){|io|io.read} - assert_equal(%w(b1 b2-1 b2 main b3-1 b3 b4 e1 e1-1 e4 e4-2 e4-1 e4-1-1 e3 e2), result.split) - - Tempfile.create(self.class.name) {|input| - inputpath = input.path - result = IO.popen([ruby, "-n", "-eBEGIN{p :begin}", "-eEND{p :end}", inputpath]){|io|io.read} - assert_equal(%w(:begin), result.split) - result = IO.popen([ruby, "-p", "-eBEGIN{p :begin}", "-eEND{p :end}", inputpath]){|io|io.read} - assert_equal(%w(:begin), result.split) - input.puts "foo\nbar" - input.close - result = IO.popen([ruby, "-n", "-eBEGIN{p :begin}", "-eEND{p :end}", inputpath]){|io|io.read} - assert_equal(%w(:begin :end), result.split) - result = IO.popen([ruby, "-p", "-eBEGIN{p :begin}", "-eEND{p :end}", inputpath]){|io|io.read} - assert_equal(%w(:begin foo bar :end), result.split) - } + assert_in_out_err([target], '', %w(b1 b2-1 b2 main b3-1 b3 b4 e1 e1-1 e4 e4-2 e4-1 e4-1-1 e3 e2)) + + assert_in_out_err(["-n", "-eBEGIN{p :begin}", "-eEND{p :end}"], '', %w(:begin)) + assert_in_out_err(["-p", "-eBEGIN{p :begin}", "-eEND{p :end}"], '', %w(:begin)) + assert_in_out_err(["-n", "-eBEGIN{p :begin}", "-eEND{p :end}"], "foo\nbar\n", %w(:begin :end)) + assert_in_out_err(["-p", "-eBEGIN{p :begin}", "-eEND{p :end}"], "foo\nbar\n", %w(:begin foo bar :end)) + end + + def test_endblock_variable + assert_in_out_err(["-n", "-ea = :ok", "-eEND{p a}"], "foo\n", %w(:ok)) + assert_in_out_err(["-p", "-ea = :ok", "-eEND{p a}"], "foo\n", %w(foo :ok)) end def test_begininmethod - e = assert_raise(SyntaxError) do + assert_raise_with_message(SyntaxError, /BEGIN is permitted only at toplevel/) do eval("def foo; BEGIN {}; end") end - assert_match(/BEGIN is permitted only at toplevel/, e.message) - e = assert_raise(SyntaxError) do + assert_raise_with_message(SyntaxError, /BEGIN is permitted only at toplevel/) do eval('eval("def foo; BEGIN {}; end")') end - assert_match(/BEGIN is permitted only at toplevel/, e.message) end def test_begininclass - e = assert_raise(SyntaxError) do + assert_raise_with_message(SyntaxError, /BEGIN is permitted only at toplevel/) do eval("class TestBeginEndBlock; BEGIN {}; end") end - assert_match(/BEGIN is permitted only at toplevel/, e.message) end def test_endblockwarn - ruby = EnvUtil.rubybin - # Use Tempfile to create temporary file path. - Tempfile.create(self.class.name) {|launcher| - Tempfile.create(self.class.name) {|errout| - - launcher << <<EOF -# -*- coding: #{ruby.encoding.name} -*- -errout = ARGV.shift -STDERR.reopen(File.open(errout, "w")) -STDERR.sync = true -Dir.chdir(#{q(DIR)}) -system("#{ruby}", "endblockwarn_rb") -EOF - launcher.close - launcherpath = launcher.path - errout.close - erroutpath = errout.path - system(ruby, launcherpath, erroutpath) - expected = <<EOW -endblockwarn_rb:2: warning: END in method; use at_exit -(eval):2: warning: END in method; use at_exit -EOW - assert_equal(expected, File.read(erroutpath)) - } - } + assert_in_out_err([], "#{<<~"begin;"}#{<<~'end;'}", [], ['-:2: warning: END in method; use at_exit']) + begin; + def end1 + END {} + end + end; + end + + def test_endblockwarn_in_eval + assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", [], ['test.rb:1: warning: END in method; use at_exit']) + begin; + eval <<-EOE, nil, "test.rb", 0 + def end2 + END {} + end + EOE + end; end def test_raise_in_at_exit - ruby = EnvUtil.rubybin - out = IO.popen([ruby, '-e', 'STDERR.reopen(STDOUT)', - '-e', 'at_exit{raise %[SomethingBad]}', - '-e', 'raise %[SomethingElse]']) {|f| - f.read - } - assert_match(/SomethingBad/, out, "[ruby-core:9675]") - assert_match(/SomethingElse/, out, "[ruby-core:9675]") + args = ['-e', 'at_exit{raise %[SomethingBad]}', + '-e', 'raise %[SomethingElse]'] + expected = [:*, /SomethingBad/, :*, /SomethingElse/, :*] + status = assert_in_out_err(args, '', [], expected, "[ruby-core:9675]") + assert_not_predicate(status, :success?) end - def test_should_propagate_exit_code + def test_exitcode_in_at_exit + bug8501 = '[ruby-core:55365] [Bug #8501]' + args = ['-e', 'o = Object.new; def o.inspect; raise "[Bug #8501]"; end', + '-e', 'at_exit{o.nope}'] + status = assert_in_out_err(args, '', [], /undefined method 'nope'/, bug8501) + assert_not_predicate(status, :success?, bug8501) + end + + def test_propagate_exit_code ruby = EnvUtil.rubybin assert_equal false, system(ruby, '-e', 'at_exit{exit 2}') assert_equal 2, $?.exitstatus assert_nil $?.termsig end - def test_should_propagate_signaled - ruby = EnvUtil.rubybin - out = IO.popen( - [ruby, - '-e', 'STDERR.reopen(STDOUT)', - '-e', 'at_exit{Process.kill(:INT, $$); sleep 5 }']) {|f| - timeout(10) { - f.read - } - } - assert_match(/Interrupt$/, out) + def test_propagate_signaled + status = assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", [], /Interrupt$/) + begin; + trap(:INT, "DEFAULT") + at_exit{Process.kill(:INT, $$)} + end; Process.kill(0, 0) rescue return # check if signal works - assert_nil $?.exitstatus - assert_equal Signal.list["INT"], $?.termsig + assert_nil status.exitstatus + assert_equal Signal.list["INT"], status.termsig end def test_endblock_raise - ruby = EnvUtil.rubybin - out = IO.popen( - [ruby, - '-e', 'class C; def write(x); puts x; STDOUT.flush; sleep 0.01; end; end', - '-e', '$stderr = C.new', - '-e', 'END {raise "e1"}; END {puts "e2"}', - '-e', 'END {raise "e3"}; END {puts "e4"}', - '-e', 'END {raise "e5"}; END {puts "e6"}']) {|f| - Thread.new {sleep 5; Process.kill :KILL, f.pid} - f.read - } - assert_match(/e1/, out) - assert_match(/e6/, out) + assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", %w(e6 e4 e2), [:*, /e5/, :*, /e3/, :*, /e1/, :*]) + begin; + END {raise "e1"}; END {puts "e2"} + END {raise "e3"}; END {puts "e4"} + END {raise "e5"}; END {puts "e6"} + end; end def test_nested_at_exit - Tempfile.create(["test_nested_at_exit_", ".rb"]) {|t| - t.puts "at_exit { puts :outer0 }" - t.puts "at_exit { puts :outer1_begin; at_exit { puts :inner1 }; puts :outer1_end }" - t.puts "at_exit { puts :outer2_begin; at_exit { puts :inner2 }; puts :outer2_end }" - t.puts "at_exit { puts :outer3 }" - t.flush - - expected = [ "outer3", - "outer2_begin", - "outer2_end", - "inner2", - "outer1_begin", - "outer1_end", - "inner1", - "outer0" ] - - assert_in_out_err(t.path, "", expected, [], "[ruby-core:35237]") - } + expected = [ "outer3", + "outer2_begin", + "outer2_end", + "inner2", + "outer1_begin", + "outer1_end", + "inner1", + "outer0" ] + + assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", expected, [], "[ruby-core:35237]") + begin; + at_exit { puts :outer0 } + at_exit { puts :outer1_begin; at_exit { puts :inner1 }; puts :outer1_end } + at_exit { puts :outer2_begin; at_exit { puts :inner2 }; puts :outer2_end } + at_exit { puts :outer3 } + end; end def test_rescue_at_exit @@ -161,4 +130,58 @@ EOW assert_equal(["", "", 42], [out, err, status.exitstatus], "#{bug5218}: #{ex}") end end + + def test_callcc_at_exit + omit 'requires callcc support' unless respond_to?(:callcc) + + bug9110 = '[ruby-core:58329][Bug #9110]' + assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}", bug9110) + begin; + require "continuation" + c = nil + at_exit { c.call } + at_exit { callcc {|_c| c = _c } } + end; + end + + def test_errinfo_at_exit + bug12302 = '[ruby-core:75038] [Bug #12302]' + assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", %w[2:exit 1:exit], [], bug12302) + begin; + at_exit do + puts "1:#{$!}" + end + + at_exit do + puts "2:#{$!}" + raise 'x' rescue nil + end + + at_exit do + exit + end + end; + end + + if defined?(fork) + def test_internal_errinfo_at_exit + # TODO: use other than break-in-fork to throw an internal + # error info. + error, pid, status = IO.pipe do |r, w| + pid = fork do + r.close + STDERR.reopen(w) + at_exit do + $!.class + end + break + end + w.close + [r.read, *Process.wait2(pid)] + end + assert_not_predicate(status, :success?) + assert_not_predicate(status, :signaled?) + assert_match(/unexpected break/, error) + end + end end |
