zlib / tests /tests_gzlib_gz_error.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>
/* Declare the target function with a compatible prototype.
We use void* for the state parameter to avoid depending on internal headers. */
extern void gz_error(void *state, int err, const char *msg);
static void remove_if_exists(const char *path) {
if (path) {
remove(path);
}
}
void setUp(void) {
/* Setup code here, or leave empty */
}
void tearDown(void) {
/* Cleanup code here, or leave empty */
}
static gzFile open_temp_gz(const char *path, const char *mode) {
remove_if_exists(path);
gzFile f = gzopen(path, mode);
TEST_ASSERT_MESSAGE(f != NULL, "gzopen failed to create/open temporary gzip file");
return f;
}
static void close_and_cleanup(gzFile f, const char *path) {
if (f) {
int rc = gzclose(f);
TEST_ASSERT_MESSAGE(rc == Z_OK, "gzclose failed");
}
remove_if_exists(path);
}
/* Test: gz_error with (Z_OK, NULL) clears error and leaves empty message. */
void test_gz_error_clears_with_null_message(void) {
const char *path = "tmp_gzlib_gz_error_clear.gz";
gzFile f = open_temp_gz(path, "wb");
/* Ensure we start clean */
int errnum = 777;
const char *msg = gzerror(f, &errnum);
TEST_ASSERT_EQUAL_INT(Z_OK, errnum);
TEST_ASSERT_NOT_NULL(msg);
/* Explicitly clear with Z_OK and NULL message */
gz_error((void*)f, Z_OK, NULL);
errnum = 777;
msg = gzerror(f, &errnum);
TEST_ASSERT_EQUAL_INT(Z_OK, errnum);
/* When no message is set, gzerror returns an empty string */
TEST_ASSERT_NOT_NULL(msg);
TEST_ASSERT_EQUAL_UINT32(0, (unsigned)strlen(msg));
close_and_cleanup(f, path);
}
/* Test: gz_error sets error code and allocates message "path: msg". */
void test_gz_error_sets_message_with_path_prefix(void) {
const char *path = "tmp_gzlib_gz_error_basic.gz";
gzFile f = open_temp_gz(path, "wb");
const char *user_msg = "whoops";
gz_error((void*)f, Z_STREAM_ERROR, user_msg);
int errnum = 0;
const char *ret = gzerror(f, &errnum);
TEST_ASSERT_EQUAL_INT(Z_STREAM_ERROR, errnum);
TEST_ASSERT_NOT_NULL(ret);
char expected[512];
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
(void)snprintf(expected, sizeof(expected), "%s: %s", path, user_msg);
#else
strcpy(expected, path);
strcat(expected, ": ");
strcat(expected, user_msg);
#endif
TEST_ASSERT_EQUAL_STRING(expected, ret);
close_and_cleanup(f, path);
}
/* Test: Calling gz_error repeatedly replaces the previous message and updates the code. */
void test_gz_error_replaces_previous_message(void) {
const char *path = "tmp_gzlib_gz_error_replace.gz";
gzFile f = open_temp_gz(path, "wb");
gz_error((void*)f, Z_DATA_ERROR, "first");
int err1 = 0;
const char *msg1 = gzerror(f, &err1);
TEST_ASSERT_EQUAL_INT(Z_DATA_ERROR, err1);
TEST_ASSERT_NOT_NULL(msg1);
gz_error((void*)f, Z_BUF_ERROR, "second");
int err2 = 0;
const char *msg2 = gzerror(f, &err2);
TEST_ASSERT_EQUAL_INT(Z_BUF_ERROR, err2);
TEST_ASSERT_NOT_NULL(msg2);
/* Pointer should change because a new allocation occurs for the new message */
TEST_ASSERT_NOT_EQUAL(msg1, msg2);
char expected[512];
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
(void)snprintf(expected, sizeof(expected), "%s: %s", path, "second");
#else
strcpy(expected, path);
strcat(expected, ": ");
strcat(expected, "second");
#endif
TEST_ASSERT_EQUAL_STRING(expected, msg2);
close_and_cleanup(f, path);
}
/* Test: Z_MEM_ERROR returns the literal "out of memory" and does not allocate a message. */
void test_gz_error_mem_error_returns_literal(void) {
const char *path = "tmp_gzlib_gz_error_mem.gz";
gzFile f = open_temp_gz(path, "wb");
/* Trigger a memory error; the message argument should be ignored for allocation. */
gz_error((void*)f, Z_MEM_ERROR, "ignored");
int err = 0;
const char *ret = gzerror(f, &err);
TEST_ASSERT_EQUAL_INT(Z_MEM_ERROR, err);
TEST_ASSERT_NOT_NULL(ret);
TEST_ASSERT_EQUAL_STRING("out of memory", ret);
/* After a mem error, subsequent errors should still work and set a message */
gz_error((void*)f, Z_STREAM_ERROR, "later");
err = 0;
ret = gzerror(f, &err);
TEST_ASSERT_EQUAL_INT(Z_STREAM_ERROR, err);
char expected[512];
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
(void)snprintf(expected, sizeof(expected), "%s: %s", path, "later");
#else
strcpy(expected, path);
strcat(expected, ": ");
strcat(expected, "later");
#endif
TEST_ASSERT_EQUAL_STRING(expected, ret);
close_and_cleanup(f, path);
}
/* Test: Z_OK with a non-NULL message stores a message while err stays Z_OK. */
void test_gz_error_ok_with_message_stores_message(void) {
const char *path = "tmp_gzlib_gz_error_okmsg.gz";
gzFile f = open_temp_gz(path, "wb");
gz_error((void*)f, Z_OK, "note");
int err = 0;
const char *ret = gzerror(f, &err);
TEST_ASSERT_EQUAL_INT(Z_OK, err);
TEST_ASSERT_NOT_NULL(ret);
char expected[512];
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
(void)snprintf(expected, sizeof(expected), "%s: %s", path, "note");
#else
strcpy(expected, path);
strcat(expected, ": ");
strcat(expected, "note");
#endif
TEST_ASSERT_EQUAL_STRING(expected, ret);
close_and_cleanup(f, path);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_gz_error_clears_with_null_message);
RUN_TEST(test_gz_error_sets_message_with_path_prefix);
RUN_TEST(test_gz_error_replaces_previous_message);
RUN_TEST(test_gz_error_mem_error_returns_literal);
RUN_TEST(test_gz_error_ok_with_message_stores_message);
return UNITY_END();
}