Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / examples / common / QRCode / repo / c / qrcodegen-test.c
1 /* 
2  * QR Code generator test suite (C)
3  * 
4  * When compiling this program, the library qrcodegen.c needs QRCODEGEN_TEST
5  * to be defined. Run this command line program with no arguments.
6  * 
7  * Copyright (c) Project Nayuki. (MIT License)
8  * https://www.nayuki.io/page/qr-code-generator-library
9  * 
10  * Permission is hereby granted, free of charge, to any person obtaining a copy of
11  * this software and associated documentation files (the "Software"), to deal in
12  * the Software without restriction, including without limitation the rights to
13  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
14  * the Software, and to permit persons to whom the Software is furnished to do so,
15  * subject to the following conditions:
16  * - The above copyright notice and this permission notice shall be included in
17  *   all copies or substantial portions of the Software.
18  * - The Software is provided "as is", without warranty of any kind, express or
19  *   implied, including but not limited to the warranties of merchantability,
20  *   fitness for a particular purpose and noninfringement. In no event shall the
21  *   authors or copyright holders be liable for any claim, damages or other
22  *   liability, whether in an action of contract, tort or otherwise, arising from,
23  *   out of or in connection with the Software or the use or other dealings in the
24  *   Software.
25  */
26
27 #include <assert.h>
28 #include <limits.h>
29 #include <stdbool.h>
30 #include <stddef.h>
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <time.h>
36 #include "qrcodegen.h"
37
38 #define ARRAY_LENGTH(name)  (sizeof(name) / sizeof(name[0]))
39
40
41 // Global variables
42 static int numTestCases = 0;
43
44
45 // Prototypes of private functions under test
46 extern const int8_t ECC_CODEWORDS_PER_BLOCK[4][41];
47 extern const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41];
48 void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen);
49 void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]);
50 int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl);
51 int getNumRawDataModules(int version);
52 void reedSolomonComputeDivisor(int degree, uint8_t result[]);
53 void reedSolomonComputeRemainder(const uint8_t data[], int dataLen, const uint8_t generator[], int degree, uint8_t result[]);
54 uint8_t reedSolomonMultiply(uint8_t x, uint8_t y);
55 void initializeFunctionModules(int version, uint8_t qrcode[]);
56 int getAlignmentPatternPositions(int version, uint8_t result[7]);
57 bool getModule(const uint8_t qrcode[], int x, int y);
58 void setModule(uint8_t qrcode[], int x, int y, bool isBlack);
59 void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack);
60 int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars);
61 int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version);
62
63
64 /*---- Test cases ----*/
65
66 static void testAppendBitsToBuffer(void) {
67         {
68                 uint8_t buf[1] = {0};
69                 int bitLen = 0;
70                 appendBitsToBuffer(0, 0, buf, &bitLen);
71                 assert(bitLen == 0);
72                 assert(buf[0] == 0);
73                 appendBitsToBuffer(1, 1, buf, &bitLen);
74                 assert(bitLen == 1);
75                 assert(buf[0] == 0x80);
76                 appendBitsToBuffer(0, 1, buf, &bitLen);
77                 assert(bitLen == 2);
78                 assert(buf[0] == 0x80);
79                 appendBitsToBuffer(5, 3, buf, &bitLen);
80                 assert(bitLen == 5);
81                 assert(buf[0] == 0xA8);
82                 appendBitsToBuffer(6, 3, buf, &bitLen);
83                 assert(bitLen == 8);
84                 assert(buf[0] == 0xAE);
85                 numTestCases++;
86         }
87         {
88                 uint8_t buf[6] = {0};
89                 int bitLen = 0;
90                 appendBitsToBuffer(16942, 16, buf, &bitLen);
91                 assert(bitLen == 16);
92                 assert(buf[0] == 0x42 && buf[1] == 0x2E && buf[2] == 0x00 && buf[3] == 0x00 && buf[4] == 0x00 && buf[5] == 0x00);
93                 appendBitsToBuffer(10, 7, buf, &bitLen);
94                 assert(bitLen == 23);
95                 assert(buf[0] == 0x42 && buf[1] == 0x2E && buf[2] == 0x14 && buf[3] == 0x00 && buf[4] == 0x00 && buf[5] == 0x00);
96                 appendBitsToBuffer(15, 4, buf, &bitLen);
97                 assert(bitLen == 27);
98                 assert(buf[0] == 0x42 && buf[1] == 0x2E && buf[2] == 0x15 && buf[3] == 0xE0 && buf[4] == 0x00 && buf[5] == 0x00);
99                 appendBitsToBuffer(26664, 15, buf, &bitLen);
100                 assert(bitLen == 42);
101                 assert(buf[0] == 0x42 && buf[1] == 0x2E && buf[2] == 0x15 && buf[3] == 0xFA && buf[4] == 0x0A && buf[5] == 0x00);
102                 numTestCases++;
103         }
104 }
105
106
107 // Ported from the Java version of the code.
108 static uint8_t *addEccAndInterleaveReference(const uint8_t *data, int version, enum qrcodegen_Ecc ecl) {
109         // Calculate parameter numbers
110         size_t numBlocks = (size_t)NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version];
111         size_t blockEccLen = (size_t)ECC_CODEWORDS_PER_BLOCK[(int)ecl][version];
112         size_t rawCodewords = (size_t)getNumRawDataModules(version) / 8;
113         size_t numShortBlocks = numBlocks - rawCodewords % numBlocks;
114         size_t shortBlockLen = rawCodewords / numBlocks;
115         
116         // Split data into blocks and append ECC to each block
117         uint8_t **blocks = malloc(numBlocks * sizeof(uint8_t*));
118         uint8_t *generator = malloc(blockEccLen * sizeof(uint8_t));
119         reedSolomonComputeDivisor((int)blockEccLen, generator);
120         for (size_t i = 0, k = 0; i < numBlocks; i++) {
121                 uint8_t *block = malloc((shortBlockLen + 1) * sizeof(uint8_t));
122                 size_t datLen = shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1);
123                 memcpy(block, &data[k], datLen * sizeof(uint8_t));
124                 reedSolomonComputeRemainder(&data[k], (int)datLen, generator, (int)blockEccLen, &block[shortBlockLen + 1 - blockEccLen]);
125                 k += datLen;
126                 blocks[i] = block;
127         }
128         free(generator);
129         
130         // Interleave (not concatenate) the bytes from every block into a single sequence
131         uint8_t *result = malloc(rawCodewords * sizeof(uint8_t));
132         for (size_t i = 0, k = 0; i < shortBlockLen + 1; i++) {
133                 for (size_t j = 0; j < numBlocks; j++) {
134                         // Skip the padding byte in short blocks
135                         if (i != shortBlockLen - blockEccLen || j >= numShortBlocks) {
136                                 result[k] = blocks[j][i];
137                                 k++;
138                         }
139                 }
140         }
141         for (size_t i = 0; i < numBlocks; i++)
142                 free(blocks[i]);
143         free(blocks);
144         return result;
145 }
146
147
148 static void testAddEccAndInterleave(void) {
149         for (int version = 1; version <= 40; version++) {
150                 for (int ecl = 0; ecl < 4; ecl++) {
151                         size_t dataLen = (size_t)getNumDataCodewords(version, (enum qrcodegen_Ecc)ecl);
152                         uint8_t *pureData = malloc(dataLen * sizeof(uint8_t));
153                         for (size_t i = 0; i < dataLen; i++)
154                                 pureData[i] = (uint8_t)(rand() % 256);
155                         uint8_t *expectOutput = addEccAndInterleaveReference(pureData, version, (enum qrcodegen_Ecc)ecl);
156                         
157                         size_t dataAndEccLen = (size_t)getNumRawDataModules(version) / 8;
158                         uint8_t *paddedData = malloc(dataAndEccLen * sizeof(uint8_t));
159                         memcpy(paddedData, pureData, dataLen * sizeof(uint8_t));
160                         uint8_t *actualOutput = malloc(dataAndEccLen * sizeof(uint8_t));
161                         addEccAndInterleave(paddedData, version, (enum qrcodegen_Ecc)ecl, actualOutput);
162                         
163                         assert(memcmp(actualOutput, expectOutput, dataAndEccLen * sizeof(uint8_t)) == 0);
164                         free(pureData);
165                         free(expectOutput);
166                         free(paddedData);
167                         free(actualOutput);
168                         numTestCases++;
169                 }
170         }
171 }
172
173
174 static void testGetNumDataCodewords(void) {
175         const int cases[][3] = {
176                 { 3, 1,   44},
177                 { 3, 2,   34},
178                 { 3, 3,   26},
179                 { 6, 0,  136},
180                 { 7, 0,  156},
181                 { 9, 0,  232},
182                 { 9, 1,  182},
183                 {12, 3,  158},
184                 {15, 0,  523},
185                 {16, 2,  325},
186                 {19, 3,  341},
187                 {21, 0,  932},
188                 {22, 0, 1006},
189                 {22, 1,  782},
190                 {22, 3,  442},
191                 {24, 0, 1174},
192                 {24, 3,  514},
193                 {28, 0, 1531},
194                 {30, 3,  745},
195                 {32, 3,  845},
196                 {33, 0, 2071},
197                 {33, 3,  901},
198                 {35, 0, 2306},
199                 {35, 1, 1812},
200                 {35, 2, 1286},
201                 {36, 3, 1054},
202                 {37, 3, 1096},
203                 {39, 1, 2216},
204                 {40, 1, 2334},
205         };
206         for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
207                 const int *tc = cases[i];
208                 assert(getNumDataCodewords(tc[0], (enum qrcodegen_Ecc)tc[1]) == tc[2]);
209                 numTestCases++;
210         }
211 }
212
213
214 static void testGetNumRawDataModules(void) {
215         const int cases[][2] = {
216                 { 1,   208},
217                 { 2,   359},
218                 { 3,   567},
219                 { 6,  1383},
220                 { 7,  1568},
221                 {12,  3728},
222                 {15,  5243},
223                 {18,  7211},
224                 {22, 10068},
225                 {26, 13652},
226                 {32, 19723},
227                 {37, 25568},
228                 {40, 29648},
229         };
230         for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
231                 const int *tc = cases[i];
232                 assert(getNumRawDataModules(tc[0]) == tc[1]);
233                 numTestCases++;
234         }
235 }
236
237
238 static void testReedSolomonComputeDivisor(void) {
239         uint8_t generator[30];
240         
241         reedSolomonComputeDivisor(1, generator);
242         assert(generator[0] == 0x01);
243         numTestCases++;
244         
245         reedSolomonComputeDivisor(2, generator);
246         assert(generator[0] == 0x03);
247         assert(generator[1] == 0x02);
248         numTestCases++;
249         
250         reedSolomonComputeDivisor(5, generator);
251         assert(generator[0] == 0x1F);
252         assert(generator[1] == 0xC6);
253         assert(generator[2] == 0x3F);
254         assert(generator[3] == 0x93);
255         assert(generator[4] == 0x74);
256         numTestCases++;
257         
258         reedSolomonComputeDivisor(30, generator);
259         assert(generator[ 0] == 0xD4);
260         assert(generator[ 1] == 0xF6);
261         assert(generator[ 5] == 0xC0);
262         assert(generator[12] == 0x16);
263         assert(generator[13] == 0xD9);
264         assert(generator[20] == 0x12);
265         assert(generator[27] == 0x6A);
266         assert(generator[29] == 0x96);
267         numTestCases++;
268 }
269
270
271 static void testReedSolomonComputeRemainder(void) {
272         {
273                 uint8_t data[1];
274                 uint8_t generator[3];
275                 uint8_t remainder[ARRAY_LENGTH(generator)];
276                 reedSolomonComputeDivisor(ARRAY_LENGTH(generator), generator);
277                 reedSolomonComputeRemainder(data, 0, generator, ARRAY_LENGTH(generator), remainder);
278                 assert(remainder[0] == 0);
279                 assert(remainder[1] == 0);
280                 assert(remainder[2] == 0);
281                 numTestCases++;
282         }
283         {
284                 uint8_t data[2] = {0, 1};
285                 uint8_t generator[4];
286                 uint8_t remainder[ARRAY_LENGTH(generator)];
287                 reedSolomonComputeDivisor(ARRAY_LENGTH(generator), generator);
288                 reedSolomonComputeRemainder(data, ARRAY_LENGTH(data), generator, ARRAY_LENGTH(generator), remainder);
289                 assert(remainder[0] == generator[0]);
290                 assert(remainder[1] == generator[1]);
291                 assert(remainder[2] == generator[2]);
292                 assert(remainder[3] == generator[3]);
293                 numTestCases++;
294         }
295         {
296                 uint8_t data[5] = {0x03, 0x3A, 0x60, 0x12, 0xC7};
297                 uint8_t generator[5];
298                 uint8_t remainder[ARRAY_LENGTH(generator)];
299                 reedSolomonComputeDivisor(ARRAY_LENGTH(generator), generator);
300                 reedSolomonComputeRemainder(data, ARRAY_LENGTH(data), generator, ARRAY_LENGTH(generator), remainder);
301                 assert(remainder[0] == 0xCB);
302                 assert(remainder[1] == 0x36);
303                 assert(remainder[2] == 0x16);
304                 assert(remainder[3] == 0xFA);
305                 assert(remainder[4] == 0x9D);
306                 numTestCases++;
307         }
308         {
309                 uint8_t data[43] = {
310                         0x38, 0x71, 0xDB, 0xF9, 0xD7, 0x28, 0xF6, 0x8E, 0xFE, 0x5E,
311                         0xE6, 0x7D, 0x7D, 0xB2, 0xA5, 0x58, 0xBC, 0x28, 0x23, 0x53,
312                         0x14, 0xD5, 0x61, 0xC0, 0x20, 0x6C, 0xDE, 0xDE, 0xFC, 0x79,
313                         0xB0, 0x8B, 0x78, 0x6B, 0x49, 0xD0, 0x1A, 0xAD, 0xF3, 0xEF,
314                         0x52, 0x7D, 0x9A,
315                 };
316                 uint8_t generator[30];
317                 uint8_t remainder[ARRAY_LENGTH(generator)];
318                 reedSolomonComputeDivisor(ARRAY_LENGTH(generator), generator);
319                 reedSolomonComputeRemainder(data, ARRAY_LENGTH(data), generator, ARRAY_LENGTH(generator), remainder);
320                 assert(remainder[ 0] == 0xCE);
321                 assert(remainder[ 1] == 0xF0);
322                 assert(remainder[ 2] == 0x31);
323                 assert(remainder[ 3] == 0xDE);
324                 assert(remainder[ 8] == 0xE1);
325                 assert(remainder[12] == 0xCA);
326                 assert(remainder[17] == 0xE3);
327                 assert(remainder[19] == 0x85);
328                 assert(remainder[20] == 0x50);
329                 assert(remainder[24] == 0xBE);
330                 assert(remainder[29] == 0xB3);
331                 numTestCases++;
332         }
333 }
334
335
336 static void testReedSolomonMultiply(void) {
337         const uint8_t cases[][3] = {
338                 {0x00, 0x00, 0x00},
339                 {0x01, 0x01, 0x01},
340                 {0x02, 0x02, 0x04},
341                 {0x00, 0x6E, 0x00},
342                 {0xB2, 0xDD, 0xE6},
343                 {0x41, 0x11, 0x25},
344                 {0xB0, 0x1F, 0x11},
345                 {0x05, 0x75, 0xBC},
346                 {0x52, 0xB5, 0xAE},
347                 {0xA8, 0x20, 0xA4},
348                 {0x0E, 0x44, 0x9F},
349                 {0xD4, 0x13, 0xA0},
350                 {0x31, 0x10, 0x37},
351                 {0x6C, 0x58, 0xCB},
352                 {0xB6, 0x75, 0x3E},
353                 {0xFF, 0xFF, 0xE2},
354         };
355         for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
356                 const uint8_t *tc = cases[i];
357                 assert(reedSolomonMultiply(tc[0], tc[1]) == tc[2]);
358                 numTestCases++;
359         }
360 }
361
362
363 static void testInitializeFunctionModulesEtc(void) {
364         for (int ver = 1; ver <= 40; ver++) {
365                 uint8_t *qrcode = malloc((size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(ver) * sizeof(uint8_t));
366                 assert(qrcode != NULL);
367                 initializeFunctionModules(ver, qrcode);
368                 
369                 int size = qrcodegen_getSize(qrcode);
370                 if (ver == 1)
371                         assert(size == 21);
372                 else if (ver == 40)
373                         assert(size == 177);
374                 else
375                         assert(size == ver * 4 + 17);
376                 
377                 bool hasWhite = false;
378                 bool hasBlack = false;
379                 for (int y = 0; y < size; y++) {
380                         for (int x = 0; x < size; x++) {
381                                 bool color = qrcodegen_getModule(qrcode, x, y);
382                                 if (color)
383                                         hasBlack = true;
384                                 else
385                                         hasWhite = true;
386                         }
387                 }
388                 assert(hasWhite && hasBlack);
389                 free(qrcode);
390                 numTestCases++;
391         }
392 }
393
394
395 static void testGetAlignmentPatternPositions(void) {
396         const int cases[][9] = {
397                 { 1, 0,  -1,  -1,  -1,  -1,  -1,  -1,  -1},
398                 { 2, 2,   6,  18,  -1,  -1,  -1,  -1,  -1},
399                 { 3, 2,   6,  22,  -1,  -1,  -1,  -1,  -1},
400                 { 6, 2,   6,  34,  -1,  -1,  -1,  -1,  -1},
401                 { 7, 3,   6,  22,  38,  -1,  -1,  -1,  -1},
402                 { 8, 3,   6,  24,  42,  -1,  -1,  -1,  -1},
403                 {16, 4,   6,  26,  50,  74,  -1,  -1,  -1},
404                 {25, 5,   6,  32,  58,  84, 110,  -1,  -1},
405                 {32, 6,   6,  34,  60,  86, 112, 138,  -1},
406                 {33, 6,   6,  30,  58,  86, 114, 142,  -1},
407                 {39, 7,   6,  26,  54,  82, 110, 138, 166},
408                 {40, 7,   6,  30,  58,  86, 114, 142, 170},
409         };
410         for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
411                 const int *tc = cases[i];
412                 uint8_t pos[7];
413                 int num = getAlignmentPatternPositions(tc[0], pos);
414                 assert(num == tc[1]);
415                 for (int j = 0; j < num; j++)
416                         assert(pos[j] == tc[2 + j]);
417                 numTestCases++;
418         }
419 }
420
421
422 static void testGetSetModule(void) {
423         uint8_t qrcode[qrcodegen_BUFFER_LEN_FOR_VERSION(23)];
424         initializeFunctionModules(23, qrcode);
425         int size = qrcodegen_getSize(qrcode);
426         
427         for (int y = 0; y < size; y++) {  // Clear all to white
428                 for (int x = 0; x < size; x++)
429                         setModule(qrcode, x, y, false);
430         }
431         for (int y = 0; y < size; y++) {  // Check all white
432                 for (int x = 0; x < size; x++)
433                         assert(qrcodegen_getModule(qrcode, x, y) == false);
434         }
435         for (int y = 0; y < size; y++) {  // Set all to black
436                 for (int x = 0; x < size; x++)
437                         setModule(qrcode, x, y, true);
438         }
439         for (int y = 0; y < size; y++) {  // Check all black
440                 for (int x = 0; x < size; x++)
441                         assert(qrcodegen_getModule(qrcode, x, y) == true);
442         }
443         
444         // Set some out of bounds modules to white
445         setModuleBounded(qrcode, -1, -1, false);
446         setModuleBounded(qrcode, -1, 0, false);
447         setModuleBounded(qrcode, 0, -1, false);
448         setModuleBounded(qrcode, size, 5, false);
449         setModuleBounded(qrcode, 72, size, false);
450         setModuleBounded(qrcode, size, size, false);
451         for (int y = 0; y < size; y++) {  // Check all black
452                 for (int x = 0; x < size; x++)
453                         assert(qrcodegen_getModule(qrcode, x, y) == true);
454         }
455         
456         // Set some modules to white
457         setModule(qrcode, 3, 8, false);
458         setModule(qrcode, 61, 49, false);
459         for (int y = 0; y < size; y++) {  // Check most black
460                 for (int x = 0; x < size; x++) {
461                         bool white = (x == 3 && y == 8) || (x == 61 && y == 49);
462                         assert(qrcodegen_getModule(qrcode, x, y) != white);
463                 }
464         }
465         numTestCases++;
466 }
467
468
469 static void testGetSetModuleRandomly(void) {
470         uint8_t qrcode[qrcodegen_BUFFER_LEN_FOR_VERSION(1)];
471         initializeFunctionModules(1, qrcode);
472         int size = qrcodegen_getSize(qrcode);
473         
474         bool modules[21][21];
475         for (int y = 0; y < size; y++) {
476                 for (int x = 0; x < size; x++)
477                         modules[y][x] = qrcodegen_getModule(qrcode, x, y);
478         }
479         
480         long trials = 100000;
481         for (long i = 0; i < trials; i++) {
482                 int x = rand() % (size * 2) - size / 2;
483                 int y = rand() % (size * 2) - size / 2;
484                 bool isInBounds = 0 <= x && x < size && 0 <= y && y < size;
485                 bool oldColor = isInBounds && modules[y][x];
486                 if (isInBounds)
487                         assert(getModule(qrcode, x, y) == oldColor);
488                 assert(qrcodegen_getModule(qrcode, x, y) == oldColor);
489                 
490                 bool newColor = rand() % 2 == 0;
491                 if (isInBounds)
492                         modules[y][x] = newColor;
493                 if (isInBounds && rand() % 2 == 0)
494                         setModule(qrcode, x, y, newColor);
495                 else
496                         setModuleBounded(qrcode, x, y, newColor);
497         }
498         numTestCases++;
499 }
500
501
502 static void testIsAlphanumeric(void) {
503         struct TestCase {
504                 bool answer;
505                 const char *text;
506         };
507         const struct TestCase cases[] = {
508                 {true, ""},
509                 {true, "0"},
510                 {true, "A"},
511                 {false, "a"},
512                 {true, " "},
513                 {true, "."},
514                 {true, "*"},
515                 {false, ","},
516                 {false, "|"},
517                 {false, "@"},
518                 {true, "XYZ"},
519                 {false, "XYZ!"},
520                 {true, "79068"},
521                 {true, "+123 ABC$"},
522                 {false, "\x01"},
523                 {false, "\x7F"},
524                 {false, "\x80"},
525                 {false, "\xC0"},
526                 {false, "\xFF"},
527         };
528         for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
529                 assert(qrcodegen_isAlphanumeric(cases[i].text) == cases[i].answer);
530                 numTestCases++;
531         }
532 }
533
534
535 static void testIsNumeric(void) {
536         struct TestCase {
537                 bool answer;
538                 const char *text;
539         };
540         const struct TestCase cases[] = {
541                 {true, ""},
542                 {true, "0"},
543                 {false, "A"},
544                 {false, "a"},
545                 {false, " "},
546                 {false, "."},
547                 {false, "*"},
548                 {false, ","},
549                 {false, "|"},
550                 {false, "@"},
551                 {false, "XYZ"},
552                 {false, "XYZ!"},
553                 {true, "79068"},
554                 {false, "+123 ABC$"},
555                 {false, "\x01"},
556                 {false, "\x7F"},
557                 {false, "\x80"},
558                 {false, "\xC0"},
559                 {false, "\xFF"},
560         };
561         for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
562                 assert(qrcodegen_isNumeric(cases[i].text) == cases[i].answer);
563                 numTestCases++;
564         }
565 }
566
567
568 static void testCalcSegmentBufferSize(void) {
569         {
570                 const size_t cases[][2] = {
571                         {0, 0},
572                         {1, 1},
573                         {2, 1},
574                         {3, 2},
575                         {4, 2},
576                         {5, 3},
577                         {6, 3},
578                         {1472, 614},
579                         {2097, 874},
580                         {5326, 2220},
581                         {9828, 4095},
582                         {9829, 4096},
583                         {9830, 4096},
584                         {9831, SIZE_MAX},
585                         {9832, SIZE_MAX},
586                         {12000, SIZE_MAX},
587                         {28453, SIZE_MAX},
588                         {55555, SIZE_MAX},
589                         {SIZE_MAX / 6, SIZE_MAX},
590                         {SIZE_MAX / 4, SIZE_MAX},
591                         {SIZE_MAX / 2, SIZE_MAX},
592                         {SIZE_MAX / 1, SIZE_MAX},
593                 };
594                 for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
595                         assert(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, cases[i][0]) == cases[i][1]);
596                         numTestCases++;
597                 }
598         }
599         {
600                 const size_t cases[][2] = {
601                         {0, 0},
602                         {1, 1},
603                         {2, 2},
604                         {3, 3},
605                         {4, 3},
606                         {5, 4},
607                         {6, 5},
608                         {1472, 1012},
609                         {2097, 1442},
610                         {5326, 3662},
611                         {5955, 4095},
612                         {5956, 4095},
613                         {5957, 4096},
614                         {5958, SIZE_MAX},
615                         {5959, SIZE_MAX},
616                         {12000, SIZE_MAX},
617                         {28453, SIZE_MAX},
618                         {55555, SIZE_MAX},
619                         {SIZE_MAX / 10, SIZE_MAX},
620                         {SIZE_MAX / 8, SIZE_MAX},
621                         {SIZE_MAX / 5, SIZE_MAX},
622                         {SIZE_MAX / 2, SIZE_MAX},
623                         {SIZE_MAX / 1, SIZE_MAX},
624                 };
625                 for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
626                         assert(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, cases[i][0]) == cases[i][1]);
627                         numTestCases++;
628                 }
629         }
630         {
631                 const size_t cases[][2] = {
632                         {0, 0},
633                         {1, 1},
634                         {2, 2},
635                         {3, 3},
636                         {1472, 1472},
637                         {2097, 2097},
638                         {4094, 4094},
639                         {4095, 4095},
640                         {4096, SIZE_MAX},
641                         {4097, SIZE_MAX},
642                         {5957, SIZE_MAX},
643                         {12000, SIZE_MAX},
644                         {28453, SIZE_MAX},
645                         {55555, SIZE_MAX},
646                         {SIZE_MAX / 16 + 1, SIZE_MAX},
647                         {SIZE_MAX / 14, SIZE_MAX},
648                         {SIZE_MAX / 9, SIZE_MAX},
649                         {SIZE_MAX / 7, SIZE_MAX},
650                         {SIZE_MAX / 4, SIZE_MAX},
651                         {SIZE_MAX / 3, SIZE_MAX},
652                         {SIZE_MAX / 2, SIZE_MAX},
653                         {SIZE_MAX / 1, SIZE_MAX},
654                 };
655                 for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
656                         assert(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_BYTE, cases[i][0]) == cases[i][1]);
657                         numTestCases++;
658                 }
659         }
660         {
661                 const size_t cases[][2] = {
662                         {0, 0},
663                         {1, 2},
664                         {2, 4},
665                         {3, 5},
666                         {1472, 2392},
667                         {2097, 3408},
668                         {2519, 4094},
669                         {2520, 4095},
670                         {2521, SIZE_MAX},
671                         {5957, SIZE_MAX},
672                         {2522, SIZE_MAX},
673                         {12000, SIZE_MAX},
674                         {28453, SIZE_MAX},
675                         {55555, SIZE_MAX},
676                         {SIZE_MAX / 13 + 1, SIZE_MAX},
677                         {SIZE_MAX / 12, SIZE_MAX},
678                         {SIZE_MAX / 9, SIZE_MAX},
679                         {SIZE_MAX / 4, SIZE_MAX},
680                         {SIZE_MAX / 3, SIZE_MAX},
681                         {SIZE_MAX / 2, SIZE_MAX},
682                         {SIZE_MAX / 1, SIZE_MAX},
683                 };
684                 for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
685                         assert(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_KANJI, cases[i][0]) == cases[i][1]);
686                         numTestCases++;
687                 }
688         }
689         {
690                 assert(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ECI, 0) == 3);
691                 numTestCases++;
692         }
693 }
694
695
696 static void testCalcSegmentBitLength(void) {
697         struct TestCase {
698                 size_t numChars;
699                 int result;
700         };
701         {
702                 const struct TestCase CASES[] = {
703                         {0, 0},
704                         {1, 4},
705                         {2, 7},
706                         {3, 10},
707                         {4, 14},
708                         {5, 17},
709                         {6, 20},
710                         {1472, 4907},
711                         {2097, 6990},
712                         {5326, 17754},
713                         {9828, 32760},
714                         {9829, 32764},
715                         {9830, 32767},
716                         {9831, -1},
717                         {9832, -1},
718                         {12000, -1},
719                         {28453, -1},
720                         {SIZE_MAX / 6, -1},
721                         {SIZE_MAX / 3, -1},
722                         {SIZE_MAX / 2, -1},
723                         {SIZE_MAX / 1, -1},
724                 };
725                 for (size_t i = 0; i < ARRAY_LENGTH(CASES); i++) {
726                         assert(calcSegmentBitLength(qrcodegen_Mode_NUMERIC, CASES[i].numChars) == CASES[i].result);
727                         numTestCases++;
728                 }
729         }
730         {
731                 const struct TestCase CASES[] = {
732                         {0, 0},
733                         {1, 6},
734                         {2, 11},
735                         {3, 17},
736                         {4, 22},
737                         {5, 28},
738                         {6, 33},
739                         {1472, 8096},
740                         {2097, 11534},
741                         {5326, 29293},
742                         {5955, 32753},
743                         {5956, 32758},
744                         {5957, 32764},
745                         {5958, -1},
746                         {5959, -1},
747                         {12000, -1},
748                         {28453, -1},
749                         {SIZE_MAX / 10, -1},
750                         {SIZE_MAX / 5, -1},
751                         {SIZE_MAX / 2, -1},
752                         {SIZE_MAX / 1, -1},
753                 };
754                 for (size_t i = 0; i < ARRAY_LENGTH(CASES); i++) {
755                         assert(calcSegmentBitLength(qrcodegen_Mode_ALPHANUMERIC, CASES[i].numChars) == CASES[i].result);
756                         numTestCases++;
757                 }
758         }
759         {
760                 const struct TestCase CASES[] = {
761                         {0, 0},
762                         {1, 8},
763                         {2, 16},
764                         {3, 24},
765                         {1472, 11776},
766                         {2097, 16776},
767                         {4094, 32752},
768                         {4095, 32760},
769                         {4096, -1},
770                         {4097, -1},
771                         {5957, -1},
772                         {12000, -1},
773                         {28453, -1},
774                         {SIZE_MAX / 15, -1},
775                         {SIZE_MAX / 12, -1},
776                         {SIZE_MAX / 7, -1},
777                         {SIZE_MAX / 3, -1},
778                         {SIZE_MAX / 1, -1},
779                 };
780                 for (size_t i = 0; i < ARRAY_LENGTH(CASES); i++) {
781                         assert(calcSegmentBitLength(qrcodegen_Mode_BYTE, CASES[i].numChars) == CASES[i].result);
782                         numTestCases++;
783                 }
784         }
785         {
786                 const struct TestCase CASES[] = {
787                         {0, 0},
788                         {1, 13},
789                         {2, 26},
790                         {3, 39},
791                         {1472, 19136},
792                         {2097, 27261},
793                         {2519, 32747},
794                         {2520, 32760},
795                         {2521, -1},
796                         {5957, -1},
797                         {2522, -1},
798                         {12000, -1},
799                         {28453, -1},
800                         {SIZE_MAX / 25, -1},
801                         {SIZE_MAX / 20, -1},
802                         {SIZE_MAX / 11, -1},
803                         {SIZE_MAX / 4, -1},
804                         {SIZE_MAX / 2, -1},
805                         {SIZE_MAX / 1, -1},
806                 };
807                 for (size_t i = 0; i < ARRAY_LENGTH(CASES); i++) {
808                         assert(calcSegmentBitLength(qrcodegen_Mode_KANJI, CASES[i].numChars) == CASES[i].result);
809                         numTestCases++;
810                 }
811         }
812         {
813                 assert(calcSegmentBitLength(qrcodegen_Mode_ECI, 0) == 24);
814                 numTestCases++;
815         }
816 }
817
818
819 static void testMakeBytes(void) {
820         {
821                 struct qrcodegen_Segment seg = qrcodegen_makeBytes(NULL, 0, NULL);
822                 assert(seg.mode == qrcodegen_Mode_BYTE);
823                 assert(seg.numChars == 0);
824                 assert(seg.bitLength == 0);
825                 numTestCases++;
826         }
827         {
828                 const uint8_t data[] = {0x00};
829                 uint8_t buf[1];
830                 struct qrcodegen_Segment seg = qrcodegen_makeBytes(data, 1, buf);
831                 assert(seg.numChars == 1);
832                 assert(seg.bitLength == 8);
833                 assert(seg.data[0] == 0x00);
834                 numTestCases++;
835         }
836         {
837                 const uint8_t data[] = {0xEF, 0xBB, 0xBF};
838                 uint8_t buf[3];
839                 struct qrcodegen_Segment seg = qrcodegen_makeBytes(data, 3, buf);
840                 assert(seg.numChars == 3);
841                 assert(seg.bitLength == 24);
842                 assert(seg.data[0] == 0xEF);
843                 assert(seg.data[1] == 0xBB);
844                 assert(seg.data[2] == 0xBF);
845                 numTestCases++;
846         }
847 }
848
849
850 static void testMakeNumeric(void) {
851         {
852                 struct qrcodegen_Segment seg = qrcodegen_makeNumeric("", NULL);
853                 assert(seg.mode == qrcodegen_Mode_NUMERIC);
854                 assert(seg.numChars == 0);
855                 assert(seg.bitLength == 0);
856                 numTestCases++;
857         }
858         {
859                 uint8_t buf[1];
860                 struct qrcodegen_Segment seg = qrcodegen_makeNumeric("9", buf);
861                 assert(seg.numChars == 1);
862                 assert(seg.bitLength == 4);
863                 assert(seg.data[0] == 0x90);
864                 numTestCases++;
865         }
866         {
867                 uint8_t buf[1];
868                 struct qrcodegen_Segment seg = qrcodegen_makeNumeric("81", buf);
869                 assert(seg.numChars == 2);
870                 assert(seg.bitLength == 7);
871                 assert(seg.data[0] == 0xA2);
872                 numTestCases++;
873         }
874         {
875                 uint8_t buf[2];
876                 struct qrcodegen_Segment seg = qrcodegen_makeNumeric("673", buf);
877                 assert(seg.numChars == 3);
878                 assert(seg.bitLength == 10);
879                 assert(seg.data[0] == 0xA8);
880                 assert(seg.data[1] == 0x40);
881                 numTestCases++;
882         }
883         {
884                 uint8_t buf[5];
885                 struct qrcodegen_Segment seg = qrcodegen_makeNumeric("3141592653", buf);
886                 assert(seg.numChars == 10);
887                 assert(seg.bitLength == 34);
888                 assert(seg.data[0] == 0x4E);
889                 assert(seg.data[1] == 0x89);
890                 assert(seg.data[2] == 0xF4);
891                 assert(seg.data[3] == 0x24);
892                 assert(seg.data[4] == 0xC0);
893                 numTestCases++;
894         }
895 }
896
897
898 static void testMakeAlphanumeric(void) {
899         {
900                 struct qrcodegen_Segment seg = qrcodegen_makeAlphanumeric("", NULL);
901                 assert(seg.mode == qrcodegen_Mode_ALPHANUMERIC);
902                 assert(seg.numChars == 0);
903                 assert(seg.bitLength == 0);
904                 numTestCases++;
905         }
906         {
907                 uint8_t buf[1];
908                 struct qrcodegen_Segment seg = qrcodegen_makeAlphanumeric("A", buf);
909                 assert(seg.numChars == 1);
910                 assert(seg.bitLength == 6);
911                 assert(seg.data[0] == 0x28);
912                 numTestCases++;
913         }
914         {
915                 uint8_t buf[2];
916                 struct qrcodegen_Segment seg = qrcodegen_makeAlphanumeric("%:", buf);
917                 assert(seg.numChars == 2);
918                 assert(seg.bitLength == 11);
919                 assert(seg.data[0] == 0xDB);
920                 assert(seg.data[1] == 0x40);
921                 numTestCases++;
922         }
923         {
924                 uint8_t buf[3];
925                 struct qrcodegen_Segment seg = qrcodegen_makeAlphanumeric("Q R", buf);
926                 assert(seg.numChars == 3);
927                 assert(seg.bitLength == 17);
928                 assert(seg.data[0] == 0x96);
929                 assert(seg.data[1] == 0xCD);
930                 assert(seg.data[2] == 0x80);
931                 numTestCases++;
932         }
933 }
934
935
936 static void testMakeEci(void) {
937         {
938                 uint8_t buf[1];
939                 struct qrcodegen_Segment seg = qrcodegen_makeEci(127, buf);
940                 assert(seg.mode == qrcodegen_Mode_ECI);
941                 assert(seg.numChars == 0);
942                 assert(seg.bitLength == 8);
943                 assert(seg.data[0] == 0x7F);
944                 numTestCases++;
945         }
946         {
947                 uint8_t buf[2];
948                 struct qrcodegen_Segment seg = qrcodegen_makeEci(10345, buf);
949                 assert(seg.numChars == 0);
950                 assert(seg.bitLength == 16);
951                 assert(seg.data[0] == 0xA8);
952                 assert(seg.data[1] == 0x69);
953                 numTestCases++;
954         }
955         {
956                 uint8_t buf[3];
957                 struct qrcodegen_Segment seg = qrcodegen_makeEci(999999, buf);
958                 assert(seg.numChars == 0);
959                 assert(seg.bitLength == 24);
960                 assert(seg.data[0] == 0xCF);
961                 assert(seg.data[1] == 0x42);
962                 assert(seg.data[2] == 0x3F);
963                 numTestCases++;
964         }
965 }
966
967
968 static void testGetTotalBits(void) {
969         {
970                 assert(getTotalBits(NULL, 0, 1) == 0);
971                 numTestCases++;
972                 assert(getTotalBits(NULL, 0, 40) == 0);
973                 numTestCases++;
974         }
975         {
976                 struct qrcodegen_Segment segs[] = {
977                         {qrcodegen_Mode_BYTE, 3, NULL, 24},
978                 };
979                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 2) == 36);
980                 numTestCases++;
981                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 10) == 44);
982                 numTestCases++;
983                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 39) == 44);
984                 numTestCases++;
985         }
986         {
987                 struct qrcodegen_Segment segs[] = {
988                         {qrcodegen_Mode_ECI, 0, NULL, 8},
989                         {qrcodegen_Mode_NUMERIC, 7, NULL, 24},
990                         {qrcodegen_Mode_ALPHANUMERIC, 1, NULL, 6},
991                         {qrcodegen_Mode_KANJI, 4, NULL, 52},
992                 };
993                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 9) == 133);
994                 numTestCases++;
995                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 21) == 139);
996                 numTestCases++;
997                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 27) == 145);
998                 numTestCases++;
999         }
1000         {
1001                 struct qrcodegen_Segment segs[] = {
1002                         {qrcodegen_Mode_BYTE, 4093, NULL, 32744},
1003                 };
1004                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 1) == -1);
1005                 numTestCases++;
1006                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 10) == 32764);
1007                 numTestCases++;
1008                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 27) == 32764);
1009                 numTestCases++;
1010         }
1011         {
1012                 struct qrcodegen_Segment segs[] = {
1013                         {qrcodegen_Mode_NUMERIC, 2047, NULL, 6824},
1014                         {qrcodegen_Mode_NUMERIC, 2047, NULL, 6824},
1015                         {qrcodegen_Mode_NUMERIC, 2047, NULL, 6824},
1016                         {qrcodegen_Mode_NUMERIC, 2047, NULL, 6824},
1017                         {qrcodegen_Mode_NUMERIC, 1617, NULL, 5390},
1018                 };
1019                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 1) == -1);
1020                 numTestCases++;
1021                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 10) == 32766);
1022                 numTestCases++;
1023                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 27) == -1);
1024                 numTestCases++;
1025         }
1026         {
1027                 struct qrcodegen_Segment segs[] = {
1028                         {qrcodegen_Mode_KANJI, 255, NULL, 3315},
1029                         {qrcodegen_Mode_KANJI, 255, NULL, 3315},
1030                         {qrcodegen_Mode_KANJI, 255, NULL, 3315},
1031                         {qrcodegen_Mode_KANJI, 255, NULL, 3315},
1032                         {qrcodegen_Mode_KANJI, 255, NULL, 3315},
1033                         {qrcodegen_Mode_KANJI, 255, NULL, 3315},
1034                         {qrcodegen_Mode_KANJI, 255, NULL, 3315},
1035                         {qrcodegen_Mode_KANJI, 255, NULL, 3315},
1036                         {qrcodegen_Mode_KANJI, 255, NULL, 3315},
1037                         {qrcodegen_Mode_ALPHANUMERIC, 511, NULL, 2811},
1038                 };
1039                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 9) == 32767);
1040                 numTestCases++;
1041                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 26) == -1);
1042                 numTestCases++;
1043                 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 40) == -1);
1044                 numTestCases++;
1045         }
1046 }
1047
1048
1049 /*---- Main runner ----*/
1050
1051 int main(void) {
1052         srand((unsigned int)time(NULL));
1053         testAppendBitsToBuffer();
1054         testAddEccAndInterleave();
1055         testGetNumDataCodewords();
1056         testGetNumRawDataModules();
1057         testReedSolomonComputeDivisor();
1058         testReedSolomonComputeRemainder();
1059         testReedSolomonMultiply();
1060         testInitializeFunctionModulesEtc();
1061         testGetAlignmentPatternPositions();
1062         testGetSetModule();
1063         testGetSetModuleRandomly();
1064         testIsAlphanumeric();
1065         testIsNumeric();
1066         testCalcSegmentBufferSize();
1067         testCalcSegmentBitLength();
1068         testMakeBytes();
1069         testMakeNumeric();
1070         testMakeAlphanumeric();
1071         testMakeEci();
1072         testGetTotalBits();
1073         printf("All %d test cases passed\n", numTestCases);
1074         return EXIT_SUCCESS;
1075 }