File indexing completed on 2024-11-24 04:44:01
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 "imaptestbase.h" 0009 0010 #include "highestmodseqattribute.h" 0011 #include "retrieveitemstask.h" 0012 #include "uidnextattribute.h" 0013 #include "uidvalidityattribute.h" 0014 0015 #include <Akonadi/MessageParts> 0016 0017 #include <Akonadi/CachePolicy> 0018 #include <Akonadi/CollectionStatistics> 0019 0020 #include <QTest> 0021 0022 class TestRetrieveItemsTask : public ImapTestBase 0023 { 0024 Q_OBJECT 0025 0026 private Q_SLOTS: 0027 void shouldIntrospectCollection_data() 0028 { 0029 QTest::addColumn<Akonadi::Collection>("collection"); 0030 QTest::addColumn<QList<QByteArray>>("scenario"); 0031 QTest::addColumn<QStringList>("callNames"); 0032 0033 Akonadi::Collection collection; 0034 QList<QByteArray> scenario; 0035 QStringList callNames; 0036 0037 collection = createCollectionChain(QStringLiteral("/INBOX/Foo")); 0038 collection.attribute<UidValidityAttribute>(Akonadi::Collection::AddIfMissing)->setUidValidity(1149151135); 0039 0040 scenario.clear(); 0041 scenario << defaultPoolConnectionScenario() << "C: A000003 SELECT \"INBOX/Foo\"" 0042 << "S: A000003 OK select done" 0043 << "C: A000004 EXPUNGE" 0044 << "S: A000004 OK expunge done" 0045 << "C: A000005 SELECT \"INBOX/Foo\"" 0046 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0047 << R"(S: * OK [ PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen) ])" 0048 << "S: * 1 EXISTS" 0049 << "S: * 0 RECENT" 0050 << "S: * OK [ UIDVALIDITY 1149151135 ]" 0051 << "S: * OK [ UIDNEXT 9 ]" 0052 << "S: A000005 OK select done" 0053 << "C: A000006 UID SEARCH UID 1:9" 0054 << "S: * SEARCH 1 2 3 4 5 6 7 8 9" 0055 << "S: A000006 OK search done" 0056 << "C: A000007 UID FETCH 1:9 (RFC822.SIZE INTERNALDATE " 0057 "BODY.PEEK[HEADER] " 0058 "FLAGS UID)" 0059 << "S: * 1 FETCH ( FLAGS (\\Seen) UID 7 INTERNALDATE \"29-Jun-2010 15:26:42 +0200\" " 0060 "RFC822.SIZE 75 BODY[HEADER] {69}\r\n" 0061 "From: Foo <foo@kde.org>\r\n" 0062 "To: Bar <bar@kde.org>\r\n" 0063 "Subject: Test Mail\r\n" 0064 "\r\n" 0065 " )" 0066 << "S: A000007 OK fetch done"; 0067 0068 callNames.clear(); 0069 callNames << QStringLiteral("itemsRetrieved") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievalDone"); 0070 0071 QTest::newRow("first listing, connected IMAP") << collection << scenario << callNames; 0072 0073 scenario.clear(); 0074 scenario << defaultPoolConnectionScenario() << "C: A000003 SELECT \"INBOX/Foo\"" 0075 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0076 << R"(S: * OK [ PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen) ])" 0077 << "S: * 1 EXISTS" 0078 << "S: * 0 RECENT" 0079 << "S: * OK [ UIDVALIDITY 1149151135 ]" 0080 << "S: * OK [ UIDNEXT 9 ]" 0081 << "S: A000003 OK [READ-ONLY] select done" 0082 << "C: A000004 UID SEARCH UID 1:9" 0083 << "S: * SEARCH 1 2 3 4 5 6 7 8 9" 0084 << "S: A000004 OK search done" 0085 << "C: A000005 UID FETCH 1:9 (RFC822.SIZE INTERNALDATE " 0086 "BODY.PEEK[HEADER] " 0087 "FLAGS UID)" 0088 << "S: * 1 FETCH ( FLAGS (\\Seen) UID 7 INTERNALDATE \"29-Jun-2010 15:26:42 +0200\" " 0089 "RFC822.SIZE 75 BODY[HEADER] {69}\r\n" 0090 "From: Foo <foo@kde.org>\r\n" 0091 "To: Bar <bar@kde.org>\r\n" 0092 "Subject: Test Mail\r\n" 0093 "\r\n" 0094 " )" 0095 << "S: A000005 OK fetch done"; 0096 callNames.clear(); 0097 callNames << QStringLiteral("itemsRetrieved") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievalDone"); 0098 0099 QTest::newRow("retrieval from read-only mailbox (no expunge)") << collection << scenario << callNames; 0100 0101 Akonadi::CachePolicy policy; 0102 policy.setLocalParts(QStringList() << QLatin1StringView(Akonadi::MessagePart::Envelope) << QLatin1StringView(Akonadi::MessagePart::Header) 0103 << QLatin1StringView(Akonadi::MessagePart::Body)); 0104 0105 collection = createCollectionChain(QStringLiteral("/INBOX/Foo")); 0106 collection.attribute<UidValidityAttribute>(Akonadi::Collection::AddIfMissing)->setUidValidity(1149151135); 0107 collection.setCachePolicy(policy); 0108 0109 scenario.clear(); 0110 scenario << defaultPoolConnectionScenario() << "C: A000003 SELECT \"INBOX/Foo\"" 0111 << "S: A000003 OK select done" 0112 << "C: A000004 EXPUNGE" 0113 << "S: A000004 OK expunge done" 0114 << "C: A000005 SELECT \"INBOX/Foo\"" 0115 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0116 << R"(S: * OK [ PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen) ])" 0117 << "S: * 1 EXISTS" 0118 << "S: * 0 RECENT" 0119 << "S: * OK [ UIDVALIDITY 1149151135 ]" 0120 << "S: * OK [ UIDNEXT 9 ]" 0121 << "S: A000005 OK select done" 0122 << "C: A000006 UID SEARCH UID 1:9" 0123 << "S: * SEARCH 1 2 3 4 5 6 7 8 9" 0124 << "S: A000006 OK search done" 0125 << "C: A000007 UID FETCH 1:9 (RFC822.SIZE INTERNALDATE BODY.PEEK[] FLAGS UID)" 0126 << "S: * 1 FETCH ( FLAGS (\\Seen) UID 7 INTERNALDATE \"29-Jun-2010 15:26:42 +0200\" " 0127 "RFC822.SIZE 75 BODY[] {75}\r\n" 0128 "From: Foo <foo@kde.org>\r\n" 0129 "To: Bar <bar@kde.org>\r\n" 0130 "Subject: Test Mail\r\n" 0131 "\r\n" 0132 "Test\r\n" 0133 " )" 0134 << "S: A000007 OK fetch done"; 0135 0136 callNames.clear(); 0137 callNames << QStringLiteral("itemsRetrieved") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievalDone"); 0138 0139 QTest::newRow("first listing, disconnected IMAP") << collection << scenario << callNames; 0140 0141 Akonadi::CollectionStatistics stats; 0142 stats.setCount(1); 0143 0144 collection = createCollectionChain(QStringLiteral("/INBOX/Foo")); 0145 collection.attribute<UidValidityAttribute>(Akonadi::Collection::AddIfMissing)->setUidValidity(1149151135); 0146 collection.attribute<UidNextAttribute>(Akonadi::Collection::AddIfMissing)->setUidNext(9); 0147 collection.setCachePolicy(policy); 0148 collection.setStatistics(stats); 0149 0150 scenario.clear(); 0151 scenario << defaultPoolConnectionScenario() << "C: A000003 SELECT \"INBOX/Foo\"" 0152 << "S: A000003 OK select done" 0153 << "C: A000004 EXPUNGE" 0154 << "S: A000004 OK expunge done" 0155 << "C: A000005 SELECT \"INBOX/Foo\"" 0156 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0157 << R"(S: * OK [ PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen) ])" 0158 << "S: * 1 EXISTS" 0159 << "S: * 0 RECENT" 0160 << "S: * OK [ UIDVALIDITY 1149151135 ]" 0161 << "S: * OK [ UIDNEXT 9 ]" 0162 << "S: A000005 OK select done" 0163 << "C: A000006 UID SEARCH UID 1:9" 0164 << "S: * SEARCH 1 2 3 4 5 6 7 8 9" 0165 << "S: A000006 OK search done" 0166 << "C: A000007 UID FETCH 1:9 (FLAGS UID)" 0167 << "S: * 1 FETCH ( FLAGS (\\Seen) UID 7 )" 0168 << "S: A000007 OK fetch done"; 0169 0170 callNames.clear(); 0171 callNames << QStringLiteral("itemsRetrievedIncremental") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievedIncremental") 0172 << QStringLiteral("itemsRetrievalDone"); 0173 0174 // Disabled test since the flag sync is disabled if CONDSTORE is not supported 0175 // QTest::newRow( "second listing, checking for flag changes" ) << collection << scenario << callNames; 0176 0177 collection = createCollectionChain(QStringLiteral("/INBOX/Foo")); 0178 collection.attribute<UidValidityAttribute>(Akonadi::Collection::AddIfMissing)->setUidValidity(1149151135); 0179 collection.setCachePolicy(policy); 0180 stats.setCount(1); 0181 collection.setStatistics(stats); 0182 scenario.clear(); 0183 scenario << defaultPoolConnectionScenario() << "C: A000003 SELECT \"INBOX/Foo\"" 0184 << "S: A000003 OK select done" 0185 << "C: A000004 EXPUNGE" 0186 << "S: A000004 OK expunge done" 0187 << "C: A000005 SELECT \"INBOX/Foo\"" 0188 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0189 << R"(S: * OK [ PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen) ])" 0190 << "S: * 0 EXISTS" 0191 << "S: * 0 RECENT" 0192 << "S: * OK [ UIDVALIDITY 1149151135 ]" 0193 << "S: * OK [ UIDNEXT 9 ]" 0194 << "S: A000005 OK select done"; 0195 0196 callNames.clear(); 0197 callNames << QStringLiteral("itemsRetrieved") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievalDone"); 0198 0199 QTest::newRow("third listing, full sync, empty folder") << collection << scenario << callNames; 0200 0201 collection.attribute<UidNextAttribute>(Akonadi::Collection::AddIfMissing)->setUidNext(8); 0202 stats.setCount(4); 0203 collection.setStatistics(stats); 0204 collection.attribute<HighestModSeqAttribute>(Akonadi::Collection::AddIfMissing)->setHighestModSeq(123456788); 0205 scenario.clear(); 0206 scenario << defaultPoolConnectionScenario() << "C: A000003 SELECT \"INBOX/Foo\"" 0207 << "S: A000003 OK select done" 0208 << "C: A000004 EXPUNGE" 0209 << "S: A000004 OK expunge done" 0210 << "C: A000005 SELECT \"INBOX/Foo\"" 0211 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0212 << R"(S: * OK [ PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen) ])" 0213 << "S: * 5 EXISTS" 0214 << "S: * 0 RECENT" 0215 << "S: * OK [ UIDVALIDITY 1149151135 ]" 0216 << "S: * OK [ UIDNEXT 9 ]" 0217 << "S: * OK [ HIGHESTMODSEQ 123456789 ]" 0218 << "S: A000005 OK select done" 0219 << "C: A000006 UID SEARCH UID 8:9" 0220 << "S: * SEARCH 8 9" 0221 << "S: A000006 OK search done" 0222 << "C: A000007 UID FETCH 8:9 (RFC822.SIZE INTERNALDATE BODY.PEEK[] FLAGS UID)" 0223 << "S: * 5 FETCH ( FLAGS (\\Seen) UID 9 INTERNALDATE \"29-Jun-2010 15:26:42 +0200\" " 0224 "RFC822.SIZE 75 BODY[] {75}\r\n" 0225 "From: Foo <foo@kde.org>\r\n" 0226 "To: Bar <bar@kde.org>\r\n" 0227 "Subject: Test Mail\r\n" 0228 "\r\n" 0229 "Test\r\n" 0230 " )" 0231 << "S: A000007 OK fetch done" 0232 << "C: A000008 UID SEARCH UID 1:7" 0233 << "S: * SEARCH 1 2 3 4 5 6 7" 0234 << "S: A000008 OK search done" 0235 << "C: A000009 UID FETCH 1:7 (FLAGS UID)" 0236 << "S: * 1 FETCH" 0237 << "S: * 2 FETCH" 0238 << "S: * 3 FETCH" 0239 << "S: * 4 FETCH" 0240 << "S: A000009 OK fetch done"; 0241 0242 callNames.clear(); 0243 callNames << QStringLiteral("itemsRetrievedIncremental") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievedIncremental") 0244 << QStringLiteral("itemsRetrievalDone"); 0245 0246 // We know no messages have been removed, so we can do an incremental update 0247 QTest::newRow("uidnext changed, fetch new messages incrementally") << collection << scenario << callNames; 0248 0249 collection.attribute<UidNextAttribute>(Akonadi::Collection::AddIfMissing)->setUidNext(8); 0250 stats.setCount(5); 0251 collection.setStatistics(stats); 0252 scenario.clear(); 0253 scenario << defaultPoolConnectionScenario() << "C: A000003 SELECT \"INBOX/Foo\"" 0254 << "S: A000003 OK select done" 0255 << "C: A000004 EXPUNGE" 0256 << "S: A000004 OK expunge done" 0257 << "C: A000005 SELECT \"INBOX/Foo\"" 0258 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0259 << R"(S: * OK [ PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen) ])" 0260 << "S: * 5 EXISTS" 0261 << "S: * 0 RECENT" 0262 << "S: * OK [ UIDVALIDITY 1149151135 ]" 0263 << "S: * OK [ UIDNEXT 9 ]" 0264 << "S: * OK [ HIGHESTMODSEQ 123456789 ]" 0265 << "S: A000005 OK select done" 0266 << "C: A000006 UID SEARCH UID 8:9" 0267 << "S: * SEARCH 8 9" 0268 << "S: A000006 OK search done" 0269 << "C: A000007 UID FETCH 8:9 (RFC822.SIZE INTERNALDATE BODY.PEEK[] FLAGS UID)" 0270 << "S: * 4 FETCH ( FLAGS (\\Seen) UID 8 INTERNALDATE \"29-Jun-2010 15:26:42 +0200\" " 0271 "RFC822.SIZE 75 BODY[] {75}\r\n" 0272 "From: Foo <foo@kde.org>\r\n" 0273 "To: Bar <bar@kde.org>\r\n" 0274 "Subject: Test Mail\r\n" 0275 "\r\n" 0276 "Test\r\n" 0277 " )" 0278 << "S: * 5 FETCH ( FLAGS (\\Seen) UID 9 INTERNALDATE \"29-Jun-2010 15:26:42 +0200\" " 0279 "RFC822.SIZE 75 BODY[] {75}\r\n" 0280 "From: Foo <foo@kde.org>\r\n" 0281 "To: Bar <bar@kde.org>\r\n" 0282 "Subject: Test Mail\r\n" 0283 "\r\n" 0284 "Test\r\n" 0285 " )" 0286 << "S: A000007 OK fetch done" 0287 << "C: A000008 UID SEARCH UID 1:7" 0288 << "S: * SEARCH 1 2 3 4 5 6 7" 0289 << "S: A000008 OK search done" 0290 << "C: A000009 UID FETCH 1:7 (FLAGS UID)" 0291 << "S: * 1 FETCH" 0292 << "S: * 2 FETCH" 0293 << "S: * 3 FETCH" 0294 << "S: A000009 OK fetch done"; 0295 0296 callNames.clear(); 0297 callNames << QStringLiteral("itemsRetrieved") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievalDone"); 0298 0299 // A new message has been added and an old one removed, we can't do an incremental update 0300 QTest::newRow("uidnext changed, fetch new messages and list flags") << collection << scenario << callNames; 0301 0302 collection = createCollectionChain(QStringLiteral("/INBOX/Foo")); 0303 collection.attribute<UidValidityAttribute>(Akonadi::Collection::AddIfMissing)->setUidValidity(1149151135); 0304 collection.setCachePolicy(policy); 0305 collection.attribute<UidNextAttribute>(Akonadi::Collection::AddIfMissing)->setUidNext(9); 0306 collection.attribute<HighestModSeqAttribute>(Akonadi::Collection::AddIfMissing)->setHighestModSeq(123456789); 0307 stats.setCount(5); 0308 collection.setStatistics(stats); 0309 scenario.clear(); 0310 scenario << defaultPoolConnectionScenario(QList<QByteArray>() << "CONDSTORE") << "C: A000003 SELECT \"INBOX/Foo\" (CONDSTORE)" 0311 << "S: A000003 OK select done" 0312 << "C: A000004 EXPUNGE" 0313 << "S: A000004 OK expunge DONE" 0314 << "C: A000005 SELECT \"INBOX/Foo\" (CONDSTORE)" 0315 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0316 << R"(S: * OK [ PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen) ])" 0317 << "S: * 5 EXISTS" 0318 << "S: * 0 RECENT" 0319 << "S: * OK [ UIDVALIDITY 1149151135 ]" 0320 << "S: * OK [ UIDNEXT 9 ]" 0321 << "S: * OK [ HIGHESTMODSEQ 123456789 ]" 0322 << "S: A000005 OK select done"; 0323 callNames.clear(); 0324 callNames << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievedIncremental") << QStringLiteral("itemsRetrievalDone"); 0325 0326 // No flags have changed 0327 QTest::newRow("highestmodseq test") << collection << scenario << callNames; 0328 0329 collection = createCollectionChain(QStringLiteral("/INBOX/Foo")); 0330 collection.attribute<UidValidityAttribute>(Akonadi::Collection::AddIfMissing)->setUidValidity(1149151135); 0331 collection.setCachePolicy(policy); 0332 collection.attribute<UidNextAttribute>(Akonadi::Collection::AddIfMissing)->setUidNext(9); 0333 collection.attribute<HighestModSeqAttribute>(Akonadi::Collection::AddIfMissing)->setHighestModSeq(123456788); 0334 stats.setCount(5); 0335 collection.setStatistics(stats); 0336 scenario.clear(); 0337 scenario << defaultPoolConnectionScenario(QList<QByteArray>() << "CONDSTORE") << "C: A000003 SELECT \"INBOX/Foo\" (CONDSTORE)" 0338 << "S: A000003 OK select done" 0339 << "C: A000004 EXPUNGE" 0340 << "S: A000004 OK expunge DONE" 0341 << "C: A000005 SELECT \"INBOX/Foo\" (CONDSTORE)" 0342 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0343 << R"(S: * OK [ PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen) ])" 0344 << "S: * 5 EXISTS" 0345 << "S: * 0 RECENT" 0346 << "S: * OK [ UIDVALIDITY 1149151135 ]" 0347 << "S: * OK [ UIDNEXT 9 ]" 0348 << "S: * OK [ HIGHESTMODSEQ 123456789 ]" 0349 << "S: A000005 OK select done" 0350 << "C: A000006 UID FETCH 1:9 (FLAGS UID) (CHANGEDSINCE 123456788)" 0351 << "S: * 5 FETCH ( UID 8 FLAGS () )" 0352 << "S: A000006 OK fetch done"; 0353 callNames.clear(); 0354 callNames << QStringLiteral("itemsRetrievedIncremental") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievedIncremental") 0355 << QStringLiteral("itemsRetrievalDone"); 0356 0357 // fetch only changed flags 0358 QTest::newRow("changedsince test") << collection << scenario << callNames; 0359 0360 collection = createCollectionChain(QStringLiteral("/INBOX/Foo")); 0361 collection.setCachePolicy(policy); 0362 collection.attribute<UidValidityAttribute>(Akonadi::Collection::AddIfMissing)->setUidValidity(1149151135); 0363 collection.attribute<UidNextAttribute>(Akonadi::Collection::AddIfMissing)->setUidNext(9); 0364 collection.attribute<HighestModSeqAttribute>(Akonadi::Collection::AddIfMissing)->setHighestModSeq(123456788); 0365 stats.setCount(5); 0366 collection.setStatistics(stats); 0367 scenario.clear(); 0368 scenario << defaultPoolConnectionScenario(QList<QByteArray>() << "XYMHIGHESTMODSEQ") << "C: A000003 SELECT \"INBOX/Foo\"" 0369 << "S: A000003 OK select done" 0370 << "C: A000004 EXPUNGE" 0371 << "S: A000004 OK expunge DONE" 0372 << "C: A000005 SELECT \"INBOX/Foo\"" 0373 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0374 << R"(S: * OK [ PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen) ])" 0375 << "S: * 5 EXISTS" 0376 << "S: * 0 RECENT" 0377 << "S: * OK [ UIDVALIDITY 1149151135 ]" 0378 << "S: * OK [ UIDNEXT 9 ]" 0379 << "S: * OK [ HIGHESTMODSEQ 123456789 ]" 0380 << "S: A000005 OK select done"; 0381 // Disabled since the flag sync is disabled if CONDSTORE is not supported 0382 // << "C: A000006 UID SEARCH UID 1:9" 0383 // << "S: * SEARCH 1 2 3 4 5 6 7 8 9" 0384 // << "S: A000006 OK search done" 0385 // << "C: A000007 UID FETCH 1:9 (FLAGS UID)" 0386 // << "S: * 5 FETCH ( UID 8 FLAGS () )" 0387 // << "S: A000007 OK fetch done"; 0388 callNames.clear(); 0389 0390 // Disabled since the flag sync is disabled if CONDSTORE is not supported 0391 callNames << /*"itemsRetrievedIncremental" << */ QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievedIncremental") 0392 << QStringLiteral("itemsRetrievalDone"); 0393 0394 // Don't rely on yahoos highestmodseq implementation 0395 QTest::newRow("yahoo highestmodseq test") << collection << scenario << callNames; 0396 0397 collection = createCollectionChain(QStringLiteral("/INBOX/Foo")); 0398 collection.attribute<UidNextAttribute>(Akonadi::Collection::AddIfMissing)->setUidNext(9); 0399 collection.attribute<UidValidityAttribute>(Akonadi::Collection::AddIfMissing)->setUidValidity(3); 0400 collection.setCachePolicy(policy); 0401 stats.setCount(1); 0402 collection.setStatistics(stats); 0403 0404 scenario.clear(); 0405 scenario << defaultPoolConnectionScenario() << "C: A000003 SELECT \"INBOX/Foo\"" 0406 << "S: A000003 OK select done" 0407 << "C: A000004 EXPUNGE" 0408 << "S: A000004 OK expunge done" 0409 << "C: A000005 SELECT \"INBOX/Foo\"" 0410 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0411 << R"(S: * OK [ PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen) ])" 0412 << "S: * 1 EXISTS" 0413 << "S: * 0 RECENT" 0414 << "S: * OK [ UIDVALIDITY 1149151135 ]" 0415 << "S: * OK [ UIDNEXT 9 ]" 0416 << "S: A000005 OK select done" 0417 << "C: A000006 UID SEARCH UID 1:9" 0418 << "S: * SEARCH 1 2 3 4 5 6 7 8 9" 0419 << "S: A000006 OK search done" 0420 << "C: A000007 UID FETCH 1:9 (RFC822.SIZE INTERNALDATE BODY.PEEK[] FLAGS UID)" 0421 << "S: * 1 FETCH ( FLAGS (\\Seen) UID 2321 INTERNALDATE \"29-Jun-2010 15:26:42 +0200\" " 0422 "RFC822.SIZE 75 BODY[] {75}\r\n" 0423 "From: Foo <foo@kde.org>\r\n" 0424 "To: Bar <bar@kde.org>\r\n" 0425 "Subject: Test Mail\r\n" 0426 "\r\n" 0427 "Test\r\n" 0428 " )" 0429 << "S: A000007 OK fetch done"; 0430 0431 callNames.clear(); 0432 callNames << QStringLiteral("itemsRetrieved") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievalDone"); 0433 0434 QTest::newRow("uidvalidity changed") << collection << scenario << callNames; 0435 0436 collection = createCollectionChain(QStringLiteral("/INBOX/Foo")); 0437 collection.attribute<UidNextAttribute>(Akonadi::Collection::AddIfMissing)->setUidNext(105); 0438 collection.attribute<UidValidityAttribute>(Akonadi::Collection::AddIfMissing)->setUidValidity(1149151135); 0439 collection.setCachePolicy(policy); 0440 stats.setCount(104); 0441 collection.setStatistics(stats); 0442 0443 scenario.clear(); 0444 scenario << defaultPoolConnectionScenario() << "C: A000003 SELECT \"INBOX/Foo\"" 0445 << "S: A000003 OK select done" 0446 << "C: A000004 EXPUNGE" 0447 << "S: A000004 OK expunge done" 0448 << "C: A000005 SELECT \"INBOX/Foo\"" 0449 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0450 << R"(S: * OK [ PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen) ])" 0451 << "S: * 119 EXISTS" 0452 << "S: * 0 RECENT" 0453 << "S: * OK [ UIDVALIDITY 1149151135 ]" 0454 << "S: * OK [ UIDNEXT 120 ]" 0455 << "S: A000005 OK select done" 0456 << "C: A000006 UID SEARCH UID 105:120" 0457 // We asked for until 120 but only 119 is available (120 is uidnext) 0458 << "S: * SEARCH 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119" 0459 << "S: A000006 OK search done" 0460 << "C: A000007 UID FETCH 105:114 (RFC822.SIZE INTERNALDATE BODY.PEEK[] FLAGS UID)" 0461 << "S: * 1 FETCH ( FLAGS (\\Seen) UID 105 INTERNALDATE \"29-Jun-2010 15:26:42 +0200\" " 0462 "RFC822.SIZE 75 BODY[] {75}\r\n" 0463 "From: Foo <foo@kde.org>\r\n" 0464 "To: Bar <bar@kde.org>\r\n" 0465 "Subject: Test Mail\r\n" 0466 "\r\n" 0467 "Test\r\n" 0468 " )" 0469 // 9 more would follow but are excluded for clarity 0470 << "S: A000007 OK fetch done" 0471 << "C: A000008 UID FETCH 115:119 (RFC822.SIZE INTERNALDATE BODY.PEEK[] FLAGS UID)" 0472 << "S: * 1 FETCH ( FLAGS (\\Seen) UID 115 INTERNALDATE \"29-Jun-2010 15:26:42 +0200\" " 0473 "RFC822.SIZE 75 BODY[] {75}\r\n" 0474 "From: Foo <foo@kde.org>\r\n" 0475 "To: Bar <bar@kde.org>\r\n" 0476 "Subject: Test Mail\r\n" 0477 "\r\n" 0478 "Test\r\n" 0479 " )" 0480 // 4 more would follow but are excluded for clarity 0481 << "S: A000008 OK fetch done" 0482 << "C: A000009 UID SEARCH UID 1:104" 0483 << "S: * SEARCH 1 2 99 100" 0484 << "S: A000009 OK search done" 0485 << "C: A000010 UID FETCH 1:2,99:100 (FLAGS UID)" 0486 << "S: * 1 FETCH ( FLAGS (\\Seen) UID 1 )" 0487 // 3 more would follow but are excluded for clarity 0488 << "S: A000010 OK fetch done"; 0489 0490 callNames.clear(); 0491 callNames << QStringLiteral("itemsRetrievedIncremental") << QStringLiteral("itemsRetrievedIncremental") << QStringLiteral("itemsRetrievedIncremental") 0492 << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievedIncremental") << QStringLiteral("itemsRetrievalDone"); 0493 0494 QTest::newRow("test batch processing") << collection << scenario << callNames; 0495 0496 collection = createCollectionChain(QStringLiteral("/INBOX/Foo")); 0497 collection.attribute<UidValidityAttribute>(Akonadi::Collection::AddIfMissing)->setUidValidity(1149151135); 0498 collection.setCachePolicy(policy); 0499 collection.attribute<UidNextAttribute>(Akonadi::Collection::AddIfMissing)->setUidNext(9); 0500 collection.attribute<HighestModSeqAttribute>(Akonadi::Collection::AddIfMissing)->setHighestModSeq(123456789); 0501 stats.setCount(5); 0502 collection.setStatistics(stats); 0503 scenario.clear(); 0504 scenario << defaultPoolConnectionScenario(QList<QByteArray>() << "CONDSTORE") << "C: A000003 SELECT \"INBOX/Foo\" (CONDSTORE)" 0505 << "S: A000003 OK select done" 0506 << "C: A000004 EXPUNGE" 0507 << "S: A000004 OK expunge DONE" 0508 << "C: A000005 SELECT \"INBOX/Foo\" (CONDSTORE)" 0509 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0510 << R"(S: * OK [ PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen) ])" 0511 << "S: * 4 EXISTS" 0512 << "S: * 0 RECENT" 0513 << "S: * OK [ UIDVALIDITY 1149151135 ]" 0514 << "S: * OK [ UIDNEXT 9 ]" 0515 << "S: * OK [ HIGHESTMODSEQ 123456789 ]" 0516 << "S: A000005 OK select done" 0517 << "C: A000006 UID SEARCH UID 1:9" 0518 << "S: * SEARCH 1 2 3 4" 0519 << "S: A000006 OK search done" 0520 << "C: A000007 UID FETCH 1:4 (FLAGS UID)" 0521 << "S: * 1 FETCH ( FLAGS (\\Seen) UID 1 )" 0522 << "S: * 2 FETCH ( FLAGS (\\Seen) UID 2 )" 0523 << "S: * 3 FETCH ( FLAGS (\\Seen) UID 3 )" 0524 << "S: * 4 FETCH ( FLAGS (\\Seen) UID 4 )" 0525 << "S: A000007 OK fetch done"; 0526 callNames.clear(); 0527 callNames << QStringLiteral("itemsRetrieved") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievalDone"); 0528 0529 // fetch only changed flags 0530 QTest::newRow("remote message deleted") << collection << scenario << callNames; 0531 0532 collection = createCollectionChain(QStringLiteral("/INBOX/Foo")); 0533 collection.attribute<UidValidityAttribute>(Akonadi::Collection::AddIfMissing)->setUidValidity(1149151135); 0534 collection.setCachePolicy(policy); 0535 collection.attribute<UidNextAttribute>(Akonadi::Collection::AddIfMissing)->setUidNext(-1); 0536 collection.attribute<HighestModSeqAttribute>(Akonadi::Collection::AddIfMissing)->setHighestModSeq(123456789); 0537 stats.setCount(0); 0538 collection.setStatistics(stats); 0539 scenario.clear(); 0540 scenario << defaultPoolConnectionScenario() << "C: A000003 SELECT \"INBOX/Foo\"" 0541 << "S: A000003 OK select done" 0542 << "C: A000004 EXPUNGE" 0543 << "S: A000004 OK expunge done" 0544 << "C: A000005 SELECT \"INBOX/Foo\"" 0545 << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" 0546 << R"(S: * OK [ PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen) ])" 0547 << "S: * 1 EXISTS" 0548 << "S: * 0 RECENT" 0549 << "S: * OK [ UIDVALIDITY 1149151135 ]" 0550 << "S: A000005 OK select done" 0551 << "C: A000006 STATUS \"INBOX/Foo\" (UIDNEXT)" 0552 << "S: * STATUS \"INBOX/Foo\" (UIDNEXT 10)" 0553 << "S: A000006 OK status done" 0554 << "C: A000007 UID SEARCH UID 1:10" 0555 << "S: * SEARCH 1 2 3 4 5 6 7 8 9" 0556 << "S: A000007 OK search done" 0557 << "C: A000008 UID FETCH 1:9 (RFC822.SIZE INTERNALDATE BODY.PEEK[] FLAGS UID)" 0558 << "S: * 1 FETCH ( FLAGS (\\Seen) UID 2321 INTERNALDATE \"29-Jun-2010 15:26:42 +0200\" " 0559 "RFC822.SIZE 75 BODY[] {75}\r\n" 0560 "From: Foo <foo@kde.org>\r\n" 0561 "To: Bar <bar@kde.org>\r\n" 0562 "Subject: Test Mail\r\n" 0563 "\r\n" 0564 "Test\r\n" 0565 " )" 0566 << "S: A000008 OK fetch done"; 0567 0568 callNames.clear(); 0569 callNames << QStringLiteral("itemsRetrieved") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievalDone"); 0570 0571 QTest::newRow("missing uidnext") << collection << scenario << callNames; 0572 } 0573 0574 void shouldIntrospectCollection() 0575 { 0576 QFETCH(Akonadi::Collection, collection); 0577 QFETCH(QList<QByteArray>, scenario); 0578 QFETCH(QStringList, callNames); 0579 0580 FakeServer server; 0581 server.setScenario(scenario); 0582 server.startAndWait(); 0583 0584 SessionPool pool(1); 0585 0586 pool.setPasswordRequester(createDefaultRequester()); 0587 QVERIFY(pool.connect(createDefaultAccount())); 0588 QVERIFY(waitForSignal(&pool, SIGNAL(connectDone(int, QString)))); 0589 0590 DummyResourceState::Ptr state = DummyResourceState::Ptr(new DummyResourceState); 0591 state->setServerCapabilities(pool.serverCapabilities()); 0592 state->setCollection(collection); 0593 0594 auto task = new RetrieveItemsTask(state); 0595 task->setFetchMissingItemBodies(false); 0596 task->start(&pool); 0597 0598 QTRY_COMPARE(state->calls().count(), callNames.size()); 0599 qDebug() << state->calls(); 0600 for (int i = 0; i < callNames.size(); i++) { 0601 QString command = QString::fromUtf8(state->calls().at(i).first); 0602 QVariant parameter = state->calls().at(i).second; 0603 0604 if (command == QLatin1StringView("cancelTask") && callNames[i] != QLatin1StringView("cancelTask")) { 0605 qDebug() << "Got a cancel:" << parameter.toString(); 0606 } 0607 0608 QCOMPARE(command, callNames[i]); 0609 0610 if (command == QLatin1StringView("cancelTask")) { 0611 QVERIFY(!parameter.toString().isEmpty()); 0612 } 0613 } 0614 0615 QVERIFY(server.isAllScenarioDone()); 0616 0617 server.quit(); 0618 } 0619 }; 0620 0621 QTEST_GUILESS_MAIN(TestRetrieveItemsTask) 0622 0623 #include "testretrieveitemstask.moc"