#include "unity/unity.h" #include "zlib.h" #include #include #include /* 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(); }