AusweisApp2/test/qt/ui/qml/test_NumberModel.cpp
2019-09-30 17:22:19 +02:00

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"