| ... | ... | @@ -44,14 +44,13 @@ const State = union(enum) { |
| 44 | 44 | pub const Error = Container.Error || error{ |
| 45 | 45 | InvalidCode, |
| 46 | 46 | InvalidMatch, |
| 47 | | InvalidBlockType, |
| 48 | 47 | WrongStoredBlockNlen, |
| 49 | 48 | InvalidDynamicBlockHeader, |
| 50 | | EndOfStream, |
| 51 | 49 | ReadFailed, |
| 52 | 50 | OversubscribedHuffmanTree, |
| 53 | 51 | IncompleteHuffmanTree, |
| 54 | 52 | MissingEndOfBlockCode, |
| 53 | EndOfStream, |
| 55 | 54 | }; |
| 56 | 55 | |
| 57 | 56 | pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress { |
| ... | ... | @@ -153,7 +152,14 @@ fn decodeSymbol(self: *Decompress, decoder: anytype) !Symbol { |
| 153 | 152 | pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!usize { |
| 154 | 153 | const d: *Decompress = @alignCast(@fieldParentPtr("reader", r)); |
| 155 | 154 | return readInner(d, w, limit) catch |err| switch (err) { |
| 156 | | error.EndOfStream => return error.EndOfStream, |
| 155 | error.EndOfStream => { |
| 156 | if (d.state == .end) { |
| 157 | return error.EndOfStream; |
| 158 | } else { |
| 159 | d.read_err = error.EndOfStream; |
| 160 | return error.ReadFailed; |
| 161 | } |
| 162 | }, |
| 157 | 163 | error.WriteFailed => return error.WriteFailed, |
| 158 | 164 | else => |e| { |
| 159 | 165 | // In the event of an error, state is unmodified so that it can be |
| ... | ... | @@ -922,120 +928,109 @@ test "zlib decompress non compressed block (type 0)" { |
| 922 | 928 | } |
| 923 | 929 | |
| 924 | 930 | test "failing end-of-stream" { |
| 925 | | try testFailure(@embedFile("testdata/fuzz/end-of-stream.input"), error.EndOfStream); |
| 931 | try testFailure(.raw, @embedFile("testdata/fuzz/end-of-stream.input"), error.EndOfStream); |
| 926 | 932 | } |
| 927 | 933 | test "failing invalid-distance" { |
| 928 | | try testFailure(@embedFile("testdata/fuzz/invalid-distance.input"), error.InvalidMatch); |
| 934 | try testFailure(.raw, @embedFile("testdata/fuzz/invalid-distance.input"), error.InvalidMatch); |
| 929 | 935 | } |
| 930 | 936 | test "failing invalid-tree01" { |
| 931 | | try testFailure(@embedFile("testdata/fuzz/invalid-tree01.input"), error.IncompleteHuffmanTree); |
| 937 | try testFailure(.raw, @embedFile("testdata/fuzz/invalid-tree01.input"), error.IncompleteHuffmanTree); |
| 932 | 938 | } |
| 933 | 939 | test "failing invalid-tree02" { |
| 934 | | try testFailure(@embedFile("testdata/fuzz/invalid-tree02.input"), error.IncompleteHuffmanTree); |
| 940 | try testFailure(.raw, @embedFile("testdata/fuzz/invalid-tree02.input"), error.IncompleteHuffmanTree); |
| 935 | 941 | } |
| 936 | 942 | test "failing invalid-tree03" { |
| 937 | | try testFailure(@embedFile("testdata/fuzz/invalid-tree03.input"), error.IncompleteHuffmanTree); |
| 943 | try testFailure(.raw, @embedFile("testdata/fuzz/invalid-tree03.input"), error.IncompleteHuffmanTree); |
| 938 | 944 | } |
| 939 | 945 | test "failing lengths-overflow" { |
| 940 | | try testFailure(@embedFile("testdata/fuzz/lengths-overflow.input"), error.InvalidDynamicBlockHeader); |
| 946 | try testFailure(.raw, @embedFile("testdata/fuzz/lengths-overflow.input"), error.InvalidDynamicBlockHeader); |
| 941 | 947 | } |
| 942 | 948 | test "failing out-of-codes" { |
| 943 | | try testFailure(@embedFile("testdata/fuzz/out-of-codes.input"), error.InvalidCode); |
| 949 | try testFailure(.raw, @embedFile("testdata/fuzz/out-of-codes.input"), error.InvalidCode); |
| 944 | 950 | } |
| 945 | 951 | test "failing puff01" { |
| 946 | | try testFailure(@embedFile("testdata/fuzz/puff01.input"), error.WrongStoredBlockNlen); |
| 952 | try testFailure(.raw, @embedFile("testdata/fuzz/puff01.input"), error.WrongStoredBlockNlen); |
| 947 | 953 | } |
| 948 | 954 | test "failing puff02" { |
| 949 | | try testFailure(@embedFile("testdata/fuzz/puff02.input"), error.EndOfStream); |
| 955 | try testFailure(.raw, @embedFile("testdata/fuzz/puff02.input"), error.EndOfStream); |
| 950 | 956 | } |
| 951 | 957 | test "failing puff04" { |
| 952 | | try testFailure(@embedFile("testdata/fuzz/puff04.input"), error.InvalidCode); |
| 958 | try testFailure(.raw, @embedFile("testdata/fuzz/puff04.input"), error.InvalidCode); |
| 953 | 959 | } |
| 954 | 960 | test "failing puff05" { |
| 955 | | try testFailure(@embedFile("testdata/fuzz/puff05.input"), error.EndOfStream); |
| 961 | try testFailure(.raw, @embedFile("testdata/fuzz/puff05.input"), error.EndOfStream); |
| 956 | 962 | } |
| 957 | 963 | test "failing puff06" { |
| 958 | | try testFailure(@embedFile("testdata/fuzz/puff06.input"), error.EndOfStream); |
| 964 | try testFailure(.raw, @embedFile("testdata/fuzz/puff06.input"), error.EndOfStream); |
| 959 | 965 | } |
| 960 | 966 | test "failing puff08" { |
| 961 | | try testFailure(@embedFile("testdata/fuzz/puff08.input"), error.InvalidCode); |
| 967 | try testFailure(.raw, @embedFile("testdata/fuzz/puff08.input"), error.InvalidCode); |
| 962 | 968 | } |
| 963 | 969 | test "failing puff10" { |
| 964 | | try testFailure(@embedFile("testdata/fuzz/puff10.input"), error.InvalidCode); |
| 970 | try testFailure(.raw, @embedFile("testdata/fuzz/puff10.input"), error.InvalidCode); |
| 965 | 971 | } |
| 966 | 972 | test "failing puff11" { |
| 967 | | try testFailure(@embedFile("testdata/fuzz/puff11.input"), error.InvalidMatch); |
| 973 | try testFailure(.raw, @embedFile("testdata/fuzz/puff11.input"), error.InvalidMatch); |
| 968 | 974 | } |
| 969 | 975 | test "failing puff12" { |
| 970 | | try testFailure(@embedFile("testdata/fuzz/puff12.input"), error.InvalidDynamicBlockHeader); |
| 976 | try testFailure(.raw, @embedFile("testdata/fuzz/puff12.input"), error.InvalidDynamicBlockHeader); |
| 971 | 977 | } |
| 972 | 978 | test "failing puff13" { |
| 973 | | try testFailure(@embedFile("testdata/fuzz/puff13.input"), error.IncompleteHuffmanTree); |
| 979 | try testFailure(.raw, @embedFile("testdata/fuzz/puff13.input"), error.IncompleteHuffmanTree); |
| 974 | 980 | } |
| 975 | 981 | test "failing puff14" { |
| 976 | | try testFailure(@embedFile("testdata/fuzz/puff14.input"), error.EndOfStream); |
| 982 | try testFailure(.raw, @embedFile("testdata/fuzz/puff14.input"), error.EndOfStream); |
| 977 | 983 | } |
| 978 | 984 | test "failing puff15" { |
| 979 | | try testFailure(@embedFile("testdata/fuzz/puff15.input"), error.IncompleteHuffmanTree); |
| 985 | try testFailure(.raw, @embedFile("testdata/fuzz/puff15.input"), error.IncompleteHuffmanTree); |
| 980 | 986 | } |
| 981 | 987 | test "failing puff16" { |
| 982 | | try testFailure(@embedFile("testdata/fuzz/puff16.input"), error.InvalidDynamicBlockHeader); |
| 988 | try testFailure(.raw, @embedFile("testdata/fuzz/puff16.input"), error.InvalidDynamicBlockHeader); |
| 983 | 989 | } |
| 984 | 990 | test "failing puff17" { |
| 985 | | try testFailure(@embedFile("testdata/fuzz/puff17.input"), error.MissingEndOfBlockCode); |
| 991 | try testFailure(.raw, @embedFile("testdata/fuzz/puff17.input"), error.MissingEndOfBlockCode); |
| 986 | 992 | } |
| 987 | 993 | test "failing fuzz1" { |
| 988 | | try testFailure(@embedFile("testdata/fuzz/fuzz1.input"), error.InvalidDynamicBlockHeader); |
| 994 | try testFailure(.raw, @embedFile("testdata/fuzz/fuzz1.input"), error.InvalidDynamicBlockHeader); |
| 989 | 995 | } |
| 990 | 996 | test "failing fuzz2" { |
| 991 | | try testFailure(@embedFile("testdata/fuzz/fuzz2.input"), error.InvalidDynamicBlockHeader); |
| 997 | try testFailure(.raw, @embedFile("testdata/fuzz/fuzz2.input"), error.InvalidDynamicBlockHeader); |
| 992 | 998 | } |
| 993 | 999 | test "failing fuzz3" { |
| 994 | | try testFailure(@embedFile("testdata/fuzz/fuzz3.input"), error.InvalidMatch); |
| 1000 | try testFailure(.raw, @embedFile("testdata/fuzz/fuzz3.input"), error.InvalidMatch); |
| 995 | 1001 | } |
| 996 | 1002 | test "failing fuzz4" { |
| 997 | | try testFailure(@embedFile("testdata/fuzz/fuzz4.input"), error.OversubscribedHuffmanTree); |
| 1003 | try testFailure(.raw, @embedFile("testdata/fuzz/fuzz4.input"), error.OversubscribedHuffmanTree); |
| 998 | 1004 | } |
| 999 | 1005 | test "failing puff18" { |
| 1000 | | try testFailure(@embedFile("testdata/fuzz/puff18.input"), error.OversubscribedHuffmanTree); |
| 1006 | try testFailure(.raw, @embedFile("testdata/fuzz/puff18.input"), error.OversubscribedHuffmanTree); |
| 1001 | 1007 | } |
| 1002 | 1008 | test "failing puff19" { |
| 1003 | | try testFailure(@embedFile("testdata/fuzz/puff19.input"), error.OversubscribedHuffmanTree); |
| 1009 | try testFailure(.raw, @embedFile("testdata/fuzz/puff19.input"), error.OversubscribedHuffmanTree); |
| 1004 | 1010 | } |
| 1005 | 1011 | test "failing puff20" { |
| 1006 | | try testFailure(@embedFile("testdata/fuzz/puff20.input"), error.OversubscribedHuffmanTree); |
| 1012 | try testFailure(.raw, @embedFile("testdata/fuzz/puff20.input"), error.OversubscribedHuffmanTree); |
| 1007 | 1013 | } |
| 1008 | 1014 | test "failing puff21" { |
| 1009 | | try testFailure(@embedFile("testdata/fuzz/puff21.input"), error.OversubscribedHuffmanTree); |
| 1015 | try testFailure(.raw, @embedFile("testdata/fuzz/puff21.input"), error.OversubscribedHuffmanTree); |
| 1010 | 1016 | } |
| 1011 | 1017 | test "failing puff22" { |
| 1012 | | try testFailure(@embedFile("testdata/fuzz/puff22.input"), error.OversubscribedHuffmanTree); |
| 1018 | try testFailure(.raw, @embedFile("testdata/fuzz/puff22.input"), error.OversubscribedHuffmanTree); |
| 1013 | 1019 | } |
| 1014 | 1020 | test "failing puff23" { |
| 1015 | | try testFailure(@embedFile("testdata/fuzz/puff23.input"), error.OversubscribedHuffmanTree); |
| 1021 | try testFailure(.raw, @embedFile("testdata/fuzz/puff23.input"), error.OversubscribedHuffmanTree); |
| 1016 | 1022 | } |
| 1017 | 1023 | test "failing puff24" { |
| 1018 | | try testFailure(@embedFile("testdata/fuzz/puff24.input"), error.IncompleteHuffmanTree); |
| 1024 | try testFailure(.raw, @embedFile("testdata/fuzz/puff24.input"), error.IncompleteHuffmanTree); |
| 1019 | 1025 | } |
| 1020 | 1026 | test "failing puff25" { |
| 1021 | | try testFailure(@embedFile("testdata/fuzz/puff25.input"), error.OversubscribedHuffmanTree); |
| 1027 | try testFailure(.raw, @embedFile("testdata/fuzz/puff25.input"), error.OversubscribedHuffmanTree); |
| 1022 | 1028 | } |
| 1023 | 1029 | test "failing puff26" { |
| 1024 | | try testFailure(@embedFile("testdata/fuzz/puff26.input"), error.InvalidDynamicBlockHeader); |
| 1030 | try testFailure(.raw, @embedFile("testdata/fuzz/puff26.input"), error.InvalidDynamicBlockHeader); |
| 1025 | 1031 | } |
| 1026 | 1032 | test "failing puff27" { |
| 1027 | | try testFailure(@embedFile("testdata/fuzz/puff27.input"), error.InvalidDynamicBlockHeader); |
| 1028 | | } |
| 1029 | | |
| 1030 | | fn testFailure(in: []const u8, expected_err: anyerror) !void { |
| 1031 | | var reader: Reader = .fixed(in); |
| 1032 | | var aw: Writer.Allocating = .init(testing.allocator); |
| 1033 | | try aw.ensureUnusedCapacity(flate.history_len); |
| 1034 | | defer aw.deinit(); |
| 1035 | | |
| 1036 | | var decompress: Decompress = .init(&reader, .raw, &.{}); |
| 1037 | | try testing.expectError(error.ReadFailed, decompress.reader.streamRemaining(&aw.writer)); |
| 1038 | | try testing.expectEqual(expected_err, decompress.read_err orelse return error.TestFailed); |
| 1033 | try testFailure(.raw, @embedFile("testdata/fuzz/puff27.input"), error.InvalidDynamicBlockHeader); |
| 1039 | 1034 | } |
| 1040 | 1035 | |
| 1041 | 1036 | test "deflate-stream" { |
| ... | ... | @@ -1097,82 +1092,57 @@ test "don't read past deflate stream's end" { |
| 1097 | 1092 | |
| 1098 | 1093 | test "zlib header" { |
| 1099 | 1094 | // Truncated header |
| 1100 | | try testing.expectError( |
| 1101 | | error.EndOfStream, |
| 1102 | | testDecompress(.zlib, &[_]u8{0x78}, ""), |
| 1103 | | ); |
| 1095 | try testFailure(.zlib, &[_]u8{0x78}, error.EndOfStream); |
| 1096 | |
| 1104 | 1097 | // Wrong CM |
| 1105 | | try testing.expectError( |
| 1106 | | error.BadZlibHeader, |
| 1107 | | testDecompress(.zlib, &[_]u8{ 0x79, 0x94 }, ""), |
| 1108 | | ); |
| 1098 | try testFailure(.zlib, &[_]u8{ 0x79, 0x94 }, error.BadZlibHeader); |
| 1099 | |
| 1109 | 1100 | // Wrong CINFO |
| 1110 | | try testing.expectError( |
| 1111 | | error.BadZlibHeader, |
| 1112 | | testDecompress(.zlib, &[_]u8{ 0x88, 0x98 }, ""), |
| 1113 | | ); |
| 1101 | try testFailure(.zlib, &[_]u8{ 0x88, 0x98 }, error.BadZlibHeader); |
| 1102 | |
| 1114 | 1103 | // Wrong checksum |
| 1115 | | try testing.expectError( |
| 1116 | | error.WrongZlibChecksum, |
| 1117 | | testDecompress(.zlib, &[_]u8{ 0x78, 0xda, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 }, ""), |
| 1118 | | ); |
| 1104 | try testFailure(.zlib, &[_]u8{ 0x78, 0xda, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 }, error.WrongZlibChecksum); |
| 1105 | |
| 1119 | 1106 | // Truncated checksum |
| 1120 | | try testing.expectError( |
| 1121 | | error.EndOfStream, |
| 1122 | | testDecompress(.zlib, &[_]u8{ 0x78, 0xda, 0x03, 0x00, 0x00 }, ""), |
| 1123 | | ); |
| 1107 | try testFailure(.zlib, &[_]u8{ 0x78, 0xda, 0x03, 0x00, 0x00 }, error.EndOfStream); |
| 1124 | 1108 | } |
| 1125 | 1109 | |
| 1126 | 1110 | test "gzip header" { |
| 1127 | 1111 | // Truncated header |
| 1128 | | try testing.expectError( |
| 1129 | | error.EndOfStream, |
| 1130 | | testDecompress(.gzip, &[_]u8{ 0x1f, 0x8B }, undefined), |
| 1131 | | ); |
| 1112 | try testFailure(.gzip, &[_]u8{ 0x1f, 0x8B }, error.EndOfStream); |
| 1113 | |
| 1132 | 1114 | // Wrong CM |
| 1133 | | try testing.expectError( |
| 1134 | | error.BadGzipHeader, |
| 1135 | | testDecompress(.gzip, &[_]u8{ |
| 1136 | | 0x1f, 0x8b, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1137 | | 0x00, 0x03, |
| 1138 | | }, undefined), |
| 1139 | | ); |
| 1115 | try testFailure(.gzip, &[_]u8{ |
| 1116 | 0x1f, 0x8b, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1117 | 0x00, 0x03, |
| 1118 | }, error.BadGzipHeader); |
| 1140 | 1119 | |
| 1141 | 1120 | // Wrong checksum |
| 1142 | | try testing.expectError( |
| 1143 | | error.WrongGzipChecksum, |
| 1144 | | testDecompress(.gzip, &[_]u8{ |
| 1145 | | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1146 | | 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, |
| 1147 | | 0x00, 0x00, 0x00, 0x00, |
| 1148 | | }, undefined), |
| 1149 | | ); |
| 1121 | try testFailure(.gzip, &[_]u8{ |
| 1122 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1123 | 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, |
| 1124 | 0x00, 0x00, 0x00, 0x00, |
| 1125 | }, error.WrongGzipChecksum); |
| 1126 | |
| 1150 | 1127 | // Truncated checksum |
| 1151 | | try testing.expectError( |
| 1152 | | error.EndOfStream, |
| 1153 | | testDecompress(.gzip, &[_]u8{ |
| 1154 | | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1155 | | 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, |
| 1156 | | }, undefined), |
| 1157 | | ); |
| 1128 | try testFailure(.gzip, &[_]u8{ |
| 1129 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1130 | 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, |
| 1131 | }, error.EndOfStream); |
| 1132 | |
| 1158 | 1133 | // Wrong initial size |
| 1159 | | try testing.expectError( |
| 1160 | | error.WrongGzipSize, |
| 1161 | | testDecompress(.gzip, &[_]u8{ |
| 1162 | | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1163 | | 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1164 | | 0x00, 0x00, 0x00, 0x01, |
| 1165 | | }, undefined), |
| 1166 | | ); |
| 1134 | try testFailure(.gzip, &[_]u8{ |
| 1135 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1136 | 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1137 | 0x00, 0x00, 0x00, 0x01, |
| 1138 | }, error.WrongGzipSize); |
| 1139 | |
| 1167 | 1140 | // Truncated initial size field |
| 1168 | | try testing.expectError( |
| 1169 | | error.EndOfStream, |
| 1170 | | testDecompress(.gzip, &[_]u8{ |
| 1171 | | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1172 | | 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1173 | | 0x00, 0x00, 0x00, |
| 1174 | | }, undefined), |
| 1175 | | ); |
| 1141 | try testFailure(.gzip, &[_]u8{ |
| 1142 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1143 | 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1144 | 0x00, 0x00, 0x00, |
| 1145 | }, error.EndOfStream); |
| 1176 | 1146 | |
| 1177 | 1147 | try testDecompress(.gzip, &[_]u8{ |
| 1178 | 1148 | // GZIP header |
| ... | ... | @@ -1184,17 +1154,6 @@ test "gzip header" { |
| 1184 | 1154 | }, ""); |
| 1185 | 1155 | } |
| 1186 | 1156 | |
| 1187 | | fn testDecompress(container: Container, compressed: []const u8, expected_plain: []const u8) !void { |
| 1188 | | var in: std.Io.Reader = .fixed(compressed); |
| 1189 | | var aw: std.Io.Writer.Allocating = .init(testing.allocator); |
| 1190 | | try aw.ensureUnusedCapacity(flate.history_len); |
| 1191 | | defer aw.deinit(); |
| 1192 | | |
| 1193 | | var decompress: Decompress = .init(&in, container, &.{}); |
| 1194 | | _ = try decompress.reader.streamRemaining(&aw.writer); |
| 1195 | | try testing.expectEqualSlices(u8, expected_plain, aw.getWritten()); |
| 1196 | | } |
| 1197 | | |
| 1198 | 1157 | test "zlib should not overshoot" { |
| 1199 | 1158 | // Compressed zlib data with extra 4 bytes at the end. |
| 1200 | 1159 | const data = [_]u8{ |
| ... | ... | @@ -1220,3 +1179,25 @@ test "zlib should not overshoot" { |
| 1220 | 1179 | try std.testing.expectEqual(n, 4); |
| 1221 | 1180 | try std.testing.expectEqualSlices(u8, data[data.len - 4 .. data.len], out[0..n]); |
| 1222 | 1181 | } |
| 1182 | |
| 1183 | fn testFailure(container: Container, in: []const u8, expected_err: anyerror) !void { |
| 1184 | var reader: Reader = .fixed(in); |
| 1185 | var aw: Writer.Allocating = .init(testing.allocator); |
| 1186 | try aw.ensureUnusedCapacity(flate.history_len); |
| 1187 | defer aw.deinit(); |
| 1188 | |
| 1189 | var decompress: Decompress = .init(&reader, container, &.{}); |
| 1190 | try testing.expectError(error.ReadFailed, decompress.reader.streamRemaining(&aw.writer)); |
| 1191 | try testing.expectEqual(expected_err, decompress.read_err orelse return error.TestFailed); |
| 1192 | } |
| 1193 | |
| 1194 | fn testDecompress(container: Container, compressed: []const u8, expected_plain: []const u8) !void { |
| 1195 | var in: std.Io.Reader = .fixed(compressed); |
| 1196 | var aw: std.Io.Writer.Allocating = .init(testing.allocator); |
| 1197 | try aw.ensureUnusedCapacity(flate.history_len); |
| 1198 | defer aw.deinit(); |
| 1199 | |
| 1200 | var decompress: Decompress = .init(&in, container, &.{}); |
| 1201 | _ = try decompress.reader.streamRemaining(&aw.writer); |
| 1202 | try testing.expectEqualSlices(u8, expected_plain, aw.getWritten()); |
| 1203 | } |