Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,208 @@
|
||||
module gzip
|
||||
|
||||
import hash.crc32
|
||||
import os
|
||||
|
||||
const test_ftext = u8(0b0000_0001)
|
||||
const test_fhcrc = u8(0b0000_0010)
|
||||
const test_fextra = u8(0b0000_0100)
|
||||
const test_fname = u8(0b0000_1000)
|
||||
const test_fcomment = u8(0b0001_0000)
|
||||
const samples_folder = os.join_path(os.dir(@FILE), 'samples')
|
||||
|
||||
fn test_gzip() {
|
||||
uncompressed := 'Hello world!'
|
||||
compressed := compress(uncompressed.bytes())!
|
||||
decompressed := decompress(compressed)!
|
||||
assert decompressed == uncompressed.bytes()
|
||||
}
|
||||
|
||||
fn assert_decompress_error(data []u8, reason string) ! {
|
||||
decompress(data) or {
|
||||
assert err.msg() == reason
|
||||
return
|
||||
}
|
||||
return error('did not error')
|
||||
}
|
||||
|
||||
fn test_gzip_invalid_too_short() {
|
||||
assert_decompress_error([]u8{}, 'invalid gzip stream: too short')!
|
||||
}
|
||||
|
||||
fn test_gzip_invalid_magic_numbers() {
|
||||
assert_decompress_error([]u8{len: 100}, 'invalid gzip stream: bad magic')!
|
||||
}
|
||||
|
||||
fn test_gzip_invalid_compression() {
|
||||
mut data := []u8{len: 100}
|
||||
data[0] = 0x1f
|
||||
data[1] = 0x8b
|
||||
assert_decompress_error(data, 'invalid gzip stream: unsupported compression method')!
|
||||
}
|
||||
|
||||
fn test_gzip_with_ftext() {
|
||||
uncompressed := 'Hello world!'
|
||||
mut compressed := compress(uncompressed.bytes())!
|
||||
compressed[3] |= test_ftext
|
||||
decompressed := decompress(compressed)!
|
||||
assert decompressed == uncompressed.bytes()
|
||||
}
|
||||
|
||||
fn test_gzip_with_fname() {
|
||||
uncompressed := 'Hello world!'
|
||||
mut compressed := compress(uncompressed.bytes())!
|
||||
compressed[3] |= test_fname
|
||||
compressed.insert(10, `h`)
|
||||
compressed.insert(11, `i`)
|
||||
compressed.insert(12, 0x00)
|
||||
decompressed := decompress(compressed)!
|
||||
assert decompressed == uncompressed.bytes()
|
||||
}
|
||||
|
||||
fn test_gzip_with_fcomment() {
|
||||
uncompressed := 'Hello world!'
|
||||
mut compressed := compress(uncompressed.bytes())!
|
||||
compressed[3] |= test_fcomment
|
||||
compressed.insert(10, `h`)
|
||||
compressed.insert(11, `i`)
|
||||
compressed.insert(12, 0x00)
|
||||
decompressed := decompress(compressed)!
|
||||
assert decompressed == uncompressed.bytes()
|
||||
}
|
||||
|
||||
fn test_gzip_with_fname_fcomment() {
|
||||
uncompressed := 'Hello world!'
|
||||
mut compressed := compress(uncompressed.bytes())!
|
||||
compressed[3] |= (test_fname | test_fcomment)
|
||||
compressed.insert(10, `h`)
|
||||
compressed.insert(11, `i`)
|
||||
compressed.insert(12, 0x00)
|
||||
compressed.insert(10, `h`)
|
||||
compressed.insert(11, `i`)
|
||||
compressed.insert(12, 0x00)
|
||||
decompressed := decompress(compressed)!
|
||||
assert decompressed == uncompressed.bytes()
|
||||
}
|
||||
|
||||
fn test_gzip_with_fextra() {
|
||||
uncompressed := 'Hello world!'
|
||||
mut compressed := compress(uncompressed.bytes())!
|
||||
compressed[3] |= test_fextra
|
||||
// XLEN is 2-byte little-endian value
|
||||
xlen := u16(2)
|
||||
compressed.insert(10, u8(xlen))
|
||||
compressed.insert(11, u8(xlen >> 8))
|
||||
compressed.insert(12, `h`)
|
||||
compressed.insert(13, `i`)
|
||||
decompressed := decompress(compressed)!
|
||||
assert decompressed == uncompressed.bytes()
|
||||
}
|
||||
|
||||
fn test_gzip_with_hcrc() {
|
||||
uncompressed := 'Hello world!'
|
||||
mut compressed := compress(uncompressed.bytes())!
|
||||
compressed[3] |= test_fhcrc
|
||||
// FHCRC is 2-byte CRC-16 (low 16 bits of CRC32) in little-endian format
|
||||
checksum := crc32.sum(compressed[..10])
|
||||
crc16 := u16(checksum & 0xffff)
|
||||
compressed.insert(10, u8(crc16))
|
||||
compressed.insert(11, u8(crc16 >> 8))
|
||||
decompressed := decompress(compressed)!
|
||||
assert decompressed == uncompressed.bytes()
|
||||
}
|
||||
|
||||
fn test_gzip_with_invalid_hcrc() {
|
||||
uncompressed := 'Hello world!'
|
||||
mut compressed := compress(uncompressed.bytes())!
|
||||
compressed[3] |= test_fhcrc
|
||||
// FHCRC is 2-byte CRC-16 (low 16 bits of CRC32) in little-endian format
|
||||
checksum := crc32.sum(compressed[..10])
|
||||
crc16 := u16(checksum & 0xffff)
|
||||
compressed.insert(10, u8(crc16))
|
||||
compressed.insert(11, u8((crc16 >> 8) + 1)) // corrupt high byte
|
||||
assert_decompress_error(compressed, 'invalid gzip stream: header crc16 mismatch')!
|
||||
}
|
||||
|
||||
fn test_gzip_with_invalid_checksum() {
|
||||
uncompressed := 'Hello world!'
|
||||
mut compressed := compress(uncompressed.bytes())!
|
||||
compressed[compressed.len - 5] += 1
|
||||
assert_decompress_error(compressed, 'invalid gzip stream: crc32 mismatch')!
|
||||
}
|
||||
|
||||
fn test_gzip_with_invalid_length() {
|
||||
uncompressed := 'Hello world!'
|
||||
mut compressed := compress(uncompressed.bytes())!
|
||||
compressed[compressed.len - 1] += 1
|
||||
assert_decompress_error(compressed, 'invalid gzip stream: size mismatch')!
|
||||
}
|
||||
|
||||
fn test_gzip_with_invalid_flags() {
|
||||
uncompressed := 'Hello world!'
|
||||
mut compressed := compress(uncompressed.bytes())!
|
||||
compressed[3] |= 0b1000_0000
|
||||
assert_decompress_error(compressed, 'invalid gzip stream: reserved flags set')!
|
||||
}
|
||||
|
||||
fn test_gzip_decompress_callback() {
|
||||
uncompressed := '321323'.repeat(10_000)
|
||||
gz := compress(uncompressed.bytes())!
|
||||
mut size := 0
|
||||
mut ref := &size
|
||||
decoded := decompress_with_callback(gz, fn (chunk []u8, ref &int) int {
|
||||
unsafe {
|
||||
*ref += chunk.len
|
||||
}
|
||||
return chunk.len
|
||||
}, ref)!
|
||||
assert decoded == size
|
||||
assert decoded == uncompressed.len
|
||||
}
|
||||
|
||||
fn test_gzip_decompress_callback_rejects_non_gzip() {
|
||||
z := [u8(0x78), 0x9c, 0x03, 0x00, 0x00, 0x00, 0x01]
|
||||
decompress_with_callback(z, fn (chunk []u8, _ voidptr) int {
|
||||
return chunk.len
|
||||
}, unsafe { nil }) or {
|
||||
assert err.msg() == 'invalid gzip stream: too short'
|
||||
return
|
||||
}
|
||||
assert false
|
||||
}
|
||||
|
||||
fn s(fname string) string {
|
||||
return os.join_path(samples_folder, fname)
|
||||
}
|
||||
|
||||
fn read_and_decode_file(fpath string) !([]u8, string) {
|
||||
compressed := os.read_bytes(fpath)!
|
||||
decoded := decompress(compressed)!
|
||||
content := decoded.bytestr()
|
||||
return compressed, content
|
||||
}
|
||||
|
||||
fn test_reading_and_decoding_a_known_gziped_file() {
|
||||
compressed, content := read_and_decode_file(s('known.gz'))!
|
||||
assert compressed#[0..3] == [u8(31), 139, 8]
|
||||
assert compressed#[-5..] == [u8(127), 115, 1, 0, 0]
|
||||
assert content.contains('## Description')
|
||||
assert content.contains('## Examples:')
|
||||
assert content.ends_with('```\n')
|
||||
}
|
||||
|
||||
fn test_decoding_all_samples_files() {
|
||||
for gz_file in os.walk_ext(samples_folder, '.gz') {
|
||||
_, content := read_and_decode_file(gz_file)!
|
||||
assert content.len > 0, 'decoded content should not be empty: `${content}`'
|
||||
}
|
||||
}
|
||||
|
||||
fn test_reading_gzip_files_compressed_with_different_options() {
|
||||
_, content1 := read_and_decode_file(s('readme_level_1.gz'))!
|
||||
_, content5 := read_and_decode_file(s('readme_level_5.gz'))!
|
||||
_, content9 := read_and_decode_file(s('readme_level_9.gz'))!
|
||||
_, content9_rsyncable := read_and_decode_file(s('readme_level_9_rsyncable.gz'))!
|
||||
assert content9_rsyncable == content9
|
||||
assert content9 == content5
|
||||
assert content5 == content1
|
||||
}
|
||||
Reference in new issue
Block a user