| 1 | module deflate |
| 2 | |
| 3 | fn test_zlib_roundtrip() { |
| 4 | data := 'Hello world!'.bytes() |
| 5 | compressed := compress(data)! |
| 6 | assert compressed[0] == 0x78 && compressed[1] == 0x9c // zlib header |
| 7 | assert decompress(compressed)! == data |
| 8 | } |
| 9 | |
| 10 | fn test_gzip_roundtrip() { |
| 11 | data := 'Hello gzip!'.repeat(10).bytes() |
| 12 | compressed := compress(data, format: .gzip)! |
| 13 | assert compressed[0] == 0x1f && compressed[1] == 0x8b // gzip magic |
| 14 | assert decompress(compressed)! == data |
| 15 | } |
| 16 | |
| 17 | fn test_raw_deflate_roundtrip() { |
| 18 | data := 'raw deflate'.repeat(20).bytes() |
| 19 | raw := compress(data, format: .raw_deflate)! |
| 20 | decoded := decompress(raw)! // auto-detected as raw |
| 21 | assert decoded == data |
| 22 | } |
| 23 | |
| 24 | fn test_decompress_auto_detects_all_formats() { |
| 25 | data := 'multi-format detection test'.repeat(5).bytes() |
| 26 | assert decompress(compress(data)!)! == data |
| 27 | assert decompress(compress(data, format: .gzip)!)! == data |
| 28 | assert decompress(compress(data, format: .raw_deflate)!)! == data |
| 29 | } |
| 30 | |
| 31 | fn test_wrapper_helpers_match_unified_api() { |
| 32 | data := 'wrapper compatibility'.repeat(8).bytes() |
| 33 | assert compress(data)! == compress(data, format: .zlib)! |
| 34 | assert compress_gzip(data)! == compress(data, format: .gzip)! |
| 35 | assert compress_raw(data)! == compress(data, format: .raw_deflate)! |
| 36 | } |
| 37 | |
| 38 | fn test_roundtrip_repeated() { |
| 39 | data := 'abcabc'.repeat(100).bytes() |
| 40 | compressed := compress(data)! |
| 41 | assert compressed.len < data.len |
| 42 | assert decompress(compressed)! == data |
| 43 | } |
| 44 | |
| 45 | fn test_bad_compression_method_fails() { |
| 46 | bad := [u8(0x79), 0x18, 0x00, 0x00, 0x00, 0x00] |
| 47 | decompress(bad) or { |
| 48 | assert err.msg().len > 0 |
| 49 | return |
| 50 | } |
| 51 | assert false |
| 52 | } |
| 53 | |
| 54 | fn test_corrupt_checksum_fails() { |
| 55 | mut enc := compress(('hello world').repeat(10).bytes())! |
| 56 | // flip a byte in the adler32 footer |
| 57 | enc[enc.len - 1] ^= 0xff |
| 58 | decompress(enc) or { |
| 59 | assert err.msg().contains('adler32') |
| 60 | return |
| 61 | } |
| 62 | assert false |
| 63 | } |
| 64 | |
| 65 | fn test_truncated_zlib_payload_fails() { |
| 66 | decompress([u8(0x78), 0x9c, 0x03, 0x00, 0x00, 0x00, 0x01]) or { |
| 67 | assert err.msg().contains('unexpected end of stream') |
| 68 | return |
| 69 | } |
| 70 | assert false |
| 71 | } |
| 72 | |
| 73 | fn test_zlib_inserted_bytes_before_adler_fails() { |
| 74 | enc := compress('zlib injected trailer bytes'.repeat(4).bytes())! |
| 75 | mut bad := []u8{cap: enc.len + 2} |
| 76 | bad << enc[..enc.len - 4] |
| 77 | bad << [u8(0xaa), 0x55] |
| 78 | bad << enc[enc.len - 4..] |
| 79 | decompress(bad) or { |
| 80 | assert err.msg() == 'invalid zlib stream: trailing data before adler32' |
| 81 | return |
| 82 | } |
| 83 | assert false |
| 84 | } |
| 85 | |
| 86 | fn test_gzip_inserted_bytes_before_trailer_fails() { |
| 87 | enc := compress('gzip injected trailer bytes'.repeat(4).bytes(), format: .gzip)! |
| 88 | mut bad := []u8{cap: enc.len + 1} |
| 89 | bad << enc[..enc.len - 8] |
| 90 | bad << u8(0x42) |
| 91 | bad << enc[enc.len - 8..] |
| 92 | decompress(bad) or { |
| 93 | assert err.msg() == 'invalid gzip stream: trailing data before trailer' |
| 94 | return |
| 95 | } |
| 96 | assert false |
| 97 | } |
| 98 | |