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();
}