summaryrefslogtreecommitdiff
path: root/genqrcode/tests/test_qrinput.c
diff options
context:
space:
mode:
Diffstat (limited to 'genqrcode/tests/test_qrinput.c')
-rw-r--r--genqrcode/tests/test_qrinput.c1130
1 files changed, 1130 insertions, 0 deletions
diff --git a/genqrcode/tests/test_qrinput.c b/genqrcode/tests/test_qrinput.c
new file mode 100644
index 0000000000..2aab36a8b6
--- /dev/null
+++ b/genqrcode/tests/test_qrinput.c
@@ -0,0 +1,1130 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "common.h"
+#include "../qrinput.h"
+#include "../qrencode_inner.h"
+#include "../split.h"
+#include "decoder.h"
+
+/* taken from the Table 7 of JIS X0510:2018 (pp. 31-34) */
+static int maxCharacterLengths[40][4] = {
+ { 41, 25, 17, 10}, /* ver 1 */
+ { 77, 47, 32, 20}, /* ver 2 */
+ { 127, 77, 53, 32}, /* ver 3 */
+ { 187, 114, 78, 48}, /* ver 4 */
+ { 255, 154, 106, 65}, /* ver 5 */
+ { 322, 195, 134, 82}, /* ver 6 */
+ { 370, 224, 154, 95}, /* ver 7 */
+ { 461, 279, 192, 118}, /* ver 8 */
+ { 552, 335, 230, 141}, /* ver 9 */
+ { 652, 395, 271, 167}, /* ver 10 */
+ { 772, 468, 321, 198}, /* ver 11 */
+ { 883, 535, 367, 226}, /* ver 12 */
+ {1022, 619, 425, 262}, /* ver 13 */
+ {1101, 667, 458, 282}, /* ver 14 */
+ {1250, 758, 520, 320}, /* ver 15 */
+ {1408, 854, 586, 361}, /* ver 16 */
+ {1548, 938, 644, 397}, /* ver 17 */
+ {1725, 1046, 718, 442}, /* ver 18 */
+ {1903, 1153, 792, 488}, /* ver 19 */
+ {2061, 1249, 858, 528}, /* ver 20 */
+ {2232, 1352, 929, 572}, /* ver 21 */
+ {2409, 1460, 1003, 618}, /* ver 22 */
+ {2620, 1588, 1091, 672}, /* ver 23 */
+ {2812, 1704, 1171, 721}, /* ver 24 */
+ {3057, 1853, 1273, 784}, /* ver 25 */
+ {3283, 1990, 1367, 842}, /* ver 26 */
+ {3517, 2132, 1465, 902}, /* ver 27 */
+ {3669, 2223, 1528, 940}, /* ver 28 */
+ {3909, 2369, 1628, 1002}, /* ver 29 */
+ {4158, 2520, 1732, 1066}, /* ver 30 */
+ {4417, 2677, 1840, 1132}, /* ver 31 */
+ {4686, 2840, 1952, 1201}, /* ver 32 */
+ {4965, 3009, 2068, 1273}, /* ver 33 */
+ {5253, 3183, 2188, 1347}, /* ver 34 */
+ {5529, 3351, 2303, 1417}, /* ver 35 */
+ {5836, 3537, 2431, 1496}, /* ver 36 */
+ {6153, 3729, 2563, 1577}, /* ver 37 */
+ {6479, 3927, 2699, 1661}, /* ver 38 */
+ {6743, 4087, 2809, 1729}, /* ver 39 */
+ {7089, 4296, 2953, 1817} /* ver 40 */
+};
+
+static int encodeAndCheckBStream(int mqr, int version, QRecLevel level, QRencodeMode mode, char *data, char *correct)
+{
+ QRinput *input;
+ BitStream *bstream;
+ int ret;
+
+ if(mqr) {
+ input = QRinput_newMQR(version, level);
+ } else {
+ input = QRinput_new2(version, level);
+ }
+ QRinput_append(input, mode, strlen(data), (unsigned char *)data);
+ bstream = BitStream_new();
+ QRinput_getBitStream(input, bstream);
+ ret = cmpBin(correct, bstream);
+ if(ret) {
+ printf("result : ");
+ printBstream(bstream);
+ printf("correct: %s\n", correct);
+ }
+ QRinput_free(input);
+ BitStream_free(bstream);
+
+ return ret;
+}
+
+static int mergeAndCheckBStream(int mqr, QRencodeMode mode, char *data, char *correct)
+{
+ QRinput *input;
+ BitStream *bstream;
+ int ret;
+
+ if(mqr) {
+ input = QRinput_newMQR(1, QR_ECLEVEL_L);
+ } else {
+ input = QRinput_new();
+ }
+ QRinput_append(input, mode, strlen(data), (unsigned char *)data);
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(input, bstream);
+ ret = cmpBin(correct, bstream);
+
+ QRinput_free(input);
+ BitStream_free(bstream);
+
+ return ret;
+}
+
+static void test_encodeKanji(void)
+{
+ char str[5]= {0x93, 0x5f, 0xe4, 0xaa, 0x00};
+ char *correct = "10000000001001101100111111101010101010";
+
+ testStart("Encoding kanji stream.");
+ testEnd(mergeAndCheckBStream(0, QR_MODE_KANJI, str, correct));
+}
+
+static void test_encode8(void)
+{
+ char str[] = "AC-42";
+ char correct[] = "0100000001010100000101000011001011010011010000110010";
+
+ testStart("Encoding 8bit stream.");
+ testEnd(mergeAndCheckBStream(0, QR_MODE_8, str, correct));
+}
+
+static void test_encode8_versionup(void)
+{
+ QRinput *stream;
+ BitStream *bstream;
+ char *str;
+ int version;
+
+ testStart("Encoding 8bit stream. (auto-version up test)");
+ str = (char *)malloc(2900);
+ memset(str, 0xff, 2900);
+ stream = QRinput_new();
+ bstream = BitStream_new();
+ QRinput_append(stream, QR_MODE_8, 2900, (unsigned char *)str);
+ QRinput_mergeBitStream(stream, bstream);
+ version = QRinput_getVersion(stream);
+ assert_equal(version, 40, "Version is %d (40 expected).\n", version);
+ testFinish();
+ QRinput_free(stream);
+ BitStream_free(bstream);
+ free(str);
+}
+
+static void test_encodeAn(void)
+{
+ char *str = "AC-42";
+ char correct[] = "00100000001010011100111011100111001000010";
+
+ testStart("Encoding alphabet-numeric stream.");
+ testEnd(mergeAndCheckBStream(0, QR_MODE_AN, str, correct));
+}
+
+static void test_encodeAn2(void)
+{
+ QRinput *stream;
+ char str[] = "!,;$%";
+ int ret;
+
+ testStart("Encoding INVALID alphabet-numeric stream.");
+ stream = QRinput_new();
+ ret = QRinput_append(stream, QR_MODE_AN, 5, (unsigned char *)str);
+ testEnd(!ret);
+ QRinput_free(stream);
+}
+
+static void test_encodeNumeric(void)
+{
+ char *str = "01234567";
+ char correct[] = "00010000001000000000110001010110011000011";
+
+ testStart("Encoding numeric stream. (8 digits)");
+ testEnd(mergeAndCheckBStream(0, QR_MODE_NUM, str, correct));
+}
+
+static void test_encodeNumeric_versionup(void)
+{
+ QRinput *stream;
+ BitStream *bstream;
+ char *str;
+ int version;
+
+ testStart("Encoding numeric stream. (auto-version up test)");
+ str = (char *)malloc(1050);
+ memset(str, '1', 1050);
+ stream = QRinput_new2(0, QR_ECLEVEL_L);
+ bstream = BitStream_new();
+ QRinput_append(stream, QR_MODE_NUM, 1050, (unsigned char *)str);
+ QRinput_mergeBitStream(stream, bstream);
+ version = QRinput_getVersion(stream);
+ assert_equal(version, 14, "Version is %d (14 expected).", version);
+ testFinish();
+ QRinput_free(stream);
+ BitStream_free(bstream);
+ free(str);
+}
+
+static void test_encodeNumericPadded(void)
+{
+ char *str = "01234567";
+ char *correct;
+ char *correctHead = "000100000010000000001100010101100110000110000000";
+ int i, ret;
+
+ testStart("Encoding numeric stream. (8 digits)(padded)");
+ correct = (char *)malloc(19 * 8 + 1);
+ correct[0] = '\0';
+ strcat(correct, correctHead);
+ for(i=0; i<13; i++) {
+ strcat(correct, (i&1)?"00010001":"11101100");
+ }
+ ret = encodeAndCheckBStream(0, 0, QR_ECLEVEL_L, QR_MODE_NUM, str, correct);
+ testEnd(ret);
+
+ free(correct);
+}
+
+static void test_encodeNumericPadded2(void)
+{
+ char *str = "0123456";
+ char *correct;
+ char *correctHead = "000100000001110000001100010101100101100000000000";
+ int i, ret;
+
+ testStart("Encoding numeric stream. (7 digits)(padded)");
+ correct = (char *)malloc(19 * 8 + 1);
+ correct[0] = '\0';
+ strcat(correct, correctHead);
+ for(i=0; i<13; i++) {
+ strcat(correct, (i&1)?"00010001":"11101100");
+ }
+ ret = encodeAndCheckBStream(0, 0, QR_ECLEVEL_L, QR_MODE_NUM, str, correct);
+ testEnd(ret);
+
+ free(correct);
+}
+
+static void test_padding(void)
+{
+ QRinput *input;
+ BitStream *bstream;
+ int i, size;
+ char data[] = "0123456789ABCDeFG";
+ unsigned char c;
+
+ testStart("Padding bit check. (less than 5 bits)");
+ input = QRinput_new2(1, QR_ECLEVEL_L);
+ QRinput_append(input, QR_MODE_8, 17, (unsigned char *)data);
+ bstream = BitStream_new();
+ QRinput_getBitStream(input, bstream);
+ size = BitStream_size(bstream);
+ assert_equal(size, 152, "# of bit is incorrect (%d != 152).\n", size);
+ c = 0;
+ for(i=0; i<4; i++) {
+ c += bstream->data[size - i - 1];
+ }
+ assert_zero(c, "Padding bits are not zero.");
+ testFinish();
+
+ QRinput_free(input);
+ BitStream_free(bstream);
+}
+
+static void test_padding2(void)
+{
+ QRinput *input;
+ BitStream *bstream;
+ int i, size, ret;
+ char data[] = "0123456789ABCDeF";
+ char correct[153];
+ unsigned char c;
+
+ testStart("Padding bit check. (1 or 2 padding bytes)");
+
+ /* 16 byte data (4 bit terminator and 1 byte padding) */
+ memset(correct, 0, 153);
+ memcpy(correct, "010000010000", 12);
+ for(size=0; size<16; size++) {
+ c = 0x80;
+ for(i=0; i<8; i++) {
+ correct[size * 8 + i + 12] = (data[size]&c)?'1':'0';
+ c = c >> 1;
+ }
+ }
+ memcpy(correct + 140, "000011101100", 12);
+
+ input = QRinput_new2(1, QR_ECLEVEL_L);
+ QRinput_append(input, QR_MODE_8, 16, (unsigned char *)data);
+ bstream = BitStream_new();
+ QRinput_getBitStream(input, bstream);
+ size = BitStream_size(bstream);
+ assert_equal(size, 152, "16byte: # of bit is incorrect (%d != 152).\n", size);
+ ret = ncmpBin(correct, bstream, 152);
+ assert_zero(ret, "Padding bits incorrect.\n");
+
+ QRinput_free(input);
+ BitStream_free(bstream);
+
+ /* 15 byte data (4 bit terminator and 2 byte paddings) */
+
+ memcpy(correct, "010000001111", 12);
+ memcpy(correct + 132, "00001110110000010001", 20);
+
+ input = QRinput_new2(1, QR_ECLEVEL_L);
+ QRinput_append(input, QR_MODE_8, 15, (unsigned char *)data);
+ bstream = BitStream_new();
+ QRinput_getBitStream(input, bstream);
+ size = BitStream_size(bstream);
+ assert_equal(size, 152, "15byte: # of bit is incorrect (%d != 152).\n", size);
+ ret = ncmpBin(correct, bstream, 152);
+ assert_zero(ret, "Padding bits incorrect.\n");
+
+ testFinish();
+
+ QRinput_free(input);
+ BitStream_free(bstream);
+}
+
+static void test_encodeNumeric2(void)
+{
+ char *str = "0123456789012345";
+ char *correct = "00010000010000000000110001010110011010100110111000010100111010100101";
+
+ testStart("Encoding numeric stream. (16 digits)");
+ testEnd(mergeAndCheckBStream(0, QR_MODE_NUM, str, correct));
+}
+
+static void test_encodeNumeric3(void)
+{
+ char *str = "0123456";
+ char *correct = "0001 0000000111 0000001100 0101011001 0110";
+
+ testStart("Encoding numeric stream. (7 digits)");
+ testEnd(mergeAndCheckBStream(0, QR_MODE_NUM, str, correct));
+}
+
+static void test_encodeAnNum(void)
+{
+ QRinput *input;
+ BitStream *bstream;
+
+ testStart("Bit length check of alpha-numeric stream. (11 + 12)");
+ input = QRinput_new();
+ QRinput_append(input, QR_MODE_AN, 11, (unsigned char *)"ABCDEFGHIJK");
+ QRinput_append(input, QR_MODE_NUM, 12, (unsigned char *)"123456789012");
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(input, bstream);
+ testEndExp(BitStream_size(bstream) == 128);
+ QRinput_free(input);
+ BitStream_free(bstream);
+
+ testStart("Bit length check of alphabet stream. (23)");
+ input = QRinput_new();
+ QRinput_append(input, QR_MODE_AN, 23, (unsigned char *)"ABCDEFGHIJK123456789012");
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(input, bstream);
+ testEndExp(BitStream_size(bstream) == 140);
+ QRinput_free(input);
+ BitStream_free(bstream);
+}
+
+static void test_struct_listop(void)
+{
+ QRinput_Struct *s;
+ QRinput *inputs[5];
+ QRinput_InputList *l;
+ int i, ret;
+
+ testStart("QRinput_Struct list operation test.");
+ s = QRinput_Struct_new();
+ QRinput_Struct_setParity(s, 10);
+ assert_nonnull(s, "QRinput_Struct_new() failed.");
+ assert_equal(s->parity, 10, "QRinput_Struct_setParity() failed.");
+
+ for(i=0; i<5; i++) {
+ inputs[i] = QRinput_new();
+ QRinput_append(inputs[i], QR_MODE_AN, 5, (unsigned char *)"ABCDE");
+ ret = QRinput_Struct_appendInput(s, inputs[i]);
+ }
+ assert_equal(ret, 5, "QRinput_Struct_appendInput() returns wrong num?");
+ assert_equal(s->size, 5, "QRiput_Struct.size counts wrong number.");
+
+ l = s->head;
+ i = 0;
+ while(l != NULL) {
+ assert_equal(l->input, inputs[i], "QRinput_Struct input list order would be wrong?");
+ l = l->next;
+ i++;
+ }
+
+ QRinput_Struct_free(s);
+ testFinish();
+}
+
+static void test_insertStructuredAppendHeader(void)
+{
+ QRinput *stream;
+ char correct[] = "0011000011111010010101000000000101000001";
+ BitStream *bstream;
+ int ret;
+
+ testStart("Insert a structured-append header");
+ stream = QRinput_new();
+ bstream = BitStream_new();
+ QRinput_append(stream, QR_MODE_8, 1, (unsigned char *)"A");
+ ret = QRinput_insertStructuredAppendHeader(stream, 16, 1, 0xa5);
+ assert_zero(ret, "QRinput_insertStructuredAppendHeader() returns nonzero.\n");
+ QRinput_mergeBitStream(stream, bstream);
+ assert_nonnull(bstream->data, "Bstream->data is null.");
+ assert_zero(cmpBin(correct, bstream), "bitstream is wrong.");
+ testFinish();
+
+ QRinput_free(stream);
+ BitStream_free(bstream);
+}
+
+static void test_insertStructuredAppendHeader_error(void)
+{
+ QRinput *stream;
+ int ret;
+
+ testStart("Insert a structured-append header (errors expected)");
+ stream = QRinput_new();
+ QRinput_append(stream, QR_MODE_8, 1, (unsigned char *)"A");
+ ret = QRinput_insertStructuredAppendHeader(stream, 17, 1, 0xa5);
+ assert_equal(-1, ret, "QRinput_insertStructuredAppendHeader() returns 0.");
+ assert_equal(EINVAL, errno, "errno is not set correctly (%d returned).", errno);
+ ret = QRinput_insertStructuredAppendHeader(stream, 16, 17, 0xa5);
+ assert_equal(-1, ret, "QRinput_insertStructuredAppendHeader() returns 0.");
+ assert_equal(EINVAL, errno, "errno is not set correctly (%d returned).", errno);
+ ret = QRinput_insertStructuredAppendHeader(stream, 16, 0, 0xa5);
+ assert_equal(-1, ret, "QRinput_insertStructuredAppendHeader() returns 0.");
+ assert_equal(EINVAL, errno, "errno is not set correctly (%d returned).", errno);
+ testFinish();
+
+ QRinput_free(stream);
+}
+
+static void test_struct_insertStructuredAppendHeaders(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ QRinput_InputList *p;
+ int i;
+
+ testStart("Insert structured-append headers to a QRinput_Struct.");
+ s = QRinput_Struct_new();
+ for(i=0; i<10; i++) {
+ input = QRinput_new();
+ QRinput_append(input, QR_MODE_8, 1, (unsigned char *)"A");
+ QRinput_Struct_appendInput(s, input);
+ }
+ QRinput_Struct_insertStructuredAppendHeaders(s);
+ p = s->head;
+ i = 1;
+ while(p != NULL) {
+ assert_equal(p->input->head->mode, QR_MODE_STRUCTURE, "a structured-append header is not inserted.");
+ assert_equal(p->input->head->data[0], 10, "size of the structured-header is wrong: #%d, %d should be %d\n", i, p->input->head->data[0], 10);
+ assert_equal(p->input->head->data[1], i, "index of the structured-header is wrong: #%d, %d should be %d\n", i, p->input->head->data[1], i);
+ assert_equal(p->input->head->data[2], 0, "parity of the structured-header is wrong: #%d\n", i);
+ p = p->next;
+ i++;
+ }
+ testFinish();
+ QRinput_Struct_free(s);
+}
+
+static int check_lengthOfCode(QRencodeMode mode, char *data, int size, int version)
+{
+ QRinput *input;
+ BitStream *b;
+ size_t bits;
+ int bytes;
+
+ input = QRinput_new();
+ QRinput_setVersion(input, version);
+ QRinput_append(input, mode, size, (unsigned char *)data);
+ b = BitStream_new();
+ QRinput_mergeBitStream(input, b);
+ bits = BitStream_size(b);
+ bytes = QRinput_lengthOfCode(mode, version, bits);
+ QRinput_free(input);
+ BitStream_free(b);
+
+ return bytes;
+}
+
+static void test_lengthOfCode_num(void)
+{
+ int i, bytes;
+ char *data;
+
+ data = (char *)malloc(8000);
+ for(i=0; i<8000; i++) {
+ data[i] = '0' + i % 10;
+ }
+
+ testStart("Checking length of code (numeric)");
+ for(i=1; i<=9; i++) {
+ bytes = check_lengthOfCode(QR_MODE_NUM, data, i, 1);
+ assert_equal(i, bytes, "lengthOfCode failed. (QR_MODE_NUM, version:1, size:%d)\n", i);
+ }
+ for(i=1023; i<=1025; i++) {
+ bytes = check_lengthOfCode(QR_MODE_NUM, data, i, 1);
+ assert_equal(1023, bytes, "lengthOfCode failed. (QR_MODE_NUM, version:1, size:%d)\n", i);
+ }
+ testFinish();
+ free(data);
+}
+
+static void test_lengthOfCode_kanji(void)
+{
+ int i, bytes;
+ unsigned char str[12]= {0x93, 0x5f, 0xe4, 0xaa, 0x81, 0x40, 0x9f, 0xfc, 0xe0, 0x40, 0xeb, 0xbf};
+
+ testStart("Checking length of code (kanji)");
+ for(i=2; i<=12; i+=2) {
+ bytes = check_lengthOfCode(QR_MODE_KANJI, (char *)str, i, 1);
+ assert_equal(i, bytes, "lengthOfCode failed. (QR_MODE_KANJI, version:1, size:%d)\n", i);
+ }
+ testFinish();
+}
+
+static void test_struct_split_example(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ QRinput_InputList *e;
+ QRinput_List *l;
+ const char *str[4] = { "an example ", "of four Str", "uctured Appe", "nd symbols,"};
+ int i;
+ BitStream *bstream;
+
+ testStart("Testing the example of structured-append symbols");
+ s = QRinput_Struct_new();
+ for(i=0; i<4; i++) {
+ input = QRinput_new2(1, QR_ECLEVEL_M);
+ QRinput_append(input, QR_MODE_8, strlen(str[i]), (unsigned char *)str[i]);
+ QRinput_Struct_appendInput(s, input);
+ }
+ QRinput_Struct_insertStructuredAppendHeaders(s);
+ e = s->head;
+ i = 0;
+ while(e != NULL) {
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(e->input, bstream);
+ BitStream_free(bstream);
+ l = e->input->head->next;
+ assert_equal(l->mode, QR_MODE_8, "#%d: wrong mode (%d).\n", i, l->mode);
+ assert_equal(e->input->level, QR_ECLEVEL_M, "#%d: wrong level (%d).\n", i, e->input->level);
+
+ e = e->next;
+ i++;
+ }
+ testFinish();
+ QRinput_Struct_free(s);
+}
+
+static void test_struct_split_tooLarge(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ char *str;
+ int errsv;
+
+ testStart("Testing structured-append symbols. (too large data)");
+ str = (char *)malloc(128);
+ memset(str, 'a', 128);
+ input = QRinput_new2(1, QR_ECLEVEL_H);
+ QRinput_append(input, QR_MODE_8, 128, (unsigned char *)str);
+ s = QRinput_splitQRinputToStruct(input);
+ errsv = errno;
+ assert_null(s, "returns non-null.");
+ assert_equal(errsv, ERANGE, "did not return ERANGE.");
+ testFinish();
+ if(s != NULL) QRinput_Struct_free(s);
+ QRinput_free(input);
+ free(str);
+}
+
+static void test_struct_split_invalidVersion(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ char *str;
+ int errsv;
+
+ testStart("Testing structured-append symbols. (invalid version 0)");
+ str = (char *)malloc(128);
+ memset(str, 'a', 128);
+ input = QRinput_new2(0, QR_ECLEVEL_H);
+ QRinput_append(input, QR_MODE_8, 128, (unsigned char *)str);
+ s = QRinput_splitQRinputToStruct(input);
+ errsv = errno;
+ assert_null(s, "returns non-null.");
+ assert_equal(errsv, ERANGE, "did not return ERANGE.");
+ testFinish();
+ if(s != NULL) QRinput_Struct_free(s);
+ QRinput_free(input);
+ free(str);
+}
+
+static void test_struct_singlestructure(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ char *str = "TEST";
+
+ testStart("Testing structured-append symbols. (single structure)");
+ input = QRinput_new2(10, QR_ECLEVEL_H);
+ QRinput_append(input, QR_MODE_AN, strlen(str), (unsigned char *)str);
+ s = QRinput_splitQRinputToStruct(input);
+ assert_nonnull(s, "must return a code.");
+ assert_equal(s->size, 1, "size must be 1, but %d returned.", s->size);
+ if(s->size != 1) {
+ printQRinputStruct(s);
+ }
+ testFinish();
+ if(s != NULL) QRinput_Struct_free(s);
+ QRinput_free(input);
+}
+
+static void test_splitentry(void)
+{
+ QRinput *i1, *i2;
+ QRinput_List *e;
+ const char *str = "abcdefghij";
+ int size1, size2, i;
+ unsigned char *d1, *d2;
+
+ testStart("Testing QRinput_splitEntry. (next == NULL)");
+ i1 = QRinput_new();
+ QRinput_append(i1, QR_MODE_8, strlen(str), (unsigned char *)str);
+
+ i2 = QRinput_dup(i1);
+ e = i2->head;
+ QRinput_splitEntry(e, 4);
+
+ size1 = size2 = 0;
+ e = i1->head;
+ while(e != NULL) {
+ size1 += e->size;
+ e = e->next;
+ }
+ e = i2->head;
+ while(e != NULL) {
+ size2 += e->size;
+ e = e->next;
+ }
+
+ d1 = (unsigned char *)malloc(size1);
+ e = i1->head;
+ i = 0;
+ while(e != NULL) {
+ memcpy(&d1[i], e->data, e->size);
+ i += e->size;
+ e = e->next;
+ }
+ d2 = (unsigned char *)malloc(size2);
+ e = i2->head;
+ i = 0;
+ while(e != NULL) {
+ memcpy(&d2[i], e->data, e->size);
+ i += e->size;
+ e = e->next;
+ }
+
+ assert_equal(size1, size2, "sizes are different. (%d:%d)\n", size1, size2);
+ assert_equal(i2->head->size, 4, "split failed (first half)");
+ assert_equal(i2->head->next->size, 6, "split failed(second half)");
+ assert_zero(memcmp(d1, d2, size1), "strings are different.");
+ QRinput_free(i1);
+ QRinput_free(i2);
+ free(d1);
+ free(d2);
+
+ testFinish();
+}
+
+static void test_splitentry2(void)
+{
+ QRinput *i1, *i2;
+ QRinput_List *e;
+ const char *str = "abcdefghij";
+ int size1, size2, i;
+ unsigned char *d1, *d2;
+
+ testStart("Testing QRinput_splitEntry. (next != NULL)");
+ i1 = QRinput_new();
+ QRinput_append(i1, QR_MODE_8, strlen(str), (unsigned char *)str);
+ QRinput_append(i1, QR_MODE_8, strlen(str), (unsigned char *)str);
+
+ i2 = QRinput_dup(i1);
+ e = i2->head;
+ QRinput_splitEntry(e, 4);
+
+ size1 = size2 = 0;
+ e = i1->head;
+ while(e != NULL) {
+ size1 += e->size;
+ e = e->next;
+ }
+ e = i2->head;
+ while(e != NULL) {
+ size2 += e->size;
+ e = e->next;
+ }
+
+ d1 = (unsigned char *)malloc(size1);
+ e = i1->head;
+ i = 0;
+ while(e != NULL) {
+ memcpy(&d1[i], e->data, e->size);
+ i += e->size;
+ e = e->next;
+ }
+ d2 = (unsigned char *)malloc(size2);
+ e = i2->head;
+ i = 0;
+ while(e != NULL) {
+ memcpy(&d2[i], e->data, e->size);
+ i += e->size;
+ e = e->next;
+ }
+
+ assert_equal(size1, size2, "sizes are different. (%d:%d)\n", size1, size2);
+ assert_equal(i2->head->size, 4, "split failed (first half)");
+ assert_equal(i2->head->next->size, 6, "split failed(second half)");
+ assert_zero(memcmp(d1, d2, size1), "strings are different.");
+ QRinput_free(i1);
+ QRinput_free(i2);
+ free(d1);
+ free(d2);
+
+ testFinish();
+}
+
+static void test_splitentry3(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ QRinput_List *e00, *e01, *e10, *e11;
+ QRinput_InputList *list;
+ const char *str = "abcdefghijklmno";
+
+ testStart("Testing QRinput_splitEntry. (does not split an entry)");
+ /* version 1 symbol contains 152 bit (19 byte) data.
+ * 20 bits for a structured-append header, so 132 bits can be used.
+ * 15 bytes of 8-bit data is suitable for the symbol.
+ * (mode(4) + length(8) + data(120) == 132.)
+ */
+ input = QRinput_new2(1, QR_ECLEVEL_L);
+ QRinput_append(input, QR_MODE_8, strlen(str), (unsigned char *)str);
+ QRinput_append(input, QR_MODE_8, strlen(str), (unsigned char *)str);
+ s = QRinput_splitQRinputToStruct(input);
+ list = s->head;
+ e00 = list->input->head;
+ e01 = e00->next;
+ list = list->next;
+ e10 = list->input->head;
+ e11 = e10->next;
+
+ assert_equal(e00->mode, QR_MODE_STRUCTURE, "Structure header is missing?");
+ assert_equal(e01->mode, QR_MODE_8, "no data?!");
+ assert_null(e01->next, "Input list is not terminated!\n");
+ assert_equal(e10->mode, QR_MODE_STRUCTURE, "Structure header is missing?");
+ assert_equal(e11->mode, QR_MODE_8, "no data?!");
+ assert_null(e11->next, "Input list is not terminated!\n");
+
+ QRinput_free(input);
+ QRinput_Struct_free(s);
+ testFinish();
+}
+
+static void test_parity(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ const char *text = "an example of four Structured Append symbols,";
+ const char *str[4] = {
+ "an example ",
+ "of four Str",
+ "uctured Appe",
+ "nd symbols,"};
+ unsigned char p1, p2;
+ int i, len;
+
+ testStart("Testing parity calc.");
+ s = QRinput_Struct_new();
+ for(i=0; i<4; i++) {
+ input = QRinput_new2(1, QR_ECLEVEL_M);
+ QRinput_append(input, QR_MODE_8, strlen(str[i]), (unsigned char *)str[i]);
+ QRinput_Struct_appendInput(s, input);
+ }
+ QRinput_Struct_insertStructuredAppendHeaders(s);
+ p1 = s->parity;
+
+ p2 = 0;
+ len = strlen(text);
+ for(i=0; i<len; i++) {
+ p2 ^= text[i];
+ }
+ assert_equal(p1, p2, "Parity numbers didn't match. (%02x should be %02x).\n", p1, p2);
+ testFinish();
+ QRinput_Struct_free(s);
+}
+
+static void test_parity2(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ const char *text = "an example of four Structured Append symbols,";
+ unsigned char p1, p2;
+ int i, len;
+
+ testStart("Testing parity calc.(split)");
+ input = QRinput_new2(1, QR_ECLEVEL_L);
+ QRinput_append(input, QR_MODE_8, strlen(text), (unsigned char *)text);
+ s = QRinput_splitQRinputToStruct(input);
+ p1 = s->parity;
+
+ p2 = 0;
+ len = strlen(text);
+ for(i=0; i<len; i++) {
+ p2 ^= text[i];
+ }
+ assert_equal(p1, p2, "Parity numbers didn't match. (%02x should be %02x).\n", p1, p2);
+ testFinish();
+ QRinput_free(input);
+ QRinput_Struct_free(s);
+}
+
+static void test_null_free(void)
+{
+ testStart("Testing free NULL pointers");
+ assert_nothing(QRinput_free(NULL), "Check QRinput_free(NULL).\n");
+ assert_nothing(QRinput_Struct_free(NULL), "Check QRinput_Struct_free(NULL).\n");
+ testFinish();
+}
+
+static void fillCharacter(char *dest, char ch, int size)
+{
+ memset(dest, ch, size);
+ dest[size] = '\0';
+}
+
+static void checkEstimatedVersion(int ver, int mode)
+{
+ int estimatedVersion;
+ char data[7200];
+ QRinput *input;
+ QRencodeMode hint;
+ int size1, size2;
+ static char *modeStr[4] = {"numeric", "alphanumeric", "8 bit data", "kanji"};
+ static char ch[4] = {'0', 'A', 'a', '\x92'};
+
+ if(mode == QR_MODE_KANJI) {
+ hint = QR_MODE_KANJI;
+ size1 = maxCharacterLengths[ver - 1][mode] * 2;
+ size2 = size1 + 2;
+ } else {
+ hint = QR_MODE_8;
+ size1 = maxCharacterLengths[ver - 1][mode];
+ size2 = size1 + 1;
+ }
+
+ fillCharacter(data, ch[mode], size1);
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput(data, input, hint, 1);
+ estimatedVersion = QRinput_estimateVersion(input);
+ assert_equal(estimatedVersion, ver, "Estimated version %d is not equal to the expected version %d for %d %s sequence.\n", estimatedVersion, ver, maxCharacterLengths[ver - 1][mode], modeStr[mode]);
+ QRinput_free(input);
+
+ fillCharacter(data, ch[mode], size2);
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput(data, input, hint, 1);
+ estimatedVersion = QRinput_estimateVersion(input);
+ assert_equal(estimatedVersion, ver + 1, "Estimated version %d is not equal to the expected version %d for %d %s sequence.\n", estimatedVersion, ver, maxCharacterLengths[ver - 1][mode] + 1, modeStr[mode]);
+ QRinput_free(input);
+}
+
+static void test_estimateVersionBoundaryCheck(void)
+{
+ int ver;
+ testStart("Boundary check of estimateVersion");
+ for(ver = 1; ver < QRSPEC_VERSION_MAX; ver++) {
+ checkEstimatedVersion(ver, QR_MODE_NUM);
+ checkEstimatedVersion(ver, QR_MODE_AN);
+ checkEstimatedVersion(ver, QR_MODE_8);
+ checkEstimatedVersion(ver, QR_MODE_KANJI);
+ }
+ testFinish();
+}
+
+static void test_QRinput_new_invalid(void)
+{
+ testStart("Invalid input to QRinput_new2()");
+ QRinput *input;
+
+ input = QRinput_new2(-1, QR_ECLEVEL_H);
+ assert_null(input, "QRinput_new2() returns non-null for invalid version (-1).\n");
+ assert_equal(errno, EINVAL, "Error code is not EINVAL.\n");
+ input = QRinput_new2(41, QR_ECLEVEL_H);
+ assert_null(input, "QRinput_new2() returns non-null for invalid version (41).\n");
+ assert_equal(errno, EINVAL, "Error code is not EINVAL.\n");
+ input = QRinput_new2(1, -1);
+ assert_null(input, "QRinput_new2() returns non-null for invalid level (-1).\n");
+ assert_equal(errno, EINVAL, "Error code is not EINVAL.\n");
+ input = QRinput_new2(1, 5);
+ assert_null(input, "QRinput_new2() returns non-null for invalid level (5).\n");
+ assert_equal(errno, EINVAL, "Error code is not EINVAL.\n");
+ testFinish();
+}
+
+static void test_QRinput_getErrorCorrectionLevel(void)
+{
+ testStart("Invalid input to QRinput_getErrorCorrectionLevel()");
+ QRinput *input;
+ QRecLevel level;
+
+ input = QRinput_new2(1, QR_ECLEVEL_H);
+ level = QRinput_getErrorCorrectionLevel(input);
+ assert_equal(level, QR_ECLEVEL_H, "QRinput_getErrorCorrectionLevel() fails to return expected level.\n");
+ testFinish();
+ QRinput_free(input);
+}
+
+static void test_mqr_new(void)
+{
+ QRinput *input;
+ testStart("Testing QRinput_newMQR().");
+
+ input = QRinput_newMQR(0, QR_ECLEVEL_L);
+ assert_null(input, "Version 0 passed.\n");
+ QRinput_free(input);
+
+ input = QRinput_newMQR(5, QR_ECLEVEL_L);
+ assert_null(input, "Version 5 passed.\n");
+ QRinput_free(input);
+
+ input = QRinput_newMQR(1, QR_ECLEVEL_M);
+ assert_null(input, "Invalid ECLEVEL passed.\n");
+ QRinput_free(input);
+
+ input = QRinput_newMQR(1, QR_ECLEVEL_L);
+ assert_equal(input->version, 1, "QRinput.version was not as expected.\n");
+ assert_equal(input->level, QR_ECLEVEL_L, "QRinput.version was not as expected.\n");
+ QRinput_free(input);
+
+ testFinish();
+}
+
+static void test_mqr_setversion(void)
+{
+ QRinput *input;
+ int ret;
+ testStart("Testing QRinput_setVersion() for MQR.");
+
+ input = QRinput_newMQR(1, QR_ECLEVEL_L);
+ ret = QRinput_setVersion(input, 2);
+ assert_exp((ret < 0), "QRinput_setVersion should be denied.\n");
+ QRinput_free(input);
+
+ testFinish();
+}
+
+static void test_mqr_setlevel(void)
+{
+ QRinput *input;
+ int ret;
+ testStart("Testing QRinput_setErrorCorrectionLevel() for MQR.");
+
+ input = QRinput_newMQR(1, QR_ECLEVEL_L);
+ ret = QRinput_setErrorCorrectionLevel(input, QR_ECLEVEL_M);
+ assert_exp((ret < 0), "QRinput_setErrorCorrectionLevel should be denied.\n");
+ QRinput_free(input);
+
+ testFinish();
+}
+
+static void test_paddingMQR(void)
+{
+ char *dataM1[] = {"65", "513", "5139", "51365"};
+ char *correctM1[] = {"01010000010000000000",
+ "01110000000010000000",
+ "10010000000011001000",
+ "10110000000011000001"};
+ char *dataM2[] = {"513513", "51351365"};
+ char *correctM2[] = {"0 0110 1000000001 1000000001 0000000",
+ "0 1000 1000000001 1000000001 1000001"};
+ int i, ret;
+
+ testStart("Padding bit check of MQR. (only 0 padding)");
+ for(i=0; i<4; i++) {
+ ret = encodeAndCheckBStream(1, 1, QR_ECLEVEL_L, QR_MODE_NUM, dataM1[i], correctM1[i]);
+ assert_zero(ret, "Number %s incorrectly encoded.\n", dataM1[i]);
+ }
+ for(i=0; i<2; i++) {
+ ret = encodeAndCheckBStream(1, 2, QR_ECLEVEL_M, QR_MODE_NUM, dataM2[i], correctM2[i]);
+ assert_zero(ret, "Number %s incorrectly encoded.\n", dataM2[i]);
+ }
+ testFinish();
+}
+
+static void test_padding2MQR(void)
+{
+ char *data[] = {"9", "513513", "513", "513"};
+ int ver[] = {1, 2, 2, 3};
+ char *correct[] = {"00110010 00000000 0000",
+ "0 0110 1000000001 1000000001 0000000 11101100",
+ "0 0011 1000000001 000000000 11101100 00010001",
+ "00 00011 1000000001 0000000 11101100 00010001 11101100 00010001 11101100 00010001 11101100 0000"
+ };
+ int i, ret;
+
+ testStart("Padding bit check. (1 or 2 padding bytes)");
+
+ for(i=0; i<4; i++) {
+ ret = encodeAndCheckBStream(1, ver[i], QR_ECLEVEL_L, QR_MODE_NUM, data[i], correct[i]);
+ assert_zero(ret, "Number %s incorrectly encoded.\n", data[i]);
+ }
+ testFinish();
+}
+
+static void test_textMQR(void)
+{
+ int version = 3;
+ QRecLevel level = QR_ECLEVEL_M;
+ char *str = "MICROQR";
+ char *correct = {"01 0111 01111110000 01000110111 10001010010 011011 0000000 0000 11101100 0000"};
+ int ret;
+
+ testStart("Text encoding (Micro QR)");
+ ret = encodeAndCheckBStream(1, version, level, QR_MODE_AN, str, correct);
+ assert_zero(ret, "AlphaNumeric string '%s' incorrectly encoded.\n", str);
+ testFinish();
+}
+
+static void test_ECIinvalid(void)
+{
+ QRinput *stream;
+ int ret;
+
+ testStart("Appending invalid ECI header");
+ stream = QRinput_new();
+ ret = QRinput_appendECIheader(stream, 999999);
+ assert_zero(ret, "Valid ECI header rejected.");
+ ret = QRinput_appendECIheader(stream, 1000000);
+ assert_nonzero(ret, "Invalid ECI header accepted.");
+ QRinput_free(stream);
+ testFinish();
+}
+
+static void test_encodeECI(void)
+{
+ QRinput *input;
+ BitStream *bstream;
+ unsigned char str[] = {0xa1, 0xa2, 0xa3, 0xa4, 0xa5};
+ char *correct = "0111 00001001 0100 00000101 10100001 10100010 10100011 10100100 10100101";
+ int ret;
+
+ testStart("Encoding characters with ECI header.");
+ input = QRinput_new();
+ ret = QRinput_appendECIheader(input, 9);
+ assert_zero(ret, "Valid ECI header rejected.\n");
+
+ ret = QRinput_append(input, QR_MODE_8, 5, str);
+ assert_zero(ret, "Failed to append characters.\n");
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(input, bstream);
+ assert_nonnull(bstream, "Failed to merge.\n");
+ if(bstream != NULL) {
+ ret = ncmpBin(correct, bstream, 64);
+ assert_zero(ret, "Encodation of ECI header was invalid.\n");
+ BitStream_free(bstream);
+ }
+ QRinput_free(input);
+ testFinish();
+}
+
+int main()
+{
+ int tests = 42;
+ testInit(tests);
+
+ test_encodeNumeric();
+ test_encodeNumeric2();
+ test_encodeNumeric3();
+ test_encodeNumeric_versionup();
+ test_encode8();
+ test_encode8_versionup();
+ test_encodeAn();
+ test_encodeAn2();
+ test_encodeKanji();
+ test_encodeNumericPadded();
+ test_encodeNumericPadded2();
+ test_encodeAnNum();
+ test_padding();
+ test_padding2();
+ test_struct_listop();
+ test_insertStructuredAppendHeader();
+ test_insertStructuredAppendHeader_error();
+ test_struct_insertStructuredAppendHeaders();
+ test_lengthOfCode_num();
+ test_lengthOfCode_kanji();
+ test_splitentry();
+ test_splitentry2();
+ test_splitentry3();
+ test_struct_split_example();
+ test_struct_split_tooLarge();
+ test_struct_split_invalidVersion();
+ test_struct_singlestructure();
+ test_parity();
+ test_parity2();
+ test_null_free();
+ test_estimateVersionBoundaryCheck();
+ test_QRinput_new_invalid();
+ test_QRinput_getErrorCorrectionLevel();
+
+ test_mqr_new();
+ test_mqr_setversion();
+ test_mqr_setlevel();
+ test_paddingMQR();
+ test_padding2MQR();
+ test_textMQR();
+
+ test_ECIinvalid();
+ test_encodeECI();
+
+ testReport(tests);
+
+ return 0;
+}