158 lines
4.1 KiB
V
158 lines
4.1 KiB
V
import hash.crc32
|
|
|
|
const reflected_test_polys = [crc32.ieee, crc32.crc32c, crc32.crc32k, crc32.crc32q_reflected]
|
|
|
|
fn sum_for_reflected_poly(poly u32, data []u8) u32 {
|
|
return match poly {
|
|
crc32.ieee { crc32.sum(data) }
|
|
crc32.crc32c { crc32.sum_crc32c(data) }
|
|
crc32.crc32k { crc32.sum_crc32k(data) }
|
|
crc32.crc32q_reflected { crc32.sum_with_poly(crc32.crc32q_reflected, data) }
|
|
else { panic('unexpected polynomial in test') }
|
|
}
|
|
}
|
|
|
|
fn expected_reflected_crc_123456789(poly u32) u32 {
|
|
return match poly {
|
|
crc32.ieee { u32(0xcbf43926) }
|
|
crc32.crc32c { u32(0xe3069283) }
|
|
crc32.crc32k { u32(0x2d3dd0ae) }
|
|
crc32.crc32q_reflected { u32(0xa9cc8179) }
|
|
else { panic('unexpected polynomial in test') }
|
|
}
|
|
}
|
|
|
|
fn expected_reflected_crc_a(poly u32) u32 {
|
|
return match poly {
|
|
crc32.ieee { u32(0xe8b7be43) }
|
|
crc32.crc32c { u32(0xc1d04330) }
|
|
crc32.crc32k { u32(0x0da2aa8a) }
|
|
crc32.crc32q_reflected { u32(0x248ca0a3) }
|
|
else { panic('unexpected polynomial in test') }
|
|
}
|
|
}
|
|
|
|
fn assert_reflected_poly_paths_match(poly u32, data []u8) {
|
|
c := crc32.new(poly)
|
|
by_new := c.checksum(data)
|
|
assert by_new == crc32.sum_with_poly(poly, data)
|
|
assert by_new == sum_for_reflected_poly(poly, data)
|
|
}
|
|
|
|
fn test_hash_crc32() {
|
|
b1 := 'testing crc32'.bytes()
|
|
sum1 := crc32.sum(b1)
|
|
assert sum1 == u32(1212124400)
|
|
assert sum1.hex() == '483f8cf0'
|
|
|
|
c := crc32.new(crc32.ieee)
|
|
b2 := 'testing crc32 again'.bytes()
|
|
sum2 := c.checksum(b2)
|
|
assert sum2 == u32(1420327025)
|
|
assert sum2.hex() == '54a87871'
|
|
}
|
|
|
|
fn test_hash_crc32_variants() {
|
|
data := '123456789'.bytes()
|
|
for poly in reflected_test_polys {
|
|
expected := expected_reflected_crc_123456789(poly)
|
|
assert sum_for_reflected_poly(poly, data) == expected
|
|
assert_reflected_poly_paths_match(poly, data)
|
|
}
|
|
}
|
|
|
|
fn test_hash_crc32q_standard() {
|
|
data := '123456789'.bytes()
|
|
assert crc32.sum_crc32q(data) == u32(0x3010bf7f)
|
|
assert crc32.sum_with_poly(crc32.crc32q, data) == u32(0x3010bf7f)
|
|
assert crc32.sum_crc32q('a'.bytes()) == u32(0xd1112b6b)
|
|
}
|
|
|
|
fn test_hash_crc32_update() {
|
|
data := '123456789'.bytes()
|
|
part1 := data[..4]
|
|
part2 := data[4..]
|
|
|
|
c := crc32.new(crc32.ieee)
|
|
mut acc := u32(0)
|
|
acc = c.update(acc, part1)
|
|
acc = c.update(acc, part2)
|
|
|
|
assert acc == c.checksum(data)
|
|
assert acc.hex() == 'cbf43926'
|
|
}
|
|
|
|
fn test_hash_crc32_edge_cases() {
|
|
empty := ''.bytes()
|
|
one := 'a'.bytes()
|
|
for poly in reflected_test_polys {
|
|
assert sum_for_reflected_poly(poly, empty) == u32(0)
|
|
assert sum_for_reflected_poly(poly, one) == expected_reflected_crc_a(poly)
|
|
}
|
|
assert crc32.sum_crc32q(empty) == u32(0)
|
|
}
|
|
|
|
fn test_hash_crc32_sum_with_poly() {
|
|
data := 'variant helper'.bytes()
|
|
for poly in reflected_test_polys {
|
|
assert_reflected_poly_paths_match(poly, data)
|
|
}
|
|
assert crc32.sum_with_poly(crc32.crc32q, data) == crc32.sum_crc32q(data)
|
|
}
|
|
|
|
fn test_hash_crc32_sum_with_poly_custom() {
|
|
data := 'custom poly checksum'.bytes()
|
|
poly := u32(0xa833982b)
|
|
|
|
assert crc32.sum_with_poly(poly, data) == crc32.new(poly).checksum(data)
|
|
}
|
|
|
|
fn test_hash_crc32_all_polys_consistent() {
|
|
data := 'all polys consistent'.bytes()
|
|
part1 := data[..7]
|
|
part2 := data[7..]
|
|
|
|
for poly in reflected_test_polys {
|
|
c := crc32.new(poly)
|
|
full := c.checksum(data)
|
|
|
|
mut split := u32(0)
|
|
split = c.update(split, part1)
|
|
split = c.update(split, part2)
|
|
|
|
assert full == split
|
|
assert full == sum_for_reflected_poly(poly, data)
|
|
}
|
|
}
|
|
|
|
fn test_hash_crc32_streaming_chunk_sizes() {
|
|
data := ('streaming data block '.repeat(64)).bytes()
|
|
for poly in reflected_test_polys {
|
|
c := crc32.new(poly)
|
|
expected := c.checksum(data)
|
|
for chunk_size in [1, 2, 3, 5, 7, 16, 31, 64, 128] {
|
|
mut state := ~u32(0)
|
|
mut start := 0
|
|
for start < data.len {
|
|
end := if start + chunk_size < data.len { start + chunk_size } else { data.len }
|
|
state = c.update_state(state, data[start..end])
|
|
start = end
|
|
}
|
|
assert ~state == expected
|
|
}
|
|
}
|
|
}
|
|
|
|
fn test_hash_crc32_update_state() {
|
|
data := 'stateful streaming'.bytes()
|
|
part1 := data[..5]
|
|
part2 := data[5..]
|
|
c := crc32.new(crc32.crc32c)
|
|
|
|
mut state := ~u32(0)
|
|
state = c.update_state(state, part1)
|
|
state = c.update_state(state, part2)
|
|
|
|
assert ~state == c.checksum(data)
|
|
}
|