425 lines
13 KiB
C++
425 lines
13 KiB
C++
|
/*!
|
||
|
* \brief Unit tests for \ref NumberModel
|
||
|
*
|
||
|
* \copyright Copyright (c) 2018-2019 Governikus GmbH & Co. KG, Germany
|
||
|
*/
|
||
|
|
||
|
#include "NumberModel.h"
|
||
|
|
||
|
#include "context/ChangePinContext.h"
|
||
|
#include "context/RemoteServiceContext.h"
|
||
|
|
||
|
#include "MockCardConnectionWorker.h"
|
||
|
|
||
|
#include <QDebug>
|
||
|
#include <QtTest>
|
||
|
|
||
|
using namespace governikus;
|
||
|
|
||
|
|
||
|
class test_NumberModel
|
||
|
: public QObject
|
||
|
{
|
||
|
Q_OBJECT
|
||
|
NumberModel * mModel;
|
||
|
|
||
|
private Q_SLOTS:
|
||
|
void init()
|
||
|
{
|
||
|
mModel = Env::getSingleton<NumberModel>();
|
||
|
}
|
||
|
|
||
|
|
||
|
void cleanup()
|
||
|
{
|
||
|
mModel->resetContext();
|
||
|
}
|
||
|
|
||
|
|
||
|
void cleanupTestCase()
|
||
|
{
|
||
|
mModel->deleteLater();
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_ResetContext()
|
||
|
{
|
||
|
const QSharedPointer<ChangePinContext> pinContext(new ChangePinContext());
|
||
|
const QSharedPointer<WorkflowContext> context(new WorkflowContext());
|
||
|
|
||
|
QSignalSpy spyCanChanged(mModel, &NumberModel::fireCanChanged);
|
||
|
QSignalSpy spyPinChanged(mModel, &NumberModel::firePinChanged);
|
||
|
QSignalSpy spyNewPinChanged(mModel, &NumberModel::fireNewPinChanged);
|
||
|
QSignalSpy spyCanAllowed(mModel, &NumberModel::fireCanAllowedModeChanged);
|
||
|
QSignalSpy spyPukChanged(mModel, &NumberModel::firePukChanged);
|
||
|
QSignalSpy spyReaderNameChanged(mModel, &NumberModel::fireReaderInfoChanged);
|
||
|
QSignalSpy spyLastPaceResultChanged(mModel, &NumberModel::fireInputErrorChanged);
|
||
|
|
||
|
mModel->resetContext();
|
||
|
QCOMPARE(spyCanChanged.count(), 1);
|
||
|
QCOMPARE(spyPinChanged.count(), 1);
|
||
|
QCOMPARE(spyNewPinChanged.count(), 1);
|
||
|
QCOMPARE(spyCanAllowed.count(), 1);
|
||
|
QCOMPARE(spyPukChanged.count(), 1);
|
||
|
QCOMPARE(spyReaderNameChanged.count(), 1);
|
||
|
QCOMPARE(spyLastPaceResultChanged.count(), 1);
|
||
|
|
||
|
mModel->resetContext(context);
|
||
|
QCOMPARE(spyCanChanged.count(), 2);
|
||
|
QCOMPARE(spyPinChanged.count(), 2);
|
||
|
QCOMPARE(spyNewPinChanged.count(), 2);
|
||
|
QCOMPARE(spyCanAllowed.count(), 2);
|
||
|
QCOMPARE(spyPukChanged.count(), 2);
|
||
|
QCOMPARE(spyReaderNameChanged.count(), 2);
|
||
|
QCOMPARE(spyLastPaceResultChanged.count(), 2);
|
||
|
Q_EMIT context->fireCanChanged();
|
||
|
QCOMPARE(spyCanChanged.count(), 3);
|
||
|
Q_EMIT context->firePinChanged();
|
||
|
QCOMPARE(spyPinChanged.count(), 3);
|
||
|
Q_EMIT context->fireCanAllowedModeChanged();
|
||
|
QCOMPARE(spyCanAllowed.count(), 3);
|
||
|
Q_EMIT context->fireReaderNameChanged();
|
||
|
QCOMPARE(spyReaderNameChanged.count(), 3);
|
||
|
Q_EMIT context->firePaceResultUpdated();
|
||
|
QCOMPARE(spyLastPaceResultChanged.count(), 4);
|
||
|
|
||
|
mModel->resetContext(pinContext);
|
||
|
QCOMPARE(spyCanChanged.count(), 4);
|
||
|
QCOMPARE(spyPinChanged.count(), 4);
|
||
|
QCOMPARE(spyNewPinChanged.count(), 3);
|
||
|
QCOMPARE(spyCanAllowed.count(), 4);
|
||
|
QCOMPARE(spyPukChanged.count(), 3);
|
||
|
QCOMPARE(spyReaderNameChanged.count(), 4);
|
||
|
QCOMPARE(spyLastPaceResultChanged.count(), 5);
|
||
|
|
||
|
Q_EMIT pinContext->fireCanChanged();
|
||
|
QCOMPARE(spyCanChanged.count(), 5);
|
||
|
Q_EMIT pinContext->firePinChanged();
|
||
|
QCOMPARE(spyPinChanged.count(), 5);
|
||
|
Q_EMIT pinContext->fireCanAllowedModeChanged();
|
||
|
QCOMPARE(spyCanAllowed.count(), 5);
|
||
|
Q_EMIT pinContext->fireReaderNameChanged();
|
||
|
QCOMPARE(spyReaderNameChanged.count(), 5);
|
||
|
Q_EMIT pinContext->firePaceResultUpdated();
|
||
|
QCOMPARE(spyLastPaceResultChanged.count(), 7);
|
||
|
Q_EMIT pinContext->fireNewPinChanged();
|
||
|
QCOMPARE(spyNewPinChanged.count(), 4);
|
||
|
Q_EMIT pinContext->firePukChanged();
|
||
|
QCOMPARE(spyPukChanged.count(), 4);
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_Can()
|
||
|
{
|
||
|
const QSharedPointer<WorkflowContext> context(new WorkflowContext());
|
||
|
const QString can = QStringLiteral("111111");
|
||
|
|
||
|
mModel->setCan(can);
|
||
|
QCOMPARE(mModel->getCan(), QString());
|
||
|
|
||
|
mModel->resetContext(context);
|
||
|
mModel->setCan(can);
|
||
|
QCOMPARE(mModel->getCan(), can);
|
||
|
QCOMPARE(context->getCan(), can);
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_Pin()
|
||
|
{
|
||
|
const QSharedPointer<WorkflowContext> context(new WorkflowContext());
|
||
|
const QString pin = QStringLiteral("111111");
|
||
|
mModel->setPin(pin);
|
||
|
QCOMPARE(mModel->getPin(), QString());
|
||
|
|
||
|
mModel->resetContext(context);
|
||
|
mModel->setPin(pin);
|
||
|
QCOMPARE(mModel->getPin(), pin);
|
||
|
QCOMPARE(context->getPin(), pin);
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_NewPin()
|
||
|
{
|
||
|
const QSharedPointer<WorkflowContext> context(new WorkflowContext());
|
||
|
const QSharedPointer<ChangePinContext> changePinContext(new ChangePinContext());
|
||
|
const QSharedPointer<RemoteServiceContext> remoteServiceContext(new RemoteServiceContext());
|
||
|
const QString pin = QStringLiteral("111111");
|
||
|
|
||
|
mModel->resetContext(context);
|
||
|
mModel->setNewPin(pin);
|
||
|
QCOMPARE(mModel->getNewPin(), QString());
|
||
|
|
||
|
mModel->resetContext(changePinContext);
|
||
|
mModel->setNewPin(pin);
|
||
|
QCOMPARE(changePinContext->getNewPin(), pin);
|
||
|
QCOMPARE(mModel->getNewPin(), pin);
|
||
|
|
||
|
mModel->resetContext(remoteServiceContext);
|
||
|
mModel->setNewPin(pin);
|
||
|
QCOMPARE(remoteServiceContext->getNewPin(), pin);
|
||
|
QCOMPARE(mModel->getNewPin(), QString());
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_Puk()
|
||
|
{
|
||
|
const QSharedPointer<WorkflowContext> context(new WorkflowContext());
|
||
|
const QString puk = QStringLiteral("111111");
|
||
|
|
||
|
mModel->resetContext(context);
|
||
|
mModel->setPuk(puk);
|
||
|
QCOMPARE(context->getPuk(), puk);
|
||
|
QCOMPARE(mModel->getPuk(), puk);
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_OnReaderInfoChanged()
|
||
|
{
|
||
|
const QSharedPointer<WorkflowContext> context(new WorkflowContext());
|
||
|
QSignalSpy spyReaderNameChanged(mModel, &NumberModel::fireReaderInfoChanged);
|
||
|
|
||
|
const QString readerName = QStringLiteral("name");
|
||
|
const QString test = QStringLiteral("test");
|
||
|
|
||
|
const auto readerManager = Env::getSingleton<ReaderManager>();
|
||
|
Q_EMIT readerManager->fireReaderPropertiesUpdated(QString());
|
||
|
QCOMPARE(spyReaderNameChanged.count(), 0);
|
||
|
|
||
|
context->setReaderName(test);
|
||
|
mModel->resetContext(context);
|
||
|
Q_EMIT readerManager->fireReaderPropertiesUpdated(QString());
|
||
|
QCOMPARE(spyReaderNameChanged.count(), 1);
|
||
|
|
||
|
context->setReaderName(readerName);
|
||
|
mModel->resetContext(context);
|
||
|
Q_EMIT readerManager->fireReaderPropertiesUpdated(QString());
|
||
|
QCOMPARE(spyReaderNameChanged.count(), 3);
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_CanAllowed()
|
||
|
{
|
||
|
const QSharedPointer<WorkflowContext> context(new WorkflowContext());
|
||
|
QVERIFY(!mModel->isCanAllowedMode());
|
||
|
|
||
|
mModel->resetContext(context);
|
||
|
QVERIFY(!mModel->isCanAllowedMode());
|
||
|
|
||
|
context->setCanAllowedMode(true);
|
||
|
QVERIFY(mModel->isCanAllowedMode());
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_PinDeactivatedFalse()
|
||
|
{
|
||
|
QVERIFY(!mModel->isPinDeactivated());
|
||
|
|
||
|
const QSharedPointer<WorkflowContext> context(new WorkflowContext());
|
||
|
mModel->resetContext(context);
|
||
|
QVERIFY(!mModel->isPinDeactivated());
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_Error()
|
||
|
{
|
||
|
QThread connectionThread;
|
||
|
connectionThread.start();
|
||
|
|
||
|
const QSharedPointer<WorkflowContext> context(new WorkflowContext());
|
||
|
|
||
|
QCOMPARE(mModel->getInputError(), QString());
|
||
|
QVERIFY(!mModel->hasError());
|
||
|
|
||
|
context->setLastPaceResult(CardReturnCode::OK);
|
||
|
mModel->resetContext(context);
|
||
|
QCOMPARE(mModel->getInputError(), QString());
|
||
|
QVERIFY(!mModel->hasError());
|
||
|
|
||
|
context->setLastPaceResult(CardReturnCode::CANCELLATION_BY_USER);
|
||
|
QCOMPARE(mModel->getInputError(), QString());
|
||
|
QVERIFY(!mModel->hasError());
|
||
|
|
||
|
const QSharedPointer<MockCardConnectionWorker> worker(new MockCardConnectionWorker());
|
||
|
worker->moveToThread(&connectionThread);
|
||
|
const QSharedPointer<CardConnection> connection(new CardConnection(worker));
|
||
|
context->setCardConnection(connection);
|
||
|
|
||
|
context->setLastPaceResult(CardReturnCode::INVALID_PIN);
|
||
|
QCOMPARE(mModel->getInputError(), tr("The given PIN is not correct. You have 2 tries to enter the correct PIN."));
|
||
|
QVERIFY(mModel->hasError());
|
||
|
|
||
|
context->setLastPaceResult(CardReturnCode::INVALID_PIN_2);
|
||
|
QCOMPARE(mModel->getInputError(), tr("You have entered the wrong PIN twice. "
|
||
|
"Prior to a third attempt, you have to enter your six-digit card access number first. "
|
||
|
"You can find your card access number on the front of your ID card."));
|
||
|
QVERIFY(mModel->hasError());
|
||
|
|
||
|
context->setLastPaceResult(CardReturnCode::INVALID_PIN_3);
|
||
|
QCOMPARE(mModel->getInputError(), tr("You have entered a wrong PIN three times. "
|
||
|
"Your PIN is now blocked. "
|
||
|
"You have to enter the PUK now for unblocking."));
|
||
|
QVERIFY(mModel->hasError());
|
||
|
|
||
|
context->setLastPaceResult(CardReturnCode::INVALID_CAN);
|
||
|
QCOMPARE(mModel->getInputError(), tr("You have entered a wrong CAN, please try again."));
|
||
|
|
||
|
context->setLastPaceResult(CardReturnCode::INVALID_PUK);
|
||
|
QCOMPARE(mModel->getInputError(), tr("You have entered a wrong PUK. "
|
||
|
"Please try again."));
|
||
|
QVERIFY(mModel->hasError());
|
||
|
|
||
|
context->setLastPaceResult(CardReturnCode::UNKNOWN);
|
||
|
QCOMPARE(mModel->getInputError(), tr("An unexpected error has occurred during processing."));
|
||
|
|
||
|
context->setLastPaceResult(CardReturnCode::UNEXPECTED_TRANSMIT_STATUS);
|
||
|
QCOMPARE(mModel->getInputError(), QStringLiteral("%1 <a href=\"%2\">%3</a>.").arg(
|
||
|
tr("A protocol error occurred. Please make sure that your ID card is placed correctly on the card reader and try again. If the problem occurs again, please contact our support at"),
|
||
|
tr("https://www.ausweisapp.bund.de/en/qa/support/"),
|
||
|
tr("AusweisApp2 Support")));
|
||
|
QVERIFY(mModel->hasError());
|
||
|
|
||
|
connectionThread.quit();
|
||
|
connectionThread.wait();
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_GetRetryCounter()
|
||
|
{
|
||
|
QThread connectionThread;
|
||
|
connectionThread.start();
|
||
|
|
||
|
const QSharedPointer<WorkflowContext> context(new WorkflowContext());
|
||
|
|
||
|
QCOMPARE(mModel->getRetryCounter(), -1);
|
||
|
|
||
|
mModel->resetContext(context);
|
||
|
QCOMPARE(mModel->getRetryCounter(), -1);
|
||
|
|
||
|
const QString name = QStringLiteral("name");
|
||
|
const CardInfo cardInfo(CardType::EID_CARD, QSharedPointer<const EFCardAccess>(),
|
||
|
3, true, false);
|
||
|
MockReader reader(name);
|
||
|
reader.getReaderInfo().setCardInfo(cardInfo);
|
||
|
const QSharedPointer<MockCardConnectionWorker> worker(new MockCardConnectionWorker(&reader));
|
||
|
worker->moveToThread(&connectionThread);
|
||
|
const QSharedPointer<CardConnection> connection(new CardConnection(worker));
|
||
|
context->setCardConnection(connection);
|
||
|
QCOMPARE(mModel->getRetryCounter(), 3);
|
||
|
|
||
|
connectionThread.quit();
|
||
|
connectionThread.wait();
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_RequestTransportPin_data()
|
||
|
{
|
||
|
QTest::addColumn<QSharedPointer<WorkflowContext> >("context");
|
||
|
QTest::addColumn<bool>("contextRequestedTransportPin");
|
||
|
|
||
|
QTest::newRow("WorkflowContext") << QSharedPointer<WorkflowContext>(new WorkflowContext()) << false;
|
||
|
QTest::newRow("ChangePinContext") << QSharedPointer<WorkflowContext>(new ChangePinContext()) << false;
|
||
|
QTest::newRow("ChangePinContext-false") << QSharedPointer<WorkflowContext>(new ChangePinContext(false)) << false;
|
||
|
QTest::newRow("ChangePinContext-true") << QSharedPointer<WorkflowContext>(new ChangePinContext(true)) << true;
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_RequestTransportPin()
|
||
|
{
|
||
|
QFETCH(QSharedPointer<WorkflowContext>, context);
|
||
|
QFETCH(bool, contextRequestedTransportPin);
|
||
|
|
||
|
QVERIFY(!mModel->isRequestTransportPin());
|
||
|
|
||
|
mModel->setRequestTransportPin(true);
|
||
|
QVERIFY(mModel->isRequestTransportPin());
|
||
|
mModel->setRequestTransportPin(false);
|
||
|
QVERIFY(!mModel->isRequestTransportPin());
|
||
|
|
||
|
mModel->resetContext(context);
|
||
|
QCOMPARE(mModel->isRequestTransportPin(), contextRequestedTransportPin);
|
||
|
|
||
|
mModel->setRequestTransportPin(true);
|
||
|
QVERIFY(mModel->isRequestTransportPin());
|
||
|
|
||
|
mModel->setRequestTransportPin(false);
|
||
|
QVERIFY(!mModel->isRequestTransportPin());
|
||
|
mModel->setRequestTransportPin(true);
|
||
|
QVERIFY(mModel->isRequestTransportPin());
|
||
|
|
||
|
mModel->resetContext();
|
||
|
QVERIFY(!mModel->isRequestTransportPin());
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_GetPasswordType_ContextIsNullptr()
|
||
|
{
|
||
|
QCOMPARE(mModel->getPasswordType(), NumberModel::QmlPasswordType::PASSWORD_PIN);
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_GetPasswordType_RequestNewPin()
|
||
|
{
|
||
|
const QSharedPointer<WorkflowContext> context(new WorkflowContext());
|
||
|
|
||
|
mModel->resetContext(context);
|
||
|
mModel->requestNewPin();
|
||
|
|
||
|
QCOMPARE(mModel->getPasswordType(), NumberModel::QmlPasswordType::PASSWORD_NEW_PIN);
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_GetPasswordType_data()
|
||
|
{
|
||
|
QTest::addColumn<PacePasswordId>("passwordId");
|
||
|
QTest::addColumn<NumberModel::QmlPasswordType>("passwordType");
|
||
|
|
||
|
QTest::newRow("unknown") << PacePasswordId::UNKNOWN << NumberModel::QmlPasswordType::PASSWORD_PIN;
|
||
|
QTest::newRow("mrz") << PacePasswordId::PACE_MRZ << NumberModel::QmlPasswordType::PASSWORD_PIN;
|
||
|
QTest::newRow("pin") << PacePasswordId::PACE_PIN << NumberModel::QmlPasswordType::PASSWORD_PIN;
|
||
|
QTest::newRow("can") << PacePasswordId::PACE_CAN << NumberModel::QmlPasswordType::PASSWORD_CAN;
|
||
|
QTest::newRow("puk") << PacePasswordId::PACE_PUK << NumberModel::QmlPasswordType::PASSWORD_PUK;
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_GetPasswordType()
|
||
|
{
|
||
|
QFETCH(PacePasswordId, passwordId);
|
||
|
QFETCH(NumberModel::QmlPasswordType, passwordType);
|
||
|
|
||
|
const QSharedPointer<WorkflowContext> context(new WorkflowContext());
|
||
|
|
||
|
mModel->resetContext(context);
|
||
|
|
||
|
context->setEstablishPaceChannelType(passwordId);
|
||
|
QCOMPARE(mModel->getPasswordType(), passwordType);
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_OnCardConnectionChanged()
|
||
|
{
|
||
|
QThread connectionThread;
|
||
|
connectionThread.start();
|
||
|
|
||
|
const QSharedPointer<WorkflowContext> context(new WorkflowContext());
|
||
|
|
||
|
mModel->resetContext(context);
|
||
|
const QSharedPointer<MockCardConnectionWorker> worker(new MockCardConnectionWorker());
|
||
|
worker->moveToThread(&connectionThread);
|
||
|
const QSharedPointer<CardConnection> connection(new CardConnection(worker));
|
||
|
context->setCardConnection(connection);
|
||
|
QSignalSpy spy(mModel, &NumberModel::fireReaderInfoChanged);
|
||
|
|
||
|
Q_EMIT context->fireCardConnectionChanged();
|
||
|
Q_EMIT connection->fireReaderInfoChanged(ReaderInfo());
|
||
|
QCOMPARE(spy.count(), 3);
|
||
|
|
||
|
connectionThread.quit();
|
||
|
connectionThread.wait();
|
||
|
}
|
||
|
|
||
|
|
||
|
};
|
||
|
|
||
|
QTEST_GUILESS_MAIN(test_NumberModel)
|
||
|
#include "test_NumberModel.moc"
|