| #include <stdio.h> |
| #include <string.h> |
| #include <errno.h> |
| #include "common.h" |
| #include "../qrencode_inner.h" |
| #include "../qrspec.h" |
| #include "../mqrspec.h" |
| #include "../qrinput.h" |
| #include "../mask.h" |
| #include "../rscode.h" |
| #include "../split.h" |
| #include "decoder.h" |
| |
| static const char decodeAnTable[45] = { |
| '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', |
| 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', |
| 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', |
| 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*', |
| '+', '-', '.', '/', ':' |
| }; |
| |
| typedef struct { |
| char *str; |
| int version; |
| QRecLevel level; |
| QRencodeMode hint; |
| int casesensitive; |
| } TestString; |
| #define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0])) |
| |
| #define drand(__scale__) ((__scale__) * (double)rand() / ((double)RAND_MAX + 1.0)) |
| |
| int inputSize(QRinput *input) |
| { |
| BitStream *bstream; |
| int size; |
| |
| bstream = QRinput_mergeBitStream(input); |
| size = BitStream_size(bstream); |
| BitStream_free(bstream); |
| |
| return size; |
| } |
| |
| void test_qrraw_new(void) |
| { |
| int i; |
| QRinput *stream; |
| char num[9] = "01234567"; |
| QRRawCode *raw; |
| |
| testStart("Test QRRaw_new()"); |
| stream = QRinput_new(); |
| QRinput_setVersion(stream, 10); |
| QRinput_setErrorCorrectionLevel(stream, QR_ECLEVEL_Q); |
| QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num); |
| |
| raw = QRraw_new(stream); |
| assert_nonnull(raw, "Failed QRraw_new().\n"); |
| assert_zero(raw->count, "QRraw.count = %d != 0\n", raw->count); |
| assert_equal(raw->version, 10, "QRraw.version was not as expected. (%d)\n", raw->version); |
| assert_equal(raw->dataLength, 19 * 6 + 20 * 2, "QRraw.dataLength was not as expected.\n"); |
| assert_equal(raw->eccLength, 24 * 8, "QRraw.eccLength was not as expected.\n"); |
| assert_equal(raw->b1, 6, "QRraw.b1 was not as expected.\n"); |
| assert_equal(raw->blocks, 8, "QRraw.blocks was not as expected.\n"); |
| |
| for(i=0; i<raw->b1; i++) { |
| assert_equal(raw->rsblock[i].dataLength, 19, "QRraw.rsblock[].dataLength was not as expected.\n"); |
| } |
| for(i=raw->b1; i<raw->blocks; i++) { |
| assert_equal(raw->rsblock[i].dataLength, 20, "QRraw.rsblock[].dataLength was not as expected.\n"); |
| } |
| for(i=0; i<raw->blocks; i++) { |
| assert_equal(raw->rsblock[i].eccLength, 24, "QRraw.rsblock[].eccLength was not as expected.\n"); |
| } |
| |
| QRinput_free(stream); |
| QRraw_free(raw); |
| testFinish(); |
| } |
| |
| void test_iterate() |
| { |
| int i; |
| QRinput *stream; |
| char num[9] = "01234567"; |
| unsigned char *data; |
| QRRawCode *raw; |
| int err = 0; |
| |
| testStart("Test getCode (1-L)"); |
| stream = QRinput_new(); |
| QRinput_setVersion(stream, 1); |
| QRinput_setErrorCorrectionLevel(stream, QR_ECLEVEL_L); |
| QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num); |
| |
| raw = QRraw_new(stream); |
| data = raw->datacode; |
| for(i=0; i<raw->dataLength; i++) { |
| if(data[i] != QRraw_getCode(raw)) { |
| err++; |
| } |
| } |
| |
| QRinput_free(stream); |
| QRraw_free(raw); |
| testEnd(err); |
| } |
| |
| void test_iterate2() |
| { |
| int i; |
| QRinput *stream; |
| char num[9] = "01234567"; |
| QRRawCode *raw; |
| int err = 0; |
| unsigned char correct[] = { |
| 0x10, 0x11, 0xec, 0xec, 0x20, 0xec, 0x11, 0x11, |
| 0x0c, 0x11, 0xec, 0xec, 0x56, 0xec, 0x11, 0x11, |
| 0x61, 0x11, 0xec, 0xec, 0x80, 0xec, 0x11, 0x11, |
| 0xec, 0x11, 0xec, 0xec, 0x11, 0xec, 0x11, 0x11, |
| 0xec, 0x11, 0xec, 0xec, 0x11, 0xec, 0x11, 0x11, |
| 0xec, 0x11, 0xec, 0xec, 0x11, 0x11, |
| 0x5c, 0xde, 0x68, 0x68, 0x4d, 0xb3, 0xdb, 0xdb, |
| 0xd5, 0x14, 0xe1, 0xe1, 0x5b, 0x2a, 0x1f, 0x1f, |
| 0x49, 0xc4, 0x78, 0x78, 0xf7, 0xe0, 0x5b, 0x5b, |
| 0xc3, 0xa7, 0xc1, 0xc1, 0x5d, 0x9a, 0xea, 0xea, |
| 0x48, 0xad, 0x9d, 0x9d, 0x58, 0xb3, 0x3f, 0x3f, |
| 0x10, 0xdb, 0xbf, 0xbf, 0xeb, 0xec, 0x05, 0x05, |
| 0x98, 0x35, 0x83, 0x83, 0xa9, 0x95, 0xa6, 0xa6, |
| 0xea, 0x7b, 0x8d, 0x8d, 0x04, 0x3c, 0x08, 0x08, |
| 0x64, 0xce, 0x3e, 0x3e, 0x4d, 0x9b, 0x30, 0x30, |
| 0x4e, 0x65, 0xd6, 0xd6, 0xe4, 0x53, 0x2c, 0x2c, |
| 0x46, 0x1d, 0x2e, 0x2e, 0x29, 0x16, 0x27, 0x27 |
| }; |
| |
| testStart("Test getCode (5-H)"); |
| stream = QRinput_new(); |
| QRinput_setVersion(stream, 5); |
| QRinput_setErrorCorrectionLevel(stream, QR_ECLEVEL_H); |
| QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num); |
| |
| raw = QRraw_new(stream); |
| for(i=0; i<raw->dataLength; i++) { |
| if(correct[i] != QRraw_getCode(raw)) { |
| err++; |
| } |
| } |
| |
| QRinput_free(stream); |
| QRraw_free(raw); |
| testEnd(err); |
| } |
| |
| void print_filler(void) |
| { |
| int width; |
| int version = 7; |
| unsigned char *frame; |
| |
| width = QRspec_getWidth(version); |
| frame = FrameFiller_test(version); |
| if(frame == NULL) abort(); |
| |
| printFrame(width, frame); |
| free(frame); |
| } |
| |
| void test_filler(void) |
| { |
| unsigned char *frame; |
| int i, j, w, e, length; |
| |
| testStart("Frame filler test"); |
| for(i=1; i<=QRSPEC_VERSION_MAX; i++) { |
| length = QRspec_getDataLength(i, QR_ECLEVEL_L) * 8 |
| + QRspec_getECCLength(i, QR_ECLEVEL_L) * 8 |
| + QRspec_getRemainder(i); |
| frame = FrameFiller_test(i); |
| if(frame == NULL) { |
| assert_nonnull(frame, "Something wrong in version %d\n", i); |
| } else { |
| w = QRspec_getWidth(i); |
| e = 0; |
| for(j=0; j<w*w; j++) { |
| if(frame[j] == 0) e++; |
| } |
| assert_zero(e, "Not filled bit is found. (%d,%d)\n", j%w,j/w); |
| e = w * (w - 9 - ((i > 6)?3:0)); |
| assert_equal(frame[e], (unsigned char)((length - 1) & 127) | 0x80, |
| "Number of cell does not match.\n"); |
| free(frame); |
| } |
| } |
| testFinish(); |
| } |
| |
| void print_fillerMQR(void) |
| { |
| int width; |
| int version = 3; |
| unsigned char *frame; |
| |
| for(version = 1; version <= MQRSPEC_VERSION_MAX; version++) { |
| width = MQRspec_getWidth(version); |
| frame = FrameFiller_testMQR(version); |
| if(frame == NULL) abort(); |
| |
| printFrame(width, frame); |
| } |
| } |
| |
| void test_fillerMQR(void) |
| { |
| unsigned char *frame; |
| int i, j, w, e, length; |
| |
| testStart("Micro QR Code Frame filler test"); |
| for(i=1; i<=MQRSPEC_VERSION_MAX; i++) { |
| length = MQRspec_getDataLengthBit(i, QR_ECLEVEL_L) |
| + MQRspec_getECCLength(i, QR_ECLEVEL_L) * 8; |
| frame = FrameFiller_testMQR(i); |
| if(frame == NULL) { |
| assert_nonnull(frame, "Something wrong in version %d\n", i); |
| } else { |
| w = MQRspec_getWidth(i); |
| e = 0; |
| for(j=0; j<w*w; j++) { |
| if(frame[j] == 0) e++; |
| } |
| assert_zero(e, "Not filled bit is found. (%d,%d)\n", j%w,j/w); |
| if(i & 1) { |
| e = w * 9 + 1; |
| } else { |
| e = w * (w - 1) + 1; |
| } |
| assert_equal(frame[e], (unsigned char)((length - 1) & 127) | 0x80, |
| "Number of cell does not match in version %d.\n", i); |
| free(frame); |
| } |
| } |
| testFinish(); |
| } |
| |
| void test_format(void) |
| { |
| unsigned char *frame; |
| unsigned int format; |
| int width; |
| int i; |
| unsigned int decode; |
| int blacks, b1 = 0, b2 = 0; |
| |
| testStart("Test format information(level L,mask 0)"); |
| width = QRspec_getWidth(1); |
| frame = QRspec_newFrame(1); |
| if(frame == NULL) goto ABORT; |
| format = QRspec_getFormatInfo(1, QR_ECLEVEL_L); |
| blacks = Mask_writeFormatInformation(width, frame, 1, QR_ECLEVEL_L); |
| decode = 0; |
| for(i=0; i<15; i++) { |
| if((1<<i) & format) b2 += 2; |
| } |
| for(i=0; i<8; i++) { |
| decode = decode << 1; |
| decode |= frame[width * 8 + i + (i > 5)] & 1; |
| if(decode & 1) b1++; |
| } |
| for(i=0; i<7; i++) { |
| decode = decode << 1; |
| decode |= frame[width * ((6 - i) + (i < 1)) + 8] & 1; |
| if(decode & 1) b1++; |
| } |
| if(decode != format) { |
| printf("Upper-left format information is invalid.\n"); |
| printf("%08x, %08x\n", format, decode); |
| testEnd(1); |
| return; |
| } |
| decode = 0; |
| for(i=0; i<7; i++) { |
| decode = decode << 1; |
| decode |= frame[width * (width - 1 - i) + 8] & 1; |
| if(decode & 1) b1++; |
| } |
| for(i=0; i<8; i++) { |
| decode = decode << 1; |
| decode |= frame[width * 8 + width - 8 + i] & 1; |
| if(decode & 1) b1++; |
| } |
| if(decode != format) { |
| printf("Bottom and right format information is invalid.\n"); |
| printf("%08x, %08x\n", format, decode); |
| testEnd(1); |
| return; |
| } |
| |
| if(b2 != blacks || b1 != b2) { |
| printf("Number of dark modules is incorrect.\n"); |
| printf("Return value: %d, dark modules in frame: %d, should be: %d\n", blacks, b1, b2); |
| testEnd(1); |
| return; |
| } |
| |
| free(frame); |
| |
| ABORT: |
| testEnd(0); |
| } |
| |
| unsigned int m1pat[8][21] = { |
| {0x1fc77f, 0x105c41, 0x174c5d, 0x174b5d, 0x175b5d, 0x104241, 0x1fd57f, |
| 0x000000, 0x154512, 0x1a16a2, 0x0376ee, 0x19abb2, 0x04eee1, 0x001442, |
| 0x1fc111, 0x10444b, 0x175d5d, 0x174aae, 0x175ae5, 0x1043b8, 0x1fd2e5}, |
| {0x1fdd7f, 0x104641, 0x17565d, 0x17415d, 0x17415d, 0x105841, 0x1fd57f, |
| 0x000a00, 0x146f25, 0x10bc08, 0x09dc44, 0x130118, 0x0e444b, 0x001ee8, |
| 0x1fdbbb, 0x104ee1, 0x1747f7, 0x174004, 0x17504f, 0x104912, 0x1fd84f}, |
| {0x1fcb7f, 0x104f41, 0x17505d, 0x17585d, 0x17575d, 0x105141, 0x1fd57f, |
| 0x001300, 0x17c97c, 0x02b52c, 0x046a9f, 0x01083c, 0x03f290, 0x0017cc, |
| 0x1fcd60, 0x1057c5, 0x17512c, 0x175920, 0x175694, 0x104036, 0x1fde94}, |
| {0x1fdb7f, 0x105441, 0x174d5d, 0x17585d, 0x174c5d, 0x104c41, 0x1fd57f, |
| 0x001800, 0x16e44b, 0x02b52c, 0x12f1f2, 0x1a258a, 0x03f290, 0x001ca1, |
| 0x1fd0d6, 0x1057c5, 0x174a41, 0x175496, 0x175694, 0x104b5b, 0x1fd322}, |
| {0x1fd37f, 0x104741, 0x17475d, 0x175f5d, 0x175f5d, 0x105941, 0x1fd57f, |
| 0x001400, 0x1171f9, 0x0c8dcf, 0x15ed83, 0x108f20, 0x0dca73, 0x001f2f, |
| 0x1fda7c, 0x1040d9, 0x1759cf, 0x1741c3, 0x174188, 0x10472a, 0x1fd677}, |
| {0x1fcd7f, 0x105741, 0x17505d, 0x17545d, 0x17475d, 0x104941, 0x1fd57f, |
| 0x001b00, 0x1059ce, 0x05a95d, 0x046a9f, 0x03001c, 0x0e444b, 0x001fec, |
| 0x1fcd60, 0x104bb4, 0x17412c, 0x174100, 0x17404f, 0x104816, 0x1fde94}, |
| {0x1fdd7f, 0x105741, 0x17545d, 0x17445d, 0x17555d, 0x104f41, 0x1fd57f, |
| 0x000b00, 0x13fd97, 0x05a95d, 0x00f8d6, 0x028604, 0x0e444b, 0x001f2f, |
| 0x1fd9f2, 0x105bb4, 0x175365, 0x175718, 0x17404f, 0x1048d5, 0x1fda06}, |
| {0x1fc77f, 0x104841, 0x174e5d, 0x174b5d, 0x174f5d, 0x105041, 0x1fd57f, |
| 0x000400, 0x12d7a0, 0x1a16a2, 0x0a527c, 0x1d39fb, 0x04eee1, 0x0010d0, |
| 0x1fc358, 0x10544b, 0x1749cf, 0x1758e7, 0x174ae5, 0x10472a, 0x1fd0ac} |
| }; |
| |
| void test_encode(void) |
| { |
| QRinput *stream; |
| char num[9] = "01234567"; |
| unsigned char *frame; |
| int err = 0; |
| int x, y, w; |
| int mask; |
| QRcode *qrcode; |
| |
| testStart("Test encode (1-M)"); |
| stream = QRinput_new(); |
| if(stream == NULL) goto ABORT; |
| QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num); |
| for(mask=0; mask<8; mask++) { |
| QRinput_setVersion(stream, 1); |
| QRinput_setErrorCorrectionLevel(stream, QR_ECLEVEL_M); |
| qrcode = QRcode_encodeMask(stream, mask); |
| if(qrcode == NULL) goto ABORT; |
| w = qrcode->width; |
| frame = qrcode->data; |
| for(y=0; y<w; y++) { |
| for(x=0; x<w; x++) { |
| if(((m1pat[mask][y] >> (20-x)) & 1) != (frame[y*w+x]&1)) { |
| printf("Diff in mask=%d (%d,%d)\n", mask, x, y); |
| err++; |
| } |
| } |
| } |
| QRcode_free(qrcode); |
| } |
| QRinput_free(stream); |
| ABORT: |
| testEnd(err); |
| } |
| |
| void test_encode2(void) |
| { |
| QRcode *qrcode; |
| |
| testStart("Test encode (2-H) (no padding test)"); |
| qrcode = QRcode_encodeString("abcdefghijk123456789012", 0, QR_ECLEVEL_H, QR_MODE_8, 0); |
| testEndExp(qrcode->version == 2); |
| QRcode_free(qrcode); |
| } |
| |
| void test_encode3(void) |
| { |
| QRcode *code1, *code2; |
| QRinput *input; |
| |
| testStart("Compare encodeString and encodeInput"); |
| code1 = QRcode_encodeString("0123456", 0, QR_ECLEVEL_L, QR_MODE_8, 0); |
| input = QRinput_new2(0, QR_ECLEVEL_L); |
| QRinput_append(input, QR_MODE_NUM, 7, (unsigned char *)"0123456"); |
| code2 = QRcode_encodeInput(input); |
| testEnd(memcmp(code1->data, code2->data, code1->width * code1->width)); |
| |
| QRcode_free(code1); |
| QRcode_free(code2); |
| QRinput_free(input); |
| } |
| |
| void test_encodeNull(void) |
| { |
| QRcode *qrcode; |
| |
| testStart("Test encode NULL."); |
| qrcode = QRcode_encodeString(NULL, 0, QR_ECLEVEL_H, QR_MODE_8, 0); |
| assert_null(qrcode, "QRcode_encodeString() returned something.\n"); |
| testFinish(); |
| if(qrcode != NULL) QRcode_free(qrcode); |
| } |
| |
| |
| void test_encodeEmpty(void) |
| { |
| QRcode *qrcode; |
| |
| testStart("Test encode an empty string."); |
| qrcode = QRcode_encodeString("", 0, QR_ECLEVEL_H, QR_MODE_8, 0); |
| assert_null(qrcode, "QRcode_encodeString() returned something.\n"); |
| testFinish(); |
| if(qrcode != NULL) QRcode_free(qrcode); |
| } |
| |
| void test_encodeNull8(void) |
| { |
| QRcode *qrcode; |
| |
| testStart("Test encode NULL."); |
| qrcode = QRcode_encodeString8bit(NULL, 0, QR_ECLEVEL_H); |
| assert_null(qrcode, "QRcode_encodeString8bit() returned something.\n"); |
| testFinish(); |
| if(qrcode != NULL) QRcode_free(qrcode); |
| } |
| |
| |
| void test_encodeEmpty8(void) |
| { |
| QRcode *qrcode; |
| |
| testStart("Test encode an empty string."); |
| qrcode = QRcode_encodeString8bit("", 0, QR_ECLEVEL_H); |
| assert_null(qrcode, "QRcode_encodeString8bit() returned something.\n"); |
| testFinish(); |
| if(qrcode != NULL) QRcode_free(qrcode); |
| } |
| |
| void test_encodeTooLong(void) |
| { |
| QRcode *code; |
| char *data; |
| |
| testStart("Encode too large data"); |
| data = (char *)malloc(4300); |
| memset(data, 'a', 4295); |
| memset(data + 4295, '0', 4); |
| data[4299] = '\0'; |
| |
| code = QRcode_encodeString(data, 0, QR_ECLEVEL_L, QR_MODE_8, 0); |
| assert_null(code, "Too large data is incorrectly accepted.\n"); |
| assert_equal(errno, ERANGE, "errno != ERANGE\n"); |
| testFinish(); |
| |
| if(code != NULL) { |
| QRcode_free(code); |
| } |
| free(data); |
| } |
| |
| void test_01234567(void) |
| { |
| QRinput *stream; |
| char num[9] = "01234567"; |
| int i, err = 0; |
| QRcode *qrcode; |
| unsigned char correct[] = { |
| 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0x84, 0x03, 0x02, 0x03, 0x03, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, |
| 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x84, 0x03, 0x03, 0x03, 0x03, 0xc0, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, |
| 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x02, 0x02, 0x02, 0xc0, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, |
| 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x03, 0x02, 0x02, 0x02, 0xc0, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, |
| 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x03, 0x03, 0x03, 0xc0, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, |
| 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x02, 0x02, 0x03, 0xc0, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, |
| 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0x91, 0x90, 0x91, 0x90, 0x91, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, |
| 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x85, 0x02, 0x02, 0x03, 0x03, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, |
| 0x85, 0x84, 0x85, 0x85, 0x85, 0x85, 0x91, 0x84, 0x84, 0x03, 0x02, 0x02, 0x03, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, 0x84, |
| 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x90, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, 0x02, |
| 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x91, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, |
| 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x90, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, |
| 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x91, 0x03, 0x03, 0x02, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, |
| 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x81, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, |
| 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0x84, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, |
| 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, |
| 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, 0x02, |
| 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x03, 0x02, 0x02, 0x03, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, |
| 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x03, 0x03, 0x02, 0x03, 0x02, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, |
| 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x84, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, |
| 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0x85, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02}; |
| |
| testStart("Encode 01234567 in 1-M"); |
| stream = QRinput_new2(1, QR_ECLEVEL_M); |
| QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num); |
| qrcode = QRcode_encodeInput(stream); |
| for(i=0; i<qrcode->width * qrcode->width; i++) { |
| if(qrcode->data[i] != correct[i]) { |
| err++; |
| } |
| } |
| testEnd(err); |
| QRinput_free(stream); |
| QRcode_free(qrcode); |
| } |
| |
| void print_01234567(void) |
| { |
| QRinput *stream; |
| char num[9] = "01234567"; |
| QRcode *qrcode; |
| |
| stream = QRinput_new2(1, QR_ECLEVEL_M); |
| QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num); |
| qrcode = QRcode_encodeInput(stream); |
| printQRcode(qrcode); |
| QRinput_free(stream); |
| QRcode_free(qrcode); |
| } |
| |
| void test_invalid_input(void) |
| { |
| QRinput *input; |
| QRcode *code; |
| |
| testStart("Testing invalid input."); |
| input = QRinput_new(); |
| QRinput_append(input, QR_MODE_AN, 5, (unsigned char *)"TEST1"); |
| input->version = -1; |
| input->level = QR_ECLEVEL_L; |
| code = QRcode_encodeInput(input); |
| assert_null(code, "invalid version(-1) was not checked.\n"); |
| if(code != NULL) QRcode_free(code); |
| |
| input->version = 41; |
| input->level = QR_ECLEVEL_L; |
| code = QRcode_encodeInput(input); |
| assert_null(code, "invalid version(41) access was not checked.\n"); |
| if(code != NULL) QRcode_free(code); |
| |
| input->version = 1; |
| input->level = (QRecLevel)(QR_ECLEVEL_H + 1); |
| code = QRcode_encodeInput(input); |
| assert_null(code, "invalid level(H+1) access was not checked.\n"); |
| if(code != NULL) QRcode_free(code); |
| |
| input->version = 1; |
| input->level = (QRecLevel)-1; |
| code = QRcode_encodeInput(input); |
| assert_null(code, "invalid level(-1) access was not checked.\n"); |
| if(code != NULL) QRcode_free(code); |
| |
| QRinput_free(input); |
| |
| testFinish(); |
| } |
| |
| void test_struct_semilong(void) |
| { |
| QRcode_List *codes, *list; |
| const char *str = "asdfasdfasdfasdfasdfASDFASDASDFASDFAsdfasdfasdfasdASDFASDFADSADadsfasdf"; |
| int num, size; |
| |
| testStart("Testing semi-long structured-append symbols"); |
| codes = QRcode_encodeString8bitStructured(str, 1, QR_ECLEVEL_L); |
| list = codes; |
| num = 0; |
| while(list != NULL) { |
| num++; |
| assert_equal(list->code->version, 1, "version number is %d (1 expected)\n", list->code->version); |
| list = list->next; |
| } |
| size = QRcode_List_size(codes); |
| assert_equal(num, size, "QRcode_List_size returns wrong size?"); |
| QRcode_List_free(codes); |
| |
| codes = QRcode_encodeStringStructured(str, 1, QR_ECLEVEL_L, QR_MODE_8, 1); |
| list = codes; |
| num = 0; |
| while(list != NULL) { |
| num++; |
| assert_equal(list->code->version, 1, "version number is %d (1 expected)\n", list->code->version); |
| list = list->next; |
| } |
| size = QRcode_List_size(codes); |
| assert_equal(num, size, "QRcode_List_size returns wrong size?"); |
| QRcode_List_free(codes); |
| |
| testFinish(); |
| } |
| |
| void test_struct_example(void) |
| { |
| QRcode_List *codes, *list; |
| const char *str = "an example of four Structured Append symbols,"; |
| int num; |
| |
| testStart("Testing the example of structured-append symbols"); |
| codes = QRcode_encodeString8bitStructured(str, 1, QR_ECLEVEL_M); |
| list = codes; |
| num = 0; |
| while(list != NULL) { |
| num++; |
| assert_equal(list->code->version, 1, "version number is %d (1 expected)\n", list->code->version); |
| list = list->next; |
| } |
| assert_equal(num, 4, "number of symbols is %d (4 expected).", num); |
| testFinish(); |
| QRcode_List_free(codes); |
| } |
| |
| void test_null_free(void) |
| { |
| testStart("Testing free NULL pointers"); |
| assert_nothing(QRcode_free(NULL), "Check QRcode_free(NULL).\n"); |
| assert_nothing(QRcode_List_free(NULL), "Check QRcode_List_free(NULL).\n"); |
| assert_nothing(QRraw_free(NULL), "Check QRraw_free(NULL).\n"); |
| testFinish(); |
| } |
| |
| void test_encodeTooLongMQR(void) |
| { |
| QRcode *code; |
| char *data[] = {"012345", "ABC0EFG", "0123456789", "0123456789ABCDEFG"}; |
| |
| testStart("Encode too large data for MQR."); |
| |
| code = QRcode_encodeStringMQR(data[0], 1, QR_ECLEVEL_L, QR_MODE_8, 0); |
| assert_null(code, "6 byte length numeric string was accepted to version 1.\n"); |
| assert_equal(errno, ERANGE, "errno != ERANGE\n"); |
| code = QRcode_encodeStringMQR(data[1], 2, QR_ECLEVEL_L, QR_MODE_8, 0); |
| assert_null(code, "7 byte length alphanumeric string was accepted to version 2.\n"); |
| assert_equal(errno, ERANGE, "errno != ERANGE\n"); |
| code = QRcode_encodeString8bitMQR(data[2], 3, QR_ECLEVEL_L); |
| assert_null(code, "9 byte length 8bit string was accepted to version 3.\n"); |
| assert_equal(errno, ERANGE, "errno != ERANGE\n"); |
| code = QRcode_encodeString8bitMQR(data[3], 4, QR_ECLEVEL_L); |
| assert_null(code, "16 byte length 8bit string was accepted to version 4.\n"); |
| assert_equal(errno, ERANGE, "errno != ERANGE\n"); |
| testFinish(); |
| |
| if(code != NULL) { |
| printQRcode(code); |
| QRcode_free(code); |
| } |
| } |
| |
| void test_mqrraw_new(void) |
| { |
| QRinput *stream; |
| char *num = "01234"; |
| unsigned char datacode[] = {0xa0, 0x62, 0x02}; |
| MQRRawCode *raw; |
| |
| testStart("Test MQRRaw_new()"); |
| stream = QRinput_newMQR(1, QR_ECLEVEL_L); |
| QRinput_append(stream, QR_MODE_NUM, 5, (unsigned char *)num); |
| |
| raw = MQRraw_new(stream); |
| assert_nonnull(raw, "Failed MQRraw_new().\n"); |
| assert_zero(raw->count, "MQRraw.count = %d != 0\n", raw->count); |
| assert_equal(raw->version, 1, "MQRraw.version was not as expected. (%d)\n", raw->version); |
| assert_equal(raw->dataLength, 3, "MQRraw.dataLength was not as expected.\n"); |
| assert_equal(raw->eccLength, 2, "MQRraw.eccLength was not as expected.\n"); |
| assert_zero(memcmp(raw->datacode, datacode, 3), "Datacode doesn't match.\n"); |
| |
| |
| QRinput_free(stream); |
| MQRraw_free(raw); |
| testFinish(); |
| } |
| |
| void test_encodeData(void) |
| { |
| QRcode *qrcode; |
| |
| testStart("Test QRencode_encodeData."); |
| qrcode = QRcode_encodeData(0, NULL, 0, QR_ECLEVEL_H); |
| assert_null(qrcode, "QRcode_encodeData(NULL, 0) returned something.\n"); |
| if(qrcode != NULL) QRcode_free(qrcode); |
| |
| qrcode = QRcode_encodeData(10, (unsigned char*)"test\0\0test", 0, QR_ECLEVEL_H); |
| assert_nonnull(qrcode, "QRcode_encodeData() failed.\n"); |
| if(qrcode != NULL) QRcode_free(qrcode); |
| |
| testFinish(); |
| } |
| |
| void test_formatInfo(void) |
| { |
| QRcode *qrcode; |
| QRecLevel level; |
| int mask; |
| int ret; |
| |
| testStart("Test format info in QR code."); |
| qrcode = QRcode_encodeString("AC-42", 1, QR_ECLEVEL_H, QR_MODE_8, 1); |
| ret = QRcode_decodeFormat(qrcode, &level, &mask); |
| assert_zero(ret, "Failed to decode.\n"); |
| assert_equal(level, QR_ECLEVEL_H, "Decoded format is wrong.\n"); |
| |
| if(qrcode != NULL) QRcode_free(qrcode); |
| |
| testFinish(); |
| } |
| |
| void test_formatInfoMQR(void) |
| { |
| QRcode *qrcode; |
| QRecLevel level; |
| int version, mask; |
| int i, ret; |
| |
| testStart("Test format info in Micro QR code."); |
| for(i=0; i<8; i++) { |
| qrcode = QRcode_encodeStringMQR("1", |
| MQRformat[i].version, |
| MQRformat[i].level, |
| QR_MODE_8, 1); |
| ret = QRcode_decodeFormatMQR(qrcode, &version, &level, &mask); |
| assert_zero(ret, "Failed to decode.\n"); |
| assert_equal(MQRformat[i].version, version, "Decoded verion is wrong.\n"); |
| assert_equal(MQRformat[i].level, level, "Decoded level is wrong.\n"); |
| QRcode_free(qrcode); |
| } |
| |
| testFinish(); |
| } |
| |
| void test_decodeSimple(void) |
| { |
| char *str = "AC-42"; |
| QRcode *qrcode; |
| QRdata *qrdata; |
| |
| testStart("Test code words."); |
| qrcode = QRcode_encodeString(str, 1, QR_ECLEVEL_H, QR_MODE_8, 1); |
| qrdata = QRcode_decode(qrcode); |
| |
| assert_nonnull(qrdata, "Failed to decode.\n"); |
| if(qrdata != NULL) { |
| assert_equal(strlen(str), qrdata->size, "Lengths of input/output mismatched: %d, expected %d.\n", qrdata->size, (int)strlen(str)); |
| assert_zero(strncmp(str, (char *)(qrdata->data), qrdata->size), "Decoded data %s is different from the original %s\n", qrdata->data, str); |
| } |
| if(qrdata != NULL) QRdata_free(qrdata); |
| if(qrcode != NULL) QRcode_free(qrcode); |
| |
| testFinish(); |
| } |
| |
| |
| void test_decodeLong(void) |
| { |
| char *str = "12345678901234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ?????????????"; |
| QRcode *qrcode; |
| QRdata *qrdata; |
| |
| testStart("Test code words (long, splitted)."); |
| qrcode = QRcode_encodeString(str, 0, QR_ECLEVEL_H, QR_MODE_8, 1); |
| qrdata = QRcode_decode(qrcode); |
| |
| assert_nonnull(qrdata, "Failed to decode.\n"); |
| if(qrdata != NULL) { |
| assert_equal(strlen(str), qrdata->size, "Lengths of input/output mismatched.\n"); |
| assert_zero(strncmp(str, (char *)(qrdata->data), qrdata->size), "Decoded data %s is different from the original %s\n", qrdata->data, str); |
| } |
| if(qrdata != NULL) QRdata_free(qrdata); |
| if(qrcode != NULL) QRcode_free(qrcode); |
| |
| testFinish(); |
| } |
| |
| void test_decodeVeryLong(void) |
| { |
| char str[4000]; |
| int i; |
| QRcode *qrcode; |
| QRdata *qrdata; |
| |
| testStart("Test code words (very long string)."); |
| |
| for(i=0; i<3999; i++) { |
| str[i] = decodeAnTable[(int)drand(45)]; |
| } |
| str[3999] = '\0'; |
| |
| qrcode = QRcode_encodeString(str, 0, QR_ECLEVEL_L, QR_MODE_8, 0); |
| qrdata = QRcode_decode(qrcode); |
| |
| assert_nonnull(qrdata, "Failed to decode.\n"); |
| if(qrdata != NULL) { |
| assert_equal(strlen(str), qrdata->size, "Lengths of input/output mismatched.\n"); |
| assert_zero(strncmp(str, (char *)(qrdata->data), qrdata->size), "Decoded data %s is different from the original %s\n", qrdata->data, str); |
| } |
| if(qrdata != NULL) QRdata_free(qrdata); |
| if(qrcode != NULL) QRcode_free(qrcode); |
| |
| testFinish(); |
| } |
| |
| void test_decodeShortMQR(void) |
| { |
| char str[]="55"; |
| QRcode *qrcode; |
| QRdata *qrdata; |
| int i; |
| |
| testStart("Test code words (MQR)."); |
| for(i=0; i<8; i++) { |
| qrcode = QRcode_encodeStringMQR(str, |
| MQRformat[i].version, |
| MQRformat[i].level, |
| QR_MODE_8, 1); |
| qrdata = QRcode_decodeMQR(qrcode); |
| |
| assert_nonnull(qrdata, "Failed to decode.\n"); |
| assert_zero(strcmp((char *)qrdata->data, str), "Decoded data (%s) mismatched (%s)\n", (char *)qrdata->data, str); |
| if(qrdata != NULL) QRdata_free(qrdata); |
| if(qrcode != NULL) QRcode_free(qrcode); |
| } |
| |
| testFinish(); |
| } |
| |
| void test_oddBitCalcMQR(void) |
| { |
| /* test issue #25 (odd bits calculation bug) */ |
| /* test pattern contributed by vlad417 */ |
| TestString tests[] = { |
| {"46194", 1, QR_ECLEVEL_L, QR_MODE_8, 1}, |
| {"WBA5Y47YPQQ", 3, QR_ECLEVEL_L, QR_MODE_8, 1} |
| }; |
| QRcode *qrcode; |
| QRdata *qrdata; |
| int i; |
| |
| testStart("Odd bits calculation bug checking (MQR)."); |
| |
| for(i=0; i<_countof(tests); i++) { |
| qrcode = QRcode_encodeStringMQR(tests[i].str, |
| tests[i].version, |
| tests[i].level, |
| tests[i].hint, |
| tests[i].casesensitive); |
| assert_nonnull(qrcode, "Failed to encode: %s\n", tests[i].str); |
| if(qrcode == NULL) continue; |
| qrdata = QRcode_decodeMQR(qrcode); |
| assert_nonnull(qrdata, "Failed to decode.\n"); |
| assert_zero(strcmp((char *)qrdata->data, tests[i].str), "Decoded data (%s) mismatched (%s)\n", (char *)qrdata->data, tests[i].str); |
| if(qrdata != NULL) QRdata_free(qrdata); |
| QRcode_free(qrcode); |
| } |
| |
| testFinish(); |
| } |
| |
| void test_mqrencode(void) |
| { |
| char *str = "MICROQR"; |
| char pattern[] = { |
| "#######_#_#_#_#" |
| "#_____#_#__####" |
| "#_###_#_#_####_" |
| "#_###_#_#__##_#" |
| "#_###_#___#__##" |
| "#_____#____#_#_" |
| "#######__##_#_#" |
| "_________#__#__" |
| "#___#__####_#_#" |
| "_#######_#_##_#" |
| "##___#_#____#__" |
| "_##_#_####____#" |
| "#__###___#__##_" |
| "_###_#_###_#_#_" |
| "##____####_###_" |
| }; |
| QRcode qrcode; |
| QRdata *qrdata; |
| unsigned char *frame; |
| int i; |
| |
| testStart("Encoding test (MQR)."); |
| |
| qrcode.width = 15; |
| qrcode.version = 3; |
| |
| frame = MQRspec_newFrame(qrcode.version); |
| for(i=0; i<225; i++) { |
| frame[i] ^= (pattern[i] == '#')?1:0; |
| } |
| |
| qrcode.data = frame; |
| qrdata = QRcode_decodeMQR(&qrcode); |
| assert_equal(qrdata->version, 3, "Format info decoder returns wrong version number: %d (%d expected)\n", qrdata->version, 3); |
| assert_equal(qrdata->level, 1, "Format info decoder returns wrong level: %d (%d expected)\n", qrdata->level, 1); |
| assert_zero(strcmp((char *)qrdata->data, str), "Decoded data (%s) mismatched (%s)\n", (char *)qrdata->data, str); |
| |
| QRdata_free(qrdata); |
| free(frame); |
| |
| testFinish(); |
| } |
| |
| void test_apiversion(void) |
| { |
| int major_version, minor_version, micro_version; |
| char *str, *str2; |
| |
| testStart("API Version check"); |
| QRcode_APIVersion(&major_version, &minor_version, µ_version); |
| assert_equal(major_version, MAJOR_VERSION, "Major version number mismatched: %d (%d expected)\n", major_version, MAJOR_VERSION); |
| assert_equal(minor_version, MINOR_VERSION, "Minor version number mismatched: %d (%d expected)\n", minor_version, MINOR_VERSION); |
| assert_equal(micro_version, MICRO_VERSION, "Micro version number mismatched: %d (%d expected)\n", micro_version, MICRO_VERSION); |
| str = QRcode_APIVersionString(); |
| str2 = QRcode_APIVersionString(); |
| assert_zero(strcmp(VERSION, str), "Version string mismatched: %s (%s expected)\n", str, VERSION); |
| assert_equal(str, str2, "Version strings are not identical."); |
| testFinish(); |
| } |
| |
| int main(void) |
| { |
| test_iterate(); |
| test_iterate2(); |
| //print_filler(); |
| test_filler(); |
| test_format(); |
| test_encode(); |
| test_encode2(); |
| test_encode3(); |
| test_encodeNull(); |
| test_encodeEmpty(); |
| test_encodeNull8(); |
| test_encodeEmpty8(); |
| test_encodeTooLong(); |
| test_01234567(); |
| test_invalid_input(); |
| // print_01234567(); |
| test_struct_example(); |
| test_struct_semilong(); |
| test_null_free(); |
| test_qrraw_new(); |
| test_mqrraw_new(); |
| test_encodeData(); |
| test_formatInfo(); |
| test_decodeSimple(); |
| test_decodeLong(); |
| test_decodeVeryLong(); |
| //print_fillerMQR(); |
| test_fillerMQR(); |
| test_formatInfoMQR(); |
| test_encodeTooLongMQR(); |
| test_decodeShortMQR(); |
| test_oddBitCalcMQR(); |
| test_mqrencode(); |
| test_apiversion(); |
| |
| QRcode_clearCache(); |
| |
| report(); |
| |
| return 0; |
| } |