zlib / tests /tests_adler32_adler32_combine_.c
AryaWu's picture
Upload folder using huggingface_hub
e996a55 verified
#include "unity/unity.h"
#include "zlib.h"
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
/* Wrapper for the local function under test (provided in the module) */
extern uLong test_adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
/* Unity hooks */
void setUp(void) {
/* Setup code here, or leave empty */
}
void tearDown(void) {
/* Cleanup code here, or leave empty */
}
/* Helpers */
static void fill_pattern(unsigned char *buf, size_t len, unsigned int seed) {
/* Deterministic pseudo-random-ish but simple pattern based on seed */
uint32_t x = 0x1234567u ^ seed;
for (size_t i = 0; i < len; i++) {
/* LCG */
x = 1664525u * x + 1013904223u;
buf[i] = (unsigned char)((x >> 24) & 0xFFu);
}
}
static void fill_incrementing(unsigned char *buf, size_t len, unsigned char start) {
for (size_t i = 0; i < len; i++) {
buf[i] = (unsigned char)(start + (unsigned char)i);
}
}
static void fill_constant(unsigned char *buf, size_t len, unsigned char value) {
memset(buf, value, len);
}
static uLong adler_empty(void) {
/* Standard initial Adler-32 value via zlib API */
return adler32(0L, Z_NULL, 0);
}
static uLong adler_for(const unsigned char *buf, uInt len) {
return adler32(adler_empty(), (const Bytef *)buf, len);
}
static uLong adler_stream_two(const unsigned char *a, uInt lena,
const unsigned char *b, uInt lenb) {
uLong a1 = adler32(adler_empty(), (const Bytef *)a, lena);
return adler32(a1, (const Bytef *)b, lenb);
}
static uLong adler_stream_three(const unsigned char *a, uInt lena,
const unsigned char *b, uInt lenb,
const unsigned char *c, uInt lenc) {
uLong a1 = adler32(adler_empty(), (const Bytef *)a, lena);
uLong a2 = adler32(a1, (const Bytef *)b, lenb);
return adler32(a2, (const Bytef *)c, lenc);
}
/* Tests */
void test_adler32_combine__negative_length_returns_invalid(void) {
uLong a1 = adler_empty();
uLong a2 = adler_empty();
uLong res = test_adler32_combine_(a1, a2, (z_off64_t)-12345);
TEST_ASSERT_EQUAL_HEX32(0xFFFFFFFFUL, res);
}
void test_adler32_combine__zero_length_second_block_yields_first_when_second_is_empty(void) {
/* First block non-empty, second block empty (len2 = 0, adler2 = empty) */
const char *s1 = "The quick brown fox";
uInt len1 = (uInt)strlen(s1);
uLong adler1 = adler_for((const unsigned char *)s1, len1);
uLong adler2 = adler_empty();
z_off64_t len2 = 0;
uLong combined = test_adler32_combine_(adler1, adler2, len2);
TEST_ASSERT_EQUAL_HEX32(adler1, combined);
}
void test_adler32_combine__empty_first_block_yields_second(void) {
/* First block empty (adler1 = initial), second block non-empty */
const char *s2 = " jumps over the lazy dog.";
uInt len2 = (uInt)strlen(s2);
uLong adler1 = adler_empty();
uLong adler2 = adler_for((const unsigned char *)s2, len2);
uLong combined = test_adler32_combine_(adler1, adler2, (z_off64_t)len2);
TEST_ASSERT_EQUAL_HEX32(adler2, combined);
}
void test_adler32_combine__matches_streaming_small_text(void) {
const char *s1 = "Hello, ";
const char *s2 = "world!";
uInt len1 = (uInt)strlen(s1);
uInt len2 = (uInt)strlen(s2);
uLong adler1 = adler_for((const unsigned char *)s1, len1);
uLong adler2 = adler_for((const unsigned char *)s2, len2);
uLong combined = test_adler32_combine_(adler1, adler2, (z_off64_t)len2);
uLong reference = adler_stream_two((const unsigned char *)s1, len1,
(const unsigned char *)s2, len2);
TEST_ASSERT_EQUAL_HEX32(reference, combined);
}
void test_adler32_combine__matches_streaming_large_blocks_crossing_NMAX_boundaries(void) {
/* Create two large buffers, each > NMAX (~5552), to exercise modulo logic */
const uInt len1 = 6000;
const uInt len2 = 7000;
unsigned char *buf1 = (unsigned char *)malloc(len1);
unsigned char *buf2 = (unsigned char *)malloc(len2);
TEST_ASSERT_NOT_NULL(buf1);
TEST_ASSERT_NOT_NULL(buf2);
fill_pattern(buf1, len1, 101u);
fill_incrementing(buf2, len2, 37u);
uLong a1 = adler_for(buf1, len1);
uLong a2 = adler_for(buf2, len2);
uLong combined = test_adler32_combine_(a1, a2, (z_off64_t)len2);
uLong reference = adler_stream_two(buf1, len1, buf2, len2);
TEST_ASSERT_EQUAL_HEX32(reference, combined);
free(buf1);
free(buf2);
}
void test_adler32_combine__associativity_three_segments(void) {
const uInt lenA = 100;
const uInt lenB = 2000;
const uInt lenC = 6000;
unsigned char *A = (unsigned char *)malloc(lenA);
unsigned char *B = (unsigned char *)malloc(lenB);
unsigned char *C = (unsigned char *)malloc(lenC);
TEST_ASSERT_NOT_NULL(A);
TEST_ASSERT_NOT_NULL(B);
TEST_ASSERT_NOT_NULL(C);
fill_incrementing(A, lenA, 0u);
fill_pattern(B, lenB, 777u);
fill_pattern(C, lenC, 424242u);
uLong aA = adler_for(A, lenA);
uLong aB = adler_for(B, lenB);
uLong aC = adler_for(C, lenC);
/* (A + B) + C */
uLong aAB = test_adler32_combine_(aA, aB, (z_off64_t)lenB);
uLong aABC1 = test_adler32_combine_(aAB, aC, (z_off64_t)lenC);
/* A + (B + C) */
uLong aBC = test_adler32_combine_(aB, aC, (z_off64_t)lenC);
uLong aABC2 = test_adler32_combine_(aA, aBC, (z_off64_t)((z_off64_t)lenB + (z_off64_t)lenC));
/* Reference via streaming */
uLong reference = adler_stream_three(A, lenA, B, lenB, C, lenC);
TEST_ASSERT_EQUAL_HEX32(reference, aABC1);
TEST_ASSERT_EQUAL_HEX32(reference, aABC2);
TEST_ASSERT_EQUAL_HEX32(aABC1, aABC2);
free(A);
free(B);
free(C);
}
void test_adler32_combine__second_block_all_0xFF(void) {
const uInt len1 = 513;
const uInt len2 = 4096;
unsigned char *buf1 = (unsigned char *)malloc(len1);
unsigned char *buf2 = (unsigned char *)malloc(len2);
TEST_ASSERT_NOT_NULL(buf1);
TEST_ASSERT_NOT_NULL(buf2);
fill_pattern(buf1, len1, 1234u);
fill_constant(buf2, len2, 0xFFu);
uLong a1 = adler_for(buf1, len1);
uLong a2 = adler_for(buf2, len2);
uLong combined = test_adler32_combine_(a1, a2, (z_off64_t)len2);
uLong reference = adler_stream_two(buf1, len1, buf2, len2);
TEST_ASSERT_EQUAL_HEX32(reference, combined);
free(buf1);
free(buf2);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_adler32_combine__negative_length_returns_invalid);
RUN_TEST(test_adler32_combine__zero_length_second_block_yields_first_when_second_is_empty);
RUN_TEST(test_adler32_combine__empty_first_block_yields_second);
RUN_TEST(test_adler32_combine__matches_streaming_small_text);
RUN_TEST(test_adler32_combine__matches_streaming_large_blocks_crossing_NMAX_boundaries);
RUN_TEST(test_adler32_combine__associativity_three_segments);
RUN_TEST(test_adler32_combine__second_block_all_0xFF);
return UNITY_END();
}