Merge pull request #1269 from pkendall64/crsf-max-output
[ExpressLRS.git] / src / test / crc_native / test_crc.cpp
blob1e7d36443851ba43676ab82d94a7d956d4f1910c
1 #include <cstdint>
2 #include <unity.h>
3 #include "ucrc_t.h"
4 #include <crc.h>
5 #include "common.h"
7 #ifdef BIG_TEST
8 #define NUM_ITERATIONS 1000000
9 #else
10 #define NUM_ITERATIONS 1000
11 #endif
13 static char *genMsg(uint8_t bytes[], int len) {
14 static char buf[80];
15 char hex[4];
16 sprintf(buf, "bytes ");
17 for (int i = 0; i < len; i++)
19 sprintf(hex, "%02x ", bytes[i]);
20 strcat(buf, hex);
22 return buf;
25 void test_crc14_implementation_compatibility(void)
27 uint8_t bytes[7];
28 for (int i = 0; i < sizeof(bytes); i++)
29 bytes[i] = random() % 255;
30 bytes[0] &= 0b11;
32 uCRC_t ccrc = uCRC_t("CRC14", 14, ELRS_CRC14_POLY, 0, false, false, 0);
33 uint64_t crc = ccrc.get_raw_crc(bytes, 7, 0);
35 GENERIC_CRC14 ecrc = GENERIC_CRC14(ELRS_CRC14_POLY);
36 uint16_t c = ecrc.calc(bytes, 7, 0);
38 TEST_ASSERT_EQUAL_MESSAGE((int)(crc & 0x3FFF), c, genMsg(bytes, sizeof(bytes)));
41 void test_crc14_flip_random(int flip)
43 int false_positive = 0;
44 GENERIC_CRC14 ccrc = GENERIC_CRC14(ELRS_CRC14_POLY);
46 for (int x = 0; x < NUM_ITERATIONS; x++)
48 uint8_t bytes[7];
49 uint8_t fbytes[7];
51 for (int i = 0; i < sizeof(bytes); i++)
52 bytes[i] = random() % 255;
53 bytes[0] &= 0b11;
54 memcpy(fbytes, bytes, 7);
56 uint16_t c = ccrc.calc(bytes, 7, 0);
58 // Flip 'flip' random bits
59 do {
60 memcpy(bytes, fbytes, 7);
61 for (int i = 0; i < flip; i++)
63 int bit = random() % 50;
64 bytes[bit / 8] ^= 1 << (bit % 8);
66 } while (memcmp(fbytes, bytes, 7) == 0);
68 uint16_t e = ccrc.calc(bytes, 7, 0);
69 if (c == e)
71 //fprintf(stderr, "False +ve %s\n", genMsg(bytes, sizeof(bytes)));
72 false_positive++;
75 printf("%d out of %d false positives, %f%%\n", false_positive, NUM_ITERATIONS, false_positive * 100.0 / NUM_ITERATIONS);
78 void test_crc14_flip_sequential(int flip)
80 int false_positive = 0;
81 GENERIC_CRC14 ccrc = GENERIC_CRC14(ELRS_CRC14_POLY);
83 for (int x=0 ; x<NUM_ITERATIONS ; x++) {
84 uint8_t bytes[7];
85 uint8_t fbytes[7];
87 for (int i = 0; i < sizeof(bytes); i++)
88 bytes[i] = random() % 255;
89 bytes[0] &= 0b11;
91 memcpy(fbytes, bytes, 7);
93 uint16_t c = ccrc.calc(bytes, 7, 0);
95 // Flip 'flip' bits starting at a random position
96 do {
97 memcpy(bytes, fbytes, 7);
98 int pos = random() % (50 - flip);
99 for(int bit=pos ; bit<pos+flip ; bit++) {
100 int f = bit>1 ? bit+6 : bit;
101 bytes[f / 8] ^= 1 << (f % 8);
103 } while (memcmp(fbytes, bytes, 7) == 0);
105 uint16_t e = ccrc.calc(bytes, 7, 0);
106 if (c == e)
108 //fprintf(stderr, "False +ve %s\n", genMsg(bytes, sizeof(bytes)));
109 false_positive++;
112 printf("%d out of %d false positives, %f%%\n", false_positive, NUM_ITERATIONS, false_positive*100.0/NUM_ITERATIONS);
115 void test_crc14_flip_within(int flip)
117 int false_positive = 0;
118 GENERIC_CRC14 ccrc = GENERIC_CRC14(ELRS_CRC14_POLY);
120 for (int x = 0; x < NUM_ITERATIONS; x++)
122 uint8_t bytes[7];
123 uint8_t fbytes[7];
125 for (int i = 0; i < sizeof(bytes); i++)
126 bytes[i] = random() % 255;
127 bytes[0] &= 0b11;
129 memcpy(fbytes, bytes, 7);
131 uint16_t c = ccrc.calc(bytes, 7, 0);
133 // Flip 'flip' bits starting at a random position
134 int start = random() % (50 - 13);
135 do {
136 memcpy(bytes, fbytes, 7);
137 for (int i = 0; i < flip; i++)
139 int bit = random() % 13 + start;
140 if (bit>1) bit += 6;
141 bytes[bit / 8] ^= 1 << (bit % 8);
143 } while (memcmp(fbytes, bytes, 7)==0);
145 uint16_t e = ccrc.calc(bytes, 7, 0);
146 if (c == e)
148 //fprintf(stderr, "False +ve %s\n", genMsg(bytes, sizeof(bytes)));
149 false_positive++;
152 printf("%d out of %d false positives, %f%%\n", false_positive, NUM_ITERATIONS, false_positive * 100.0 / NUM_ITERATIONS);
155 void test_crc14_flip5(void)
157 GENERIC_CRC14 ccrc = GENERIC_CRC14(ELRS_CRC14_POLY);
159 for (int x = 0; x < NUM_ITERATIONS; x++)
161 uint8_t bytes[7];
162 uint8_t fbytes[7];
164 for (int i = 0; i < sizeof(bytes); i++)
165 bytes[i] = random() % 255;
166 bytes[0] &= 0b11;
168 memcpy(fbytes, bytes, 7);
170 uint16_t c = ccrc.calc(bytes, 7, 0);
172 // Flip 4 random bits
173 do {
174 memcpy(bytes, fbytes, 7);
175 for (int i = 0; i < 4; i++)
177 int pos = random() % 50;
178 if (pos > 1)
179 pos += 6;
180 bytes[pos / 8] ^= 1 << (pos % 8);
183 while (memcmp(fbytes, bytes, 7) == 0);
185 // Flip all the bits one after the other
186 for (int i = 0; i < 50; i++)
188 // flip bit i and test
189 int pos = i;
190 if (pos > 1)
191 pos += 6;
192 bytes[pos / 8] ^= 1 << (pos % 8);
194 uint16_t e = ccrc.calc(bytes, 7, 0);
195 if (c == e && memcmp(fbytes, bytes, 7) != 0)
197 fprintf(stderr, "False +ve %s\n", genMsg(bytes, sizeof(bytes)));
200 // flip bit i back again
201 bytes[pos / 8] ^= 1 << (pos % 8);
206 void test_crc8(void)
208 // Size of a CRSF packet
209 uint8_t bytes[11];
210 for (int i = 0; i < sizeof(bytes); i++)
211 bytes[i] = random() % 255;
213 uCRC_t ccrc = uCRC_t("CRC8", 8, ELRS_CRC_POLY, 0, false, false, 0);
214 uint64_t crc = ccrc.get_raw_crc(bytes, 7, 0);
216 GENERIC_CRC8 ecrc = GENERIC_CRC8(ELRS_CRC_POLY);
217 uint16_t c = ecrc.calc(bytes, 7);
219 TEST_ASSERT_EQUAL_MESSAGE((int)(crc & 0xFF), c, genMsg(bytes, sizeof(bytes)));
222 int main(int argc, char **argv)
224 srandom(micros());
225 #ifndef BIG_TEST
226 UNITY_BEGIN();
227 RUN_TEST(test_crc14_implementation_compatibility);
228 RUN_TEST(test_crc14_flip5);
229 RUN_TEST(test_crc8);
230 UNITY_END();
231 #endif
232 #ifdef BIG_TEST
233 printf("Random flipped bits within 14-bit range\n");
234 for (int i = 1; i < 31; i++)
236 printf("%2d : ", i);
237 test_crc14_flip_within(i);
239 printf("============================================================\n");
240 printf("Flipped bits in a single sequence at random start position\n");
241 for (int i = 1; i < 31; i++)
243 printf("%2d : ", i);
244 test_crc14_flip_sequential(i);
246 printf("============================================================\n");
247 printf("Randomly flipped bits\n");
248 for (int i = 1; i < 31; i++)
250 printf("%2d : ", i);
251 test_crc14_flip_random(i);
253 printf("============================================================\n");
254 #endif
256 return 0;