/*! * \copyright Copyright (c) 2018-2019 Governikus GmbH & Co. KG, Germany */ #include "messages/IfdStatus.h" #include "AppSettings.h" #include "LogHandler.h" #include using namespace governikus; class test_IfdStatus : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase() { Env::getSingleton()->init(); } void paceCapabilities_data() { QTest::addColumn("pace"); QTest::addColumn("eid"); QTest::addColumn("esign"); QTest::addColumn("destroy"); QTest::newRow("false") << false << false << false << false; QTest::newRow("true") << true << true << true << true; } void paceCapabilities() { QFETCH(bool, pace); QFETCH(bool, eid); QFETCH(bool, esign); QFETCH(bool, destroy); PaceCapabilities capabilities(pace, eid, esign, destroy); QCOMPARE(capabilities.getPace(), pace); QCOMPARE(capabilities.getEId(), eid); QCOMPARE(capabilities.getESign(), esign); QCOMPARE(capabilities.getDestroy(), destroy); } void invalidJson() { QSignalSpy logSpy(Env::getSingleton(), &LogHandler::fireLog); QByteArray message("FooBar"); const auto& obj = QJsonDocument::fromJson(message).object(); QVERIFY(obj.isEmpty()); IfdStatus msg(obj); QVERIFY(msg.isIncomplete()); QCOMPARE(logSpy.count(), 9); QVERIFY(logSpy.at(0).at(0).toString().contains("Missing value \"msg\"")); QVERIFY(logSpy.at(1).at(0).toString().contains("Invalid messageType received: \"\"")); QVERIFY(logSpy.at(2).at(0).toString().contains("Missing value \"ContextHandle\"")); QVERIFY(logSpy.at(3).at(0).toString().contains("Missing value \"SlotName\"")); QVERIFY(logSpy.at(4).at(0).toString().contains("Missing value \"PINCapabilities\"")); QVERIFY(logSpy.at(5).at(0).toString().contains("Missing value \"MaxAPDULength\"")); QVERIFY(logSpy.at(6).at(0).toString().contains("Missing value \"ConnectedReader\"")); QVERIFY(logSpy.at(7).at(0).toString().contains("Missing value \"CardAvailable\"")); QVERIFY(logSpy.at(8).at(0).toString().contains("The value of msg should be IFDStatus")); } void values() { const IfdStatus ifdStatus( QStringLiteral("SlotName"), PaceCapabilities(true, false, true, false), 500, false, false ); QVERIFY(!ifdStatus.isIncomplete()); QCOMPARE(ifdStatus.getType(), RemoteCardMessageType::IFDStatus); QCOMPARE(ifdStatus.getContextHandle(), QString()); QCOMPARE(ifdStatus.getSlotName(), QStringLiteral("SlotName")); QVERIFY(ifdStatus.getPaceCapabilities().getPace()); QVERIFY(!ifdStatus.getPaceCapabilities().getEId()); QVERIFY(ifdStatus.getPaceCapabilities().getESign()); QVERIFY(!ifdStatus.getPaceCapabilities().getDestroy()); QCOMPARE(ifdStatus.getMaxApduLength(), 500); QVERIFY(!ifdStatus.getConnectedReader()); QVERIFY(!ifdStatus.getCardAvailable()); } void toJson() { const IfdStatus ifdStatus( QStringLiteral("SlotName"), PaceCapabilities(true, false, true, false), 500, false, false ); const QByteArray& byteArray = ifdStatus.toByteArray(QStringLiteral("TestContext")); QCOMPARE(byteArray, QByteArray("{\n" " \"CardAvailable\": false,\n" " \"ConnectedReader\": false,\n" " \"ContextHandle\": \"TestContext\",\n" " \"EFATR\": null,\n" " \"EFDIR\": null,\n" " \"MaxAPDULength\": 500,\n" " \"PINCapabilities\": {\n" " \"Destroy\": false,\n" " \"PACE\": true,\n" " \"eID\": false,\n" " \"eSign\": true\n" " },\n" " \"SlotName\": \"SlotName\",\n" " \"msg\": \"IFDStatus\"\n" "}\n")); const QJsonObject obj = QJsonDocument::fromJson(byteArray).object(); QCOMPARE(obj.size(), 9); QCOMPARE(obj.value(QLatin1String("msg")).toString(), QStringLiteral("IFDStatus")); QCOMPARE(obj.value(QLatin1String("ContextHandle")).toString(), QStringLiteral("TestContext")); QCOMPARE(obj.value(QLatin1String("SlotName")).toString(), QStringLiteral("SlotName")); const QJsonObject cap = obj.value(QLatin1String("PINCapabilities")).toObject(); QCOMPARE(cap.size(), 4); QVERIFY(cap.value(QLatin1String("PACE")).toBool()); QVERIFY(!cap.value(QLatin1String("eID")).toBool()); QVERIFY(cap.value(QLatin1String("eSign")).toBool()); QVERIFY(!cap.value(QLatin1String("Destroy")).toBool()); QCOMPARE(obj.value(QLatin1String("MaxAPDULength")).toInt(), 500); QVERIFY(!obj.value(QLatin1String("ConnectedReader")).toBool()); QVERIFY(!obj.value(QLatin1String("CardAvailable")).toBool()); } void fromJson() { QSignalSpy logSpy(Env::getSingleton(), &LogHandler::fireLog); const QByteArray message("{\n" " \"CardAvailable\": false,\n" " \"ConnectedReader\": false,\n" " \"ContextHandle\": \"TestContext\",\n" " \"EFATR\": null,\n" " \"EFDIR\": null,\n" " \"MaxAPDULength\": 500,\n" " \"PINCapabilities\": {\n" " \"Destroy\": false,\n" " \"PACE\": true,\n" " \"eID\": false,\n" " \"eSign\": true\n" " },\n" " \"SlotName\": \"SlotName\",\n" " \"msg\": \"IFDStatus\"\n" "}\n"); const QJsonObject& obj = QJsonDocument::fromJson(message).object(); const IfdStatus ifdStatus(obj); QVERIFY(!ifdStatus.isIncomplete()); QCOMPARE(ifdStatus.getType(), RemoteCardMessageType::IFDStatus); QCOMPARE(ifdStatus.getContextHandle(), QStringLiteral("TestContext")); QCOMPARE(ifdStatus.getSlotName(), QStringLiteral("SlotName")); QVERIFY(ifdStatus.getPaceCapabilities().getPace()); QVERIFY(!ifdStatus.getPaceCapabilities().getEId()); QVERIFY(ifdStatus.getPaceCapabilities().getESign()); QVERIFY(!ifdStatus.getPaceCapabilities().getDestroy()); QCOMPARE(ifdStatus.getMaxApduLength(), 500); QVERIFY(!ifdStatus.getConnectedReader()); QVERIFY(!ifdStatus.getCardAvailable()); QCOMPARE(logSpy.count(), 0); } void msgField_data() { QTest::addColumn("type"); const auto& msgTypes = Enum::getList(); for (const auto& type : msgTypes) { QTest::newRow(getEnumName(type).data()) << type; } } void msgField() { QFETCH(RemoteCardMessageType, type); QSignalSpy logSpy(Env::getSingleton(), &LogHandler::fireLog); QByteArray message("{\n" " \"CardAvailable\": false,\n" " \"ConnectedReader\": false,\n" " \"ContextHandle\": \"TestContext\",\n" " \"EFATR\": null,\n" " \"EFDIR\": null,\n" " \"MaxAPDULength\": 500,\n" " \"PINCapabilities\": {\n" " \"Destroy\": false,\n" " \"PACE\": true,\n" " \"eID\": false,\n" " \"eSign\": true\n" " },\n" " \"SlotName\": \"SlotName\",\n" " \"msg\": \"%1\"\n" "}\n"); const QJsonObject& obj = QJsonDocument::fromJson(message.replace("%1", QTest::currentDataTag())).object(); const IfdStatus ifdStatus(obj); if (type == RemoteCardMessageType::IFDStatus) { QVERIFY(!ifdStatus.isIncomplete()); QCOMPARE(ifdStatus.getType(), RemoteCardMessageType::IFDStatus); QCOMPARE(logSpy.count(), 0); return; } QVERIFY(ifdStatus.isIncomplete()); QCOMPARE(ifdStatus.getType(), type); if (type == RemoteCardMessageType::UNDEFINED) { QCOMPARE(logSpy.count(), 2); QVERIFY(logSpy.at(0).at(0).toString().contains("Invalid messageType received: \"UNDEFINED\"")); QVERIFY(logSpy.at(1).at(0).toString().contains("The value of msg should be IFDStatus")); return; } QCOMPARE(logSpy.count(), 1); QVERIFY(logSpy.at(0).at(0).toString().contains("The value of msg should be IFDStatus")); } void wrongTypes() { QSignalSpy logSpy(Env::getSingleton(), &LogHandler::fireLog); const QByteArray message("{\n" " \"CardAvailable\": 1,\n" " \"ConnectedReader\": 2,\n" " \"ContextHandle\": \"TestContext\",\n" " \"EFATR\": null,\n" " \"EFDIR\": null,\n" " \"MaxAPDULength\": \"3\",\n" " \"PINCapabilities\": 4,\n" " \"SlotName\": 5,\n" " \"msg\": \"IFDStatus\"\n" "}\n"); const QJsonObject& obj = QJsonDocument::fromJson(message).object(); const IfdStatus ifdStatus(obj); QVERIFY(ifdStatus.isIncomplete()); QCOMPARE(ifdStatus.getType(), RemoteCardMessageType::IFDStatus); QCOMPARE(ifdStatus.getContextHandle(), QStringLiteral("TestContext")); QCOMPARE(ifdStatus.getSlotName(), QString()); QVERIFY(!ifdStatus.getPaceCapabilities().getPace()); QVERIFY(!ifdStatus.getPaceCapabilities().getEId()); QVERIFY(!ifdStatus.getPaceCapabilities().getESign()); QVERIFY(!ifdStatus.getPaceCapabilities().getDestroy()); QCOMPARE(ifdStatus.getMaxApduLength(), 0); QVERIFY(!ifdStatus.getConnectedReader()); QVERIFY(!ifdStatus.getCardAvailable()); QCOMPARE(logSpy.count(), 5); QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"SlotName\" should be of type \"string\"")); QVERIFY(logSpy.at(1).at(0).toString().contains("The value of \"PINCapabilities\" should be of type \"object\"")); QVERIFY(logSpy.at(2).at(0).toString().contains("The value of \"MaxAPDULength\" should be of type \"number\"")); QVERIFY(logSpy.at(3).at(0).toString().contains("The value of \"ConnectedReader\" should be of type \"boolean\"")); QVERIFY(logSpy.at(4).at(0).toString().contains("The value of \"CardAvailable\" should be of type \"boolean\"")); } void wrongPINCapabilityTypes() { QSignalSpy logSpy(Env::getSingleton(), &LogHandler::fireLog); const QByteArray message("{\n" " \"CardAvailable\": false,\n" " \"ConnectedReader\": false,\n" " \"ContextHandle\": \"TestContext\",\n" " \"EFATR\": null,\n" " \"EFDIR\": null,\n" " \"MaxAPDULength\": 500,\n" " \"PINCapabilities\": {\n" " \"Destroy\": \"1\",\n" " \"PACE\": \"2\",\n" " \"eID\": \"3\",\n" " \"eSign\": \"4\"\n" " },\n" " \"SlotName\": \"SlotName\",\n" " \"msg\": \"IFDStatus\"\n" "}\n"); const QJsonObject& obj = QJsonDocument::fromJson(message).object(); const IfdStatus ifdStatus(obj); QVERIFY(ifdStatus.isIncomplete()); QCOMPARE(ifdStatus.getType(), RemoteCardMessageType::IFDStatus); QCOMPARE(ifdStatus.getContextHandle(), QStringLiteral("TestContext")); QCOMPARE(ifdStatus.getSlotName(), QStringLiteral("SlotName")); QVERIFY(!ifdStatus.getPaceCapabilities().getPace()); QVERIFY(!ifdStatus.getPaceCapabilities().getEId()); QVERIFY(!ifdStatus.getPaceCapabilities().getESign()); QVERIFY(!ifdStatus.getPaceCapabilities().getDestroy()); QCOMPARE(ifdStatus.getMaxApduLength(), 500); QVERIFY(!ifdStatus.getConnectedReader()); QVERIFY(!ifdStatus.getCardAvailable()); QCOMPARE(logSpy.count(), 4); QVERIFY(logSpy.at(0).at(0).toString().contains("The value of \"PACE\" should be of type \"boolean\"")); QVERIFY(logSpy.at(1).at(0).toString().contains("The value of \"eID\" should be of type \"boolean\"")); QVERIFY(logSpy.at(2).at(0).toString().contains("The value of \"eSign\" should be of type \"boolean\"")); QVERIFY(logSpy.at(3).at(0).toString().contains("The value of \"Destroy\" should be of type \"boolean\"")); } void constructionWithReaderInfo_data() { QTest::addColumn("slotName"); QTest::addColumn("isBasicReader"); QTest::addColumn("maxApduLength"); QTest::addColumn("connected"); QTest::addColumn("cardAvailable"); QTest::addColumn("pinPadMode"); QTest::newRow("Unconnected basic reader") << "BasicReader" << true << 500 << false << false << false; QTest::newRow("Connected basic reader without card") << "SlotName" << true << 500 << true << false << false; QTest::newRow("Connected basic reader with card") << "SlotName" << true << 500 << true << true << false; QTest::newRow("Connected basic reader with card without extended length") << "SlotName" << true << 200 << true << true << false; QTest::newRow("Connected basic reader with card and pin pad mode") << "SlotName" << true << 500 << true << true << true; QTest::newRow("Connected comfort reader with card and enabled pin pad mode") << "SlotName" << false << 500 << true << true << true; QTest::newRow("Connected comfort reader with card and disabled pin pad mode") << "SlotName" << false << 500 << true << true << false; } void constructionWithReaderInfo() { QFETCH(QString, slotName); QFETCH(bool, isBasicReader); QFETCH(int, maxApduLength); QFETCH(bool, connected); QFETCH(bool, cardAvailable); QFETCH(bool, pinPadMode); Env::getSingleton()->getRemoteServiceSettings().setPinPadMode(pinPadMode); const CardInfo cardInfo(cardAvailable ? CardType::EID_CARD : CardType::NONE); ReaderInfo readerInfo(slotName, ReaderManagerPlugInType::UNKNOWN, cardInfo); readerInfo.setBasicReader(isBasicReader); readerInfo.setMaxApduLength(maxApduLength); readerInfo.setConnected(connected); const IfdStatus ifdStatus(readerInfo); QVERIFY(!ifdStatus.isIncomplete()); QCOMPARE(ifdStatus.getType(), RemoteCardMessageType::IFDStatus); QCOMPARE(ifdStatus.getContextHandle(), QString()); QCOMPARE(ifdStatus.getSlotName(), slotName); QCOMPARE(ifdStatus.getPaceCapabilities().getPace(), !isBasicReader || pinPadMode); QVERIFY(!ifdStatus.getPaceCapabilities().getEId()); QVERIFY(!ifdStatus.getPaceCapabilities().getESign()); QVERIFY(!ifdStatus.getPaceCapabilities().getDestroy()); QCOMPARE(ifdStatus.getMaxApduLength(), maxApduLength); QCOMPARE(ifdStatus.getConnectedReader(), connected); QCOMPARE(ifdStatus.getCardAvailable(), cardAvailable); } }; QTEST_GUILESS_MAIN(test_IfdStatus) #include "test_IfdStatus.moc"