Added test cases for C function appendErrorCorrection().
This commit is contained in:
parent
d11707d06a
commit
a712ccc230
|
@ -43,8 +43,11 @@ static int numTestCases = 0;
|
|||
|
||||
|
||||
// Prototypes of private functions under test
|
||||
extern const int8_t ECC_CODEWORDS_PER_BLOCK[4][41];
|
||||
extern const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41];
|
||||
int getTextProperties(const char *text, bool *isNumeric, bool *isAlphanumeric, int *textBits);
|
||||
void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen);
|
||||
void appendErrorCorrection(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]);
|
||||
int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl);
|
||||
int getNumRawDataModules(int version);
|
||||
void calcReedSolomonGenerator(int degree, uint8_t result[]);
|
||||
|
@ -158,6 +161,73 @@ static void testAppendBitsToBuffer(void) {
|
|||
}
|
||||
|
||||
|
||||
// Ported from the Java version of the code.
|
||||
static uint8_t *appendErrorCorrectionReference(const uint8_t *data, int version, enum qrcodegen_Ecc ecl) {
|
||||
// Calculate parameter numbers
|
||||
int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version];
|
||||
int blockEccLen = ECC_CODEWORDS_PER_BLOCK[(int)ecl][version];
|
||||
int rawCodewords = getNumRawDataModules(version) / 8;
|
||||
int numShortBlocks = numBlocks - rawCodewords % numBlocks;
|
||||
int shortBlockLen = rawCodewords / numBlocks;
|
||||
|
||||
// Split data into blocks and append ECC to each block
|
||||
uint8_t **blocks = malloc(numBlocks * sizeof(uint8_t*));
|
||||
uint8_t *generator = malloc(blockEccLen * sizeof(uint8_t));
|
||||
calcReedSolomonGenerator(blockEccLen, generator);
|
||||
for (int i = 0, k = 0; i < numBlocks; i++) {
|
||||
uint8_t *block = malloc((shortBlockLen + 1) * sizeof(uint8_t));
|
||||
int blockDataLen = shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1);
|
||||
memcpy(block, &data[k], blockDataLen * sizeof(uint8_t));
|
||||
calcReedSolomonRemainder(&data[k], blockDataLen, generator, blockEccLen, &block[shortBlockLen + 1 - blockEccLen]);
|
||||
k += blockDataLen;
|
||||
blocks[i] = block;
|
||||
}
|
||||
free(generator);
|
||||
|
||||
// Interleave (not concatenate) the bytes from every block into a single sequence
|
||||
uint8_t *result = malloc(rawCodewords * sizeof(uint8_t));
|
||||
for (int i = 0, k = 0; i < shortBlockLen + 1; i++) {
|
||||
for (int j = 0; j < numBlocks; j++) {
|
||||
// Skip the padding byte in short blocks
|
||||
if (i != shortBlockLen - blockEccLen || j >= numShortBlocks) {
|
||||
result[k] = blocks[j][i];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < numBlocks; i++)
|
||||
free(blocks[i]);
|
||||
free(blocks);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static void testAppendErrorCorrection(void) {
|
||||
for (int version = 1; version <= 40; version++) {
|
||||
for (int ecl = 0; ecl < 4; ecl++) {
|
||||
int dataLen = getNumDataCodewords(version, (enum qrcodegen_Ecc)ecl);
|
||||
uint8_t *pureData = malloc(dataLen * sizeof(uint8_t));
|
||||
for (int i = 0; i < dataLen; i++)
|
||||
pureData[i] = rand() % 256;
|
||||
uint8_t *expectOutput = appendErrorCorrectionReference(pureData, version, (enum qrcodegen_Ecc)ecl);
|
||||
|
||||
int dataAndEccLen = getNumRawDataModules(version) / 8;
|
||||
uint8_t *paddedData = malloc(dataAndEccLen * sizeof(uint8_t));
|
||||
memcpy(paddedData, pureData, dataLen * sizeof(uint8_t));
|
||||
uint8_t *actualOutput = malloc(dataAndEccLen * sizeof(uint8_t));
|
||||
appendErrorCorrection(paddedData, version, (enum qrcodegen_Ecc)ecl, actualOutput);
|
||||
|
||||
assert(memcmp(actualOutput, expectOutput, dataAndEccLen * sizeof(uint8_t)) == 0);
|
||||
free(pureData);
|
||||
free(expectOutput);
|
||||
free(paddedData);
|
||||
free(actualOutput);
|
||||
numTestCases++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testGetNumDataCodewords(void) {
|
||||
int cases[][3] = {
|
||||
{ 3, 1, 44},
|
||||
|
@ -492,6 +562,7 @@ int main(void) {
|
|||
srand(time(NULL));
|
||||
testGetTextProperties();
|
||||
testAppendBitsToBuffer();
|
||||
testAppendErrorCorrection();
|
||||
testGetNumDataCodewords();
|
||||
testGetNumRawDataModules();
|
||||
testCalcReedSolomonGenerator();
|
||||
|
|
|
@ -60,7 +60,7 @@ static void encodeQrCodeTail(uint8_t dataAndQrcode[], int bitLen, uint8_t tempBu
|
|||
int version, enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, bool boostEcl);
|
||||
testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen);
|
||||
|
||||
static void appendErrorCorrection(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]);
|
||||
testable void appendErrorCorrection(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]);
|
||||
testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl);
|
||||
testable int getNumRawDataModules(int version);
|
||||
|
||||
|
@ -90,7 +90,7 @@ testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack);
|
|||
static const char *ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
|
||||
|
||||
// For generating error correction codes.
|
||||
static const int8_t ECC_CODEWORDS_PER_BLOCK[4][41] = {
|
||||
testable const int8_t ECC_CODEWORDS_PER_BLOCK[4][41] = {
|
||||
// Version: (note that index 0 is for padding, and is set to an illegal value)
|
||||
//0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
|
||||
{-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low
|
||||
|
@ -100,7 +100,7 @@ static const int8_t ECC_CODEWORDS_PER_BLOCK[4][41] = {
|
|||
};
|
||||
|
||||
// For generating error correction codes.
|
||||
const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41] = {
|
||||
testable const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41] = {
|
||||
// Version: (note that index 0 is for padding, and is set to an illegal value)
|
||||
//0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
|
||||
{-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low
|
||||
|
@ -356,7 +356,7 @@ testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[]
|
|||
// from the blocks and stores them in the result array. data[0 : rawCodewords - totalEcc] contains
|
||||
// the input data. data[rawCodewords - totalEcc : rawCodewords] is used as a temporary work area
|
||||
// and will be clobbered by this function. The final answer is stored in result[0 : rawCodewords].
|
||||
static void appendErrorCorrection(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]) {
|
||||
testable void appendErrorCorrection(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]) {
|
||||
// Calculate parameter numbers
|
||||
assert(0 <= (int)ecl && (int)ecl < 4 && qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX);
|
||||
int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version];
|
||||
|
|
Loading…
Reference in New Issue