From 1ca84099e7d95258c64ca2bdf835143f2953fc2d Mon Sep 17 00:00:00 2001 From: Mark Kittisopikul Date: Wed, 29 May 2024 01:13:22 -0400 Subject: [PATCH 1/2] Create ZstdError error type. Test known, stable error codes. --- src/CodecZstd.jl | 3 ++- src/compression.jl | 8 ++++---- src/decompression.jl | 8 ++++---- src/libzstd.jl | 13 ++++++++++++ test/runtests.jl | 1 + test/zstderror.jl | 47 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 test/zstderror.jl diff --git a/src/CodecZstd.jl b/src/CodecZstd.jl index 315f5f2..7982319 100644 --- a/src/CodecZstd.jl +++ b/src/CodecZstd.jl @@ -4,7 +4,8 @@ export ZstdCompressor, ZstdCompressorStream, ZstdDecompressor, - ZstdDecompressorStream + ZstdDecompressorStream, + ZstdError import TranscodingStreams: TranscodingStreams, diff --git a/src/compression.jl b/src/compression.jl index 36b93a4..2e12066 100644 --- a/src/compression.jl +++ b/src/compression.jl @@ -48,7 +48,7 @@ end function TranscodingStreams.initialize(codec::ZstdCompressor) code = initialize!(codec.cstream, codec.level) if iserror(code) - zstderror(codec.cstream, code) + throw(ZstdError(code)) end return end @@ -57,7 +57,7 @@ function TranscodingStreams.finalize(codec::ZstdCompressor) if codec.cstream.ptr != C_NULL code = free!(codec.cstream) if iserror(code) - zstderror(codec.cstream, code) + throw(ZstdError(code)) end codec.cstream.ptr = C_NULL end @@ -67,7 +67,7 @@ end function TranscodingStreams.startproc(codec::ZstdCompressor, mode::Symbol, error::Error) code = reset!(codec.cstream, 0 #=unknown source size=#) if iserror(code) - error[] = ErrorException("zstd error") + error[] = ZstdError(code) return :error end return :ok @@ -89,7 +89,7 @@ function TranscodingStreams.process(codec::ZstdCompressor, input::Memory, output Δin = Int(cstream.ibuffer.pos) Δout = Int(cstream.obuffer.pos) if iserror(code) - error[] = ErrorException("zstd error") + error[] = ZstdErorr(code) return Δin, Δout, :error else return Δin, Δout, input.size == 0 && code == 0 ? :end : :ok diff --git a/src/decompression.jl b/src/decompression.jl index 6767634..dfe53fb 100644 --- a/src/decompression.jl +++ b/src/decompression.jl @@ -36,7 +36,7 @@ end function TranscodingStreams.initialize(codec::ZstdDecompressor) code = initialize!(codec.dstream) if iserror(code) - zstderror(codec.dstream, code) + throw(ZstdError(code)) end return end @@ -45,7 +45,7 @@ function TranscodingStreams.finalize(codec::ZstdDecompressor) if codec.dstream.ptr != C_NULL code = free!(codec.dstream) if iserror(code) - zstderror(codec.dstream, code) + throw(ZstdError(code)) end codec.dstream.ptr = C_NULL end @@ -55,7 +55,7 @@ end function TranscodingStreams.startproc(codec::ZstdDecompressor, mode::Symbol, error::Error) code = reset!(codec.dstream) if iserror(code) - error[] = ErrorException("zstd error") + error[] = ZstdError(code) return :error end return :ok @@ -73,7 +73,7 @@ function TranscodingStreams.process(codec::ZstdDecompressor, input::Memory, outp Δin = Int(dstream.ibuffer.pos) Δout = Int(dstream.obuffer.pos) if iserror(code) - error[] = ErrorException("zstd error") + error[] = ZstdErorr(code) return Δin, Δout, :error else if code == 0 diff --git a/src/libzstd.jl b/src/libzstd.jl index 9906b2b..471e94d 100644 --- a/src/libzstd.jl +++ b/src/libzstd.jl @@ -5,11 +5,24 @@ function iserror(code::Csize_t) return LibZstd.ZSTD_isError(code) != 0 end +# deprecated error reporting function zstderror(stream, code::Csize_t) + zstderror(code) +end +function zstderror(code::Integer) ptr = LibZstd.ZSTD_getErrorName(code) error("zstd error: ", unsafe_string(ptr)) end +# new error reporting +struct ZstdError <: Exception + code::Csize_t +end +ZstdError() = ZstdError(typemax(Csize_t)) +function Base.show(io::IO, e::ZstdError) + print(io, "ZstdError: ", unsafe_string(LibZstd.ZSTD_getErrorName(e.code))) +end + function max_clevel() return LibZstd.ZSTD_maxCLevel() end diff --git a/test/runtests.jl b/test/runtests.jl index cdb1f64..c21596a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -45,4 +45,5 @@ Random.seed!(1234) TranscodingStreams.test_roundtrip_transcode(ZstdCompressor, ZstdDecompressor) include("compress_endOp.jl") + include("zstderror.jl") end diff --git a/test/zstderror.jl b/test/zstderror.jl new file mode 100644 index 0000000..c85481c --- /dev/null +++ b/test/zstderror.jl @@ -0,0 +1,47 @@ +using Test +using CodecZstd: ZstdError + +@static if VERSION ≥ v"1.8" +@testset "ZSTD Errors" begin + @test_throws "ZstdError: No error detected" throw(ZstdError(0)) + @test_throws "ZstdError: Error (generic)" throw(ZstdError(18446744073709551615)) + @test_throws "ZstdError: Unknown frame descriptor" throw(ZstdError(18446744073709551606)) + @test_throws "ZstdError: Version not supported" throw(ZstdError(18446744073709551604)) + @test_throws "ZstdError: Unsupported frame parameter" throw(ZstdError(18446744073709551602)) + @test_throws "ZstdError: Frame requires too much memory for decoding" throw(ZstdError(18446744073709551600)) + @test_throws "ZstdError: Data corruption detected" throw(ZstdError(18446744073709551596)) + @test_throws "ZstdError: Restored data doesn't match checksum" throw(ZstdError(18446744073709551594)) + @test_throws "ZstdError: Header of Literals' block doesn't respect format specification" throw(ZstdError(18446744073709551592)) + @test_throws "ZstdError: Dictionary is corrupted" throw(ZstdError(18446744073709551586)) + @test_throws "ZstdError: Dictionary mismatch" throw(ZstdError(18446744073709551584)) + @test_throws "ZstdError: Cannot create Dictionary from provided samples" throw(ZstdError(18446744073709551582)) + @test_throws "ZstdError: Unsupported parameter" throw(ZstdError(18446744073709551576)) + @test_throws "ZstdError: Unsupported combination of parameters" throw(ZstdError(18446744073709551575)) + @test_throws "ZstdError: Parameter is out of bound" throw(ZstdError(18446744073709551574)) + @test_throws "ZstdError: tableLog requires too much memory : unsupported" throw(ZstdError(18446744073709551572)) + @test_throws "ZstdError: Unsupported max Symbol Value : too large" throw(ZstdError(18446744073709551570)) + @test_throws "ZstdError: Specified maxSymbolValue is too small" throw(ZstdError(18446744073709551568)) + @test_throws "ZstdError: pledged buffer stability condition is not respected" throw(ZstdError(18446744073709551566)) + @test_throws "ZstdError: Operation not authorized at current processing stage" throw(ZstdError(18446744073709551556)) + @test_throws "ZstdError: Context should be init first" throw(ZstdError(18446744073709551554)) + @test_throws "ZstdError: Allocation error : not enough memory" throw(ZstdError(18446744073709551552)) + @test_throws "ZstdError: workSpace buffer is not large enough" throw(ZstdError(18446744073709551550)) + @test_throws "ZstdError: Destination buffer is too small" throw(ZstdError(18446744073709551546)) + @test_throws "ZstdError: Src size is incorrect" throw(ZstdError(18446744073709551544)) + @test_throws "ZstdError: Operation on NULL destination buffer" throw(ZstdError(18446744073709551542)) + @test_throws "ZstdError: Operation made no progress over multiple calls, due to output buffer being full" throw(ZstdError(18446744073709551536)) + @test_throws "ZstdError: Operation made no progress over multiple calls, due to input being empty" throw(ZstdError(18446744073709551534)) +end +end + +# Use the following function to print the tests above +function print_error_tests() + err_codes = [0, 1, 10, 12, 14, 16, 20, 22, 24, 30, 32, 34, 40, 41, 42, 44, 46, 48, 50, 60, 62, 64, 66, 70, 72, 74, 80, 82]; + println("@testset \"ZSTD Errors\" begin") + for err_code in err_codes + code = typemax(Csize_t)-err_code+1 + println(" @test_throws \"" * string(CodecZstd.ZstdError(typemax(Csize_t) - err_code + 1)) * "\" throw(ZstdError($code))") + end + println("end") +end + From 7d8e64c3c9ad4c974d5924dd23ae01c46c36a2eb Mon Sep 17 00:00:00 2001 From: Mark Kittisopikul Date: Wed, 29 May 2024 01:23:41 -0400 Subject: [PATCH 2/2] Fix typo --- src/decompression.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/decompression.jl b/src/decompression.jl index 49eac6b..a169068 100644 --- a/src/decompression.jl +++ b/src/decompression.jl @@ -77,7 +77,7 @@ function TranscodingStreams.process(codec::ZstdDecompressor, input::Memory, outp Δin = Int(dstream.ibuffer.pos) Δout = Int(dstream.obuffer.pos) if iserror(code) - error[] = ZstdErorr(code) + error[] = ZstdError(code) return Δin, Δout, :error else if code == 0