summaryrefslogtreecommitdiff
path: root/test/ruby/test_beginendblock.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_beginendblock.rb')
-rw-r--r--test/ruby/test_beginendblock.rb215
1 files changed, 152 insertions, 63 deletions
diff --git a/test/ruby/test_beginendblock.rb b/test/ruby/test_beginendblock.rb
index b5d898d3b6..3706efab52 100644
--- a/test/ruby/test_beginendblock.rb
+++ b/test/ruby/test_beginendblock.rb
@@ -1,98 +1,187 @@
+# frozen_string_literal: false
require 'test/unit'
-require 'tempfile'
-$:.replace([File.dirname(File.expand_path(__FILE__))] | $:)
-require '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("#{q(ruby)} #{q(target)}"){|io|io.read}
- assert_equal(%w(b1 b2-1 b2 main b3-1 b3 b4 e1 e4 e3 e2 e4-2 e4-1 e1-1 e4-1-1), 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
- assert_raises(SyntaxError) do
+ assert_raise_with_message(SyntaxError, /BEGIN is permitted only at toplevel/) do
eval("def foo; BEGIN {}; end")
end
- assert_raises(SyntaxError) do
+ assert_raise_with_message(SyntaxError, /BEGIN is permitted only at toplevel/) do
eval('eval("def foo; BEGIN {}; end")')
end
end
+ def test_begininclass
+ assert_raise_with_message(SyntaxError, /BEGIN is permitted only at toplevel/) do
+ eval("class TestBeginEndBlock; BEGIN {}; end")
+ end
+ end
+
def test_endblockwarn
- ruby = EnvUtil.rubybin
- # Use Tempfile to create temporary file path.
- launcher = Tempfile.new(self.class.name)
- errout = Tempfile.new(self.class.name)
-
- launcher << <<EOF
-errout = ARGV.shift
-STDERR.reopen(File.open(errout, "w"))
-STDERR.sync = true
-Dir.chdir(#{q(DIR)})
-cmd = "\\"#{ruby}\\" \\"endblockwarn.rb\\""
-system(cmd)
-EOF
- launcher.close
- launcherpath = launcher.path
- errout.close
- erroutpath = errout.path
- system("#{q(ruby)} #{q(launcherpath)} #{q(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))
- # expecting Tempfile to unlink launcher and errout file.
+ 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-core:09675]
- ruby = EnvUtil.rubybin
- out = IO.popen("#{q(ruby)} -e 'STDERR.reopen(STDOUT);" \
- "at_exit{raise %[SomethingBad]};" \
- "raise %[SomethingElse]'") {|f|
- f.read
- }
- assert_match /SomethingBad/, out
- assert_match /SomethingElse/, out
+ 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_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_should_propagate_exit_code
+ 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} #{File.dirname(__FILE__)}/suicide.rb"){|f|
- 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
+ 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
+ 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
+ bug5218 = '[ruby-core:43173][Bug #5218]'
+ cmd = [
+ "raise 'X' rescue nil",
+ "nil",
+ "exit(42)",
+ ]
+ %w[at_exit END].each do |ex|
+ out, err, status = EnvUtil.invoke_ruby(cmd.map {|s|["-e", "#{ex} {#{s}}"]}.flatten, "", true, true)
+ 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
- def test_begin_and_eval
- $test_begin_and_eval = :ok
- begin
- eval("BEGIN{$test_begin_and_eval = :ng}\n_/a:a")
- rescue SyntaxError
- x1 = x2 = $test_begin_and_eval
- eval("x2 = $test_begin_and_eval")
+ 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
- assert_equal(:ok, x1)
- assert_equal(:ok, x2)
end
end