Skip to content

Commit

Permalink
Tests for exception stacks and task switching
Browse files Browse the repository at this point in the history
* Test exceptions are preserved across task switches.
* Test rethrow() and rethrow(exc) preserve backtraces as expected
  across task switches.
* Arrange exception tests into proper testsets
  • Loading branch information
c42f committed Sep 18, 2018
1 parent 6d8f1bc commit b853caf
Showing 1 changed file with 95 additions and 42 deletions.
137 changes: 95 additions & 42 deletions test/exceptions.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Test

function test_exc_stack()
@testset "Exception stack nesting" begin
# Basic exception stack handling
try
error("A")
Expand Down Expand Up @@ -30,6 +30,7 @@ function test_exc_stack()
@test stack[1][1].msg == "RootCause"
@test stack[2][1].msg == "B"
end
# Stack pops correctly
stack = Base.catch_stack()
@test length(stack) == 1
@test stack[1][1].msg == "RootCause"
Expand All @@ -39,29 +40,31 @@ function test_exc_stack()
error("A")
catch
@test length(Base.catch_stack()) == 1
1
end
val
end

function test_exc_stack_tailpos()
# exercise lowering code path for tail position
try
error("A")
catch
@test length(Base.catch_stack()) == 1
@test val == 1
function test_exc_stack_tailpos()
# exercise lowering code path for tail position
try
error("A")
catch
length(Base.catch_stack())
end
end
@test test_exc_stack_tailpos() == 1
@test length(Base.catch_stack()) == 0
end

# test that exception stack is correctly on return / break / goto
function test_exc_stack_catch_return()
try
error("A")
catch
@test length(Base.catch_stack()) == 1
return
@testset "Exception stacks and gotos" begin
function test_exc_stack_catch_return()
try
error("A")
catch
@test length(Base.catch_stack()) == 1
return
end
end
end
function test_exc_stack_catch_break()
test_exc_stack_catch_return()
for i=1:1
try
error("A")
Expand All @@ -85,41 +88,91 @@ function test_exc_stack_catch_break()
@goto outofcatch
end
@label outofcatch
@test length(Base.catch_stack()) == 0
end

function test_exc_stack_deep(n)
# Generate deep exception stack with recursive handlers
# Note that if you let this overflow the program stack (not the exception
# stack) julia will crash. See #28577
n != 1 || error("RootCause")
try
test_exc_stack_deep(n-1)
catch
error("n==$n")
@testset "Deep exception stacks" begin
function test_exc_stack_deep(n)
# Generate deep exception stack with recursive handlers
# Note that if you let this overflow the program stack (not the exception
# stack) julia will crash. See #28577
n != 1 || error("RootCause")
try
test_exc_stack_deep(n-1)
catch
error("n==$n")
end
end
@test try
test_exc_stack_deep(100)
catch
length(Base.catch_stack())
end == 100
@test length(Base.catch_stack()) == 0
end

function test_exc_stack_yield()
# Regression test for #12485
@testset "Exception stacks and Task switching" begin
# See #12485
try
error("A")
catch
yield()
t = @task try
error("B")
catch ex
ex
end
yield(t)
@test t.state == :done
@test t.result == ErrorException("B")
# Task exception state is preserved around task switches
@test length(Base.catch_stack()) == 1
@test Base.catch_stack()[1][1] == ErrorException("A")
end
end

@testset "Exception stacks" begin
test_exc_stack()
test_exc_stack_tailpos()
test_exc_stack_catch_return()
@test length(Base.catch_stack()) == 0
test_exc_stack_catch_break()
# test rethrow() rethrows correct state
bt = []
try
test_exc_stack_deep(100)
catch
@test length(Base.catch_stack()) == 100
try
error("A")
catch
bt = catch_backtrace()
t = @task try
error("B")
catch ex
ex
end
yield(t)
@test t.state == :done
@test t.result == ErrorException("B")
@test bt == catch_backtrace()
rethrow()
end
catch exc
@test exc == ErrorException("A")
@test bt == catch_backtrace()
end
@test length(Base.catch_stack()) == 0
# test rethrow with argument
bt = []
try
try
error("A")
catch
t = @task try
error("B")
catch ex
ex
end
yield(t)
@test t.state == :done
@test t.result == ErrorException("B")
bt = catch_backtrace()
rethrow(ErrorException("C"))
end
catch exc
@test exc == ErrorException("C")
@test bt == catch_backtrace()
end
test_exc_stack_yield()
@test length(Base.catch_stack()) == 0
end

0 comments on commit b853caf

Please sign in to comment.