| #include "unity/unity.h" |
| #include "zlib.h" |
|
|
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdint.h> |
|
|
| |
| extern uLong test_adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); |
|
|
| |
| void setUp(void) { |
| |
| } |
| void tearDown(void) { |
| |
| } |
|
|
| |
|
|
| static void fill_pattern(unsigned char *buf, size_t len, unsigned int seed) { |
| |
| uint32_t x = 0x1234567u ^ seed; |
| for (size_t i = 0; i < len; i++) { |
| |
| 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) { |
| |
| 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); |
| } |
|
|
| |
|
|
| 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) { |
| |
| 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) { |
| |
| 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) { |
| |
| 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); |
|
|
| |
| uLong aAB = test_adler32_combine_(aA, aB, (z_off64_t)lenB); |
| uLong aABC1 = test_adler32_combine_(aAB, aC, (z_off64_t)lenC); |
|
|
| |
| 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)); |
|
|
| |
| 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(); |
| } |