File size: 3,902 Bytes
e996a55 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
#include "unity/unity.h"
#include "zlib.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
/* 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();
} |