Skip to content
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: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "FileCheck"
uuid = "4e644321-382b-4b05-b0b6-5d23c3d944fb"
authors = ["Tim Besard <[email protected]>"]
version = "1.0"
version = "1.1"

[deps]
LLVM_jll = "86de99a1-58d6-5da7-8064-bd56ce2e322c"
Expand Down
39 changes: 34 additions & 5 deletions src/FileCheck.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ function filecheck_exe(; adjust_PATH::Bool=true, adjust_LIBPATH::Bool=true)
end

function filecheck(f, input;
throws::Union{Nothing, Type{<:Exception}}=nothing,
match_full_lines::Bool=false,
strict_whitespace::Bool=false,
ignore_case::Bool=false,
Expand All @@ -50,14 +51,33 @@ function filecheck(f, input;
read(pipe, String)
end
result = nothing
thrown = false
io = IOContext(pipe)
stats = redirect_stdio(; stdout=io, stderr=io) do
redirect_stdio(; stdout=io, stderr=io) do
put!(pipe_initialized, nothing)
result = f(input)
if throws !== nothing
try
result = f(input)
catch e
e isa throws || rethrow()
thrown = true
Base.display_error(io, e, catch_backtrace())
end
else
result = f(input)
end
end
if result !== nothing
println(io)
print(io, result)
if throws !== nothing
if !thrown
close(pipe.in)
fetch(reader)
error("Expected $throws to be thrown, but no exception was thrown")
end
else
if result !== nothing
println(io)
print(io, result)
end
end
close(pipe.in)
output = fetch(reader)
Expand Down Expand Up @@ -228,6 +248,10 @@ These are forwarded to LLVM's FileCheck as CLI flags:
- `check_prefixes::Vector{String}`: Use custom check prefixes (`--check-prefixes`).
- `defines::Dict{String,String}`: Define FileCheck variables (`-Dkey=value`).
- `allow_empty::Bool`: Allow empty check files (`--allow-empty`).
- `throws::Type{<:Exception}`: Expect the expression to throw an exception of this type.
The error and backtrace are printed in standard Julia format and can be verified with
`@check*` directives. Raises an error if no exception is thrown; re-throws if the wrong
type is caught.

# Examples

Expand All @@ -248,6 +272,11 @@ end
@check literal=true "foo {{bar}}"
print("foo {{bar}}")
end

@test @filecheck throws=ArgumentError begin
@check "ArgumentError: bad"
throw(ArgumentError("bad"))
end
```
"""
macro filecheck(args...)
Expand Down
41 changes: 41 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,47 @@ end
end
end

@testset "throws" begin
# Basic: catch expected exception, verify error message
@test @filecheck throws=ErrorException begin
@check "ERROR: TestError"
error("TestError")
end

# Verify backtrace is included
@test @filecheck throws=ErrorException begin
@check "ERROR: TestError"
@check "Stacktrace:"
error("TestError")
end

# ArgumentError type
@test @filecheck throws=ArgumentError begin
@check "ArgumentError: bad arg"
throw(ArgumentError("bad arg"))
end

# Output before exception is also captured
@test @filecheck throws=ErrorException begin
@check "before"
@check "ERROR: boom"
println("before")
error("boom")
end

# No exception thrown when expected → error
@test_throws "no exception was thrown" @filecheck throws=ErrorException begin
@check "hello"
"hello"
end

# Wrong exception type → rethrown
@test_throws ArgumentError @filecheck throws=ErrorException begin
@check "hello"
throw(ArgumentError("wrong type"))
end
end

@testset "conditional checks" begin
# cond=true: check is included
@test @filecheck begin
Expand Down