| #include "unity/unity.h" |
| #include "zlib.h" |
|
|
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdint.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
|
|
| |
| |
| #include "gzguts.h" |
|
|
| |
| extern int test_gz_avail(gz_statep state); |
|
|
| |
|
|
| static gzFile gzfile_from_bytes(const unsigned char *data, size_t len) { |
| char path[] = "/tmp/gzread_test_XXXXXX"; |
| int fd = mkstemp(path); |
| TEST_ASSERT_MESSAGE(fd != -1, "mkstemp failed"); |
|
|
| ssize_t w = write(fd, data, len); |
| TEST_ASSERT_MESSAGE(w >= 0, "write failed"); |
| TEST_ASSERT_EQUAL_UINT32((uint32_t)len, (uint32_t)w); |
|
|
| |
| off_t off = lseek(fd, 0, SEEK_SET); |
| TEST_ASSERT_MESSAGE(off == 0, "lseek failed"); |
|
|
| |
| gzFile f = gzdopen(fd, "rb"); |
| TEST_ASSERT_NOT_NULL_MESSAGE(f, "gzdopen failed"); |
|
|
| |
| unlink(path); |
| return f; |
| } |
|
|
| |
| |
| static void prepare_in_buffer(gz_statep s, unsigned want) { |
| s->want = want; |
| s->in = (unsigned char *)malloc(want); |
| TEST_ASSERT_NOT_NULL(s->in); |
| s->size = want; |
|
|
| |
| s->strm.avail_in = 0; |
| s->strm.next_in = s->in; |
|
|
| |
| s->eof = 0; |
| s->err = Z_OK; |
| } |
|
|
| |
| |
| static void free_reset_buffers(gz_statep s) { |
| if (s->in) { |
| free(s->in); |
| s->in = NULL; |
| } |
| s->size = 0; |
| s->strm.avail_in = 0; |
| s->strm.next_in = NULL; |
| } |
|
|
| |
| void setUp(void) { |
| |
| } |
|
|
| void tearDown(void) { |
| |
| } |
|
|
| |
|
|
| void test_gz_avail_reads_into_empty_buffer_and_sets_eof(void) { |
| const unsigned char data[] = "Hello, zlib gz_avail!"; |
| const size_t len = sizeof(data) - 1; |
|
|
| gzFile f = gzfile_from_bytes(data, len); |
| gz_statep s = (gz_statep)f; |
|
|
| |
| prepare_in_buffer(s, 64); |
|
|
| int rc = test_gz_avail(s); |
| TEST_ASSERT_EQUAL_INT(0, rc); |
| TEST_ASSERT_EQUAL_PTR(s->in, s->strm.next_in); |
| TEST_ASSERT_EQUAL_UINT((unsigned)len, s->strm.avail_in); |
| TEST_ASSERT_EQUAL_UINT8_ARRAY(data, s->in, len); |
| TEST_ASSERT_EQUAL_INT(1, s->eof); |
|
|
| free_reset_buffers(s); |
| |
| int cr = gzclose_r(f); |
| (void)cr; |
| } |
|
|
| void test_gz_avail_moves_existing_and_loads_more(void) { |
| const unsigned char data[] = "ABCDEFGH"; |
| const size_t len = sizeof(data) - 1; |
|
|
| gzFile f = gzfile_from_bytes(data, len); |
| gz_statep s = (gz_statep)f; |
|
|
| |
| prepare_in_buffer(s, 4); |
|
|
| |
| int rc = test_gz_avail(s); |
| TEST_ASSERT_EQUAL_INT(0, rc); |
| TEST_ASSERT_EQUAL_UINT(4u, s->strm.avail_in); |
| TEST_ASSERT_EQUAL_UINT8_ARRAY("ABCD", s->in, 4); |
| TEST_ASSERT_EQUAL_INT(0, s->eof); |
|
|
| |
| s->strm.next_in = s->in + 2; |
| s->strm.avail_in = 2; |
|
|
| |
| rc = test_gz_avail(s); |
| TEST_ASSERT_EQUAL_INT(0, rc); |
| TEST_ASSERT_EQUAL_PTR(s->in, s->strm.next_in); |
| TEST_ASSERT_EQUAL_UINT(4u, s->strm.avail_in); |
| TEST_ASSERT_EQUAL_UINT8_ARRAY("CDEF", s->in, 4); |
| TEST_ASSERT_EQUAL_INT(0, s->eof); |
|
|
| free_reset_buffers(s); |
| int cr = gzclose_r(f); |
| (void)cr; |
| } |
|
|
| void test_gz_avail_sets_eof_when_end_reached(void) { |
| const unsigned char data[] = "XY"; |
| const size_t len = sizeof(data) - 1; |
|
|
| gzFile f = gzfile_from_bytes(data, len); |
| gz_statep s = (gz_statep)f; |
|
|
| |
| prepare_in_buffer(s, 8); |
|
|
| int rc = test_gz_avail(s); |
| TEST_ASSERT_EQUAL_INT(0, rc); |
| TEST_ASSERT_EQUAL_UINT((unsigned)len, s->strm.avail_in); |
| TEST_ASSERT_EQUAL_UINT8_ARRAY(data, s->in, len); |
| TEST_ASSERT_EQUAL_INT(1, s->eof); |
|
|
| free_reset_buffers(s); |
| int cr = gzclose_r(f); |
| (void)cr; |
| } |
|
|
| void test_gz_avail_returns_minus1_on_error_state(void) { |
| const unsigned char data[] = "ABC"; |
| const size_t len = sizeof(data) - 1; |
|
|
| gzFile f = gzfile_from_bytes(data, len); |
| gz_statep s = (gz_statep)f; |
|
|
| prepare_in_buffer(s, 4); |
|
|
| |
| s->strm.avail_in = 1; |
| s->in[0] = 0x42; |
| s->strm.next_in = s->in; |
|
|
| |
| s->err = Z_STREAM_ERROR; |
|
|
| int rc = test_gz_avail(s); |
| TEST_ASSERT_EQUAL_INT(-1, rc); |
| TEST_ASSERT_EQUAL_UINT(1u, s->strm.avail_in); |
| TEST_ASSERT_EQUAL_UINT8(0x42, s->in[0]); |
| |
| TEST_ASSERT_EQUAL_INT(0, s->eof); |
|
|
| free_reset_buffers(s); |
| int cr = gzclose_r(f); |
| (void)cr; |
| } |
|
|
| void test_gz_avail_noop_when_eof_already_set(void) { |
| const unsigned char data[] = "ABCDEF"; |
| const size_t len = sizeof(data) - 1; |
|
|
| gzFile f = gzfile_from_bytes(data, len); |
| gz_statep s = (gz_statep)f; |
|
|
| prepare_in_buffer(s, 4); |
|
|
| |
| s->in[0] = 'Q'; |
| s->in[1] = 'R'; |
| s->in[2] = 'S'; |
| s->in[3] = 'T'; |
| s->strm.next_in = s->in + 1; |
| s->strm.avail_in = 2; |
| s->eof = 1; |
|
|
| unsigned char before0 = s->in[0]; |
| unsigned char before1 = s->in[1]; |
| unsigned char before2 = s->in[2]; |
| unsigned char before3 = s->in[3]; |
| unsigned prev_avail = s->strm.avail_in; |
| unsigned char *prev_next = s->strm.next_in; |
|
|
| int rc = test_gz_avail(s); |
| TEST_ASSERT_EQUAL_INT(0, rc); |
| TEST_ASSERT_EQUAL_UINT(prev_avail, s->strm.avail_in); |
| TEST_ASSERT_EQUAL_PTR(prev_next, s->strm.next_in); |
| TEST_ASSERT_EQUAL_UINT8(before0, s->in[0]); |
| TEST_ASSERT_EQUAL_UINT8(before1, s->in[1]); |
| TEST_ASSERT_EQUAL_UINT8(before2, s->in[2]); |
| TEST_ASSERT_EQUAL_UINT8(before3, s->in[3]); |
| TEST_ASSERT_EQUAL_INT(1, s->eof); |
|
|
| free_reset_buffers(s); |
| int cr = gzclose_r(f); |
| (void)cr; |
| } |
|
|
| int main(void) { |
| UNITY_BEGIN(); |
| RUN_TEST(test_gz_avail_reads_into_empty_buffer_and_sets_eof); |
| RUN_TEST(test_gz_avail_moves_existing_and_loads_more); |
| RUN_TEST(test_gz_avail_sets_eof_when_end_reached); |
| RUN_TEST(test_gz_avail_returns_minus1_on_error_state); |
| RUN_TEST(test_gz_avail_noop_when_eof_already_set); |
| return UNITY_END(); |
| } |