Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new AssertionError Exception type #9734

Merged
merged 1 commit into from
Feb 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ Library improvements

* Other improvements

* `assert`, `@assert` now throws an `AssertionError` exception type ([#9734]).

* `convert` now checks for overflow when truncating integers or converting between
signed and unsigned ([#5413]).

Expand Down
7 changes: 7 additions & 0 deletions base/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ type DimensionMismatch <: Exception
end
DimensionMismatch() = DimensionMismatch("")

type AssertionError <: Exception
msg::AbstractString

AssertionError() = new("")
AssertionError(msg) = new(msg)
end

# For passing constants through type inference
immutable Val{T}
end
Expand Down
15 changes: 8 additions & 7 deletions base/error.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,18 @@ systemerror(p, b::Bool) = b ? throw(SystemError(string(p))) : nothing

## assertion functions and macros ##

assert(x) = x ? nothing : error("assertion failed")
macro assert(ex,msgs...)
assert(x) = x ? nothing : throw(AssertionError())
assert(x, msgs...) = x ? nothing : throw(AssertionError(msgs[1]))
macro assert(ex, msgs...)
msg = isempty(msgs) ? ex : msgs[1]
if !isempty(msgs) && isa(msg, Expr)
# message is an expression needing evaluating
msg = :(string("assertion failed: ", $(esc(msg))))
elseif isdefined(Base,:string)
msg = string("assertion failed: ", msg)
msg = :(string($(esc(msg))))
elseif isdefined(Base, :string)
msg = string(msg)
else
# string() might not be defined during bootstrap
msg = :(string("assertion failed: ", $(Expr(:quote,msg))))
msg = :(string($(Expr(:quote,msg))))
end
:($(esc(ex)) ? $(nothing) : error($msg))
:($(esc(ex)) ? $(nothing) : throw(AssertionError($msg)))
end
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ export
ProcessExitedException,
SystemError,
TypeError,
AssertionError,

# Global constants and variables
ARGS,
Expand Down
1 change: 1 addition & 0 deletions base/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ showerror(io::IO, ex::ErrorException) = print(io, ex.msg)
showerror(io::IO, ex::KeyError) = print(io, "KeyError: $(ex.key) not found")
showerror(io::IO, ex::InterruptException) = print(io, "InterruptException:")
showerror(io::IO, ex::ArgumentError) = print(io, "ArgumentError: $(ex.msg)")
showerror(io::IO, ex::AssertionError) = print(io, "AssertionError: $(ex.msg)")

function showerror(io::IO, ex::MethodError)
print(io, "MethodError: ")
Expand Down
10 changes: 7 additions & 3 deletions doc/stdlib/base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -785,11 +785,15 @@ Errors

.. function:: assert(cond, [text])

Raise an error if ``cond`` is false. Also available as the macro ``@assert expr``.
Throw an ``AssertionError`` if ``cond`` is false. Also available as the macro ``@assert expr``.

.. function:: @assert
.. function:: @assert cond [text]

Raise an error if ``cond`` is false. Preferred syntax for writings assertions.
Throw an ``AssertionError`` if ``cond`` is false. Preferred syntax for writings assertions.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was there before, but should be "writing assertions" not "writings assertions"


.. data:: AssertionError

The asserted condition did not evalutate to ``true``.

.. data:: ArgumentError

Expand Down
80 changes: 80 additions & 0 deletions test/misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,83 @@ let bt = backtrace()
@test contains(l, b)
end
end

# test assert() method
@test_throws AssertionError assert(false)
let res = assert(true)
@test res === nothing
end
let
try
assert(false)
@unexpected
catch ex
@test isa(ex, AssertionError)
@test isempty(ex.msg)
end
end
let
try
assert(false, "this is a test")
@unexpected
catch ex
@test isa(ex, AssertionError)
@test ex.msg == "this is a test"
end
end

# test @assert macro
@test_throws AssertionError (@assert 1 == 2)
@test_throws AssertionError (@assert false)
@test_throws AssertionError (@assert false "this is a test")
@test_throws AssertionError (@assert false "this is a test" "another test")
@test_throws AssertionError (@assert false :a)
let
try
@assert 1 == 2
@unexpected
catch ex
@test isa(ex, AssertionError)
@test contains(ex.msg, "1 == 2")
end
end
# test @assert message
let
try
@assert 1 == 2 "this is a test"
@unexpected
catch ex
@test isa(ex, AssertionError)
@test ex.msg == "this is a test"
end
end
# @assert only uses the first message string
let
try
@assert 1 == 2 "this is a test" "this is another test"
@unexpected
catch ex
@test isa(ex, AssertionError)
@test ex.msg == "this is a test"
end
end
# @assert calls string() on second argument
let
try
@assert 1 == 2 :random_object
@unexpected
catch ex
@test isa(ex, AssertionError)
@test !contains(ex.msg, "1 == 2")
@test contains(ex.msg, "random_object")
end
end
# if the second argument is an expression, c
let deepthought(x, y) = 42
try
@assert 1 == 2 string("the answer to the ultimate question: ", deepthought(6,9))
catch ex
@test isa(ex, AssertionError)
@test ex.msg == "the answer to the ultimate question: 42"
end
end