zig/lib/std/compress/deflate/deflate_fast_test.zig

160 lines
5.9 KiB
Zig

const std = @import("std");
const expect = std.testing.expect;
const io = std.io;
const mem = std.mem;
const testing = std.testing;
const ArrayList = std.ArrayList;
const deflate = @import("compressor.zig");
const inflate = @import("decompressor.zig");
const deflate_const = @import("deflate_const.zig");
test "best speed" {
// Tests that round-tripping through deflate and then inflate recovers the original input.
// The Write sizes are near the thresholds in the compressor.encSpeed method (0, 16, 128), as well
// as near `deflate_const.max_store_block_size` (65535).
var abcabc = try testing.allocator.alloc(u8, 131_072);
defer testing.allocator.free(abcabc);
for (abcabc, 0..) |_, i| {
abcabc[i] = @intCast(u8, i % 128);
}
var tc_01 = [_]u32{ 65536, 0 };
var tc_02 = [_]u32{ 65536, 1 };
var tc_03 = [_]u32{ 65536, 1, 256 };
var tc_04 = [_]u32{ 65536, 1, 65536 };
var tc_05 = [_]u32{ 65536, 14 };
var tc_06 = [_]u32{ 65536, 15 };
var tc_07 = [_]u32{ 65536, 16 };
var tc_08 = [_]u32{ 65536, 16, 256 };
var tc_09 = [_]u32{ 65536, 16, 65536 };
var tc_10 = [_]u32{ 65536, 127 };
var tc_11 = [_]u32{ 65536, 127 };
var tc_12 = [_]u32{ 65536, 128 };
var tc_13 = [_]u32{ 65536, 128, 256 };
var tc_14 = [_]u32{ 65536, 128, 65536 };
var tc_15 = [_]u32{ 65536, 129 };
var tc_16 = [_]u32{ 65536, 65536, 256 };
var tc_17 = [_]u32{ 65536, 65536, 65536 };
var test_cases = [_][]u32{
&tc_01, &tc_02, &tc_03, &tc_04, &tc_05, &tc_06, &tc_07, &tc_08, &tc_09, &tc_10,
&tc_11, &tc_12, &tc_13, &tc_14, &tc_15, &tc_16, &tc_17,
};
for (test_cases) |tc| {
var firsts = [_]u32{ 1, 65534, 65535, 65536, 65537, 131072 };
for (firsts) |first_n| {
tc[0] = first_n;
var to_flush = [_]bool{ false, true };
for (to_flush) |flush| {
var compressed = ArrayList(u8).init(testing.allocator);
defer compressed.deinit();
var want = ArrayList(u8).init(testing.allocator);
defer want.deinit();
var comp = try deflate.compressor(
testing.allocator,
compressed.writer(),
.{ .level = .best_speed },
);
defer comp.deinit();
for (tc) |n| {
try want.appendSlice(abcabc[0..n]);
try comp.writer().writeAll(abcabc[0..n]);
if (flush) {
try comp.flush();
}
}
try comp.close();
var decompressed = try testing.allocator.alloc(u8, want.items.len);
defer testing.allocator.free(decompressed);
var fib = io.fixedBufferStream(compressed.items);
var decomp = try inflate.decompressor(testing.allocator, fib.reader(), null);
defer decomp.deinit();
var read = try decomp.reader().readAll(decompressed);
_ = decomp.close();
try testing.expectEqual(want.items.len, read);
try testing.expectEqualSlices(u8, want.items, decompressed);
}
}
}
}
test "best speed max match offset" {
const abc = "abcdefgh";
const xyz = "stuvwxyz";
const input_margin = 16 - 1;
const match_before = [_]bool{ false, true };
for (match_before) |do_match_before| {
const extras = [_]u32{
0,
input_margin - 1,
input_margin,
input_margin + 1,
2 * input_margin,
};
for (extras) |extra| {
var offset_adj: i32 = -5;
while (offset_adj <= 5) : (offset_adj += 1) {
var offset = deflate_const.max_match_offset + offset_adj;
// Make src to be a []u8 of the form
// fmt("{s}{s}{s}{s}{s}", .{abc, zeros0, xyzMaybe, abc, zeros1})
// where:
// zeros0 is approximately max_match_offset zeros.
// xyzMaybe is either xyz or the empty string.
// zeros1 is between 0 and 30 zeros.
// The difference between the two abc's will be offset, which
// is max_match_offset plus or minus a small adjustment.
var src_len: usize = @intCast(usize, offset + @as(i32, abc.len) + @intCast(i32, extra));
var src = try testing.allocator.alloc(u8, src_len);
defer testing.allocator.free(src);
mem.copy(u8, src, abc);
if (!do_match_before) {
var src_offset: usize = @intCast(usize, offset - @as(i32, xyz.len));
mem.copy(u8, src[src_offset..], xyz);
}
var src_offset: usize = @intCast(usize, offset);
mem.copy(u8, src[src_offset..], abc);
var compressed = ArrayList(u8).init(testing.allocator);
defer compressed.deinit();
var comp = try deflate.compressor(
testing.allocator,
compressed.writer(),
.{ .level = .best_speed },
);
defer comp.deinit();
try comp.writer().writeAll(src);
_ = try comp.close();
var decompressed = try testing.allocator.alloc(u8, src.len);
defer testing.allocator.free(decompressed);
var fib = io.fixedBufferStream(compressed.items);
var decomp = try inflate.decompressor(testing.allocator, fib.reader(), null);
defer decomp.deinit();
var read = try decomp.reader().readAll(decompressed);
_ = decomp.close();
try testing.expectEqual(src.len, read);
try testing.expectEqualSlices(u8, src, decompressed);
}
}
}
}