zlib / tests /tests_gzread_gz_fetch.c
AryaWu's picture
Upload folder using huggingface_hub
e996a55 verified
#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>
/* Wrapper provided in gzread.c */
extern int test_gz_fetch(gz_statep state);
/* Helpers to create temporary files */
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); /* we'll reopen with gzopen */
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) {
/* Setup code here, or leave empty */
}
void tearDown(void) {
/* Cleanup code here, or leave empty */
}
/* Test: Plain (non-gzip) file should lead to COPY mode and load raw bytes */
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);
/* Call fetch: should detect no gzip header and copy */
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");
/* Ensure loaded data matches file start */
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);
}
/* Test: Gzip file should decompress into x.next/x.have matching uncompressed data */
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);
/* After a successful decode, some output should be available */
TEST_ASSERT_TRUE_MESSAGE(st->x.have > 0, "Expected decompressed output");
TEST_ASSERT_TRUE_MESSAGE(st->x.next != NULL, "x.next should be set");
/* how may be LOOK if stream ended; but direct must be 0 when decoding gzip */
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);
}
/* Test: Empty file should result in LOOK returning with EOF and no data */
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);
}
/* Test: COPY path should report error when underlying read() fails */
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);
/* Ensure buffers are allocated by an initial fetch */
(void)test_gz_fetch(st);
/* Force COPY path and simulate read error */
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);
/* Restore a valid fd to allow clean close */
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);
}
/* Test: GZIP path should report error when read for input fails */
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);
/* Ensure buffers and inflate state are allocated */
(void)test_gz_fetch(st);
/* Force GZIP path with no input buffered and simulate read error */
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);
/* Restore fd for clean close */
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();
}