From f5858a2f542376b2845eee019baa7858e67c6fcc Mon Sep 17 00:00:00 2001 From: nhz2 Date: Sat, 23 Mar 2024 21:27:40 -0400 Subject: [PATCH 1/4] broken read write tests --- .gitignore | 2 + fuzz/Project.toml | 8 ++++ fuzz/fuzz.jl | 98 ++++++++++++++++++++++++++++++++++++++++ test/codecdoubleframe.jl | 20 ++++++++ 4 files changed, 128 insertions(+) create mode 100644 fuzz/Project.toml create mode 100644 fuzz/fuzz.jl diff --git a/.gitignore b/.gitignore index 57eb3d23..9622b08d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ /Manifest.toml /docs/build/ /docs/Manifest.toml +/fuzz/test/ +/fuzz/Manifest.toml diff --git a/fuzz/Project.toml b/fuzz/Project.toml new file mode 100644 index 00000000..7387cdf9 --- /dev/null +++ b/fuzz/Project.toml @@ -0,0 +1,8 @@ +[deps] +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +Supposition = "5a0628fe-1738-4658-9b6d-0b7605a9755b" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +TranscodingStreams = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" + +[compat] +Supposition = "0.3" diff --git a/fuzz/fuzz.jl b/fuzz/fuzz.jl new file mode 100644 index 00000000..ac1e891a --- /dev/null +++ b/fuzz/fuzz.jl @@ -0,0 +1,98 @@ +# Basic Supposition.jl tests to ensure nested streams can be read and written to. + +include("../test/codecdoubleframe.jl") +using Supposition: Data, @composed, @check, event! + +datas = Data.Vectors(Data.Integers{UInt8}()) + +# Possible kwargs for TranscodingStream constructor +TS_kwarg = @composed ( + bufsize=Data.Integers(1, 2^10), + stop_on_end=Data.Booleans(), + sharedbuf=Data.Booleans(), +) -> ( + if sharedbuf + # default sharedbuf + (;bufsize, stop_on_end) + else + # sharedbuf = false + (;bufsize, stop_on_end, sharedbuf) + end +) + +# Possible NoopStream wrapper +noop_wrapper = @composed ( + kw=TS_kwarg, +) -> (function noop_wrapper(io) + event!("noop", kw) + NoopStream(io; kw...) +end) + +# Possible Encoder Decoder wrapper +dec_enc_wrapper = @composed ( + kw_enc=TS_kwarg, + kw_dec=TS_kwarg, +) -> (function r_enc_dec_wrapper(io) + event!("encoder", kw_enc) + event!("decoder", kw_dec) + DoubleFrameDecoderStream(DoubleFrameEncoderStream(io; kw_enc...); kw_dec...) +end) +enc_dec_wrapper = @composed ( + kw_enc=TS_kwarg, + kw_dec=TS_kwarg, +) -> (function w_enc_dec_wrapper(io) + event!("decoder", kw_dec) + event!("encoder", kw_enc) + DoubleFrameEncoderStream(DoubleFrameDecoderStream(io; kw_dec...); kw_enc...) +end) + +# Possible deeply nested wrappers +read_wrapper = @composed ( + w = Data.Vectors(noop_wrapper | dec_enc_wrapper; max_size=5) +) -> (function read_wrapper(io) + event!("wrapping IOBuffer with:", nothing) + (∘(identity, w...))(io) +end) +write_wrapper = @composed ( + w = Data.Vectors(noop_wrapper | enc_dec_wrapper; max_size=5) +) -> (function write_wrapper(io) + event!("wrapping IOBuffer with:", nothing) + (∘(identity, w...))(io) +end) + +@check max_examples=100000 function read_data(w=read_wrapper, data=datas) + stream = w(IOBuffer(data)) + read(stream) == data || return false + eof(stream) +end +@check max_examples=100000 function read_byte_data(w=read_wrapper, data=datas) + stream = w(IOBuffer(data)) + for i in 1:length(data) + read(stream, UInt8) == data[i] || return false + end + eof(stream) +end + +# flush all nested streams and return final data +function take_all(stream) + if stream isa Base.GenericIOBuffer + take!(stream) + else + write(stream, TranscodingStreams.TOKEN_END) + flush(stream) + take_all(stream.stream) + end +end + +@check max_examples=100000 function write_data(w=write_wrapper, data=datas) + stream = w(IOBuffer()) + write(stream, data) == length(data) || return false + take_all(stream) == data +end +@check max_examples=100000 function write_byte_data(w=write_wrapper, data=datas) + stream = w(IOBuffer()) + for i in 1:length(data) + write(stream, data[i]) == 1 || return false + end + take_all(stream) == data +end \ No newline at end of file diff --git a/test/codecdoubleframe.jl b/test/codecdoubleframe.jl index 4b5e4e53..4cdd6703 100644 --- a/test/codecdoubleframe.jl +++ b/test/codecdoubleframe.jl @@ -243,6 +243,26 @@ DoubleFrameDecoderStream(stream::IO; kwargs...) = TranscodingStream(DoubleFrameD @test String(take!(sink)) == "[ ][ aabbcc ][ ddee ]" end + @testset "stop_on_end=true in nested streams" begin + s1 = DoubleFrameDecoderStream(DoubleFrameEncoderStream( + DoubleFrameDecoderStream( + DoubleFrameEncoderStream(IOBuffer(b"")); + stop_on_end=true, + ) + )) + @test_broken read(s1) == b"" + @test_broken eof(s1) + + s2 = NoopStream( + DoubleFrameDecoderStream( + DoubleFrameEncoderStream(IOBuffer(b"")); + stop_on_end=true, + ) + ) + @test read(s2) == b"" + @test_broken eof(s2) + end + test_roundtrip_read(DoubleFrameEncoderStream, DoubleFrameDecoderStream) test_roundtrip_write(DoubleFrameEncoderStream, DoubleFrameDecoderStream) test_roundtrip_lines(DoubleFrameEncoderStream, DoubleFrameDecoderStream) From 9c95f19f8f6cca0aa5a3b2d11f88e88f0a1092c7 Mon Sep 17 00:00:00 2001 From: nhz2 Date: Sun, 24 Mar 2024 14:09:42 -0400 Subject: [PATCH 2/4] apply some suggestions and widen tests --- fuzz/fuzz.jl | 115 +++++++++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 53 deletions(-) diff --git a/fuzz/fuzz.jl b/fuzz/fuzz.jl index ac1e891a..fa503482 100644 --- a/fuzz/fuzz.jl +++ b/fuzz/fuzz.jl @@ -1,12 +1,10 @@ # Basic Supposition.jl tests to ensure nested streams can be read and written to. -include("../test/codecdoubleframe.jl") -using Supposition: Data, @composed, @check, event! +using Supposition: Data, @composed, @check, event!, produce! -datas = Data.Vectors(Data.Integers{UInt8}()) +include("../test/codecdoubleframe.jl") -# Possible kwargs for TranscodingStream constructor -TS_kwarg = @composed ( +const TS_kwarg = @composed ( bufsize=Data.Integers(1, 2^10), stop_on_end=Data.Booleans(), sharedbuf=Data.Booleans(), @@ -20,58 +18,61 @@ TS_kwarg = @composed ( end ) -# Possible NoopStream wrapper -noop_wrapper = @composed ( - kw=TS_kwarg, -) -> (function noop_wrapper(io) - event!("noop", kw) - NoopStream(io; kw...) -end) +const datas = Data.Vectors(Data.Integers{UInt8}()) +const noopcodecs = Data.Vectors(Data.Just(Noop); max_size=3) -# Possible Encoder Decoder wrapper -dec_enc_wrapper = @composed ( - kw_enc=TS_kwarg, - kw_dec=TS_kwarg, -) -> (function r_enc_dec_wrapper(io) - event!("encoder", kw_enc) - event!("decoder", kw_dec) - DoubleFrameDecoderStream(DoubleFrameEncoderStream(io; kw_enc...); kw_dec...) -end) -enc_dec_wrapper = @composed ( - kw_enc=TS_kwarg, - kw_dec=TS_kwarg, -) -> (function w_enc_dec_wrapper(io) - event!("decoder", kw_dec) - event!("encoder", kw_enc) - DoubleFrameEncoderStream(DoubleFrameDecoderStream(io; kw_dec...); kw_enc...) -end) +function codecwrap(child) + map(child) do cs + DataType[ + DoubleFrameEncoder; + cs; + DoubleFrameDecoder; + ] + end | map(child) do cs + DataType[ + cs; + produce!(child); + ] + end +end -# Possible deeply nested wrappers -read_wrapper = @composed ( - w = Data.Vectors(noop_wrapper | dec_enc_wrapper; max_size=5) -) -> (function read_wrapper(io) - event!("wrapping IOBuffer with:", nothing) - (∘(identity, w...))(io) -end) -write_wrapper = @composed ( - w = Data.Vectors(noop_wrapper | enc_dec_wrapper; max_size=5) -) -> (function write_wrapper(io) - event!("wrapping IOBuffer with:", nothing) - (∘(identity, w...))(io) -end) +# possible vector of codec types that when read from +# should be equivalent to a Noop. +# Every encoder is balanced with a decoder. +const codecs = Data.Recursive(noopcodecs, codecwrap; max_layers=4) -@check max_examples=100000 function read_data(w=read_wrapper, data=datas) - stream = w(IOBuffer(data)) - read(stream) == data || return false - eof(stream) +function prepare_kws(codecs) + # res will be a nicely printed summary of the layers of the stream. + res = [] + for codec in codecs + kw = Data.produce!(TS_kwarg) + push!(res, (codec, kw)) + end + res end -@check max_examples=100000 function read_byte_data(w=read_wrapper, data=datas) - stream = w(IOBuffer(data)) - for i in 1:length(data) + +const read_codecs_kws = map(prepare_kws, codecs) + +function wrap_stream(codecs_kws, io::IO)::IO + event!("IOBuffer:", nothing) + foldl(codecs_kws; init=io) do stream, (codec, kw) + event!("codec:", (codec, kw)) + TranscodingStream(codec(), stream; kw...) + end +end + +@check db=false function read_byte_data(kws=read_codecs_kws, data=datas) + stream = wrap_stream(kws, IOBuffer(data)) + for i in eachindex(data) read(stream, UInt8) == data[i] || return false end eof(stream) end +@check db=false function read_byte_data(kws=read_codecs_kws, data=datas) + stream = wrap_stream(kws, IOBuffer(data)) + read(stream) == data || return false + eof(stream) +end # flush all nested streams and return final data function take_all(stream) @@ -84,13 +85,21 @@ function take_all(stream) end end -@check max_examples=100000 function write_data(w=write_wrapper, data=datas) - stream = w(IOBuffer()) +const write_codecs_kws = map(reverse, read_codecs_kws) + +@check db=false function write_data( + kws=write_codecs_kws, + data=datas, + ) + stream = wrap_stream(kws, IOBuffer()) write(stream, data) == length(data) || return false take_all(stream) == data end -@check max_examples=100000 function write_byte_data(w=write_wrapper, data=datas) - stream = w(IOBuffer()) +@check db=false function write_byte_data( + kws=write_codecs_kws, + data=datas, + ) + stream = wrap_stream(kws, IOBuffer()) for i in 1:length(data) write(stream, data[i]) == 1 || return false end From b150fac03b0793b51091b0cf2f9a9ceed970883e Mon Sep 17 00:00:00 2001 From: nhz2 Date: Sun, 24 Mar 2024 14:26:01 -0400 Subject: [PATCH 3/4] nicer formatting --- fuzz/fuzz.jl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/fuzz/fuzz.jl b/fuzz/fuzz.jl index fa503482..4aeee028 100644 --- a/fuzz/fuzz.jl +++ b/fuzz/fuzz.jl @@ -61,14 +61,20 @@ function wrap_stream(codecs_kws, io::IO)::IO end end -@check db=false function read_byte_data(kws=read_codecs_kws, data=datas) +@check function read_byte_data( + kws=read_codecs_kws, + data=datas, + ) stream = wrap_stream(kws, IOBuffer(data)) for i in eachindex(data) read(stream, UInt8) == data[i] || return false end eof(stream) end -@check db=false function read_byte_data(kws=read_codecs_kws, data=datas) +@check function read_data( + kws=read_codecs_kws, + data=datas, + ) stream = wrap_stream(kws, IOBuffer(data)) read(stream) == data || return false eof(stream) @@ -87,7 +93,7 @@ end const write_codecs_kws = map(reverse, read_codecs_kws) -@check db=false function write_data( +@check function write_data( kws=write_codecs_kws, data=datas, ) @@ -95,7 +101,7 @@ const write_codecs_kws = map(reverse, read_codecs_kws) write(stream, data) == length(data) || return false take_all(stream) == data end -@check db=false function write_byte_data( +@check function write_byte_data( kws=write_codecs_kws, data=datas, ) From 68d210bb5db6656af79c31b7c4d537bea9bc29a6 Mon Sep 17 00:00:00 2001 From: nhz2 Date: Sun, 24 Mar 2024 15:48:36 -0400 Subject: [PATCH 4/4] map over vector --- fuzz/fuzz.jl | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fuzz/fuzz.jl b/fuzz/fuzz.jl index 4aeee028..57a65206 100644 --- a/fuzz/fuzz.jl +++ b/fuzz/fuzz.jl @@ -22,17 +22,14 @@ const datas = Data.Vectors(Data.Integers{UInt8}()) const noopcodecs = Data.Vectors(Data.Just(Noop); max_size=3) function codecwrap(child) - map(child) do cs + map(child) do x DataType[ DoubleFrameEncoder; - cs; + x; DoubleFrameDecoder; ] - end | map(child) do cs - DataType[ - cs; - produce!(child); - ] + end | map(Data.Vectors(child; min_size=2, max_size=2)) do x + reduce(vcat, x) end end