Multiple changes in test suite. a) Added tests for ReedSolomonEncoder (current status: failing) b) Added printing of stacktrace upon test missmatch, will work only where supported by backward.hpp code.

This commit is contained in:
favoritas37 2016-12-03 12:48:50 +02:00
parent 588d478b7b
commit 5cd96d1aae
7 changed files with 2208 additions and 22 deletions

View File

@ -13,7 +13,7 @@
namespace zxing {
namespace tests{
EncodeValidator::EncodeValidator()
EncodeValidator::EncodeValidator() : TestCase()
{
}
@ -33,7 +33,7 @@ void EncodeValidator::execute()
qrcode::tests::QRCodeTests t3;
t3.execute();
ReedSolomonEncoderTests t4;
ReedSolomonTests t4;
t4.execute();
qrcode::tests::EncoderTests t5;

View File

@ -10,6 +10,19 @@ CONFIG -= app_bundle
TEMPLATE = app
HEADERS += \
DecodeValidator.h \
ValidationStats.h \
EncodeValidator.h \
TestCase.h \
zxing/qrcode/encoder/MatrixUtilTests.h \
zxing/qrcode/encoder/MaskUtilTests.h \
zxing/qrcode/encoder/BitArrayTests.h \
zxing/qrcode/encoder/QRCodeTests.h \
zxing/qrcode/encoder/EncoderTests.h \
zxing/common/reedsolomon/ReedSolomonEncoderTests.h
#\backward.hpp
SOURCES += main.cpp \
DecodeValidator.cpp \
ValidationStats.cpp \
@ -19,18 +32,7 @@ SOURCES += main.cpp \
zxing/qrcode/encoder/BitArrayTests.cpp \
zxing/qrcode/encoder/QRCodeTests.cpp \
zxing/qrcode/encoder/EncoderTests.cpp \
zxing/common/reedsolomon/ReedSolomonEncoderTests.cpp
HEADERS += \
DecodeValidator.h \
ValidationStats.h \
EncodeValidator.h \
zxing/qrcode/encoder/MatrixUtilTests.h \
TestCase.h \
zxing/qrcode/encoder/MaskUtilTests.h \
zxing/qrcode/encoder/BitArrayTests.h \
zxing/qrcode/encoder/QRCodeTests.h \
zxing/qrcode/encoder/EncoderTests.h \
zxing/common/reedsolomon/ReedSolomonEncoderTests.h
zxing/common/reedsolomon/ReedSolomonEncoderTests.cpp \
TestCase.cpp
include(../../../src/QZXing.pri)

View File

@ -0,0 +1,13 @@
#include "TestCase.h"
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
void zxing::TestCase::initializeRandom()
{
srand(time(NULL));
}
int zxing::TestCase::generateRandomNumber(int range)
{
return rand() % range;
}

View File

@ -5,6 +5,8 @@
#include <zxing/Exception.h>
#include <QtGlobal>
#include <zxing/qrcode/decoder/Mode.h>
#include "backward.hpp"
#include <QStringList>
namespace zxing{
@ -52,6 +54,23 @@ protected:
if(expected != actual) {
QString message = QString("\nExpected: \n[") + itemToString(expected) +
QString("], \nGot: \n[") + itemToString(actual) + QString("]");
backward::StackTrace st;
st.load_here(32);
backward::TraceResolver tr;
tr.load_stacktrace(st);
for (size_t i = 0; i < st.size(); ++i) {
backward::ResolvedTrace trace = tr.resolve(st[i]);
message += QString::fromStdString("\n#");
message += QString::number(i);
message += QString::fromStdString(trace.object_filename);
message += QString::fromStdString(trace.object_function);
message += QString("[");
message += QString::number((int)trace.addr);
message += QString("]\n");
}
throw zxing::Exception(message.toStdString().c_str());
}
}
@ -77,6 +96,22 @@ protected:
assertEquals(0, (int)actual);
}
void assertDataEquals(const std::string &message,
const std::vector<int> &expected,
const std::vector<int> & received)
{
for (int i = 0; i < expected.size(); i++) {
if (expected[i] != received[i]) {
qDebug() << QString::fromStdString(message) << ". Mismatch at " << QString::number(i) /*<< ". Expected " + arrayToString(expected) + ", got " +
arrayToString(Arrays.copyOf(received, expected.length)))*/;
assertTrue(false);
}
}
}
static void initializeRandom();
static int generateRandomNumber(int range);
public:
virtual void execute()=0;
};

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,148 @@
#include "ReedSolomonEncoderTests.h"
#include "zxing/common/reedsolomon/ReedSolomonEncoder.h"
#include "zxing/common/reedsolomon/ReedSolomonDecoder.h"
namespace zxing{
namespace tests{
ReedSolomonEncoderTests::ReedSolomonEncoderTests()
const int ReedSolomonTests::DECODER_RANDOM_TEST_ITERATIONS = 3;
const int ReedSolomonTests::DECODER_TEST_ITERATIONS = 10;
ReedSolomonTests::ReedSolomonTests()
{
}
void ReedSolomonEncoderTests::execute()
void ReedSolomonTests::execute()
{
testQRCode();
}
void ReedSolomonTests::testQRCode()
{
// Test case from example given in ISO 18004, Annex I
testEncodeDecode(GenericGF::QR_CODE_FIELD_256, {
0x10, 0x20, 0x0C, 0x56, 0x61, 0x80, 0xEC, 0x11,
0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11
// 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
},
{0xA5, 0x24, 0xD4, 0xC1, 0xED, 0x36, 0xC7, 0x87,
0x2C, 0x55 });
testEncodeDecode(GenericGF::QR_CODE_FIELD_256, {
0x72, 0x67, 0x2F, 0x77, 0x69, 0x6B, 0x69, 0x2F,
0x4D, 0x61, 0x69, 0x6E, 0x5F, 0x50, 0x61, 0x67,
0x65, 0x3B, 0x3B, 0x00, 0xEC, 0x11, 0xEC, 0x11,
0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11 },
{0xD8, 0xB8, 0xEF, 0x14, 0xEC, 0xD0, 0xCC, 0x85,
0x73, 0x40, 0x0B, 0xB5, 0x5A, 0xB8, 0x8B, 0x2E,
0x08, 0x62 });
// real life test cases
// synthetic test cases
testEncodeDecodeRandom(GenericGF::QR_CODE_FIELD_256, 10, 240);
testEncodeDecodeRandom(GenericGF::QR_CODE_FIELD_256, 128, 127);
testEncodeDecodeRandom(GenericGF::QR_CODE_FIELD_256, 220, 35);
}
void ReedSolomonTests::corrupt(std::vector<int> &received, int howMany, int max)
{
std::vector<bool> corrupted(false, received.size());
for (int j = 0; j < howMany; j++) {
int location = generateRandomNumber(received.size());
int value = generateRandomNumber(max);
if (corrupted[location] || received[location] == value) {
j--;
} else {
corrupted[location] = true;
received[location] = value;
}
}
}
void ReedSolomonTests::testEncodeDecodeRandom(Ref<GenericGF> field, int dataSize, int ecSize)
{
assertTrue(dataSize > 0 && dataSize <= field->getSize() - 3); /*"Invalid data size for " + field, */
assertTrue(ecSize > 0 && ecSize + dataSize <= field->getSize()); /*"Invalid ECC size for " + field, */
ReedSolomonEncoder encoder(field);
std::vector<int> message;//(dataSize + ecSize);
std::vector<int> dataWords(dataSize);
std::vector<int> ecWords(ecSize);
initializeRandom();
int iterations = field->getSize() > 256 ? 1 : DECODER_RANDOM_TEST_ITERATIONS;
for (int i = 0; i < iterations; i++) {
// generate random data
for (int k = 0; k < dataSize; k++) {
dataWords[k] = generateRandomNumber(field->getSize());
}
// generate ECC words
message = dataWords;
encoder.encode(message, ecWords.size());
message.insert(std::end(message), std::begin(ecWords), std::end(ecWords));
// check to see if Decoder can fix up to ecWords/2 random errors
testDecoder(field, dataWords, ecWords);
}
}
void ReedSolomonTests::testEncodeDecode(Ref<GenericGF> field,
const std::vector<int> &dataWords,
const std::vector<int> & ecWords)
{
testEncoder(field, dataWords, ecWords);
testDecoder(field, dataWords, ecWords);
}
void ReedSolomonTests::testEncoder(Ref<GenericGF> field,
const std::vector<int> &dataWords,
const std::vector<int> & ecWords)
{
ReedSolomonEncoder encoder(field);
std::vector<int> messageExpected;
std::vector<int> message;
messageExpected = dataWords;
messageExpected.insert(std::end(messageExpected), std::begin(ecWords), std::end(ecWords));
message = dataWords;
encoder.encode(message, ecWords.size());
assertDataEquals("",//"Encode in " + field + " (" + dataWords.size() + ',' + ecWords.size() + ") failed",
messageExpected, message);
}
void ReedSolomonTests::testDecoder(Ref<GenericGF> field,
const std::vector<int> &dataWords,
const std::vector<int> & ecWords) {
ReedSolomonDecoder decoder(field);
std::vector<int> message;
int maxErrors = ecWords.size() / 2;
initializeRandom();
int iterations = field->getSize() > 256 ? 1 : DECODER_TEST_ITERATIONS;
for (int j = 0; j < iterations; j++) {
for (int i = 0; i < ecWords.size(); i++) {
if (i > 10 && i < ecWords.size() / 2 - 10) {
// performance improvement - skip intermediate cases in long-running tests
i += ecWords.size() / 10;
}
message = dataWords;
message.insert(std::end(message), std::begin(ecWords), std::end(ecWords));
corrupt(message, i, field->getSize());
ArrayRef<int> messageArrayRef(message.size());
for(int i=0; i<message.size(); i++)
messageArrayRef[i] = message[i];
try {
decoder.decode(messageArrayRef, ecWords.size());
} catch(zxing::Exception &e) {
// fail only if maxErrors exceeded
assertTrue(i > maxErrors); /*"Decode in " + field + " (" + dataWords.length + ',' + ecWords.length + ") failed at " + i + " errors: " + e,*/
// else stop
break;
}
if (i < maxErrors) {
//"Decode in " + field + " (" + dataWords.size() + ',' + ecWords.size() + ") failed at " + i + " errors"
assertDataEquals("",dataWords, message);
}
}
}
}
}

View File

@ -2,22 +2,37 @@
#define REEDSOLOMONENCODERTESTS_H
#include "TestCase.h"
#include "zxing/common/reedsolomon/ReedSolomonEncoder.h"
#include <zxing/common/reedsolomon/GenericGF.h>
namespace zxing{
namespace tests{
class ReedSolomonEncoderTests : public TestCase
class ReedSolomonTests : public TestCase
{
private:
static const int DECODER_RANDOM_TEST_ITERATIONS;
static const int DECODER_TEST_ITERATIONS;
public:
ReedSolomonEncoderTests();
ReedSolomonTests();
void execute();
protected:
void testQRCode();
// const std::vector<byte>& dataBytes
// void testEncoder(Ref<GenericGF> field, int[] dataWords, int[] ecWords);
private:
void corrupt(std::vector<int> &received, int howMany, int max);
void testEncodeDecodeRandom(Ref<GenericGF> field, int dataSize, int ecSize);
void testEncodeDecode(Ref<GenericGF> field,
const std::vector<int> &dataWords,
const std::vector<int> & ecWords);
void testEncoder(Ref<GenericGF> field,
const std::vector<int> &dataWords,
const std::vector<int> & ecWords);
void testDecoder(Ref<GenericGF> field,
const std::vector<int> &dataWords,
const std::vector<int> & ecWords);
};
}