File indexing completed on 2024-05-12 05:17:11
0001 /* 0002 SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> 0003 0004 SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> 0005 SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include <QTest> 0011 0012 #include "kimap/loginjob.h" 0013 #include "kimap/selectjob.h" 0014 #include "kimap/session.h" 0015 #include "kimaptest/fakeserver.h" 0016 0017 #include <QSignalSpy> 0018 #include <QTest> 0019 0020 using Messages = QMap<qint64, KIMAP::Message>; 0021 0022 Q_DECLARE_METATYPE(KIMAP::Message) 0023 Q_DECLARE_METATYPE(Messages) 0024 0025 class SelectJobTest : public QObject 0026 { 0027 Q_OBJECT 0028 0029 public: 0030 explicit SelectJobTest() 0031 { 0032 qRegisterMetaType<KIMAP::ImapSet>(); 0033 qRegisterMetaType<KIMAP::Message>(); 0034 qRegisterMetaType<QMap<qint64, KIMAP::Message>>("QMap<qint64,KIMAP::Message>"); 0035 } 0036 0037 private Q_SLOTS: 0038 0039 void testSingleSelect_data() 0040 { 0041 QTest::addColumn<QList<QByteArray>>("scenario"); 0042 QTest::addColumn<QList<QByteArray>>("flags"); 0043 QTest::addColumn<QList<QByteArray>>("permanentflags"); 0044 QTest::addColumn<int>("messagecount"); 0045 QTest::addColumn<int>("recentcount"); 0046 QTest::addColumn<int>("firstUnseenIndex"); 0047 QTest::addColumn<qint64>("uidValidity"); 0048 QTest::addColumn<qint64>("nextUid"); 0049 QTest::addColumn<quint64>("highestmodseq"); 0050 QTest::addColumn<bool>("condstoreEnabled"); 0051 QTest::addColumn<bool>("readonly"); 0052 QTest::addColumn<qint64>("lastUidvalidity"); 0053 QTest::addColumn<quint64>("lastModseq"); 0054 QTest::addColumn<KIMAP::ImapSet>("vanished"); 0055 QTest::addColumn<Messages>("modified"); 0056 0057 QList<QByteArray> scenario; 0058 QList<QByteArray> flags; 0059 QList<QByteArray> permanentflags; 0060 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\" (CONDSTORE)" 0061 << "S: * 172 EXISTS" 0062 << "S: * 1 RECENT" 0063 << "S: * OK [UNSEEN 12] Message 12 is first unseen" 0064 << "S: * OK [UIDVALIDITY 3857529045] UIDs valid" 0065 << "S: * OK [UIDNEXT 4392] Predicted next UID" 0066 << "S: * OK [HIGHESTMODSEQ 123456789]" 0067 << R"(S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft))" 0068 << R"(S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited)" 0069 << "S: A000001 OK [READ-WRITE] SELECT completed"; 0070 0071 flags << "\\Answered" 0072 << "\\Flagged" 0073 << "\\Deleted" 0074 << "\\Seen" 0075 << "\\Draft"; 0076 permanentflags << "\\Deleted" 0077 << "\\Seen" 0078 << "\\*"; 0079 QTest::newRow("good") << scenario << flags << permanentflags << 172 << 1 << 12 << 3857529045LL << 4392LL << 123456789ULL << true << false << -1LL 0080 << 0ULL << KIMAP::ImapSet{} << Messages{}; 0081 0082 scenario.clear(); 0083 flags.clear(); 0084 permanentflags.clear(); 0085 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" 0086 << "S: A000001 BAD command unknown or arguments invalid"; 0087 QTest::newRow("bad") << scenario << flags << permanentflags << 0 << 0 << 0 << 0LL << 0LL << 0ULL << false << false << -1LL << 0ULL << KIMAP::ImapSet{} 0088 << Messages{}; 0089 0090 scenario.clear(); 0091 flags.clear(); 0092 permanentflags.clear(); 0093 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" 0094 << "S: A000001 NO select failure"; 0095 QTest::newRow("no") << scenario << flags << permanentflags << 0 << 0 << 0 << 0LL << 0LL << 0ULL << false << false << -1LL << 0ULL << KIMAP::ImapSet{} 0096 << Messages{}; 0097 0098 scenario.clear(); 0099 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\" (QRESYNC (67890007 90060115194045000))" 0100 << "S: * 314 EXISTS" 0101 << "S: * 15 RECENT" 0102 << "S: * OK [UIDVALIDITY 67890007] UIDVALIDITY" 0103 << "S: * OK [UIDNEXT 567] Predicted next UID" 0104 << "S: * OK [HIGHESTMODSEQ 90060115205545359]" 0105 << "S: * OK [UNSEEN 7] There are some unseen messages in the mailbox" 0106 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0107 << R"(S: * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen \*)] Permanent flags)" 0108 << "S: * VANISHED (EARLIER) 41,43:116,118,120:211,214:540" 0109 << "S: * 49 FETCH (UID 117 FLAGS (\\Seen \\Answered) MODSEQ (90060115194045001))" 0110 << "S: * 50 FETCH (UID 119 FLAGS (\\Draft $MDNSent) MODSEQ (90060115194045308))" 0111 << "S: * 100 FETCH (UID 541 FLAGS (\\Seen $Forwarded) MODSEQ (90060115194045001))" 0112 << "S: A000001 OK [READ-WRITE] mailbox selected"; 0113 permanentflags = {"\\Answered", "\\Flagged", "\\Draft", "\\Deleted", "\\Seen", "\\*"}; 0114 flags = {"\\Answered", "\\Flagged", "\\Draft", "\\Deleted", "\\Seen"}; 0115 KIMAP::ImapSet vanished; 0116 vanished.add(41); 0117 vanished.add(KIMAP::ImapInterval{43, 116}); 0118 vanished.add(118); 0119 vanished.add(KIMAP::ImapInterval{120, 211}); 0120 vanished.add(KIMAP::ImapInterval{214, 540}); 0121 Messages modified = {{49, KIMAP::Message{117, 0, {"\\Seen", "\\Answered"}, {{"MODSEQ", QVariant{90060115194045001ULL}}}, {}, {}}}, 0122 {50, KIMAP::Message{119, 0, {"\\Draft", "$MDNSent"}, {{"MODSEQ", QVariant{90060115194045308ULL}}}, {}, {}}}, 0123 {100, KIMAP::Message{541, 0, {"\\Seen", "$Forwarded"}, {{"MODSEQ", QVariant{90060115194045001ULL}}}, {}, {}}}}; 0124 QTest::newRow("QResync") << scenario << flags << permanentflags << 314 << 15 << 7 << 67890007LL << 567LL << 90060115205545359ULL << false << false 0125 << 67890007LL << 90060115194045000ULL << vanished << modified; 0126 } 0127 0128 void testSingleSelect() 0129 { 0130 QFETCH(QList<QByteArray>, scenario); 0131 QFETCH(QList<QByteArray>, flags); 0132 QFETCH(QList<QByteArray>, permanentflags); 0133 QFETCH(int, messagecount); 0134 QFETCH(int, recentcount); 0135 QFETCH(int, firstUnseenIndex); 0136 QFETCH(qint64, uidValidity); 0137 QFETCH(qint64, nextUid); 0138 QFETCH(quint64, highestmodseq); 0139 QFETCH(bool, condstoreEnabled); 0140 QFETCH(qint64, lastUidvalidity); 0141 QFETCH(quint64, lastModseq); 0142 QFETCH(KIMAP::ImapSet, vanished); 0143 QFETCH(Messages, modified); 0144 0145 FakeServer fakeServer; 0146 fakeServer.setScenario(scenario); 0147 fakeServer.startAndWait(); 0148 0149 KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); 0150 0151 auto job = new KIMAP::SelectJob(&session); 0152 job->setCondstoreEnabled(condstoreEnabled); 0153 job->setMailBox(QStringLiteral("INBOX")); 0154 if (lastUidvalidity > -1 && lastModseq > 0) { 0155 job->setQResync(lastUidvalidity, lastModseq); 0156 } 0157 0158 QSignalSpy vanishedSpy(job, &KIMAP::SelectJob::vanished); 0159 QVERIFY(vanishedSpy.isValid()); 0160 0161 QSignalSpy modifiedSpy(job, &KIMAP::SelectJob::modified); 0162 QVERIFY(modifiedSpy.isValid()); 0163 0164 bool result = job->exec(); 0165 QEXPECT_FAIL("bad", "Expected failure on BAD scenario", Continue); 0166 QEXPECT_FAIL("no", "Expected failure on NO scenario", Continue); 0167 QVERIFY(result); 0168 if (result) { 0169 QCOMPARE(job->flags(), flags); 0170 QCOMPARE(job->permanentFlags(), permanentflags); 0171 QCOMPARE(job->messageCount(), messagecount); 0172 QCOMPARE(job->recentCount(), recentcount); 0173 QCOMPARE(job->firstUnseenIndex(), firstUnseenIndex); 0174 QCOMPARE(job->uidValidity(), uidValidity); 0175 QCOMPARE(job->nextUid(), nextUid); 0176 QCOMPARE(job->highestModSequence(), highestmodseq); 0177 0178 if (!vanished.isEmpty()) { 0179 QCOMPARE(vanishedSpy.size(), 1); 0180 QCOMPARE(vanishedSpy.at(0).at(0).value<KIMAP::ImapSet>(), vanished); 0181 } 0182 0183 if (!modified.isEmpty()) { 0184 Messages collectedModified; 0185 for (const auto &modifiedSpyCatch : modifiedSpy) { 0186 const auto msgs = modifiedSpyCatch.at(0).value<Messages>(); 0187 for (auto it = msgs.begin(); it != msgs.end(); ++it) { 0188 collectedModified.insert(it.key(), it.value()); 0189 } 0190 } 0191 0192 QCOMPARE(collectedModified, modified); 0193 } 0194 } 0195 0196 fakeServer.quit(); 0197 } 0198 0199 void testSeveralSelect() 0200 { 0201 FakeServer fakeServer; 0202 fakeServer.setScenario(QList<QByteArray>() << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" 0203 << "S: A000001 OK [READ-WRITE] SELECT completed" 0204 << "C: A000002 SELECT \"INBOX/Foo\"" 0205 << "S: A000002 OK [READ-WRITE] SELECT completed"); 0206 fakeServer.startAndWait(); 0207 0208 KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); 0209 0210 auto job = new KIMAP::SelectJob(&session); 0211 job->setMailBox(QStringLiteral("INBOX")); 0212 QVERIFY(job->exec()); 0213 0214 job = new KIMAP::SelectJob(&session); 0215 job->setMailBox(QStringLiteral("INBOX/Foo")); 0216 QVERIFY(job->exec()); 0217 } 0218 0219 void testReadOnlySelect_data() 0220 { 0221 QTest::addColumn<QList<QByteArray>>("scenario"); 0222 QTest::addColumn<bool>("examine"); 0223 QTest::addColumn<bool>("isReadOnly"); 0224 0225 { 0226 QList<QByteArray> scenario; 0227 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" 0228 << "S: A000001 OK [READ-WRITE] SELECT ok"; 0229 QTest::newRow("SELECT rw") << scenario << false << false; 0230 } 0231 0232 { 0233 QList<QByteArray> scenario; 0234 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" 0235 << "S: A000001 OK SELECT ok"; 0236 QTest::newRow("SELECT rw (without code)") << scenario << false << false; 0237 } 0238 0239 { 0240 QList<QByteArray> scenario; 0241 scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" 0242 << "S: A000001 OK [READ-ONLY] SELECT ok"; 0243 QTest::newRow("SELECT ro") << scenario << false << true; 0244 } 0245 0246 { 0247 QList<QByteArray> scenario; 0248 scenario << FakeServer::preauth() << "C: A000001 EXAMINE \"INBOX\"" 0249 << "S: A000001 OK [READ-ONLY] EXAMINE ok"; 0250 QTest::newRow("EXAMINE ro") << scenario << true << true; 0251 } 0252 } 0253 0254 void testReadOnlySelect() 0255 { 0256 QFETCH(QList<QByteArray>, scenario); 0257 QFETCH(bool, examine); 0258 QFETCH(bool, isReadOnly); 0259 0260 FakeServer fakeServer; 0261 fakeServer.setScenario(scenario); 0262 fakeServer.startAndWait(); 0263 0264 KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); 0265 0266 KIMAP::SelectJob select(&session); 0267 select.setOpenReadOnly(examine); 0268 select.setMailBox(QStringLiteral("INBOX")); 0269 QVERIFY(select.exec()); 0270 0271 QCOMPARE(select.isOpenReadOnly(), isReadOnly); 0272 } 0273 }; 0274 0275 QTEST_GUILESS_MAIN(SelectJobTest) 0276 0277 #include "selectjobtest.moc"