Added support to the execution of stress test for encode / decode operation for all possible combinations of Qr code length and error correction levels.

Created as a first step to detect the bug of #83.
This commit is contained in:
Nikos Ftylitakis 2019-01-18 01:38:10 +02:00
parent 38bbed6fcb
commit 15ddcaf181
6 changed files with 202 additions and 8 deletions

View File

@ -17,7 +17,7 @@ class EncodeValidator : public TestCase
{
public:
EncodeValidator();
void execute();
void execute() override;
};
}

View File

@ -0,0 +1,120 @@
#include "EncoderStressTest.h"
#include <iostream>
namespace zxing {
namespace tests{
EncoderStressTest::EncoderStressTest(): TestCase(), decoder(QZXing::DecoderFormat_QR_CODE),
sumOfSuccessfullTests(0), totalExecutedTests(0)
{
/**
N A B
L 7089 4296 2953
M 5596 3391 2331
Q 3993 2420 1663
H 3057 1852 1273
*/
maxCharacterNumberMap_[qrcode::ErrorCorrectionLevel::L.name()][qrcode::Mode::NUMERIC.getName()] = 7089;
maxCharacterNumberMap_[qrcode::ErrorCorrectionLevel::M.name()][qrcode::Mode::NUMERIC.getName()] = 5596;
maxCharacterNumberMap_[qrcode::ErrorCorrectionLevel::Q.name()][qrcode::Mode::NUMERIC.getName()] = 3993;
maxCharacterNumberMap_[qrcode::ErrorCorrectionLevel::H.name()][qrcode::Mode::NUMERIC.getName()] = 3057;
maxCharacterNumberMap_[qrcode::ErrorCorrectionLevel::L.name()][qrcode::Mode::ALPHANUMERIC.getName()] = 4296;
maxCharacterNumberMap_[qrcode::ErrorCorrectionLevel::M.name()][qrcode::Mode::ALPHANUMERIC.getName()] = 3391;
maxCharacterNumberMap_[qrcode::ErrorCorrectionLevel::Q.name()][qrcode::Mode::ALPHANUMERIC.getName()] = 2420;
maxCharacterNumberMap_[qrcode::ErrorCorrectionLevel::H.name()][qrcode::Mode::ALPHANUMERIC.getName()] = 1852;
maxCharacterNumberMap_[qrcode::ErrorCorrectionLevel::L.name()][qrcode::Mode::BYTE.getName()] = 2953;
maxCharacterNumberMap_[qrcode::ErrorCorrectionLevel::M.name()][qrcode::Mode::BYTE.getName()] = 2331;
maxCharacterNumberMap_[qrcode::ErrorCorrectionLevel::Q.name()][qrcode::Mode::BYTE.getName()] = 1663;
maxCharacterNumberMap_[qrcode::ErrorCorrectionLevel::H.name()][qrcode::Mode::BYTE.getName()] = 1273;
}
void zxing::tests::EncoderStressTest::execute()
{
runTests(zxing::qrcode::Mode::NUMERIC);
runTests(zxing::qrcode::Mode::ALPHANUMERIC);
runTests(zxing::qrcode::Mode::BYTE);
std::cout << "total: successful: " << sumOfSuccessfullTests << ", total: " << totalExecutedTests << std::endl;
}
int EncoderStressTest::getMaxCharacterNumber(qrcode::ErrorCorrectionLevel &errorCorrectionLevel, qrcode::Mode &mode)
{
if(maxCharacterNumberMap_.contains(errorCorrectionLevel.name()) &&
maxCharacterNumberMap_[errorCorrectionLevel.name()].contains(mode.getName()))
return maxCharacterNumberMap_[errorCorrectionLevel.name()][mode.getName()];
else
return 0;
}
char EncoderStressTest::getCharacterForQrMode(qrcode::Mode &mode)
{
/*
N
0-9
A
0 - 9
A - Z
(space)
$ % * + - . / :
B
A + a-z
*/
if(mode == qrcode::Mode::NUMERIC)
return '0';
else if (mode == qrcode::Mode::ALPHANUMERIC)
return 'A';
else if (mode == qrcode::Mode::BYTE)
return 'a';
else
return (rand() % 256);
}
void EncoderStressTest::runTests(qrcode::Mode &mode)
{
runTests(zxing::qrcode::ErrorCorrectionLevel::L, mode);
runTests(zxing::qrcode::ErrorCorrectionLevel::M, mode);
runTests(zxing::qrcode::ErrorCorrectionLevel::Q, mode);
runTests(zxing::qrcode::ErrorCorrectionLevel::H, mode);
}
void EncoderStressTest::runTests(zxing::qrcode::ErrorCorrectionLevel &errorCorrectionLevel, zxing::qrcode::Mode &mode)
{
currentSetupExecutedTests = 0;
currentSetupSuccessfullTests = 0;
QString currentCharacters;
int maxCharLength = getMaxCharacterNumber(errorCorrectionLevel, mode);
for(int i=1; i<=maxCharLength; ++i)
{
currentCharacters += getCharacterForQrMode(mode);
QImage generatedImage = QZXing::encodeData(currentCharacters);
QString decodedData = decoder.decodeImage(generatedImage);
std::cout << "M[" << mode.getName() << "], E[" << errorCorrectionLevel.name() << "], L[" << i << "]: " <<
"decoded=" << decoder.getLastDecodeOperationSucceded() <<
", match=" << (currentCharacters == decodedData) << std::endl;
if(decoder.getLastDecodeOperationSucceded() && (currentCharacters == decodedData))
{
++sumOfSuccessfullTests;
++currentSetupSuccessfullTests;
}
++totalExecutedTests;
++currentSetupExecutedTests;
}
std::cout << "subtotal: M[" << mode.getName() << "], E[" << errorCorrectionLevel.name() << "]: " <<
"successfull: " << currentSetupSuccessfullTests << ", total: " << currentSetupExecutedTests << std::endl;
}
}
}

View File

@ -0,0 +1,44 @@
#ifndef ENCODERSTRESSTEST_H
#define ENCODERSTRESSTEST_H
#include <QZXing.h>
#include <memory>
#include <vector>
#include <map>
#include <QMap>
#include <zxing/Exception.h>
#include <QtGlobal>
#include <TestCase.h>
#include <zxing/qrcode/decoder/Mode.h>
namespace zxing {
namespace tests{
class EncoderStressTest : public TestCase
{
public:
EncoderStressTest();
void execute() override;
protected:
int getMaxCharacterNumber(zxing::qrcode::ErrorCorrectionLevel &errorCorrectionLevel, zxing::qrcode::Mode &mode);
char getCharacterForQrMode(zxing::qrcode::Mode &mode);
void runTests(zxing::qrcode::Mode &mode);
void runTests(zxing::qrcode::ErrorCorrectionLevel &errorCorrectionLevel, zxing::qrcode::Mode &mode);
private:
QZXing decoder;
QMap<std::string, QMap<std::string, int>> maxCharacterNumberMap_;
int sumOfSuccessfullTests;
int totalExecutedTests;
int currentSetupSuccessfullTests;
int currentSetupExecutedTests;
};
}
}
#endif // ENCODERSTRESSTEST_H

View File

@ -15,7 +15,8 @@ HEADERS += \
zxing/qrcode/encoder/EncoderTests.h \
zxing/common/reedsolomon/ReedSolomonEncoderTests.h \
zxing/common/BitArrayTests.h \
zxing/qrcode/encoder/BitVectorTests.h
zxing/qrcode/encoder/BitVectorTests.h \
EncoderStressTest.h
#\backward.hpp
SOURCES += main.cpp \
@ -29,6 +30,7 @@ SOURCES += main.cpp \
zxing/qrcode/encoder/EncoderTests.cpp \
zxing/common/reedsolomon/ReedSolomonEncoderTests.cpp \
zxing/common/BitArrayTests.cpp \
zxing/qrcode/encoder/BitVectorTests.cpp
zxing/qrcode/encoder/BitVectorTests.cpp \
EncoderStressTest.cpp
include(../../../src/QZXing.pri)

View File

@ -156,6 +156,7 @@ protected:
static int generateRandomNumber(int range);
public:
virtual ~TestCase() {}
virtual void execute()=0;
};

View File

@ -1,14 +1,41 @@
#include <QCoreApplication>
#include <QCommandLineParser>
#include <EncodeValidator.h>
#include "DecodeValidator.h"
#include "EncoderStressTest.h"
int main(int /*argc*/, char **/*argv[]*/)
int main(int argc, char **argv)
{
DecodeValidator decodeValidator;
decodeValidator.executeTests("../../resources/");
QCoreApplication application(argc, argv);
QCoreApplication::setApplicationName("QZXingTests");
zxing::tests::EncodeValidator encodeValidator;
encodeValidator.execute();
QCommandLineParser parser;
parser.setApplicationDescription("Executes unit tests for QZXing library");
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption encoderStressTestOption(QStringList() << "encoder-stress",
QCoreApplication::translate("main", "Execute stress test for Qr Code encoding and decoding"));
parser.addOption(encoderStressTestOption);
parser.process(application);
bool isEncoderStressTestEnabled = parser.isSet(encoderStressTestOption);
if(isEncoderStressTestEnabled)
{
zxing::tests::EncoderStressTest encoderStressTest;
encoderStressTest.execute();
}
else
{
DecodeValidator decodeValidator;
decodeValidator.executeTests("../../resources/");
zxing::tests::EncodeValidator encodeValidator;
encodeValidator.execute();
}
}