Skip to content

Commit

Permalink
Improve error message on wrong usage of @check
Browse files Browse the repository at this point in the history
Previously, wrong usage such as

```
@check function foo(i=1)
    i isa Int
end
```

would throw a very bad (i.e., hard to interpret) error.
With this, the user gets a clearer & more actionable error that they
must pass a `Possibility` object instead.
  • Loading branch information
Seelengrab committed Feb 24, 2024
1 parent a89fdc0 commit 5082b3f
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 3 deletions.
14 changes: 12 additions & 2 deletions src/api.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,21 @@ function example(gen::Data.Possibility{T}, n::Integer; tries=100_000) where {T}
res
end

@noinline function fail_typecheck(@nospecialize(x), var::Symbol)
argtype = x isa Type ? Type{x} : typeof(x)
throw(ArgumentError("Can't `produce` from objects of type `$argtype` for argument `$var`, `@check` requires arguments of type `Possibility`!"))
end

function kw_to_produce(tc::Symbol, kwargs)
res = Expr(:block)
rettup = Expr(:tuple)

for e in kwargs
name, call = e.args
ass = :($name = $Data.produce($call, $tc))
obj = gensym(name)
argtypecheck = :($obj = $call; $obj isa $Data.Possibility || $fail_typecheck($obj, $(QuoteNode(name))))
push!(res.args, argtypecheck)
ass = :($name = $Data.produce($obj, $tc))
push!(res.args, ass)
push!(rettup.args, :($name = $name))
end
Expand Down Expand Up @@ -202,7 +210,9 @@ function check_func(e::Expr, tsargs)
end

function argtypes(T)
T === Union{} && throw(ArgumentError("Can't `produce` from a Type, did you mean to pass an instance?"))
# if we get this here, it means the generator will throw
# in which case we can't report anything anyway, so return the empty string
T === Union{} && return ""
T = Base.unwrap_unionall(T)
if T.name == @NamedTuple{}.name
# normalize to `Tuple`
Expand Down
16 changes: 15 additions & 1 deletion src/testset.jl
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,16 @@ record_name(sr::SuppositionReport) = sr.record_base * "_" * sr.description
struct InvalidInvocation <: Exception
res::Test.Result
end
Base.showerror(io::IO, ii::InvalidInvocation) = (print(io, "InvalidInvocation: Can't record results from `@test` to this kind of TestSet!"); show(io, ii.res))
function Base.showerror(io::IO, ii::InvalidInvocation)
print(io, "InvalidIncovation: ")
msg = if ii.res isa Test.Error
"Got an error from outside the testsuite!"
else
"Can't record results from `@test` to this kind of TestSet!"
end
println(io, msg)
show(io, ii.res)
end
Test.record(::SuppositionReport, res::Test.Result) = throw(InvalidInvocation(res))

Test.record(sr::SuppositionReport, ts::TestState) = if !isnothing(sr.final_state)
Expand All @@ -207,6 +216,11 @@ end
function Test.finish(sr::SuppositionReport)
sr.time_end = Some(time())

# if the report doesn't have a result, we probably got
# an error outside of the testsuite somewhere, somehow
# either way, trying to print a nonexistent result
# can't be done, so just return instead
isnothing(sr.result) && return sr
res = @something(sr.result)

if sr.verbose
Expand Down
26 changes: 26 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,32 @@ const verb = VERSION.major == 1 && VERSION.minor < 11
i < high+1
end
end

@testset "Wrong usage" begin
int_err = ArgumentError("Can't `produce` from objects of type `Type{$Int}` for argument `i`, `@check` requires arguments of type `Possibility`!")
err = try
@check record=false function foo(i=Int)
i isa Int
end
catch e
e
end
@test err isa Supposition.InvalidInvocation
@test err.res isa Test.Error
@test err.res.value == string(int_err)

one_err = ArgumentError("Can't `produce` from objects of type `$Int` for argument `i`, `@check` requires arguments of type `Possibility`!")
err = try
@check record=false function foo(i=1)
i isa Int
end
catch e
e
end
@test err isa Supposition.InvalidInvocation
@test err.res isa Test.Error
@test err.res.value == string(one_err)
end
end

@testset "@composed API" begin
Expand Down

0 comments on commit 5082b3f

Please sign in to comment.