2 * QR Code generator test suite (C)
4 * When compiling this program, the library qrcodegen.c needs QRCODEGEN_TEST
5 * to be defined. Run this command line program with no arguments.
7 * Copyright (c) Project Nayuki. (MIT License)
8 * https://www.nayuki.io/page/qr-code-generator-library
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
36 #include "qrcodegen.h"
38 #define ARRAY_LENGTH(name) (sizeof(name) / sizeof(name[0]))
42 static int numTestCases = 0;
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);
64 /*---- Test cases ----*/
66 static void testAppendBitsToBuffer(void) {
70 appendBitsToBuffer(0, 0, buf, &bitLen);
73 appendBitsToBuffer(1, 1, buf, &bitLen);
75 assert(buf[0] == 0x80);
76 appendBitsToBuffer(0, 1, buf, &bitLen);
78 assert(buf[0] == 0x80);
79 appendBitsToBuffer(5, 3, buf, &bitLen);
81 assert(buf[0] == 0xA8);
82 appendBitsToBuffer(6, 3, buf, &bitLen);
84 assert(buf[0] == 0xAE);
90 appendBitsToBuffer(16942, 16, buf, &bitLen);
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);
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);
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);
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;
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]);
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];
141 for (size_t i = 0; i < numBlocks; i++)
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);
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);
163 assert(memcmp(actualOutput, expectOutput, dataAndEccLen * sizeof(uint8_t)) == 0);
174 static void testGetNumDataCodewords(void) {
175 const int cases[][3] = {
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]);
214 static void testGetNumRawDataModules(void) {
215 const int cases[][2] = {
230 for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
231 const int *tc = cases[i];
232 assert(getNumRawDataModules(tc[0]) == tc[1]);
238 static void testReedSolomonComputeDivisor(void) {
239 uint8_t generator[30];
241 reedSolomonComputeDivisor(1, generator);
242 assert(generator[0] == 0x01);
245 reedSolomonComputeDivisor(2, generator);
246 assert(generator[0] == 0x03);
247 assert(generator[1] == 0x02);
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);
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);
271 static void testReedSolomonComputeRemainder(void) {
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);
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]);
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);
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,
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);
336 static void testReedSolomonMultiply(void) {
337 const uint8_t cases[][3] = {
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]);
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);
369 int size = qrcodegen_getSize(qrcode);
375 assert(size == ver * 4 + 17);
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);
388 assert(hasWhite && hasBlack);
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},
410 for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
411 const int *tc = cases[i];
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]);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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];
487 assert(getModule(qrcode, x, y) == oldColor);
488 assert(qrcodegen_getModule(qrcode, x, y) == oldColor);
490 bool newColor = rand() % 2 == 0;
492 modules[y][x] = newColor;
493 if (isInBounds && rand() % 2 == 0)
494 setModule(qrcode, x, y, newColor);
496 setModuleBounded(qrcode, x, y, newColor);
502 static void testIsAlphanumeric(void) {
507 const struct TestCase cases[] = {
528 for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
529 assert(qrcodegen_isAlphanumeric(cases[i].text) == cases[i].answer);
535 static void testIsNumeric(void) {
540 const struct TestCase cases[] = {
554 {false, "+123 ABC$"},
561 for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
562 assert(qrcodegen_isNumeric(cases[i].text) == cases[i].answer);
568 static void testCalcSegmentBufferSize(void) {
570 const size_t cases[][2] = {
589 {SIZE_MAX / 6, SIZE_MAX},
590 {SIZE_MAX / 4, SIZE_MAX},
591 {SIZE_MAX / 2, SIZE_MAX},
592 {SIZE_MAX / 1, SIZE_MAX},
594 for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
595 assert(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, cases[i][0]) == cases[i][1]);
600 const size_t cases[][2] = {
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},
625 for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
626 assert(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, cases[i][0]) == cases[i][1]);
631 const size_t cases[][2] = {
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},
655 for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
656 assert(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_BYTE, cases[i][0]) == cases[i][1]);
661 const size_t cases[][2] = {
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},
684 for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) {
685 assert(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_KANJI, cases[i][0]) == cases[i][1]);
690 assert(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ECI, 0) == 3);
696 static void testCalcSegmentBitLength(void) {
702 const struct TestCase CASES[] = {
725 for (size_t i = 0; i < ARRAY_LENGTH(CASES); i++) {
726 assert(calcSegmentBitLength(qrcodegen_Mode_NUMERIC, CASES[i].numChars) == CASES[i].result);
731 const struct TestCase CASES[] = {
754 for (size_t i = 0; i < ARRAY_LENGTH(CASES); i++) {
755 assert(calcSegmentBitLength(qrcodegen_Mode_ALPHANUMERIC, CASES[i].numChars) == CASES[i].result);
760 const struct TestCase CASES[] = {
780 for (size_t i = 0; i < ARRAY_LENGTH(CASES); i++) {
781 assert(calcSegmentBitLength(qrcodegen_Mode_BYTE, CASES[i].numChars) == CASES[i].result);
786 const struct TestCase CASES[] = {
807 for (size_t i = 0; i < ARRAY_LENGTH(CASES); i++) {
808 assert(calcSegmentBitLength(qrcodegen_Mode_KANJI, CASES[i].numChars) == CASES[i].result);
813 assert(calcSegmentBitLength(qrcodegen_Mode_ECI, 0) == 24);
819 static void testMakeBytes(void) {
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);
828 const uint8_t data[] = {0x00};
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);
837 const uint8_t data[] = {0xEF, 0xBB, 0xBF};
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);
850 static void testMakeNumeric(void) {
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);
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);
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);
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);
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);
898 static void testMakeAlphanumeric(void) {
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);
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);
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);
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);
936 static void testMakeEci(void) {
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);
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);
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);
968 static void testGetTotalBits(void) {
970 assert(getTotalBits(NULL, 0, 1) == 0);
972 assert(getTotalBits(NULL, 0, 40) == 0);
976 struct qrcodegen_Segment segs[] = {
977 {qrcodegen_Mode_BYTE, 3, NULL, 24},
979 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 2) == 36);
981 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 10) == 44);
983 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 39) == 44);
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},
993 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 9) == 133);
995 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 21) == 139);
997 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 27) == 145);
1001 struct qrcodegen_Segment segs[] = {
1002 {qrcodegen_Mode_BYTE, 4093, NULL, 32744},
1004 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 1) == -1);
1006 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 10) == 32764);
1008 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 27) == 32764);
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},
1019 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 1) == -1);
1021 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 10) == 32766);
1023 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 27) == -1);
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},
1039 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 9) == 32767);
1041 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 26) == -1);
1043 assert(getTotalBits(segs, ARRAY_LENGTH(segs), 40) == -1);
1049 /*---- Main runner ----*/
1052 srand((unsigned int)time(NULL));
1053 testAppendBitsToBuffer();
1054 testAddEccAndInterleave();
1055 testGetNumDataCodewords();
1056 testGetNumRawDataModules();
1057 testReedSolomonComputeDivisor();
1058 testReedSolomonComputeRemainder();
1059 testReedSolomonMultiply();
1060 testInitializeFunctionModulesEtc();
1061 testGetAlignmentPatternPositions();
1063 testGetSetModuleRandomly();
1064 testIsAlphanumeric();
1066 testCalcSegmentBufferSize();
1067 testCalcSegmentBitLength();
1070 testMakeAlphanumeric();
1073 printf("All %d test cases passed\n", numTestCases);
1074 return EXIT_SUCCESS;