From 019f8e11659fde638a181c2889b218cf901b9b03 Mon Sep 17 00:00:00 2001 From: nhz2 Date: Sun, 2 Feb 2025 17:21:49 -0500 Subject: [PATCH] document and test windowbits option --- src/compression.jl | 12 ++++----- src/decompression.jl | 6 ++--- test/runtests.jl | 58 ++++++++++++++++++++++++++++++++------------ 3 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/compression.jl b/src/compression.jl index d40bab5..2492c85 100644 --- a/src/compression.jl +++ b/src/compression.jl @@ -24,8 +24,8 @@ Create a gzip compression codec. Arguments --------- -- `level`: compression level (-1..9) -- `windowbits`: size of history buffer (9..15) +- `level` (-1..9): compression level. 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). -1 requests a default compromise between speed and compression (currently equivalent to level 6). +- `windowbits` (9..15): size of history buffer is `2^windowbits`. !!! warning `serialize` and `deepcopy` will not work with this codec due to stored raw pointers. @@ -72,8 +72,8 @@ Create a zlib compression codec. Arguments --------- -- `level`: compression level (-1..9) -- `windowbits`: size of history buffer (9..15) +- `level` (-1..9): compression level. 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). -1 requests a default compromise between speed and compression (currently equivalent to level 6). +- `windowbits` (9..15): size of history buffer is `2^windowbits`. !!! warning `serialize` and `deepcopy` will not work with this codec due to stored raw pointers. @@ -120,8 +120,8 @@ Create a deflate compression codec. Arguments --------- -- `level`: compression level (-1..9) -- `windowbits`: size of history buffer (9..15) +- `level` (-1..9): compression level. 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). -1 requests a default compromise between speed and compression (currently equivalent to level 6). +- `windowbits` (9..15): size of history buffer is `2^windowbits`. !!! warning `serialize` and `deepcopy` will not work with this codec due to stored raw pointers. diff --git a/src/decompression.jl b/src/decompression.jl index e20792e..67bff25 100644 --- a/src/decompression.jl +++ b/src/decompression.jl @@ -25,7 +25,7 @@ If `gziponly` is `false`, this codec can decompress the zlib format as well. Arguments --------- -- `windowbits`: size of history buffer (8..15) +- `windowbits` (8..15): Changing `windowbits` from its default of 15 will prevent decoding data using a history buffer larger than `2^windowbits`. - `gziponly`: flag to inactivate data format detection !!! warning @@ -69,7 +69,7 @@ Create a zlib decompression codec. Arguments --------- -- `windowbits`: size of history buffer (8..15) +- `windowbits` (8..15): Changing `windowbits` from its default of 15 will prevent decoding data using a history buffer larger than `2^windowbits`. !!! warning `serialize` and `deepcopy` will not work with this codec due to stored raw pointers. @@ -112,7 +112,7 @@ Create a deflate decompression codec. Arguments --------- -- `windowbits`: size of history buffer (8..15) +- `windowbits` (8..15): Changing `windowbits` from its default of 15 will prevent decoding data using a history buffer larger than `2^windowbits`. !!! warning `serialize` and `deepcopy` will not work with this codec due to stored raw pointers. diff --git a/test/runtests.jl b/test/runtests.jl index c2ba1b5..5572537 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -33,6 +33,17 @@ function decompress_bytes(decoder, data::Vector{UInt8})::Vector{UInt8} take!(io) end +# generate random data to test compression +function generate_data() + thing = rand(UInt8, 100) + d = UInt8[] + for dist in [0:258; 400:200:2000; 2000:1000:33000;] + append!(d, thing) + append!(d, rand(0x00:0x0f, dist)) + end + d +end + @testset "Gzip Codec" begin codec = GzipCompressor() @test codec isa GzipCompressor @@ -133,8 +144,6 @@ end test_reuse_encoder(GzipCompressor, GzipDecompressor) @test_throws ArgumentError GzipCompressor(level=10) - @test_throws ArgumentError GzipCompressor(windowbits=16) - @test_throws ArgumentError GzipDecompressor(windowbits=16) end @testset "Zlib Codec" begin @@ -215,8 +224,6 @@ end test_reuse_encoder(ZlibCompressor, ZlibDecompressor) @test_throws ArgumentError ZlibCompressor(level=10) - @test_throws ArgumentError ZlibCompressor(windowbits=16) - @test_throws ArgumentError ZlibDecompressor(windowbits=16) end @testset "Deflate Codec" begin @@ -243,21 +250,40 @@ end @test DeflateDecompressorStream <: TranscodingStream @test_throws ArgumentError DeflateCompressor(level=10) - @test_throws ArgumentError DeflateCompressor(windowbits=16) - @test_throws ArgumentError DeflateDecompressor(windowbits=16) # Test decoding byte by byte - # Exercise Deflate distances and lengths - for len in [10, 100, 200, 257, 258, 259] - thing = rand(UInt8, len) - d = UInt8[] - for dist in [0:258; 1000:1030; 2000:1000:33000;] - append!(d, thing) - append!(d, rand(0x00:0x0f, dist)) + d = generate_data() + c = transcode(DeflateCompressor, d) + @test transcode(DeflateDecompressor, c) == d + @test decompress_bytes(DeflateDecompressorStream, c) == d +end + +@testset "roundtrip windowbits" begin + d = generate_data() + for (encoder, decoder) in [ + (GzipCompressorStream, GzipDecompressorStream), + (ZlibCompressorStream, ZlibDecompressorStream), + (DeflateCompressorStream, DeflateDecompressorStream), + ] + for compression_windowbits in 9:15 + for decompression_windowbits in 8:15 + c = read(encoder(IOBuffer(d); windowbits=compression_windowbits, level=9)) + if compression_windowbits ≤ decompression_windowbits + @test d == read(decoder(IOBuffer(c); windowbits=decompression_windowbits)) + else + try + u = read(decoder(IOBuffer(c); windowbits=decompression_windowbits)) + @test u == d + catch e + @test e isa ZlibError + end + end + end end - c = transcode(DeflateCompressor, d) - @test transcode(DeflateDecompressor, c) == d - @test decompress_bytes(DeflateDecompressorStream, c) == d + @test_throws ArgumentError encoder(IOBuffer(d); windowbits=8) + @test_throws ArgumentError decoder(IOBuffer(d); windowbits=7) + @test_throws ArgumentError encoder(IOBuffer(d); windowbits=16) + @test_throws ArgumentError decoder(IOBuffer(d); windowbits=16) end end