zlib / tests /tests_gzlib_gzrewind.c
AryaWu's picture
Upload folder using huggingface_hub
e996a55 verified
#include "unity/unity.h"
#include "zlib.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /* mkstemp, close, unlink, pipe */
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
/* Test content */
static const char *kSampleText = "Hello world! This is a test of gzrewind.";
static const size_t kSampleLen = 44; /* strlen above, but keep constant to ensure stability */
/* Unity setup/teardown */
void setUp(void) {
/* Setup code here, or leave empty */
}
void tearDown(void) {
/* Cleanup code here, or leave empty */
}
/* Helpers */
static void make_temp_path(char *buf, size_t buflen) {
/* Create a unique temp file path template */
/* Using /tmp is typical on POSIX. Adjust if environment differs. */
snprintf(buf, buflen, "/tmp/test_gzrewind_%ld_XXXXXX", (long)getpid());
}
static void create_gz_file(const char *path, const char *data, size_t len) {
gzFile gz = gzopen(path, "wb");
TEST_ASSERT_NOT_NULL(gz);
int wrote = gzwrite(gz, data, (unsigned)len);
TEST_ASSERT_EQUAL_INT((int)len, wrote);
int rc = gzclose(gz);
TEST_ASSERT_EQUAL_INT(0, rc);
}
static void read_exact(gzFile gz, void *buf, size_t len) {
unsigned char *p = (unsigned char *)buf;
size_t total = 0;
while (total < len) {
int n = gzread(gz, p + total, (unsigned)(len - total));
TEST_ASSERT_TRUE_MESSAGE(n >= 0, "gzread returned error");
if (n == 0) break; /* EOF */
total += (size_t)n;
}
TEST_ASSERT_EQUAL_UINT64(len, total);
}
/* Tests */
void test_gzrewind_null(void) {
TEST_ASSERT_EQUAL_INT(-1, gzrewind(NULL));
}
void test_gzrewind_write_mode_returns_error(void) {
char tmpl[256];
make_temp_path(tmpl, sizeof(tmpl));
int fd = mkstemp(tmpl);
TEST_ASSERT_TRUE_MESSAGE(fd != -1, "mkstemp failed");
close(fd); /* we'll use gzopen on the path */
gzFile gz = gzopen(tmpl, "wb");
TEST_ASSERT_NOT_NULL(gz);
/* gzrewind should fail for write mode */
int rc = gzrewind(gz);
TEST_ASSERT_EQUAL_INT(-1, rc);
/* cleanup */
gzclose(gz);
unlink(tmpl);
}
void test_gzrewind_seekable_basic_reset(void) {
char tmpl[256];
make_temp_path(tmpl, sizeof(tmpl));
int fd = mkstemp(tmpl);
TEST_ASSERT_TRUE_MESSAGE(fd != -1, "mkstemp failed");
close(fd);
create_gz_file(tmpl, kSampleText, strlen(kSampleText));
gzFile gz = gzopen(tmpl, "rb");
TEST_ASSERT_NOT_NULL(gz);
/* Read first 5 bytes */
char first[6] = {0};
int n = gzread(gz, first, 5);
TEST_ASSERT_EQUAL_INT(5, n);
TEST_ASSERT_EQUAL_STRING_LEN("Hello", first, 5);
/* Position should be 5 */
z_off_t pos = gztell(gz);
TEST_ASSERT_EQUAL_INT(5, (int)pos);
/* Rewind */
int rc = gzrewind(gz);
TEST_ASSERT_EQUAL_INT(0, rc);
/* Position should be 0 */
pos = gztell(gz);
TEST_ASSERT_EQUAL_INT(0, (int)pos);
/* Read first 5 bytes again */
memset(first, 0, sizeof(first));
n = gzread(gz, first, 5);
TEST_ASSERT_EQUAL_INT(5, n);
TEST_ASSERT_EQUAL_STRING_LEN("Hello", first, 5);
gzclose(gz);
unlink(tmpl);
}
void test_gzrewind_clears_eof_and_restarts(void) {
char tmpl[256];
make_temp_path(tmpl, sizeof(tmpl));
int fd = mkstemp(tmpl);
TEST_ASSERT_TRUE_MESSAGE(fd != -1, "mkstemp failed");
close(fd);
const char *data = kSampleText;
const size_t len = strlen(kSampleText);
create_gz_file(tmpl, data, len);
gzFile gz = gzopen(tmpl, "rb");
TEST_ASSERT_NOT_NULL(gz);
/* Read entire content */
char *buf = (char *)malloc(len);
TEST_ASSERT_NOT_NULL(buf);
read_exact(gz, buf, len);
/* Should be at EOF now */
int eof = gzeof(gz);
TEST_ASSERT_TRUE(eof != 0);
/* Rewind should succeed and clear EOF */
int rc = gzrewind(gz);
TEST_ASSERT_EQUAL_INT(0, rc);
eof = gzeof(gz);
TEST_ASSERT_EQUAL_INT(0, eof);
/* Read again and compare */
memset(buf, 0, len);
read_exact(gz, buf, len);
TEST_ASSERT_EQUAL_INT(0, memcmp(buf, data, len));
free(buf);
gzclose(gz);
unlink(tmpl);
}
void test_gzrewind_nonseekable_fd_returns_error(void) {
int fds[2];
int prc = pipe(fds);
TEST_ASSERT_EQUAL_INT(0, prc);
int rfd = fds[0];
int wfd = fds[1];
/* Open a gz stream on the read end of a pipe. This is non-seekable. */
gzFile gz = gzdopen(rfd, "rb");
TEST_ASSERT_NOT_NULL(gz);
/* gzrewind should attempt to lseek and fail, returning -1 */
int rc = gzrewind(gz);
TEST_ASSERT_EQUAL_INT(-1, rc);
/* cleanup: gzclose will close rfd; close write end explicitly */
gzclose(gz);
close(wfd);
}
void test_gzrewind_multiple_calls_idempotent(void) {
char tmpl[256];
make_temp_path(tmpl, sizeof(tmpl));
int fd = mkstemp(tmpl);
TEST_ASSERT_TRUE_MESSAGE(fd != -1, "mkstemp failed");
close(fd);
create_gz_file(tmpl, kSampleText, strlen(kSampleText));
gzFile gz = gzopen(tmpl, "rb");
TEST_ASSERT_NOT_NULL(gz);
/* First rewind before any read: should succeed */
TEST_ASSERT_EQUAL_INT(0, gzrewind(gz));
/* Read a few bytes, then rewind, twice */
char buf[6] = {0};
int n = gzread(gz, buf, 5);
TEST_ASSERT_EQUAL_INT(5, n);
TEST_ASSERT_EQUAL_STRING_LEN("Hello", buf, 5);
TEST_ASSERT_EQUAL_INT(0, gzrewind(gz));
TEST_ASSERT_EQUAL_INT(0, gzrewind(gz));
/* Read again from start */
memset(buf, 0, sizeof(buf));
n = gzread(gz, buf, 5);
TEST_ASSERT_EQUAL_INT(5, n);
TEST_ASSERT_EQUAL_STRING_LEN("Hello", buf, 5);
gzclose(gz);
unlink(tmpl);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_gzrewind_null);
RUN_TEST(test_gzrewind_write_mode_returns_error);
RUN_TEST(test_gzrewind_seekable_basic_reset);
RUN_TEST(test_gzrewind_clears_eof_and_restarts);
RUN_TEST(test_gzrewind_nonseekable_fd_returns_error);
RUN_TEST(test_gzrewind_multiple_calls_idempotent);
return UNITY_END();
}