| #include "unity/unity.h" |
| #include "zlib.h" |
|
|
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <errno.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
|
|
| |
| int test_gz_load(void *state, unsigned char *buf, unsigned len, unsigned *have); |
|
|
| void setUp(void) { |
| |
| } |
|
|
| void tearDown(void) { |
| |
| } |
|
|
| |
| |
| static int make_temp_file_with_data(const unsigned char *data, size_t len, char *out_path, size_t out_path_size) { |
| const char *tmpdir = getenv("TMPDIR"); |
| if (!tmpdir) tmpdir = "/tmp"; |
| snprintf(out_path, out_path_size, "%s/gzread_test_%ld_%d_XXXXXX", tmpdir, (long)getpid(), rand()); |
| int fd = mkstemp(out_path); |
| if (fd == -1) { |
| return -1; |
| } |
| ssize_t w = write(fd, data, len); |
| if (w < 0 || (size_t)w != len) { |
| close(fd); |
| unlink(out_path); |
| return -1; |
| } |
| if (lseek(fd, 0, SEEK_SET) == (off_t)-1) { |
| close(fd); |
| unlink(out_path); |
| return -1; |
| } |
| return fd; |
| } |
|
|
| |
| static gzFile open_gzfile_from_fd_for_reading(int fd) { |
| |
| gzFile file = gzdopen(fd, "rb"); |
| return file; |
| } |
|
|
| |
| void test_gz_load_basic_sequential_reads(void) { |
| const unsigned char content[] = "ABCDEFGHIJ"; |
| char path[256]; |
| int fd = make_temp_file_with_data(content, sizeof(content) - 1, path, sizeof(path)); |
| TEST_ASSERT_MESSAGE(fd != -1, "Failed to create temp file"); |
|
|
| gzFile file = open_gzfile_from_fd_for_reading(fd); |
| TEST_ASSERT_MESSAGE(file != NULL, "gzdopen failed"); |
| |
| unlink(path); |
|
|
| unsigned char buf[8]; |
| unsigned have = 123; |
| int ret; |
|
|
| |
| ret = test_gz_load((void*)file, buf, 4U, &have); |
| TEST_ASSERT_EQUAL_INT(0, ret); |
| TEST_ASSERT_EQUAL_UINT(4U, have); |
| TEST_ASSERT_EQUAL_UINT8_ARRAY(content + 0, buf, 4); |
|
|
| |
| have = 0; |
| ret = test_gz_load((void*)file, buf, 4U, &have); |
| TEST_ASSERT_EQUAL_INT(0, ret); |
| TEST_ASSERT_EQUAL_UINT(4U, have); |
| TEST_ASSERT_EQUAL_UINT8_ARRAY(content + 4, buf, 4); |
|
|
| |
| have = 0; |
| ret = test_gz_load((void*)file, buf, 4U, &have); |
| TEST_ASSERT_EQUAL_INT(0, ret); |
| TEST_ASSERT_EQUAL_UINT(2U, have); |
| TEST_ASSERT_EQUAL_UINT8_ARRAY(content + 8, buf, 2); |
|
|
| |
| have = 777; |
| ret = test_gz_load((void*)file, buf, 4U, &have); |
| TEST_ASSERT_EQUAL_INT(0, ret); |
| TEST_ASSERT_EQUAL_UINT(0U, have); |
|
|
| |
| int c = gzclose_r(file); |
| TEST_ASSERT_MESSAGE(c == Z_OK || c == Z_BUF_ERROR, "gzclose_r failed"); |
| } |
|
|
| |
| void test_gz_load_handles_partial_read_with_pipe(void) { |
| int pfd[2]; |
| int r = pipe(pfd); |
| TEST_ASSERT_MESSAGE(r == 0, "pipe() failed"); |
|
|
| const unsigned char msg[] = "hello"; |
| ssize_t w = write(pfd[1], msg, sizeof(msg) - 1); |
| TEST_ASSERT_MESSAGE(w == (ssize_t)(sizeof(msg) - 1), "write to pipe failed"); |
| close(pfd[1]); |
|
|
| gzFile file = open_gzfile_from_fd_for_reading(pfd[0]); |
| TEST_ASSERT_MESSAGE(file != NULL, "gzdopen failed on pipe"); |
|
|
| unsigned char buf[16]; |
| unsigned have = 0; |
|
|
| int ret = test_gz_load((void*)file, buf, 10U, &have); |
| TEST_ASSERT_EQUAL_INT(0, ret); |
| TEST_ASSERT_EQUAL_UINT(5U, have); |
| TEST_ASSERT_EQUAL_UINT8_ARRAY(msg, buf, 5); |
|
|
| int c = gzclose_r(file); |
| TEST_ASSERT_MESSAGE(c == Z_OK || c == Z_BUF_ERROR, "gzclose_r failed"); |
| } |
|
|
| |
| void test_gz_load_returns_error_on_unreadable_fd(void) { |
| const unsigned char content[] = "data"; |
| char path[256]; |
| int fdw = make_temp_file_with_data(content, sizeof(content) - 1, path, sizeof(path)); |
| TEST_ASSERT_MESSAGE(fdw != -1, "Failed to create temp file for error test"); |
| close(fdw); |
|
|
| |
| int fd = open(path, O_WRONLY); |
| TEST_ASSERT_MESSAGE(fd != -1, "Failed to reopen temp file write-only"); |
| |
| unlink(path); |
|
|
| gzFile file = open_gzfile_from_fd_for_reading(fd); |
| TEST_ASSERT_MESSAGE(file != NULL, "gzdopen failed on write-only fd"); |
|
|
| unsigned char buf[8]; |
| unsigned have = 42; |
| int ret = test_gz_load((void*)file, buf, 5U, &have); |
| TEST_ASSERT_EQUAL_INT(-1, ret); |
| TEST_ASSERT_EQUAL_UINT(0U, have); |
|
|
| int c = gzclose_r(file); |
| TEST_ASSERT_MESSAGE(c == Z_OK || c == Z_BUF_ERROR, "gzclose_r failed"); |
| } |
|
|
| |
| void test_gz_load_zero_length_request(void) { |
| const unsigned char content[] = "WXYZ"; |
| char path[256]; |
| int fd = make_temp_file_with_data(content, sizeof(content) - 1, path, sizeof(path)); |
| TEST_ASSERT_MESSAGE(fd != -1, "Failed to create temp file"); |
|
|
| gzFile file = open_gzfile_from_fd_for_reading(fd); |
| TEST_ASSERT_MESSAGE(file != NULL, "gzdopen failed"); |
| unlink(path); |
|
|
| unsigned char buf[8]; |
| unsigned have = 99; |
|
|
| |
| int ret = test_gz_load((void*)file, buf, 0U, &have); |
| TEST_ASSERT_EQUAL_INT(0, ret); |
| TEST_ASSERT_EQUAL_UINT(0U, have); |
|
|
| |
| have = 0; |
| ret = test_gz_load((void*)file, buf, 4U, &have); |
| TEST_ASSERT_EQUAL_INT(0, ret); |
| TEST_ASSERT_EQUAL_UINT(4U, have); |
| TEST_ASSERT_EQUAL_UINT8_ARRAY(content, buf, 4); |
|
|
| int c = gzclose_r(file); |
| TEST_ASSERT_MESSAGE(c == Z_OK || c == Z_BUF_ERROR, "gzclose_r failed"); |
| } |
|
|
| int main(void) { |
| UNITY_BEGIN(); |
| RUN_TEST(test_gz_load_basic_sequential_reads); |
| RUN_TEST(test_gz_load_handles_partial_read_with_pipe); |
| RUN_TEST(test_gz_load_returns_error_on_unreadable_fd); |
| RUN_TEST(test_gz_load_zero_length_request); |
| return UNITY_END(); |
| } |