-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
196 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
require "spec" | ||
require "tempfile" | ||
|
||
private def build_and_run(code) | ||
code_file = Tempfile.new("exit_spec_code") | ||
code_file.close | ||
|
||
# write code to the temp file | ||
File.write(code_file.path, code) | ||
|
||
binary_file = Tempfile.new("exit_spec_output") | ||
binary_file.close | ||
|
||
`bin/crystal build #{code_file.path.inspect} -o #{binary_file.path.inspect}` | ||
File.exists?(binary_file.path).should be_true | ||
|
||
out_io, err_io = IO::Memory.new, IO::Memory.new | ||
status = Process.run binary_file.path, output: out_io, error: err_io | ||
|
||
{status, out_io.to_s, err_io.to_s} | ||
ensure | ||
File.delete(code_file.path) if code_file | ||
File.delete(binary_file.path) if binary_file | ||
end | ||
|
||
describe "exit" do | ||
it "exits normally with status 0" do | ||
status, _ = build_and_run "exit" | ||
status.success?.should be_true | ||
end | ||
|
||
it "exits with given error code" do | ||
status, _ = build_and_run "exit 42" | ||
status.success?.should be_false | ||
status.exit_code.should eq(42) | ||
end | ||
end | ||
|
||
describe "at_exit" do | ||
it "runs handlers on normal program ending" do | ||
status, output = build_and_run <<-CODE | ||
at_exit do | ||
puts "handler code" | ||
end | ||
CODE | ||
|
||
status.success?.should be_true | ||
output.should eq("handler code\n") | ||
end | ||
|
||
it "runs handlers on explicit program ending" do | ||
status, output = build_and_run <<-'CODE' | ||
at_exit do |exit_code| | ||
puts "handler code, exit code: #{exit_code}" | ||
end | ||
|
||
exit 42 | ||
CODE | ||
|
||
status.exit_code.should eq(42) | ||
output.should eq("handler code, exit code: 42\n") | ||
end | ||
|
||
it "runs handlers in reverse order" do | ||
status, output = build_and_run <<-CODE | ||
at_exit do | ||
puts "first handler code" | ||
end | ||
at_exit do | ||
puts "second handler code" | ||
end | ||
CODE | ||
|
||
status.success?.should be_true | ||
output.should eq <<-OUTPUT | ||
second handler code | ||
first handler code | ||
OUTPUT | ||
end | ||
|
||
it "runs all handlers maximum once" do | ||
status, output = build_and_run <<-CODE | ||
at_exit do | ||
puts "first handler code" | ||
end | ||
at_exit do | ||
puts "second handler code, explicit exit!" | ||
exit | ||
puts "not executed" | ||
end | ||
at_exit do | ||
puts "third handler code" | ||
end | ||
CODE | ||
|
||
status.success?.should be_true | ||
output.should eq <<-OUTPUT | ||
third handler code | ||
second handler code, explicit exit! | ||
first handler code | ||
OUTPUT | ||
end | ||
|
||
it "allow handlers to change the exit code with explicit `exit` call" do | ||
status, output = build_and_run <<-'CODE' | ||
at_exit do |exit_code| | ||
puts "first handler code, exit code: #{exit_code}" | ||
end | ||
|
||
at_exit do | ||
puts "second handler code, re-exiting" | ||
exit 42 | ||
|
||
puts "not executed" | ||
end | ||
|
||
at_exit do |exit_code| | ||
puts "third handler code, exit code: #{exit_code}" | ||
end | ||
CODE | ||
|
||
status.success?.should be_false | ||
status.exit_code.should eq(42) | ||
output.should eq <<-OUTPUT | ||
third handler code, exit code: 0 | ||
second handler code, re-exiting | ||
first handler code, exit code: 42 | ||
OUTPUT | ||
end | ||
|
||
it "allow handlers to change the exit code with explicit `exit` call (2)" do | ||
status, output = build_and_run <<-'CODE' | ||
at_exit do |exit_code| | ||
puts "first handler code, exit code: #{exit_code}" | ||
end | ||
|
||
at_exit do | ||
puts "second handler code, re-exiting" | ||
exit 42 | ||
|
||
puts "not executed" | ||
end | ||
|
||
at_exit do |exit_code| | ||
puts "third handler code, exit code: #{exit_code}" | ||
end | ||
|
||
exit 21 | ||
CODE | ||
|
||
status.success?.should be_false | ||
status.exit_code.should eq(42) | ||
output.should eq <<-OUTPUT | ||
third handler code, exit code: 21 | ||
second handler code, re-exiting | ||
first handler code, exit code: 42 | ||
OUTPUT | ||
end | ||
|
||
it "change final exit code when an handler raises an error" do | ||
status, output, error = build_and_run <<-'CODE' | ||
at_exit do |exit_code| | ||
puts "first handler code, exit code: #{exit_code}" | ||
end | ||
|
||
at_exit do | ||
puts "second handler code, raising" | ||
raise "Raised from at_exit handler!" | ||
|
||
puts "not executed" | ||
end | ||
|
||
at_exit do |exit_code| | ||
puts "third handler code, exit code: #{exit_code}" | ||
end | ||
CODE | ||
|
||
status.success?.should be_false | ||
status.exit_code.should eq(1) | ||
output.should eq <<-OUTPUT | ||
third handler code, exit code: 0 | ||
second handler code, raising | ||
first handler code, exit code: 1 | ||
OUTPUT | ||
error.should eq "Error running at_exit handler: Raised from at_exit handler!\n" | ||
end | ||
end |