zlib / tests /tests_crc32_braid.c
AryaWu's picture
Upload folder using huggingface_hub
e996a55 verified
#include "unity/unity.h"
#include "zlib.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
/*
Reference CRC32 implementation (IEEE 802.3, reflected, poly 0xEDB88320),
independent of zlib internals. This matches zlib's crc32 with initial crc=0.
*/
static uint32_t ref_crc32(const unsigned char *buf, size_t len) {
uint32_t crc = 0xFFFFFFFFu;
for (size_t i = 0; i < len; i++) {
crc ^= buf[i];
for (int k = 0; k < 8; k++) {
uint32_t mask = -(crc & 1u);
crc = (crc >> 1) ^ (0xEDB88320u & mask);
}
}
return crc ^ 0xFFFFFFFFu;
}
/* Deterministic pseudo-random filler */
static void fill_buffer(unsigned char *buf, size_t len, uint32_t seed) {
uint32_t x = seed ? seed : 1u;
for (size_t i = 0; i < len; i++) {
x = 1664525u * x + 1013904223u; /* LCG */
buf[i] = (unsigned char)(x >> 24);
}
}
void setUp(void) {
/* no-op */
}
void tearDown(void) {
/* no-op */
}
/* Sanity check with a standard test vector. */
void test_local_void_braid_z_crc_t_ltl_256_z_word_t_big_256_int_n_int_w_known_vector(void) {
const unsigned char msg[] = "123456789"; /* length 9 */
uint32_t expected = 0xCBF43926u; /* standard CRC-32 of "123456789" */
/* Force table initialization if dynamic. */
(void)get_crc_table();
uLong got = crc32(0L, msg, (uInt)sizeof(msg) - 1);
TEST_ASSERT_EQUAL_HEX32(expected, (uint32_t)got);
}
/* Large aligned buffer to exercise braided path. */
void test_local_void_braid_z_crc_t_ltl_256_z_word_t_big_256_int_n_int_w_large_aligned_buffer(void) {
const size_t len = 1u << 20; /* 1 MiB, ample to trigger braided path */
unsigned char *buf = (unsigned char *)malloc(len + 16); /* extra for potential alignment tests */
TEST_ASSERT_NOT_NULL(buf);
fill_buffer(buf, len, 0x12345678u);
/* Reference */
uint32_t ref = ref_crc32(buf, len);
/* zlib */
(void)get_crc_table();
uLong got = crc32(0L, buf, (uInt)len);
TEST_ASSERT_EQUAL_HEX32(ref, (uint32_t)got);
free(buf);
}
/* Large misaligned buffer offsets to ensure pre-alignment + braided processing works. */
void test_local_void_braid_z_crc_t_ltl_256_z_word_t_big_256_int_n_int_w_large_misaligned_offsets(void) {
const size_t len = (1u << 20) + 7; /* slightly over 1 MiB to vary alignments */
unsigned char *base = (unsigned char *)malloc(len + 16);
TEST_ASSERT_NOT_NULL(base);
fill_buffer(base, len + 8, 0xCAFEBABEu);
for (size_t off = 0; off < 4; off++) { /* test a few misalignments */
const unsigned char *buf = base + off;
size_t sublen = len - off;
uint32_t ref = ref_crc32(buf, sublen);
(void)get_crc_table();
uLong got = crc32(0L, buf, (uInt)sublen);
TEST_ASSERT_EQUAL_HEX32(ref, (uint32_t)got);
}
free(base);
}
/* Incremental processing should equal single-pass CRC (also exercises braided internals on large data). */
void test_local_void_braid_z_crc_t_ltl_256_z_word_t_big_256_int_n_int_w_incremental_equals_single_pass(void) {
const size_t len = (1u << 20) + 123; /* non-round size */
unsigned char *buf = (unsigned char *)malloc(len);
TEST_ASSERT_NOT_NULL(buf);
fill_buffer(buf, len, 0xA5A5A5A5u);
/* Single pass reference (independent) */
uint32_t ref = ref_crc32(buf, len);
/* zlib single pass */
(void)get_crc_table();
uLong z_single = crc32(0L, buf, (uInt)len);
/* zlib incremental: split in arbitrary chunks */
size_t cut1 = len / 3;
size_t cut2 = (2 * len) / 3;
uLong z_inc = crc32(0L, buf, (uInt)cut1);
z_inc = crc32(z_inc, buf + cut1, (uInt)(cut2 - cut1));
z_inc = crc32(z_inc, buf + cut2, (uInt)(len - cut2));
TEST_ASSERT_EQUAL_HEX32(ref, (uint32_t)z_single);
TEST_ASSERT_EQUAL_HEX32((uint32_t)z_single, (uint32_t)z_inc);
free(buf);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_local_void_braid_z_crc_t_ltl_256_z_word_t_big_256_int_n_int_w_known_vector);
RUN_TEST(test_local_void_braid_z_crc_t_ltl_256_z_word_t_big_256_int_n_int_w_large_aligned_buffer);
RUN_TEST(test_local_void_braid_z_crc_t_ltl_256_z_word_t_big_256_int_n_int_w_large_misaligned_offsets);
RUN_TEST(test_local_void_braid_z_crc_t_ltl_256_z_word_t_big_256_int_n_int_w_incremental_equals_single_pass);
return UNITY_END();
}