File indexing completed on 2024-05-12 05:17:10
0001 /* 0002 SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> 0003 SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include <QTest> 0009 0010 #include "kimap/idlejob.h" 0011 #include "kimap/selectjob.h" 0012 #include "kimap/session.h" 0013 #include "kimaptest/fakeserver.h" 0014 0015 #include <QSignalSpy> 0016 #include <QTest> 0017 0018 Q_DECLARE_METATYPE(QList<int>) 0019 Q_DECLARE_METATYPE(QList<qint64>) 0020 Q_DECLARE_METATYPE(KIMAP::IdleJob *) 0021 0022 class IdleJobTest : public QObject 0023 { 0024 Q_OBJECT 0025 0026 public: 0027 explicit IdleJobTest(QObject *parent = nullptr) 0028 : QObject(parent) 0029 { 0030 qRegisterMetaType<KIMAP::IdleJob *>(); 0031 } 0032 0033 private Q_SLOTS: 0034 void shouldReactToIdle_data() 0035 { 0036 QTest::addColumn<QList<QByteArray>>("scenario"); 0037 QTest::addColumn<QString>("expectedMailBox"); 0038 QTest::addColumn<QList<int>>("expectedMessageCounts"); 0039 QTest::addColumn<QList<int>>("expectedRecentCounts"); 0040 QTest::addColumn<QList<qint64>>("expectedFlagsNotifications"); 0041 0042 QList<QByteArray> scenario; 0043 QString expectedMailBox; 0044 QList<int> expectedMessageCounts; 0045 QList<int> expectedRecentCounts; 0046 QList<qint64> expectedFlagsNotifications; 0047 0048 scenario.clear(); 0049 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX/Foo\"" 0050 << "S: A000001 OK SELECT done" 0051 << "C: A000002 IDLE" 0052 << "S: + OK" 0053 << "S: * 0 RECENT" 0054 << "S: * 1 EXISTS" 0055 << "S: * 1 RECENT" 0056 << "S: * 2 EXISTS" 0057 << "S: A000002 OK done idling"; 0058 0059 expectedMailBox = QStringLiteral("INBOX/Foo"); 0060 0061 expectedMessageCounts.clear(); 0062 expectedRecentCounts.clear(); 0063 0064 expectedMessageCounts << 1 << 2; 0065 expectedRecentCounts << 0 << 1; 0066 0067 QTest::newRow("normal") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications; 0068 0069 scenario.clear(); 0070 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX/Foo\"" 0071 << "S: A000001 OK SELECT done" 0072 << "C: A000002 IDLE" 0073 << "S: + OK" 0074 << "S: * 0 RECENT" 0075 << "S: * 1 RECENT" 0076 << "S: A000002 OK done idling"; 0077 0078 expectedMailBox = QStringLiteral("INBOX/Foo"); 0079 0080 expectedMessageCounts.clear(); 0081 expectedRecentCounts.clear(); 0082 0083 expectedMessageCounts << -1 << -1; 0084 expectedRecentCounts << 0 << 1; 0085 0086 QTest::newRow("only RECENT") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications; 0087 0088 scenario.clear(); 0089 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX/Foo\"" 0090 << "S: A000001 OK SELECT done" 0091 << "C: A000002 IDLE" 0092 << "S: + OK" 0093 << "S: * 1 EXISTS" 0094 << "S: * 2 EXISTS" 0095 << "S: A000002 OK done idling"; 0096 0097 expectedMailBox = QStringLiteral("INBOX/Foo"); 0098 0099 expectedMessageCounts.clear(); 0100 expectedRecentCounts.clear(); 0101 0102 expectedMessageCounts << 1 << 2; 0103 expectedRecentCounts << -1 << -1; 0104 0105 QTest::newRow("only EXISTS") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications; 0106 0107 scenario.clear(); 0108 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX/Foo\"" 0109 << "S: A000001 OK SELECT done" 0110 << "C: A000002 IDLE" 0111 << "S: + OK" 0112 << "S: * 2 EXISTS" 0113 << "W: 150" 0114 << "S: * 1 RECENT" 0115 << "S: A000002 OK done idling"; 0116 0117 expectedMailBox = QStringLiteral("INBOX/Foo"); 0118 0119 expectedMessageCounts.clear(); 0120 expectedRecentCounts.clear(); 0121 0122 expectedMessageCounts << 2; 0123 expectedRecentCounts << 1; 0124 0125 QTest::newRow("under 200ms, same notification") 0126 << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications; 0127 0128 scenario.clear(); 0129 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX/Foo\"" 0130 << "S: A000001 OK SELECT done" 0131 << "C: A000002 IDLE" 0132 << "S: + OK" 0133 << "S: * 2 EXISTS" 0134 << "W: 250" 0135 << "S: * 1 RECENT" 0136 << "S: A000002 OK done idling"; 0137 0138 expectedMailBox = QStringLiteral("INBOX/Foo"); 0139 0140 expectedMessageCounts.clear(); 0141 expectedRecentCounts.clear(); 0142 0143 expectedMessageCounts << 2 << -1; 0144 expectedRecentCounts << -1 << 1; 0145 0146 QTest::newRow("above 200ms, two notifications") 0147 << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications; 0148 0149 scenario.clear(); 0150 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX/Foo\"" 0151 << "S: A000001 OK SELECT done" 0152 << "C: A000002 IDLE" 0153 << "S: + OK" 0154 << "S: * 1 FETCH (FLAGS ())" 0155 << "W: 200" 0156 << "S: * 2 FETCH (FLAGS (\\Seen))" 0157 << "S: A000002 OK done idling"; 0158 0159 expectedMailBox = QStringLiteral("INBOX/Foo"); 0160 0161 expectedMessageCounts.clear(); 0162 expectedRecentCounts.clear(); 0163 expectedFlagsNotifications << 1 << 2; 0164 0165 QTest::newRow("2 flags change notifications") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts 0166 << expectedFlagsNotifications; 0167 } 0168 0169 void shouldReactToIdle() 0170 { 0171 QFETCH(QList<QByteArray>, scenario); 0172 QFETCH(QString, expectedMailBox); 0173 QFETCH(QList<int>, expectedMessageCounts); 0174 QFETCH(QList<int>, expectedRecentCounts); 0175 QFETCH(QList<qint64>, expectedFlagsNotifications); 0176 0177 QVERIFY(expectedMessageCounts.size() == expectedRecentCounts.size()); 0178 0179 FakeServer fakeServer; 0180 fakeServer.setScenario(scenario); 0181 fakeServer.startAndWait(); 0182 0183 KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); 0184 0185 auto select = new KIMAP::SelectJob(&session); 0186 select->setMailBox(expectedMailBox); 0187 QVERIFY(select->exec()); 0188 0189 auto idle = new KIMAP::IdleJob(&session); 0190 0191 QSignalSpy statsSpy(idle, &KIMAP::IdleJob::mailBoxStats); 0192 QSignalSpy flagsSpy(idle, &KIMAP::IdleJob::mailBoxMessageFlagsChanged); 0193 0194 bool result = idle->exec(); 0195 0196 if (result) { 0197 QCOMPARE(statsSpy.count(), expectedMessageCounts.size()); 0198 QCOMPARE(flagsSpy.count(), expectedFlagsNotifications.size()); 0199 0200 for (int i = 0; i < statsSpy.count(); i++) { 0201 const KIMAP::IdleJob *job = statsSpy.at(i).at(0).value<KIMAP::IdleJob *>(); 0202 const QString mailBox = statsSpy.at(i).at(1).toString(); 0203 const int messageCount = statsSpy.at(i).at(2).toInt(); 0204 const int recentCount = statsSpy.at(i).at(3).toInt(); 0205 0206 QCOMPARE(job, idle); 0207 QCOMPARE(mailBox, expectedMailBox); 0208 QCOMPARE(messageCount, expectedMessageCounts.at(i)); 0209 QCOMPARE(recentCount, expectedRecentCounts.at(i)); 0210 } 0211 0212 for (int i = 0; i < flagsSpy.count(); i++) { 0213 const KIMAP::IdleJob *job = flagsSpy.at(i).at(0).value<KIMAP::IdleJob *>(); 0214 const qint64 uid = flagsSpy.at(i).at(1).toLongLong(); 0215 0216 QCOMPARE(job, idle); 0217 QCOMPARE(uid, expectedFlagsNotifications.at(i)); 0218 } 0219 } 0220 0221 fakeServer.quit(); 0222 } 0223 0224 void shouldResetTimeout_data() 0225 { 0226 QTest::addColumn<QList<QByteArray>>("scenario"); 0227 { 0228 QList<QByteArray> scenario; 0229 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" 0230 << "S: A000001 OK SELECT done" 0231 << "C: A000002 IDLE" 0232 << "S: + OK" 0233 << "S: A000002 OK done idling"; 0234 0235 QTest::newRow("good") << scenario; 0236 } 0237 0238 { 0239 QList<QByteArray> scenario; 0240 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" 0241 << "S: A000001 OK SELECT done" 0242 << "C: A000002 IDLE" 0243 << "S: + OK" 0244 << "X"; 0245 0246 QTest::newRow("bad") << scenario; 0247 } 0248 } 0249 0250 void shouldResetTimeout() 0251 { 0252 QFETCH(QList<QByteArray>, scenario); 0253 0254 FakeServer fakeServer; 0255 fakeServer.setScenario(scenario); 0256 fakeServer.startAndWait(); 0257 0258 KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); 0259 const int originalTimeout = session.timeout(); 0260 0261 auto select = new KIMAP::SelectJob(&session); 0262 select->setMailBox(QStringLiteral("INBOX")); 0263 QVERIFY(select->exec()); 0264 0265 auto idle = new KIMAP::IdleJob(&session); 0266 idle->exec(); 0267 0268 QCOMPARE(session.timeout(), originalTimeout); 0269 0270 fakeServer.quit(); 0271 } 0272 }; 0273 0274 QTEST_GUILESS_MAIN(IdleJobTest) 0275 0276 #include "idlejobtest.moc"