1 /*!
2  * \brief Unit tests for \ref Apdu
3  *
4  * \copyright Copyright (c) 2017-2021 Governikus GmbH & Co. KG, Germany
5  */
6 
7 #include "ResponseApdu.h"
8 
9 #include "LogHandler.h"
10 
11 #include <QtCore>
12 #include <QtTest>
13 
14 
15 using namespace governikus;
16 
17 
18 class test_ResponceApdu
19 	: public QObject
20 {
21 	Q_OBJECT
22 
23 	private Q_SLOTS:
initTestCase()24 		void initTestCase()
25 		{
26 			Env::getSingleton<LogHandler>()->init();
27 		}
28 
29 
cleanup()30 		void cleanup()
31 		{
32 			Env::getSingleton<LogHandler>()->resetBacklog();
33 		}
34 
35 
testRetryCounter_data()36 		void testRetryCounter_data()
37 		{
38 			QTest::addColumn<QByteArray>("apdu");
39 			QTest::addColumn<int>("retryCounter");
40 
41 			QTest::newRow("9000") << QByteArray::fromHex("9000") << 3;
42 			QTest::newRow("63c2") << QByteArray::fromHex("63c2") << 2;
43 			QTest::newRow("63c1") << QByteArray::fromHex("63c1") << 1;
44 			QTest::newRow("63c0") << QByteArray::fromHex("63c0") << 0;
45 			QTest::newRow("63c3") << QByteArray::fromHex("63c3") << -1;
46 			QTest::newRow("6400") << QByteArray::fromHex("6400") << -1;
47 			QTest::newRow("1234") << QByteArray::fromHex("1234") << -1;
48 			QTest::newRow("12") << QByteArray::fromHex("12") << -1;
49 			QTest::newRow("6283") << QByteArray::fromHex("6283") << 0;
50 			QTest::newRow("empty") << QByteArray() << -1;
51 		}
52 
53 
testRetryCounter()54 		void testRetryCounter()
55 		{
56 			QFETCH(QByteArray, apdu);
57 			QFETCH(int, retryCounter);
58 
59 			QCOMPARE(ResponseApdu(apdu).getRetryCounter(), retryCounter);
60 		}
61 
62 
testReturnCode_data()63 		void testReturnCode_data()
64 		{
65 			QTest::addColumn<StatusCode>("statusCode");
66 			QTest::addColumn<QByteArray>("bufferIn");
67 			QTest::addColumn<QByteArray>("bufferOut");
68 
69 			QTest::newRow("empty") << StatusCode::EMPTY << QByteArray() << QByteArray::fromHex("0000");
70 			QTest::newRow("01") << StatusCode::INVALID << QByteArray::fromHex("01") << QByteArray::fromHex("0001");
71 			QTest::newRow("63c2") << StatusCode::PIN_RETRY_COUNT_2 << QByteArray::fromHex("63c2") << QByteArray::fromHex("63c2");
72 			QTest::newRow("6401") << StatusCode::INPUT_CANCELLED << QByteArray::fromHex("6401") << QByteArray::fromHex("6401");
73 			QTest::newRow("73c2") << StatusCode::INVALID << QByteArray::fromHex("73c2") << QByteArray::fromHex("0001");
74 		}
75 
76 
testReturnCode()77 		void testReturnCode()
78 		{
79 			QFETCH(StatusCode, statusCode);
80 			QFETCH(QByteArray, bufferIn);
81 			QFETCH(QByteArray, bufferOut);
82 
83 			ResponseApdu apdu = ResponseApdu(statusCode);
84 			QCOMPARE(apdu.getReturnCode(), statusCode);
85 			QCOMPARE(apdu.getBuffer(), bufferOut);
86 
87 			apdu = ResponseApdu(bufferIn);
88 			QCOMPARE(apdu.getReturnCode(), statusCode);
89 			QCOMPARE(apdu.getBuffer(), bufferIn);
90 		}
91 
92 
testCardReturnCode_data()93 		void testCardReturnCode_data()
94 		{
95 			QTest::addColumn<CardReturnCode>("cardReturnCode");
96 			QTest::addColumn<StatusCode>("statCode");
97 
98 			QTest::newRow("SUCCESS") << CardReturnCode::OK << StatusCode::SUCCESS;
99 			QTest::newRow("INPUT_TIMEOUT") << CardReturnCode::INPUT_TIME_OUT << StatusCode::INPUT_TIMEOUT;
100 			QTest::newRow("INPUT_CANCELLED") << CardReturnCode::CANCELLATION_BY_USER << StatusCode::INPUT_CANCELLED;
101 			QTest::newRow("PASSWORDS_DIFFER") << CardReturnCode::NEW_PIN_MISMATCH << StatusCode::PASSWORDS_DIFFER;
102 			QTest::newRow("PASSWORD_OUTOF_RANGE") << CardReturnCode::NEW_PIN_INVALID_LENGTH << StatusCode::PASSWORD_OUTOF_RANGE;
103 			QTest::newRow("PIN_BLOCKED") << CardReturnCode::PIN_BLOCKED << StatusCode::PIN_BLOCKED;
104 			QTest::newRow("default") << CardReturnCode::PROTOCOL_ERROR << StatusCode::NOT_YET_INITIALIZED;
105 		}
106 
107 
testCardReturnCode()108 		void testCardReturnCode()
109 		{
110 			QFETCH(CardReturnCode, cardReturnCode);
111 			QFETCH(StatusCode, statCode);
112 
113 			ResponseApdu apdu = ResponseApdu(statCode);
114 			QCOMPARE(apdu.getCardReturnCode(), cardReturnCode);
115 		}
116 
117 
test_getSW2()118 		void test_getSW2()
119 		{
120 			ResponseApdu apdu1 = ResponseApdu(QByteArray());
121 			ResponseApdu apdu2 = ResponseApdu(QByteArray("a"));
122 			ResponseApdu apdu3 = ResponseApdu(QByteArray("date"));
123 			QSignalSpy logSpy(Env::getSingleton<LogHandler>()->getEventHandler(), &LogEventHandler::fireLog);
124 
125 			QCOMPARE(apdu1.getSW2(), '\0');
126 			QCOMPARE(apdu2.getSW2(), 'a');
127 			QCOMPARE(apdu3.getSW2(), 'e');
128 			QCOMPARE(logSpy.count(), 1);
129 			QVERIFY(logSpy.at(0).at(0).toString().contains("Buffer too short, returning 0"));
130 		}
131 
132 
testGetSW1_data()133 		void testGetSW1_data()
134 		{
135 			QTest::addColumn<SW1>("sw1");
136 			QTest::addColumn<QByteArray>("buffer");
137 			QTest::addColumn<QString>("warning");
138 
139 			QTest::newRow("empty") << SW1::INVALID << QByteArray() << QString("Buffer too short, returning 0");
140 			QTest::newRow("0000") << SW1::INVALID << QByteArray::fromHex("0000") << QString();
141 			QTest::newRow("6100") << SW1::MORE_DATA_AVAILABLE << QByteArray::fromHex("6100") << QString();
142 			QTest::newRow("6900") << SW1::ERROR_COMMAND_NOT_ALLOWED << QByteArray::fromHex("6900") << QString();
143 			QTest::newRow("6c00") << SW1::WRONG_LE_FIELD << QByteArray::fromHex("6c00") << QString();
144 			QTest::newRow("invalid") << SW1::INVALID << QByteArray::fromHex("3300") << QString("Unknown SW1 value, returning INVALID, value: \"33\"");
145 		}
146 
147 
testGetSW1()148 		void testGetSW1()
149 		{
150 			QFETCH(SW1, sw1);
151 			QFETCH(QByteArray, buffer);
152 			QFETCH(QString, warning);
153 			QSignalSpy logSpy(Env::getSingleton<LogHandler>()->getEventHandler(), &LogEventHandler::fireLog);
154 
155 			ResponseApdu apdu = ResponseApdu(buffer);
156 			QCOMPARE(apdu.getSW1(), sw1);
157 			if (!warning.isEmpty())
158 			{
159 				QCOMPARE(logSpy.count(), 1);
160 				QVERIFY(logSpy.takeFirst().at(0).toString().contains(warning));
161 			}
162 		}
163 
164 
165 };
166 
167 
168 QTEST_GUILESS_MAIN(test_ResponceApdu)
169 #include "test_ResponseApdu.moc"
170