| 1 | module lz |
| 2 | |
| 3 | const sample_data = ('The quick brown fox jumps over the lazy dog. '.repeat(12) + |
| 4 | 'aaaaaaaaabbbbbbbbbcccccccccdddddddddeeeeeeeee').bytes() |
| 5 | |
| 6 | fn test_roundtrip_all_formats() { |
| 7 | formats := [Format.lz77, .lz78, .lzw, .lz4, .lzss, .lzma, .lzma2, .lzjb] |
| 8 | for format in formats { |
| 9 | compressed := compress(sample_data, format)! |
| 10 | decompressed := decompress(compressed, format)! |
| 11 | assert decompressed == sample_data |
| 12 | } |
| 13 | } |
| 14 | |
| 15 | fn test_format_specific_api_roundtrip() { |
| 16 | lz77_data := compress_lz77(sample_data)! |
| 17 | assert decompress_lz77(lz77_data)! == sample_data |
| 18 | |
| 19 | lz78_data := compress_lz78(sample_data)! |
| 20 | assert decompress_lz78(lz78_data)! == sample_data |
| 21 | |
| 22 | lzw_data := compress_lzw(sample_data)! |
| 23 | assert decompress_lzw(lzw_data)! == sample_data |
| 24 | |
| 25 | lz4_data := compress_lz4(sample_data)! |
| 26 | assert decompress_lz4(lz4_data)! == sample_data |
| 27 | |
| 28 | lzss_data := compress_lzss(sample_data)! |
| 29 | assert decompress_lzss(lzss_data)! == sample_data |
| 30 | |
| 31 | lzma_data := compress_lzma(sample_data)! |
| 32 | assert decompress_lzma(lzma_data)! == sample_data |
| 33 | |
| 34 | lzma2_data := compress_lzma2(sample_data)! |
| 35 | assert decompress_lzma2(lzma2_data)! == sample_data |
| 36 | |
| 37 | lzjb_data := compress_lzjb(sample_data)! |
| 38 | assert decompress_lzjb(lzjb_data)! == sample_data |
| 39 | } |
| 40 | |
| 41 | fn test_mismatched_format_fails() { |
| 42 | compressed := compress(sample_data, .lz77)! |
| 43 | decompress(compressed, .lz4) or { |
| 44 | assert err.msg().contains('format mismatch') |
| 45 | return |
| 46 | } |
| 47 | assert false |
| 48 | } |
| 49 | |
| 50 | fn test_decoded_length_too_large_fails() { |
| 51 | mut corrupt := []u8{} |
| 52 | corrupt << stream_magic |
| 53 | corrupt << u8(Format.lz77) |
| 54 | encode_uvarint(mut corrupt, u64(1) << 31) |
| 55 | |
| 56 | decompress_lz77(corrupt) or { |
| 57 | assert err.msg().contains('decoded length too large') |
| 58 | return |
| 59 | } |
| 60 | assert false |
| 61 | } |
| 62 | |
| 63 | fn test_match_offset_too_large_fails() { |
| 64 | mut corrupt := []u8{} |
| 65 | corrupt << stream_magic |
| 66 | corrupt << u8(Format.lz77) |
| 67 | encode_uvarint(mut corrupt, u64(4)) |
| 68 | corrupt << u8(0) |
| 69 | corrupt << `A` |
| 70 | corrupt << u8(0x80) |
| 71 | encode_uvarint(mut corrupt, u64(1) << 63) |
| 72 | |
| 73 | decompress_lz77(corrupt) or { |
| 74 | assert err.msg().contains('bad match offset') |
| 75 | return |
| 76 | } |
| 77 | assert false |
| 78 | } |
| 79 | |
| 80 | fn test_high_entropy_roundtrip_large_window_formats() { |
| 81 | mut data := []u8{len: 128 * 1024} |
| 82 | mut state := u32(0x9e3779b9) |
| 83 | for i in 0 .. data.len { |
| 84 | state = state * 1664525 + 1013904223 |
| 85 | data[i] = u8(state >> 24) |
| 86 | } |
| 87 | |
| 88 | for format in [Format.lz4, .lzma, .lzma2] { |
| 89 | compressed := compress(data, format)! |
| 90 | decompressed := decompress(compressed, format)! |
| 91 | assert decompressed == data |
| 92 | } |
| 93 | } |
| 94 | |