| #include "unity/unity.h" |
| #include "zlib.h" |
| #include <stdlib.h> |
| #include <string.h> |
|
|
| |
| #define ZLIB_INTERNAL |
| #include "deflate.h" |
|
|
| |
| extern void test_slide_hash(deflate_state *s); |
|
|
| static void init_stream(z_streamp strm, int windowBits, int memLevel) { |
| memset(strm, 0, sizeof(*strm)); |
| int ret = deflateInit2_(strm, |
| Z_DEFAULT_COMPRESSION, |
| Z_DEFLATED, |
| windowBits, |
| memLevel, |
| Z_DEFAULT_STRATEGY, |
| ZLIB_VERSION, |
| (int)sizeof(z_stream)); |
| TEST_ASSERT_EQUAL_INT(Z_OK, ret); |
| } |
|
|
| static inline Pos after_one_slide(Pos m, uInt wsize) { |
| return (Pos)(m >= wsize ? (m - wsize) : (Pos)NIL); |
| } |
|
|
| static inline Pos after_n_slides(Pos m, uInt wsize, int n) { |
| for (int i = 0; i < n; i++) { |
| m = (Pos)(m >= wsize ? (m - wsize) : (Pos)NIL); |
| } |
| return m; |
| } |
|
|
| void setUp(void) { |
| |
| } |
| void tearDown(void) { |
| |
| } |
|
|
| |
| static void fill_pattern(deflate_state *s) { |
| uInt w = s->w_size; |
|
|
| for (uInt i = 0; i < s->hash_size; i++) { |
| Pos v; |
| switch (i % 5) { |
| case 0: v = (Pos)NIL; break; |
| case 1: v = (Pos)(w - 1); break; |
| case 2: v = (Pos)(w); break; |
| case 3: v = (Pos)(w + 7); break; |
| default: v = (Pos)(w * 2 + 123); break; |
| } |
| s->head[i] = v; |
| } |
|
|
| #ifndef FASTEST |
| for (uInt i = 0; i < s->w_size; i++) { |
| Pos v; |
| switch (i % 5) { |
| case 0: v = (Pos)NIL; break; |
| case 1: v = (Pos)(w - 1); break; |
| case 2: v = (Pos)(w); break; |
| case 3: v = (Pos)(w + 3); break; |
| default: v = (Pos)(w * 2 + 7); break; |
| } |
| s->prev[i] = v; |
| } |
| #endif |
| } |
|
|
| void test_slide_hash_shifts_values_correctly_small(void) { |
| z_stream strm; |
| init_stream(&strm, 9, 1); |
| deflate_state *s = (deflate_state *)strm.state; |
|
|
| fill_pattern(s); |
|
|
| |
| test_slide_hash(s); |
|
|
| |
| for (uInt i = 0; i < s->hash_size; i++) { |
| Pos before; |
| uInt w = s->w_size; |
| switch (i % 5) { |
| case 0: before = (Pos)NIL; break; |
| case 1: before = (Pos)(w - 1); break; |
| case 2: before = (Pos)(w); break; |
| case 3: before = (Pos)(w + 7); break; |
| default: before = (Pos)(w * 2 + 123); break; |
| } |
| Pos expected = after_one_slide(before, w); |
| TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, s->head[i], "head[] incorrect after one slide"); |
| } |
|
|
| #ifndef FASTEST |
| |
| for (uInt i = 0; i < s->w_size; i++) { |
| Pos before; |
| uInt w = s->w_size; |
| switch (i % 5) { |
| case 0: before = (Pos)NIL; break; |
| case 1: before = (Pos)(w - 1); break; |
| case 2: before = (Pos)(w); break; |
| case 3: before = (Pos)(w + 3); break; |
| default: before = (Pos)(w * 2 + 7); break; |
| } |
| Pos expected = after_one_slide(before, w); |
| TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, s->prev[i], "prev[] incorrect after one slide"); |
| } |
| #endif |
|
|
| TEST_ASSERT_EQUAL_INT(Z_OK, deflateEnd(&strm)); |
| } |
|
|
| void test_slide_hash_multiple_calls_accumulate_subtractions(void) { |
| z_stream strm; |
| init_stream(&strm, 9, 1); |
| deflate_state *s = (deflate_state *)strm.state; |
|
|
| fill_pattern(s); |
|
|
| |
| test_slide_hash(s); |
| test_slide_hash(s); |
|
|
| |
| for (uInt i = 0; i < s->hash_size; i++) { |
| Pos before; |
| uInt w = s->w_size; |
| switch (i % 5) { |
| case 0: before = (Pos)NIL; break; |
| case 1: before = (Pos)(w - 1); break; |
| case 2: before = (Pos)(w); break; |
| case 3: before = (Pos)(w + 7); break; |
| default: before = (Pos)(w * 2 + 123); break; |
| } |
| Pos expected = after_n_slides(before, w, 2); |
| TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, s->head[i], "head[] incorrect after two slides"); |
| } |
|
|
| #ifndef FASTEST |
| |
| for (uInt i = 0; i < s->w_size; i++) { |
| Pos before; |
| uInt w = s->w_size; |
| switch (i % 5) { |
| case 0: before = (Pos)NIL; break; |
| case 1: before = (Pos)(w - 1); break; |
| case 2: before = (Pos)(w); break; |
| case 3: before = (Pos)(w + 3); break; |
| default: before = (Pos)(w * 2 + 7); break; |
| } |
| Pos expected = after_n_slides(before, w, 2); |
| TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, s->prev[i], "prev[] incorrect after two slides"); |
| } |
| #endif |
|
|
| TEST_ASSERT_EQUAL_INT(Z_OK, deflateEnd(&strm)); |
| } |
|
|
| void test_slide_hash_leaves_params_unchanged(void) { |
| z_stream strm; |
| init_stream(&strm, 9, 1); |
| deflate_state *s = (deflate_state *)strm.state; |
|
|
| uInt w_size_before = s->w_size; |
| uInt hash_size_before = s->hash_size; |
| uInt w_mask_before = s->w_mask; |
| uInt hash_mask_before = s->hash_mask; |
|
|
| fill_pattern(s); |
| test_slide_hash(s); |
|
|
| TEST_ASSERT_EQUAL_UINT(w_size_before, s->w_size); |
| TEST_ASSERT_EQUAL_UINT(hash_size_before, s->hash_size); |
| TEST_ASSERT_EQUAL_UINT(w_mask_before, s->w_mask); |
| TEST_ASSERT_EQUAL_UINT(hash_mask_before, s->hash_mask); |
|
|
| TEST_ASSERT_EQUAL_INT(Z_OK, deflateEnd(&strm)); |
| } |
|
|
| void test_slide_hash_with_large_window_bits_boundary_cases(void) { |
| z_stream strm; |
| |
| init_stream(&strm, 15, 8); |
| deflate_state *s = (deflate_state *)strm.state; |
| uInt w = s->w_size; |
|
|
| |
| s->head[0] = (Pos)0; |
| s->head[1] = (Pos)(w - 1); |
| s->head[2] = (Pos)(w); |
| s->head[3] = (Pos)(w + 1); |
| s->head[4] = (Pos)(w + 123); |
|
|
| #ifndef FASTEST |
| |
| s->prev[0] = (Pos)0; |
| s->prev[1] = (Pos)(w - 1); |
| s->prev[2] = (Pos)(w); |
| s->prev[3] = (Pos)(w + 1); |
| s->prev[4] = (Pos)(w + 77); |
| #endif |
|
|
| test_slide_hash(s); |
|
|
| TEST_ASSERT_EQUAL_UINT16((Pos)0, s->head[0]); |
| TEST_ASSERT_EQUAL_UINT16((Pos)0, s->head[1]); |
| TEST_ASSERT_EQUAL_UINT16((Pos)0, s->head[2]); |
| TEST_ASSERT_EQUAL_UINT16((Pos)1, s->head[3]); |
| TEST_ASSERT_EQUAL_UINT16((Pos)123, s->head[4]); |
|
|
| #ifndef FASTEST |
| TEST_ASSERT_EQUAL_UINT16((Pos)0, s->prev[0]); |
| TEST_ASSERT_EQUAL_UINT16((Pos)0, s->prev[1]); |
| TEST_ASSERT_EQUAL_UINT16((Pos)0, s->prev[2]); |
| TEST_ASSERT_EQUAL_UINT16((Pos)1, s->prev[3]); |
| TEST_ASSERT_EQUAL_UINT16((Pos)77, s->prev[4]); |
| #endif |
|
|
| TEST_ASSERT_EQUAL_INT(Z_OK, deflateEnd(&strm)); |
| } |
|
|
| int main(void) { |
| UNITY_BEGIN(); |
| RUN_TEST(test_slide_hash_shifts_values_correctly_small); |
| RUN_TEST(test_slide_hash_multiple_calls_accumulate_subtractions); |
| RUN_TEST(test_slide_hash_leaves_params_unchanged); |
| RUN_TEST(test_slide_hash_with_large_window_bits_boundary_cases); |
| return UNITY_END(); |
| } |