#include "unity/unity.h" #include "zlib.h" #include #include #include #include /* The wrapper provided in the module for the local function. */ extern unsigned long test_multmodp(unsigned long a, unsigned long b); static uint32_t ref_multmodp(uint32_t a, uint32_t b) { /* Reference polynomial multiplication in GF(2) modulo reflected CRC-32 POLY. */ const uint32_t POLY = 0xEDB88320u; uint32_t p = 0; while (a) { if (a & 1u) { p ^= b; } a >>= 1; if (b & 1u) { b = (b >> 1) ^ POLY; } else { b >>= 1; } } return p; } void setUp(void) { /* Setup code here, or leave empty */ } void tearDown(void) { /* Cleanup code here, or leave empty */ } static uint32_t call_ut(uint32_t a, uint32_t b) { /* Helper to call the unit under test and cast to 32-bit for assertions. */ unsigned long r = test_multmodp((unsigned long)a, (unsigned long)b); return (uint32_t)r; } void test_multmodp_identity_right(void) { uint32_t a = 0xCAFEBABEu; /* non-zero */ uint32_t b = 1u; uint32_t got = call_ut(a, b); TEST_ASSERT_EQUAL_HEX32(a, got); } void test_multmodp_identity_left(void) { uint32_t a = 1u; /* non-zero */ uint32_t b = 0xAABBCCDDu; uint32_t got = call_ut(a, b); TEST_ASSERT_EQUAL_HEX32(b, got); } void test_multmodp_zero_b(void) { uint32_t a = 0x12345678u; /* non-zero */ uint32_t b = 0u; uint32_t got = call_ut(a, b); TEST_ASSERT_EQUAL_HEX32(0u, got); } void test_multmodp_commutative_fixed(void) { uint32_t a = 0x13579BDFu; /* non-zero */ uint32_t b = 0x2468ACE1u; /* non-zero */ uint32_t ab = call_ut(a, b); uint32_t ba = call_ut(b, a); TEST_ASSERT_EQUAL_HEX32(ab, ba); /* Also verify against reference for extra certainty. */ uint32_t ref = ref_multmodp(a, b); TEST_ASSERT_EQUAL_HEX32(ref, ab); } void test_multmodp_distributive_over_xor(void) { uint32_t a = 0xDEADBEEFu; /* non-zero */ uint32_t b = 0x0F0F0F0Fu; uint32_t c = 0x33333333u; uint32_t left = call_ut(a, b ^ c); uint32_t right = call_ut(a, b) ^ call_ut(a, c); TEST_ASSERT_EQUAL_HEX32(right, left); } void test_multmodp_single_bit_a_positions(void) { uint32_t b = 0x89ABCDEFu; uint8_t positions[] = {0, 1, 7, 15, 31}; for (size_t i = 0; i < sizeof(positions)/sizeof(positions[0]); i++) { uint32_t a = 1u << positions[i]; uint32_t got = call_ut(a, b); uint32_t exp = ref_multmodp(a, b); TEST_ASSERT_EQUAL_HEX32(exp, got); } } void test_multmodp_max_values(void) { uint32_t a = 0xFFFFFFFFu; /* non-zero */ uint32_t b = 0xFFFFFFFFu; uint32_t got = call_ut(a, b); uint32_t exp = ref_multmodp(a, b); TEST_ASSERT_EQUAL_HEX32(exp, got); } static uint32_t rand32(void) { /* Compose a 32-bit value from multiple rand() calls to avoid low-bit bias. */ uint32_t r = 0; r ^= ((uint32_t)rand() & 0x3FFu) << 22; r ^= ((uint32_t)rand() & 0x7FFFu) << 7; r ^= ((uint32_t)rand() & 0x7Fu); return r; } void test_multmodp_matches_reference_random(void) { srand(12345); for (int i = 0; i < 100; i++) { uint32_t a = rand32() | 1u; /* ensure non-zero to avoid undefined behavior */ uint32_t b = rand32(); uint32_t got = call_ut(a, b); uint32_t exp = ref_multmodp(a, b); TEST_ASSERT_EQUAL_HEX32(exp, got); } } int main(void) { UNITY_BEGIN(); RUN_TEST(test_multmodp_identity_right); RUN_TEST(test_multmodp_identity_left); RUN_TEST(test_multmodp_zero_b); RUN_TEST(test_multmodp_commutative_fixed); RUN_TEST(test_multmodp_distributive_over_xor); RUN_TEST(test_multmodp_single_bit_a_positions); RUN_TEST(test_multmodp_max_values); RUN_TEST(test_multmodp_matches_reference_random); return UNITY_END(); }