#include "../../unity/unity.h" #include #include #include #include #include #include /* Unity fixture hooks */ void setUp(void) { /* Setup code here, or leave empty */ } void tearDown(void) { /* Cleanup code here, or leave empty */ } /* Forward declarations of functions under test (already visible since this test is included into the same translation unit): static bool cksum_slice8 (FILE *fp, uint_fast32_t *crc_out, uintmax_t *length_out); int crc_sum_stream (FILE *stream, void *resstream, uintmax_t *length); */ /* Helper: write data to a new temporary file, rewind, and return the stream. Caller must fclose(fp). Returns NULL on failure. */ static FILE* make_tmp_stream_with_data(const unsigned char *data, size_t size) { FILE *fp = tmpfile(); if (!fp) return NULL; if (size > 0) { if (fwrite(data, 1, size, fp) != size) { fclose(fp); return NULL; } } fflush(fp); rewind(fp); return fp; } /* Helper: finalize POSIX cksum CRC from cksum_slice8 outputs. This mirrors the finalization in crc_sum_stream: for (; len; len >>= 8) crc = (crc << 8) ^ crctab[0][((crc >> 24) ^ len) & 0xFF]; crc = ~crc & 0xFFFFFFFF; crctab is declared by the program headers included earlier in this TU. */ static uint32_t finalize_posix_crc(uint_fast32_t crc, uintmax_t len) { for (; len; len >>= 8) { crc = (crc << 8) ^ crctab[0][((crc >> 24) ^ len) & 0xFF]; } crc = ~crc & 0xFFFFFFFFu; return (uint32_t)crc; } /* Helper: run cksum_slice8 and crc_sum_stream on identical data and compare finalized CRCs and lengths. */ static void check_cksum_slice8_matches_crc_sum_stream(const unsigned char *data, size_t size) { /* Prepare two identical streams */ FILE *fp1 = make_tmp_stream_with_data(data, size); FILE *fp2 = make_tmp_stream_with_data(data, size); TEST_ASSERT_NOT_NULL_MESSAGE(fp1, "tmpfile creation failed for fp1"); TEST_ASSERT_NOT_NULL_MESSAGE(fp2, "tmpfile creation failed for fp2"); uint_fast32_t crc_mid = 0; uintmax_t len_mid = 0; bool ok = cksum_slice8(fp1, &crc_mid, &len_mid); TEST_ASSERT_TRUE_MESSAGE(ok, "cksum_slice8 returned false unexpectedly"); TEST_ASSERT_EQUAL_UINT64((uint64_t)size, (uint64_t)len_mid); uint32_t crc_final_from_mid = finalize_posix_crc(crc_mid, len_mid); uint32_t crc_final_stream = 0; uintmax_t len_stream = 0; int rc = crc_sum_stream(fp2, &crc_final_stream, &len_stream); TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc, "crc_sum_stream failed"); TEST_ASSERT_EQUAL_UINT64((uint64_t)size, (uint64_t)len_stream); TEST_ASSERT_EQUAL_UINT32(crc_final_stream, crc_final_from_mid); fclose(fp1); fclose(fp2); } /* Tests */ static void test_cksum_slice8_null_params(void) { uint_fast32_t crc; uintmax_t length; /* NULL file pointer */ TEST_ASSERT_FALSE(cksum_slice8(NULL, &crc, &length)); /* Valid stream but NULL crc_out */ FILE *fp = make_tmp_stream_with_data(NULL, 0); TEST_ASSERT_NOT_NULL(fp); TEST_ASSERT_FALSE(cksum_slice8(fp, NULL, &length)); rewind(fp); /* Valid stream but NULL length_out */ TEST_ASSERT_FALSE(cksum_slice8(fp, &crc, NULL)); fclose(fp); } static void test_cksum_slice8_empty_stream(void) { FILE *fp1 = make_tmp_stream_with_data(NULL, 0); FILE *fp2 = make_tmp_stream_with_data(NULL, 0); TEST_ASSERT_NOT_NULL(fp1); TEST_ASSERT_NOT_NULL(fp2); uint_fast32_t crc_mid = 0; uintmax_t len_mid = 0; bool ok = cksum_slice8(fp1, &crc_mid, &len_mid); TEST_ASSERT_TRUE(ok); TEST_ASSERT_EQUAL_UINT64(0, (uint64_t)len_mid); TEST_ASSERT_EQUAL_UINT32(0u, (uint32_t)crc_mid); uint32_t crc_final_from_mid = finalize_posix_crc(crc_mid, len_mid); uint32_t crc_final_stream = 0; uintmax_t len_stream = 0; int rc = crc_sum_stream(fp2, &crc_final_stream, &len_stream); TEST_ASSERT_EQUAL_INT(0, rc); TEST_ASSERT_EQUAL_UINT64(0, (uint64_t)len_stream); TEST_ASSERT_EQUAL_UINT32(crc_final_stream, crc_final_from_mid); fclose(fp1); fclose(fp2); } static void test_cksum_slice8_single_byte(void) { const unsigned char data[1] = { 'A' }; check_cksum_slice8_matches_crc_sum_stream(data, sizeof(data)); } static void test_cksum_slice8_various_small_inputs(void) { const unsigned char s1[] = "abc"; check_cksum_slice8_matches_crc_sum_stream(s1, strlen((const char*)s1)); const unsigned char s2[] = "abcdefg"; /* 7 bytes */ check_cksum_slice8_matches_crc_sum_stream(s2, strlen((const char*)s2)); const unsigned char s3[] = "abcdefgh"; /* 8 bytes exact */ check_cksum_slice8_matches_crc_sum_stream(s3, strlen((const char*)s3)); const unsigned char s4[] = "abcdefghi"; /* 9 bytes */ check_cksum_slice8_matches_crc_sum_stream(s4, strlen((const char*)s4)); /* Binary data with zeros and 0xFF */ unsigned char s5[16]; for (size_t i = 0; i < sizeof(s5); i++) s5[i] = (i % 2) ? 0x00 : 0xFF; check_cksum_slice8_matches_crc_sum_stream(s5, sizeof(s5)); } static void test_cksum_slice8_large_buffer_spanning_chunks(void) { /* Use size > BUFLEN to ensure multiple fread loops and both aligned and remainder processing */ const size_t big_size = (size_t)BUFLEN * 3 + 123; unsigned char *buf = (unsigned char *)malloc(big_size); TEST_ASSERT_NOT_NULL(buf); for (size_t i = 0; i < big_size; i++) { buf[i] = (unsigned char)(i & 0xFFu); } check_cksum_slice8_matches_crc_sum_stream(buf, big_size); free(buf); } /* Unity main */ int main(void) { UNITY_BEGIN(); RUN_TEST(test_cksum_slice8_null_params); RUN_TEST(test_cksum_slice8_empty_stream); RUN_TEST(test_cksum_slice8_single_byte); RUN_TEST(test_cksum_slice8_various_small_inputs); RUN_TEST(test_cksum_slice8_large_buffer_spanning_chunks); return UNITY_END(); }