#include "unity/unity.h" #include "zlib.h" #include #include #include #include #include /* Utilities for temporary filenames */ static void make_temp_path(char *out, size_t n) { /* Simple unique-ish filename in the current directory */ unsigned long r = (unsigned long)rand(); long t = (long)time(NULL); #if !defined(NO_snprintf) && !defined(NO_vsnprintf) (void)snprintf(out, n, "gzbuffer_test_%lu_%ld.gz", r, t); #else sprintf(out, "gzbuffer_test_%lu_%ld.gz", r, t); #endif } /* Create a plain empty file at path */ static int create_empty_file(const char *path) { FILE *f = fopen(path, "wb"); if (!f) return -1; fclose(f); return 0; } /* Write a small gzipped file with provided content */ static int write_gz_file(const char *path, const void *data, unsigned len) { gzFile gz = gzopen(path, "wb"); if (gz == NULL) return -1; int wrote = gzwrite(gz, data, len); int ok = (wrote == (int)len) ? 0 : -1; if (gzclose(gz) != Z_OK) ok = -1; return ok; } void setUp(void) { /* Setup code here, or leave empty */ } void tearDown(void) { /* Cleanup code here, or leave empty */ } /* Test: gzbuffer(NULL, size) returns -1 */ void test_gzbuffer_null_file_returns_minus_one(void) { int ret = gzbuffer(NULL, 1234U); TEST_ASSERT_EQUAL_INT(-1, ret); } /* Test: In write mode, calling gzbuffer before any I/O succeeds and can be called multiple times */ void test_gzbuffer_write_mode_before_io_multiple_calls_succeed(void) { char path[256]; make_temp_path(path, sizeof(path)); gzFile gz = gzopen(path, "wb"); TEST_ASSERT_NOT_NULL(gz); /* size 0 and size < 8 should both succeed (rounded internally), multiple calls allowed */ TEST_ASSERT_EQUAL_INT(0, gzbuffer(gz, 0U)); TEST_ASSERT_EQUAL_INT(0, gzbuffer(gz, 1U)); TEST_ASSERT_EQUAL_INT(0, gzbuffer(gz, 4096U)); /* Clean up */ TEST_ASSERT_EQUAL_INT(Z_OK, gzclose(gz)); remove(path); } /* Test: Passing a size that overflows when doubled results in -1 (before any I/O) */ void test_gzbuffer_overflow_size_returns_minus_one_before_io(void) { char path[256]; make_temp_path(path, sizeof(path)); gzFile gz = gzopen(path, "wb"); TEST_ASSERT_NOT_NULL(gz); /* Using UINT_MAX should trigger (size << 1) < size overflow check */ TEST_ASSERT_EQUAL_INT(-1, gzbuffer(gz, (unsigned)UINT_MAX)); TEST_ASSERT_EQUAL_INT(Z_OK, gzclose(gz)); remove(path); } /* Test: After writing (which allocates internal buffers), gzbuffer returns -1 */ void test_gzbuffer_after_write_returns_minus_one(void) { char path[256]; make_temp_path(path, sizeof(path)); gzFile gz = gzopen(path, "wb"); TEST_ASSERT_NOT_NULL(gz); const char *msg = "hello"; int wrote = gzwrite(gz, msg, (unsigned)strlen(msg)); TEST_ASSERT_EQUAL_INT((int)strlen(msg), wrote); /* Now buffers should have been allocated; gzbuffer must fail */ TEST_ASSERT_EQUAL_INT(-1, gzbuffer(gz, 8192U)); TEST_ASSERT_EQUAL_INT(Z_OK, gzclose(gz)); remove(path); } /* Test: In read mode, calling gzbuffer before any read succeeds */ void test_gzbuffer_read_mode_before_read_succeeds(void) { char path[256]; make_temp_path(path, sizeof(path)); /* Create an empty plain file */ TEST_ASSERT_EQUAL_INT(0, create_empty_file(path)); gzFile gz = gzopen(path, "rb"); TEST_ASSERT_NOT_NULL(gz); TEST_ASSERT_EQUAL_INT(0, gzbuffer(gz, 512U)); TEST_ASSERT_EQUAL_INT(Z_OK, gzclose(gz)); remove(path); } /* Test: In read mode, after a read occurs, gzbuffer returns -1 */ void test_gzbuffer_read_mode_after_read_returns_minus_one(void) { char path[256]; make_temp_path(path, sizeof(path)); const char *payload = "The quick brown fox jumps over the lazy dog"; TEST_ASSERT_EQUAL_INT(0, write_gz_file(path, payload, (unsigned)strlen(payload))); gzFile gz = gzopen(path, "rb"); TEST_ASSERT_NOT_NULL(gz); unsigned char buf[8]; int r = gzread(gz, buf, sizeof(buf)); TEST_ASSERT_TRUE(r > 0); TEST_ASSERT_EQUAL_INT(-1, gzbuffer(gz, 2048U)); TEST_ASSERT_EQUAL_INT(Z_OK, gzclose(gz)); remove(path); } int main(void) { srand((unsigned)time(NULL)); UNITY_BEGIN(); RUN_TEST(test_gzbuffer_null_file_returns_minus_one); RUN_TEST(test_gzbuffer_write_mode_before_io_multiple_calls_succeed); RUN_TEST(test_gzbuffer_overflow_size_returns_minus_one_before_io); RUN_TEST(test_gzbuffer_after_write_returns_minus_one); RUN_TEST(test_gzbuffer_read_mode_before_read_succeeds); RUN_TEST(test_gzbuffer_read_mode_after_read_returns_minus_one); return UNITY_END(); }