| #include "unity/unity.h" |
| #include "zlib.h" |
|
|
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdint.h> |
|
|
| |
| extern int test_deflate_stored(void *s, int flush); |
|
|
| static void fill_pattern(unsigned char *buf, size_t len) { |
| |
| for (size_t i = 0; i < len; i++) { |
| buf[i] = (unsigned char)((i * 31u + 7u) & 0xFF); |
| } |
| } |
|
|
| void setUp(void) { |
| |
| } |
|
|
| void tearDown(void) { |
| |
| } |
|
|
| |
| static void init_stream(z_stream *strm, int level) { |
| memset(strm, 0, sizeof(*strm)); |
| |
| int ret = deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, 8, Z_DEFAULT_STRATEGY); |
| TEST_ASSERT_EQUAL_INT(Z_OK, ret); |
| } |
|
|
| |
| static void cleanup_stream(z_stream *strm) { |
| int ret = deflateEnd(strm); |
| TEST_ASSERT_EQUAL_INT(Z_OK, ret); |
| } |
|
|
| |
| |
| static void assert_output_has_input_tail(const unsigned char *out, uLong total_out, |
| const unsigned char *in, size_t in_len) { |
| TEST_ASSERT_TRUE_MESSAGE(total_out >= (uLong)in_len, "total_out is smaller than input length; no room for header"); |
| size_t header_len = (size_t)(total_out - (uLong)in_len); |
| |
| TEST_ASSERT_TRUE_MESSAGE(header_len >= 1, "Header length should be at least 1 byte"); |
| TEST_ASSERT_EQUAL_UINT8_ARRAY(in, out + header_len, in_len); |
| } |
|
|
| void test_deflate_stored_direct_copy_no_flush(void) { |
| z_stream strm; |
| init_stream(&strm, 0); |
|
|
| const size_t in_len = 1000; |
| unsigned char *in = (unsigned char *)malloc(in_len); |
| TEST_ASSERT_NOT_NULL(in); |
| fill_pattern(in, in_len); |
|
|
| const size_t out_cap = in_len + 128; |
| unsigned char *out = (unsigned char *)malloc(out_cap); |
| TEST_ASSERT_NOT_NULL(out); |
| memset(out, 0xA5, out_cap); |
|
|
| strm.next_in = in; |
| strm.avail_in = (uInt)in_len; |
| strm.next_out = out; |
| strm.avail_out = (uInt)out_cap; |
|
|
| |
| int bstate = test_deflate_stored(strm.state, Z_NO_FLUSH); |
|
|
| |
| TEST_ASSERT_EQUAL_INT(0, bstate); |
|
|
| |
| TEST_ASSERT_EQUAL_UINT(0, strm.avail_in); |
|
|
| |
| TEST_ASSERT_TRUE(strm.total_out >= (uLong)in_len); |
| assert_output_has_input_tail(out, strm.total_out, in, in_len); |
|
|
| |
| uLong expected = adler32(adler32(0L, Z_NULL, 0), in, (uInt)in_len); |
| TEST_ASSERT_EQUAL_UINT(expected, strm.adler); |
|
|
| free(in); |
| free(out); |
| cleanup_stream(&strm); |
| } |
|
|
| void test_deflate_stored_finish_done_single_block(void) { |
| z_stream strm; |
| init_stream(&strm, 0); |
|
|
| const size_t in_len = 50; |
| unsigned char *in = (unsigned char *)malloc(in_len); |
| TEST_ASSERT_NOT_NULL(in); |
| fill_pattern(in, in_len); |
|
|
| const size_t out_cap = in_len + 128; |
| unsigned char *out = (unsigned char *)malloc(out_cap); |
| TEST_ASSERT_NOT_NULL(out); |
| memset(out, 0, out_cap); |
|
|
| strm.next_in = in; |
| strm.avail_in = (uInt)in_len; |
| strm.next_out = out; |
| strm.avail_out = (uInt)out_cap; |
|
|
| int bstate = test_deflate_stored(strm.state, Z_FINISH); |
|
|
| |
| TEST_ASSERT_EQUAL_INT(3, bstate); |
| TEST_ASSERT_EQUAL_UINT(0, strm.avail_in); |
|
|
| |
| TEST_ASSERT_TRUE(strm.total_out >= (uLong)in_len); |
| assert_output_has_input_tail(out, strm.total_out, in, in_len); |
|
|
| |
| uLong expected = adler32(adler32(0L, Z_NULL, 0), in, (uInt)in_len); |
| TEST_ASSERT_EQUAL_UINT(expected, strm.adler); |
|
|
| free(in); |
| free(out); |
| cleanup_stream(&strm); |
| } |
|
|
| void test_deflate_stored_no_output_space_large_input(void) { |
| z_stream strm; |
| init_stream(&strm, 0); |
|
|
| const size_t in_len = 70000; |
| unsigned char *in = (unsigned char *)malloc(in_len); |
| TEST_ASSERT_NOT_NULL(in); |
| fill_pattern(in, in_len); |
|
|
| unsigned char out_dummy; |
|
|
| strm.next_in = in; |
| strm.avail_in = (uInt)in_len; |
| strm.next_out = &out_dummy; |
| strm.avail_out = 0; |
|
|
| uLong total_in_before = strm.total_in; |
| uLong total_out_before = strm.total_out; |
|
|
| int bstate = test_deflate_stored(strm.state, Z_NO_FLUSH); |
|
|
| |
| TEST_ASSERT_EQUAL_INT(0, bstate); |
|
|
| |
| TEST_ASSERT_TRUE(strm.total_in > total_in_before); |
|
|
| |
| TEST_ASSERT_EQUAL_UINT(total_out_before, strm.total_out); |
|
|
| |
| uLong consumed = strm.total_in - total_in_before; |
| uLong expected = adler32(adler32(0L, Z_NULL, 0), in, (uInt)consumed); |
| TEST_ASSERT_EQUAL_UINT(expected, strm.adler); |
|
|
| free(in); |
| cleanup_stream(&strm); |
| } |
|
|
| void test_deflate_stored_sync_flush_block_done(void) { |
| z_stream strm; |
| init_stream(&strm, 0); |
|
|
| const size_t in_len = 10; |
| unsigned char *in = (unsigned char *)malloc(in_len); |
| TEST_ASSERT_NOT_NULL(in); |
| fill_pattern(in, in_len); |
|
|
| const size_t out_cap = in_len + 64; |
| unsigned char *out = (unsigned char *)malloc(out_cap); |
| TEST_ASSERT_NOT_NULL(out); |
| memset(out, 0, out_cap); |
|
|
| strm.next_in = in; |
| strm.avail_in = (uInt)in_len; |
| strm.next_out = out; |
| strm.avail_out = (uInt)out_cap; |
|
|
| int bstate = test_deflate_stored(strm.state, Z_SYNC_FLUSH); |
|
|
| |
| TEST_ASSERT_EQUAL_INT(1, bstate); |
| TEST_ASSERT_EQUAL_UINT(0, strm.avail_in); |
|
|
| |
| TEST_ASSERT_TRUE(strm.total_out >= (uLong)in_len); |
| assert_output_has_input_tail(out, strm.total_out, in, in_len); |
|
|
| |
| uLong expected = adler32(adler32(0L, Z_NULL, 0), in, (uInt)in_len); |
| TEST_ASSERT_EQUAL_UINT(expected, strm.adler); |
|
|
| free(in); |
| free(out); |
| cleanup_stream(&strm); |
| } |
|
|
| void test_deflate_stored_too_little_out_for_header_small_input(void) { |
| z_stream strm; |
| init_stream(&strm, 0); |
|
|
| const size_t in_len = 10; |
| unsigned char *in = (unsigned char *)malloc(in_len); |
| TEST_ASSERT_NOT_NULL(in); |
| fill_pattern(in, in_len); |
|
|
| unsigned char out4[4]; |
|
|
| strm.next_in = in; |
| strm.avail_in = (uInt)in_len; |
| strm.next_out = out4; |
| strm.avail_out = 4; |
|
|
| uLong total_in_before = strm.total_in; |
| uLong total_out_before = strm.total_out; |
|
|
| int bstate = test_deflate_stored(strm.state, Z_NO_FLUSH); |
|
|
| |
| TEST_ASSERT_EQUAL_INT(0, bstate); |
|
|
| |
| TEST_ASSERT_EQUAL_UINT((uLong)(total_in_before + in_len), strm.total_in); |
|
|
| |
| TEST_ASSERT_EQUAL_UINT(total_out_before, strm.total_out); |
|
|
| |
| uLong expected = adler32(adler32(0L, Z_NULL, 0), in, (uInt)in_len); |
| TEST_ASSERT_EQUAL_UINT(expected, strm.adler); |
|
|
| free(in); |
| cleanup_stream(&strm); |
| } |
|
|
| int main(void) { |
| UNITY_BEGIN(); |
| RUN_TEST(test_deflate_stored_direct_copy_no_flush); |
| RUN_TEST(test_deflate_stored_finish_done_single_block); |
| RUN_TEST(test_deflate_stored_no_output_space_large_input); |
| RUN_TEST(test_deflate_stored_sync_flush_block_done); |
| RUN_TEST(test_deflate_stored_too_little_out_for_header_small_input); |
| return UNITY_END(); |
| } |