|
|
#include "unity/unity.h" |
|
|
#include "zlib.h" |
|
|
#include "gzguts.h" |
|
|
|
|
|
#include <stdio.h> |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
#include <unistd.h> |
|
|
#include <fcntl.h> |
|
|
|
|
|
|
|
|
extern int test_gz_fetch(gz_statep state); |
|
|
|
|
|
|
|
|
static char *make_temp_plain(const unsigned char *data, size_t len) { |
|
|
char template[] = "gzread_test_plain_XXXXXX"; |
|
|
int fd = mkstemp(template); |
|
|
TEST_ASSERT_TRUE_MESSAGE(fd >= 0, "mkstemp failed for plain file"); |
|
|
ssize_t wrote = write(fd, data, len); |
|
|
TEST_ASSERT_EQUAL_INT64((long long)len, (long long)wrote); |
|
|
close(fd); |
|
|
return strdup(template); |
|
|
} |
|
|
|
|
|
static char *make_temp_gzip(const unsigned char *data, size_t len) { |
|
|
char template[] = "gzread_test_gzip_XXXXXX"; |
|
|
int fd = mkstemp(template); |
|
|
TEST_ASSERT_TRUE_MESSAGE(fd >= 0, "mkstemp failed for gzip file"); |
|
|
close(fd); |
|
|
gzFile gz = gzopen(template, "wb"); |
|
|
TEST_ASSERT_NOT_NULL_MESSAGE(gz, "gzopen for writing failed"); |
|
|
int wrote = gzwrite(gz, data, (unsigned)len); |
|
|
TEST_ASSERT_TRUE_MESSAGE(wrote == 0 || wrote > 0, "gzwrite returned invalid value"); |
|
|
TEST_ASSERT_EQUAL_INT((int)len, wrote); |
|
|
int zret = gzclose(gz); |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(Z_OK, zret, "gzclose write failed"); |
|
|
return strdup(template); |
|
|
} |
|
|
|
|
|
static char *make_temp_empty(void) { |
|
|
char template[] = "gzread_test_empty_XXXXXX"; |
|
|
int fd = mkstemp(template); |
|
|
TEST_ASSERT_TRUE_MESSAGE(fd >= 0, "mkstemp failed for empty file"); |
|
|
close(fd); |
|
|
return strdup(template); |
|
|
} |
|
|
|
|
|
static gz_statep open_state_for_read(const char *path) { |
|
|
gzFile f = gzopen(path, "rb"); |
|
|
TEST_ASSERT_NOT_NULL_MESSAGE(f, "gzopen for reading failed"); |
|
|
return (gz_statep)f; |
|
|
} |
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
|
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void test_gz_fetch_copy_mode_reads_plain_file(void) { |
|
|
const char *text = "The quick brown fox jumps over the lazy dog."; |
|
|
size_t text_len = strlen(text); |
|
|
char *path = make_temp_plain((const unsigned char *)text, text_len); |
|
|
|
|
|
gz_statep st = open_state_for_read(path); |
|
|
|
|
|
|
|
|
int ret = test_gz_fetch(st); |
|
|
TEST_ASSERT_EQUAL_INT(0, ret); |
|
|
TEST_ASSERT_EQUAL_INT(COPY, st->how); |
|
|
TEST_ASSERT_TRUE_MESSAGE(st->x.have > 0, "No data loaded in COPY mode"); |
|
|
|
|
|
TEST_ASSERT_LESS_OR_EQUAL_size_t(text_len, (size_t)(st->size << 1)); |
|
|
TEST_ASSERT_LESS_OR_EQUAL_size_t(text_len, (size_t)(st->x.have <= text_len ? st->x.have : text_len)); |
|
|
TEST_ASSERT_TRUE_MESSAGE(st->x.next != NULL, "x.next should point to output buffer"); |
|
|
size_t cmp_len = st->x.have < text_len ? st->x.have : text_len; |
|
|
TEST_ASSERT_EQUAL_INT(0, memcmp(st->x.next, text, cmp_len)); |
|
|
|
|
|
int cclose = gzclose_r((gzFile)st); |
|
|
TEST_ASSERT_TRUE_MESSAGE(cclose == Z_OK || cclose == Z_BUF_ERROR, "gzclose_r returned error"); |
|
|
unlink(path); |
|
|
free(path); |
|
|
} |
|
|
|
|
|
|
|
|
void test_gz_fetch_gzip_mode_decompresses(void) { |
|
|
const char *text = "Hello, world! This is gzip data.\n"; |
|
|
size_t text_len = strlen(text); |
|
|
char *path = make_temp_gzip((const unsigned char *)text, text_len); |
|
|
|
|
|
gz_statep st = open_state_for_read(path); |
|
|
|
|
|
int ret = test_gz_fetch(st); |
|
|
TEST_ASSERT_EQUAL_INT(0, ret); |
|
|
|
|
|
TEST_ASSERT_TRUE_MESSAGE(st->x.have > 0, "Expected decompressed output"); |
|
|
TEST_ASSERT_TRUE_MESSAGE(st->x.next != NULL, "x.next should be set"); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(0, st->direct); |
|
|
|
|
|
size_t cmp_len = st->x.have < text_len ? st->x.have : text_len; |
|
|
TEST_ASSERT_EQUAL_INT(0, memcmp(st->x.next, text, cmp_len)); |
|
|
|
|
|
int cclose = gzclose_r((gzFile)st); |
|
|
TEST_ASSERT_TRUE_MESSAGE(cclose == Z_OK || cclose == Z_BUF_ERROR, "gzclose_r returned error"); |
|
|
unlink(path); |
|
|
free(path); |
|
|
} |
|
|
|
|
|
|
|
|
void test_gz_fetch_look_eof_empty_file(void) { |
|
|
char *path = make_temp_empty(); |
|
|
gz_statep st = open_state_for_read(path); |
|
|
|
|
|
int ret = test_gz_fetch(st); |
|
|
TEST_ASSERT_EQUAL_INT(0, ret); |
|
|
TEST_ASSERT_EQUAL_UINT(0u, st->x.have); |
|
|
TEST_ASSERT_TRUE_MESSAGE(st->eof != 0, "EOF should be set for empty file"); |
|
|
|
|
|
int cclose = gzclose_r((gzFile)st); |
|
|
TEST_ASSERT_TRUE_MESSAGE(cclose == Z_OK || cclose == Z_BUF_ERROR, "gzclose_r returned error"); |
|
|
unlink(path); |
|
|
free(path); |
|
|
} |
|
|
|
|
|
|
|
|
void test_gz_fetch_copy_mode_read_error(void) { |
|
|
const char *text = "plain content to read"; |
|
|
size_t text_len = strlen(text); |
|
|
char *path = make_temp_plain((const unsigned char *)text, text_len); |
|
|
gz_statep st = open_state_for_read(path); |
|
|
|
|
|
|
|
|
(void)test_gz_fetch(st); |
|
|
|
|
|
|
|
|
st->x.have = 0; |
|
|
st->how = COPY; |
|
|
st->eof = 0; |
|
|
st->strm.avail_in = 0; |
|
|
int origfd = st->fd; |
|
|
st->fd = -1; |
|
|
|
|
|
int ret = test_gz_fetch(st); |
|
|
TEST_ASSERT_EQUAL_INT(-1, ret); |
|
|
TEST_ASSERT_EQUAL_INT(Z_ERRNO, st->err); |
|
|
|
|
|
|
|
|
st->fd = origfd; |
|
|
|
|
|
int cclose = gzclose_r((gzFile)st); |
|
|
TEST_ASSERT_TRUE_MESSAGE(cclose == Z_OK || cclose == Z_BUF_ERROR || cclose == Z_ERRNO, "gzclose_r returned unexpected error"); |
|
|
unlink(path); |
|
|
free(path); |
|
|
} |
|
|
|
|
|
|
|
|
void test_gz_fetch_gzip_mode_read_error(void) { |
|
|
const char *text = "gzip data for error path"; |
|
|
size_t text_len = strlen(text); |
|
|
char *path = make_temp_gzip((const unsigned char *)text, text_len); |
|
|
gz_statep st = open_state_for_read(path); |
|
|
|
|
|
|
|
|
(void)test_gz_fetch(st); |
|
|
|
|
|
|
|
|
st->how = GZIP; |
|
|
st->x.have = 0; |
|
|
st->strm.avail_in = 0; |
|
|
st->eof = 0; |
|
|
int origfd = st->fd; |
|
|
st->fd = -1; |
|
|
|
|
|
int ret = test_gz_fetch(st); |
|
|
TEST_ASSERT_EQUAL_INT(-1, ret); |
|
|
TEST_ASSERT_EQUAL_INT(Z_ERRNO, st->err); |
|
|
|
|
|
|
|
|
st->fd = origfd; |
|
|
|
|
|
int cclose = gzclose_r((gzFile)st); |
|
|
TEST_ASSERT_TRUE_MESSAGE(cclose == Z_OK || cclose == Z_BUF_ERROR || cclose == Z_ERRNO, "gzclose_r returned unexpected error"); |
|
|
unlink(path); |
|
|
free(path); |
|
|
} |
|
|
|
|
|
int main(void) { |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_gz_fetch_copy_mode_reads_plain_file); |
|
|
RUN_TEST(test_gz_fetch_gzip_mode_decompresses); |
|
|
RUN_TEST(test_gz_fetch_look_eof_empty_file); |
|
|
RUN_TEST(test_gz_fetch_copy_mode_read_error); |
|
|
RUN_TEST(test_gz_fetch_gzip_mode_read_error); |
|
|
return UNITY_END(); |
|
|
} |