| #include "unity/unity.h" |
| #include "zlib.h" |
|
|
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
|
|
| |
| void setUp(void) { |
| |
| } |
| void tearDown(void) { |
| |
| } |
|
|
| |
|
|
| static char *make_temp_filename(char *buf, size_t buflen) { |
| |
| if (buf == NULL || buflen < L_tmpnam) return NULL; |
| char *res = tmpnam(buf); |
| if (res == NULL) return NULL; |
| |
| |
| return buf; |
| } |
|
|
| static int write_gzip_file(const char *path, const void *data, unsigned len) { |
| gzFile gz = gzopen(path, "wb"); |
| if (gz == NULL) return -1; |
| int written = gzwrite(gz, data, (unsigned)len); |
| int close_ret = gzclose(gz); |
| if (written != (int)len) return -2; |
| if (close_ret != Z_OK) return -3; |
| return 0; |
| } |
|
|
| static int corrupt_file_last_byte(const char *path) { |
| FILE *fp = fopen(path, "rb+"); |
| if (!fp) return -1; |
| if (fseek(fp, 0, SEEK_END) != 0) { fclose(fp); return -2; } |
| long sz = ftell(fp); |
| if (sz <= 0) { fclose(fp); return -3; } |
| if (fseek(fp, -1L, SEEK_END) != 0) { fclose(fp); return -4; } |
| int c = fgetc(fp); |
| if (c == EOF) { fclose(fp); return -5; } |
| if (fseek(fp, -1L, SEEK_END) != 0) { fclose(fp); return -6; } |
| if (fputc((c ^ 0xFF) & 0xFF, fp) == EOF) { fclose(fp); return -7; } |
| if (fclose(fp) != 0) return -8; |
| return 0; |
| } |
|
|
| |
|
|
| void test_gzclearerr_null_does_not_crash(void) { |
| |
| gzclearerr(NULL); |
| TEST_ASSERT_TRUE(1); |
| } |
|
|
| void test_gzclearerr_clears_eof_and_past_after_read_past_end(void) { |
| char path[L_tmpnam]; |
| TEST_ASSERT_NOT_NULL(make_temp_filename(path, sizeof(path))); |
|
|
| const char *payload = "Hello, world!"; |
| TEST_ASSERT_EQUAL_INT(0, write_gzip_file(path, payload, (unsigned)strlen(payload))); |
|
|
| gzFile gz = gzopen(path, "rb"); |
| TEST_ASSERT_NOT_NULL(gz); |
|
|
| |
| int ch; |
| while ((ch = gzgetc(gz)) != -1) { |
| |
| } |
|
|
| |
| int errnum_before = Z_OK; |
| const char *msg_before = gzerror(gz, &errnum_before); |
| (void)msg_before; |
| TEST_ASSERT_EQUAL_INT(Z_OK, errnum_before); |
| TEST_ASSERT_EQUAL_INT(1, gzeof(gz)); |
|
|
| |
| gzclearerr(gz); |
|
|
| int errnum_after = -1; |
| const char *msg_after = gzerror(gz, &errnum_after); |
| TEST_ASSERT_EQUAL_INT(Z_OK, errnum_after); |
| TEST_ASSERT_NOT_NULL(msg_after); |
| TEST_ASSERT_EQUAL_STRING("", msg_after); |
| TEST_ASSERT_EQUAL_INT(0, gzeof(gz)); |
|
|
| TEST_ASSERT_EQUAL_INT(Z_OK, gzclose(gz)); |
| remove(path); |
| } |
|
|
| void test_gzclearerr_clears_error_and_message_after_crc_error(void) { |
| char path[L_tmpnam]; |
| TEST_ASSERT_NOT_NULL(make_temp_filename(path, sizeof(path))); |
|
|
| const char *payload = "This will be corrupted."; |
| TEST_ASSERT_EQUAL_INT(0, write_gzip_file(path, payload, (unsigned)strlen(payload))); |
|
|
| |
| TEST_ASSERT_EQUAL_INT(0, corrupt_file_last_byte(path)); |
|
|
| gzFile gz = gzopen(path, "rb"); |
| TEST_ASSERT_NOT_NULL(gz); |
|
|
| |
| unsigned char buf[64]; |
| int ret; |
| int saw_error = 0; |
| while ((ret = gzread(gz, buf, sizeof(buf))) > 0) { |
| |
| } |
| if (ret == -1) { |
| saw_error = 1; |
| } |
| TEST_ASSERT_EQUAL_INT(1, saw_error); |
|
|
| int errnum_before = Z_OK; |
| const char *msg_before = gzerror(gz, &errnum_before); |
| TEST_ASSERT_NOT_NULL(msg_before); |
| TEST_ASSERT_NOT_EQUAL(Z_OK, errnum_before); |
| TEST_ASSERT_TRUE(msg_before[0] != '\0'); |
|
|
| |
| gzclearerr(gz); |
|
|
| int errnum_after = -1; |
| const char *msg_after = gzerror(gz, &errnum_after); |
| TEST_ASSERT_EQUAL_INT(Z_OK, errnum_after); |
| TEST_ASSERT_NOT_NULL(msg_after); |
| TEST_ASSERT_EQUAL_STRING("", msg_after); |
|
|
| |
| TEST_ASSERT_EQUAL_INT(0, gzeof(gz)); |
|
|
| |
| TEST_ASSERT_EQUAL_INT(Z_OK, gzclose(gz)); |
| remove(path); |
| } |
|
|
| void test_gzclearerr_on_write_mode_noop_and_ok(void) { |
| char path[L_tmpnam]; |
| TEST_ASSERT_NOT_NULL(make_temp_filename(path, sizeof(path))); |
|
|
| gzFile gz = gzopen(path, "wb"); |
| TEST_ASSERT_NOT_NULL(gz); |
|
|
| |
| int errnum_before = -1; |
| const char *msg_before = gzerror(gz, &errnum_before); |
| TEST_ASSERT_EQUAL_INT(Z_OK, errnum_before); |
| TEST_ASSERT_NOT_NULL(msg_before); |
|
|
| |
| gzclearerr(gz); |
|
|
| int errnum_after = -1; |
| const char *msg_after = gzerror(gz, &errnum_after); |
| TEST_ASSERT_EQUAL_INT(Z_OK, errnum_after); |
| TEST_ASSERT_NOT_NULL(msg_after); |
| TEST_ASSERT_TRUE(msg_after[0] == '\0' || msg_after == msg_before); |
|
|
| |
| TEST_ASSERT_EQUAL_INT(Z_OK, gzclose(gz)); |
| remove(path); |
| } |
|
|
| |
| int main(void) { |
| UNITY_BEGIN(); |
| RUN_TEST(test_gzclearerr_null_does_not_crash); |
| RUN_TEST(test_gzclearerr_clears_eof_and_past_after_read_past_end); |
| RUN_TEST(test_gzclearerr_clears_error_and_message_after_crc_error); |
| RUN_TEST(test_gzclearerr_on_write_mode_noop_and_ok); |
| return UNITY_END(); |
| } |