zlib / tests /tests_deflate_fill_window.c
AryaWu's picture
Upload folder using huggingface_hub
e996a55 verified
#include "unity/unity.h"
#include "zlib.h"
#include "deflate.h"
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
/* Wrapper provided in the module under test */
void test_fill_window(deflate_state *s);
static void init_deflater(z_stream *strm) {
memset(strm, 0, sizeof(*strm));
int ret = deflateInit(strm, Z_DEFAULT_COMPRESSION);
TEST_ASSERT_EQUAL_INT(Z_OK, ret);
}
static void cleanup_deflater(z_stream *strm) {
int ret = deflateEnd(strm);
TEST_ASSERT(ret == Z_OK || ret == Z_DATA_ERROR);
}
void setUp(void) {
/* Setup code here, or leave empty */
}
void tearDown(void) {
/* Cleanup code here, or leave empty */
}
/*
* Test that fill_window reads available input into the sliding window,
* updates lookahead, total_in, next_in, and adler (for zlib wrapper).
*/
void test_fill_window_reads_data_and_updates_adler_and_window(void) {
z_stream strm;
init_deflater(&strm);
deflate_state *s = (deflate_state *)strm.state;
TEST_ASSERT_NOT_NULL(s);
/* Prepare input */
const size_t in_len = 100;
unsigned char inbuf[in_len];
for (size_t i = 0; i < in_len; i++) inbuf[i] = (unsigned char)(i ^ 0x5A);
strm.next_in = inbuf;
strm.avail_in = (uInt)in_len;
/* Preconditions per fill_window assertion */
TEST_ASSERT_TRUE(s->lookahead < MIN_LOOKAHEAD);
/* Expected adler after read_buf with wrap==1 */
uLong expected_adler = adler32(strm.adler, inbuf, (uInt)in_len);
test_fill_window(s);
/* All input consumed */
TEST_ASSERT_EQUAL_UINT32_MESSAGE(in_len, strm.total_in, "total_in should equal input length");
TEST_ASSERT_EQUAL_UINT_MESSAGE(0, strm.avail_in, "avail_in should be zero after read");
/* Data copied into window at current position */
TEST_ASSERT_TRUE_MESSAGE(s->lookahead == in_len, "lookahead should equal input length when input is exhausted");
TEST_ASSERT_EQUAL_INT(0, memcmp(s->window + s->strstart, inbuf, in_len));
/* Adler updated (zlib wrapper default) */
TEST_ASSERT_EQUAL_UINT32(expected_adler, strm.adler);
/* High water advanced to at least current end */
TEST_ASSERT_TRUE(s->high_water >= (ulg)(s->strstart + s->lookahead));
cleanup_deflater(&strm);
}
/*
* Test that when there is no input available, fill_window doesn't change lookahead
* and doesn't consume anything.
*/
void test_fill_window_no_input_no_change(void) {
z_stream strm;
init_deflater(&strm);
deflate_state *s = (deflate_state *)strm.state;
TEST_ASSERT_NOT_NULL(s);
/* Ensure no input */
strm.next_in = Z_NULL;
strm.avail_in = 0;
/* track initial values */
uInt initial_lookahead = s->lookahead;
uLong initial_total_in = strm.total_in;
/* Precondition */
TEST_ASSERT_TRUE(s->lookahead < MIN_LOOKAHEAD);
test_fill_window(s);
TEST_ASSERT_EQUAL_UINT(initial_lookahead, s->lookahead);
TEST_ASSERT_EQUAL_UINT32(initial_total_in, strm.total_in);
cleanup_deflater(&strm);
}
/*
* Test that the high-water zeroing logic clears the window bytes after the
* current data position, up to WIN_INIT or window end, whichever is smaller.
*/
void test_fill_window_zeroes_high_water_region(void) {
z_stream strm;
init_deflater(&strm);
deflate_state *s = (deflate_state *)strm.state;
TEST_ASSERT_NOT_NULL(s);
/* Prefill entire window with non-zero so we can detect zeroing */
memset(s->window, 0xA5, (size_t)s->w_size * 2);
s->high_water = 0; /* ensure zeroing will be performed */
/* Small input to set curr just beyond start */
const uInt in_len = 16;
unsigned char inbuf[in_len];
for (uInt i = 0; i < in_len; i++) inbuf[i] = (unsigned char)(0xC3 ^ i);
strm.next_in = inbuf;
strm.avail_in = in_len;
/* Precondition */
TEST_ASSERT_TRUE(s->lookahead < MIN_LOOKAHEAD);
test_fill_window(s);
/* curr = s->strstart + s->lookahead (strstart is 0 initially) */
ulg curr = s->strstart + (ulg)s->lookahead;
TEST_ASSERT_EQUAL_UINT(in_len, curr);
/* Expected zero length */
ulg expected_zero = s->window_size - curr;
if (expected_zero > WIN_INIT) expected_zero = WIN_INIT;
/* Verify zeroing */
for (ulg i = 0; i < expected_zero; i++) {
TEST_ASSERT_EQUAL_UINT8_MESSAGE(0, s->window[curr + i], "high-water region should be zeroed");
}
/* High water should have advanced */
TEST_ASSERT_TRUE(s->high_water >= curr);
cleanup_deflater(&strm);
}
/*
* Test that when strstart is far enough, fill_window triggers a slide of the
* window, moving the upper half down, and adjusts match_start accordingly.
*/
void test_fill_window_triggers_slide_and_adjusts_pointers(void) {
z_stream strm;
init_deflater(&strm);
deflate_state *s = (deflate_state *)strm.state;
TEST_ASSERT_NOT_NULL(s);
uInt wsize = s->w_size; /* 32K by default */
ulg win_size = s->window_size; /* 2 * wsize */
/* Prepare window upper half with a known pattern */
uInt more = MIN_LOOKAHEAD; /* we will force 'more' to this */
uInt copy_len = wsize - more; /* amount copied during slide */
memset(s->window, 0x00, (size_t)wsize * 2);
memset(s->window + wsize, 0x5B, copy_len); /* pattern in upper half */
/* Force conditions to trigger the slide: strstart >= wsize + MAX_DIST(s)
which equals 2*wsize - MIN_LOOKAHEAD, with lookahead == 0 */
s->strstart = (uInt)(win_size - MIN_LOOKAHEAD);
s->lookahead = 0;
s->block_start = 0;
s->insert = 0;
s->match_start = wsize + 5; /* will be reduced by wsize */
/* Provide a byte of input so fill_window proceeds after sliding */
unsigned char inbyte = 0xAA;
strm.next_in = &inbyte;
strm.avail_in = 1;
test_fill_window(s);
/* After sliding, the lower part should contain the copied pattern */
for (uInt i = 0; i < copy_len; i++) {
TEST_ASSERT_EQUAL_UINT8(0x5B, s->window[i]);
}
/* match_start should be adjusted down by wsize */
TEST_ASSERT_EQUAL_UINT((uInt)5, s->match_start);
cleanup_deflater(&strm);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_fill_window_reads_data_and_updates_adler_and_window);
RUN_TEST(test_fill_window_no_input_no_change);
RUN_TEST(test_fill_window_zeroes_high_water_region);
RUN_TEST(test_fill_window_triggers_slide_and_adjusts_pointers);
return UNITY_END();
}