File indexing completed on 2024-12-22 04:57:37
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net> 0003 SPDX-FileContributor: Kevin Krammer <krake@kdab.com> 0004 0005 SPDX-FileCopyrightText: 2011 Kevin Krammer <kevin.krammer@gmx.at> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #include "mixedmaildirstore.h" 0011 0012 #include "testdatautil.h" 0013 0014 #include "filestore/itemfetchjob.h" 0015 #include "filestore/itemmodifyjob.h" 0016 #include "filestore/storecompactjob.h" 0017 0018 #include "libmaildir/maildir.h" 0019 0020 #include <Akonadi/MessageParts> 0021 0022 #include <Akonadi/ItemFetchScope> 0023 0024 #include <KMbox/MBox> 0025 0026 #include <KMime/Message> 0027 0028 #include <KRandom> 0029 0030 #include <QCryptographicHash> 0031 #include <QDir> 0032 #include <QFileInfo> 0033 #include <QRandomGenerator> 0034 #include <QTemporaryDir> 0035 #include <QTest> 0036 0037 using namespace Akonadi; 0038 using namespace KMBox; 0039 0040 static bool fullEntryCompare(const MBoxEntry &a, const MBoxEntry &b) 0041 { 0042 return a.messageOffset() == b.messageOffset() && a.separatorSize() == b.separatorSize() && a.messageSize() == b.messageSize(); 0043 } 0044 0045 class ItemModifyTest : public QObject 0046 { 0047 Q_OBJECT 0048 0049 public: 0050 ItemModifyTest() 0051 : QObject() 0052 , mStore(nullptr) 0053 , mDir(nullptr) 0054 { 0055 } 0056 0057 ~ItemModifyTest() override 0058 { 0059 delete mStore; 0060 delete mDir; 0061 } 0062 0063 private: 0064 MixedMaildirStore *mStore = nullptr; 0065 QTemporaryDir *mDir = nullptr; 0066 0067 private Q_SLOTS: 0068 void init(); 0069 void cleanup(); 0070 void testExpectedFail(); 0071 void testIgnorePayload(); 0072 void testModifyPayload(); 0073 void testModifyFlags(); 0074 void testModifyFlagsAndPayload(); 0075 }; 0076 0077 void ItemModifyTest::init() 0078 { 0079 mStore = new MixedMaildirStore; 0080 0081 mDir = new QTemporaryDir; 0082 QVERIFY(mDir->isValid()); 0083 QVERIFY(QDir(mDir->path()).exists()); 0084 } 0085 0086 void ItemModifyTest::cleanup() 0087 { 0088 delete mStore; 0089 mStore = nullptr; 0090 delete mDir; 0091 mDir = nullptr; 0092 } 0093 0094 void ItemModifyTest::testExpectedFail() 0095 { 0096 QDir topDir(mDir->path()); 0097 0098 QVERIFY(TestDataUtil::installFolder(QLatin1StringView("maildir"), topDir.path(), QStringLiteral("collection1"))); 0099 QVERIFY(TestDataUtil::installFolder(QLatin1StringView("mbox"), topDir.path(), QStringLiteral("collection2"))); 0100 0101 KPIM::Maildir topLevelMd(topDir.path(), true); 0102 0103 KPIM::Maildir md1 = topLevelMd.subFolder(QStringLiteral("collection1")); 0104 QStringList md1EntryList = md1.entryList(); 0105 QSet<QString> entrySet1(md1EntryList.cbegin(), md1EntryList.cend()); 0106 QCOMPARE((int)entrySet1.count(), 4); 0107 0108 QFileInfo fileInfo2(topDir.path(), QStringLiteral("collection2")); 0109 MBox mbox2; 0110 QVERIFY(mbox2.load(fileInfo2.absoluteFilePath())); 0111 const MBoxEntry::List entryList2 = mbox2.entries(); 0112 QCOMPARE((int)entryList2.count(), 4); 0113 0114 QSet<qint64> entrySet2; 0115 for (const MBoxEntry &entry : entryList2) { 0116 entrySet2 << entry.messageOffset(); 0117 } 0118 0119 mStore->setPath(topDir.path()); 0120 0121 // common variables 0122 FileStore::ItemModifyJob *job = nullptr; 0123 0124 // test failure of modifying a non-existent maildir entry 0125 Collection collection1; 0126 collection1.setName(QStringLiteral("collection1")); 0127 collection1.setRemoteId(QStringLiteral("collection1")); 0128 collection1.setParentCollection(mStore->topLevelCollection()); 0129 0130 QString remoteId1; 0131 do { 0132 remoteId1 = KRandom::randomString(20); 0133 } while (entrySet1.contains(remoteId1)); 0134 0135 KMime::Message::Ptr msgPtr(new KMime::Message); 0136 0137 Item item1; 0138 item1.setMimeType(KMime::Message::mimeType()); 0139 item1.setRemoteId(remoteId1); 0140 item1.setParentCollection(collection1); 0141 item1.setPayload<KMime::Message::Ptr>(msgPtr); 0142 0143 job = mStore->modifyItem(item1); 0144 0145 QVERIFY(!job->exec()); 0146 QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext); 0147 0148 md1EntryList = md1.entryList(); 0149 QSet<QString> entrySet(md1EntryList.cbegin(), md1EntryList.cend()); 0150 QCOMPARE(entrySet, entrySet1); 0151 0152 // test failure of modifying a non-existent mbox entry 0153 Collection collection2; 0154 collection2.setName(QStringLiteral("collection2")); 0155 collection2.setRemoteId(QStringLiteral("collection2")); 0156 collection2.setParentCollection(mStore->topLevelCollection()); 0157 0158 qint64 remoteId2; 0159 do { 0160 remoteId2 = QRandomGenerator::global()->generate(); 0161 } while (entrySet2.contains(remoteId2)); 0162 0163 Item item2; 0164 item2.setMimeType(KMime::Message::mimeType()); 0165 item2.setRemoteId(QString::number(remoteId2)); 0166 item2.setParentCollection(collection2); 0167 item2.setPayload<KMime::Message::Ptr>(msgPtr); 0168 0169 job = mStore->modifyItem(item2); 0170 0171 QVERIFY(!job->exec()); 0172 QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext); 0173 0174 QVERIFY(mbox2.load(mbox2.fileName())); 0175 MBoxEntry::List entryList = mbox2.entries(); 0176 QVERIFY(std::equal(entryList.begin(), entryList.end(), entryList2.begin(), fullEntryCompare)); 0177 } 0178 0179 void ItemModifyTest::testIgnorePayload() 0180 { 0181 QDir topDir(mDir->path()); 0182 0183 QVERIFY(TestDataUtil::installFolder(QLatin1StringView("maildir"), topDir.path(), QStringLiteral("collection1"))); 0184 QVERIFY(TestDataUtil::installFolder(QLatin1StringView("mbox"), topDir.path(), QStringLiteral("collection2"))); 0185 0186 KPIM::Maildir topLevelMd(topDir.path(), true); 0187 0188 KPIM::Maildir md1 = topLevelMd.subFolder(QStringLiteral("collection1")); 0189 QStringList entryList1 = md1.entryList(); 0190 QCOMPARE((int)entryList1.count(), 4); 0191 0192 QFileInfo fileInfo2(topDir.path(), QStringLiteral("collection2")); 0193 MBox mbox2; 0194 QVERIFY(mbox2.load(fileInfo2.absoluteFilePath())); 0195 MBoxEntry::List entryList2 = mbox2.entries(); 0196 QCOMPARE((int)entryList2.count(), 4); 0197 0198 mStore->setPath(topDir.path()); 0199 0200 // common variables 0201 FileStore::ItemModifyJob *job = nullptr; 0202 0203 // test failure of modifying a non-existent maildir entry 0204 Collection collection1; 0205 collection1.setName(QStringLiteral("collection1")); 0206 collection1.setRemoteId(QStringLiteral("collection1")); 0207 collection1.setParentCollection(mStore->topLevelCollection()); 0208 0209 const QByteArray data1 = md1.readEntry(entryList1.first()); 0210 0211 KMime::Message::Ptr msgPtr(new KMime::Message); 0212 msgPtr->subject()->from7BitString("Modify Test"); 0213 msgPtr->assemble(); 0214 0215 Item item1; 0216 item1.setMimeType(KMime::Message::mimeType()); 0217 item1.setRemoteId(entryList1.first()); 0218 item1.setParentCollection(collection1); 0219 item1.setPayload<KMime::Message::Ptr>(msgPtr); 0220 0221 job = mStore->modifyItem(item1); 0222 job->setIgnorePayload(true); 0223 0224 QVERIFY(job->exec()); 0225 QCOMPARE(job->error(), 0); 0226 0227 QCOMPARE(md1.entryList(), entryList1); 0228 QCOMPARE(md1.readEntry(entryList1.first()), data1); 0229 0230 // test failure of modifying a non-existent mbox entry 0231 Collection collection2; 0232 collection2.setName(QStringLiteral("collection2")); 0233 collection2.setRemoteId(QStringLiteral("collection2")); 0234 collection2.setParentCollection(mStore->topLevelCollection()); 0235 0236 const QByteArray data2 = mbox2.readRawMessage(MBoxEntry(0)); 0237 0238 Item item2; 0239 item2.setMimeType(KMime::Message::mimeType()); 0240 item2.setRemoteId(QStringLiteral("0")); 0241 item2.setParentCollection(collection2); 0242 item2.setPayload<KMime::Message::Ptr>(msgPtr); 0243 0244 job = mStore->modifyItem(item2); 0245 job->setIgnorePayload(true); 0246 0247 QVERIFY(job->exec()); 0248 QCOMPARE(job->error(), 0); 0249 0250 QVERIFY(mbox2.load(mbox2.fileName())); 0251 QCOMPARE(mbox2.entries(), entryList2); 0252 QCOMPARE(mbox2.readRawMessage(MBoxEntry(0)), data2); 0253 } 0254 0255 void ItemModifyTest::testModifyPayload() 0256 { 0257 QDir topDir(mDir->path()); 0258 0259 QVERIFY(TestDataUtil::installFolder(QLatin1StringView("maildir"), topDir.path(), QStringLiteral("collection1"))); 0260 QVERIFY(TestDataUtil::installFolder(QLatin1StringView("mbox"), topDir.path(), QStringLiteral("collection2"))); 0261 0262 KPIM::Maildir topLevelMd(topDir.path(), true); 0263 0264 KPIM::Maildir md1 = topLevelMd.subFolder(QStringLiteral("collection1")); 0265 QStringList entryList1 = md1.entryList(); 0266 QCOMPARE((int)entryList1.count(), 4); 0267 0268 QFileInfo fileInfo2(topDir.path(), QStringLiteral("collection2")); 0269 MBox mbox2; 0270 QVERIFY(mbox2.load(fileInfo2.absoluteFilePath())); 0271 MBoxEntry::List entryList2 = mbox2.entries(); 0272 QCOMPARE((int)entryList2.count(), 4); 0273 0274 mStore->setPath(topDir.path()); 0275 0276 // common variables 0277 FileStore::ItemModifyJob *job = nullptr; 0278 0279 const QVariant colListVar = QVariant::fromValue<Collection::List>(Collection::List()); 0280 QVariant var; 0281 Collection::List collections; 0282 0283 // test modifying a maildir entry's header 0284 Collection collection1; 0285 collection1.setName(QStringLiteral("collection1")); 0286 collection1.setRemoteId(QStringLiteral("collection1")); 0287 collection1.setParentCollection(mStore->topLevelCollection()); 0288 0289 const QByteArray data1 = md1.readEntry(entryList1.first()); 0290 0291 KMime::Message::Ptr msgPtr(new KMime::Message); 0292 msgPtr->setContent(KMime::CRLFtoLF(data1)); 0293 msgPtr->subject()->from7BitString("Modify Test"); 0294 msgPtr->assemble(); 0295 0296 Item item1; 0297 item1.setMimeType(KMime::Message::mimeType()); 0298 item1.setRemoteId(entryList1.first()); 0299 item1.setParentCollection(collection1); 0300 item1.setPayload<KMime::Message::Ptr>(msgPtr); 0301 0302 job = mStore->modifyItem(item1); 0303 // changing subject, so indicate a header change 0304 job->setParts(QSet<QByteArray>() << QByteArray("PLD:") + QByteArray(MessagePart::Header)); 0305 0306 QVERIFY(job->exec()); 0307 QCOMPARE(job->error(), 0); 0308 0309 QCOMPARE(md1.entryList(), entryList1); 0310 0311 QCOMPARE(md1.readEntry(entryList1.first()).size(), msgPtr->encodedContent().size()); 0312 QCOMPARE(md1.readEntry(entryList1.first()), msgPtr->encodedContent()); 0313 0314 // check for index preservation 0315 var = job->property("onDiskIndexInvalidated"); 0316 QVERIFY(var.isValid()); 0317 QCOMPARE(var.userType(), colListVar.userType()); 0318 0319 collections = var.value<Collection::List>(); 0320 QCOMPARE((int)collections.count(), 1); 0321 QCOMPARE(collections.first(), collection1); 0322 0323 // test modifying an mbox entry's header 0324 Collection collection2; 0325 collection2.setName(QStringLiteral("collection2")); 0326 collection2.setRemoteId(QStringLiteral("collection2")); 0327 collection2.setParentCollection(mStore->topLevelCollection()); 0328 0329 const QByteArray data2 = mbox2.readRawMessage(MBoxEntry(0)); 0330 0331 msgPtr->setContent(KMime::CRLFtoLF(data2)); 0332 msgPtr->subject()->from7BitString("Modify Test"); 0333 msgPtr->assemble(); 0334 0335 Item item2; 0336 item2.setMimeType(KMime::Message::mimeType()); 0337 item2.setRemoteId(QStringLiteral("0")); 0338 item2.setParentCollection(collection2); 0339 item2.setPayload<KMime::Message::Ptr>(msgPtr); 0340 0341 job = mStore->modifyItem(item2); 0342 // changing subject, so indicate a header change 0343 job->setParts(QSet<QByteArray>() << QByteArray("PLD:") + QByteArray(MessagePart::Header)); 0344 0345 QVERIFY(job->exec()); 0346 QCOMPARE(job->error(), 0); 0347 0348 Item item = job->item(); 0349 0350 QVERIFY(mbox2.load(mbox2.fileName())); 0351 MBoxEntry::List entryList = mbox2.entries(); 0352 QCOMPARE((int)entryList.count(), 5); // mbox file not purged yet 0353 QCOMPARE(entryList.last().messageOffset(), item.remoteId().toULongLong()); 0354 0355 var = job->property("compactStore"); 0356 QVERIFY(var.isValid()); 0357 QCOMPARE(var.userType(), QMetaType::Bool); 0358 QCOMPARE(var.toBool(), true); 0359 0360 // check for index preservation 0361 var = job->property("onDiskIndexInvalidated"); 0362 QVERIFY(var.isValid()); 0363 QCOMPARE(var.userType(), colListVar.userType()); 0364 0365 collections = var.value<Collection::List>(); 0366 QCOMPARE((int)collections.count(), 1); 0367 QCOMPARE(collections.first(), collection2); 0368 0369 FileStore::ItemFetchJob *itemFetch = mStore->fetchItem(item2); 0370 QVERIFY(!itemFetch->exec()); // item at old offset gone 0371 0372 FileStore::StoreCompactJob *storeCompact = mStore->compactStore(); 0373 QVERIFY(storeCompact->exec()); 0374 0375 QVERIFY(mbox2.load(mbox2.fileName())); 0376 entryList = mbox2.entries(); 0377 QCOMPARE((int)entryList.count(), 4); 0378 0379 QCOMPARE(mbox2.readRawMessage(entryList.last()), msgPtr->encodedContent()); 0380 } 0381 0382 void ItemModifyTest::testModifyFlags() 0383 { 0384 QDir topDir(mDir->path()); 0385 0386 QVERIFY(TestDataUtil::installFolder(QLatin1StringView("maildir"), topDir.path(), QStringLiteral("collection1"))); 0387 QVERIFY(TestDataUtil::installFolder(QLatin1StringView("mbox"), topDir.path(), QStringLiteral("collection2"))); 0388 0389 KPIM::Maildir topLevelMd(topDir.path(), true); 0390 0391 KPIM::Maildir md1 = topLevelMd.subFolder(QStringLiteral("collection1")); 0392 const QStringList entryList1 = md1.entryList(); 0393 QCOMPARE((int)entryList1.count(), 4); 0394 0395 QFileInfo fileInfo2(topDir.path(), QStringLiteral("collection2")); 0396 MBox mbox2; 0397 QVERIFY(mbox2.load(fileInfo2.absoluteFilePath())); 0398 MBoxEntry::List entryList2 = mbox2.entries(); 0399 QCOMPARE((int)entryList2.count(), 4); 0400 0401 QCryptographicHash cryptoHash(QCryptographicHash::Sha1); 0402 0403 QFile file2(fileInfo2.absoluteFilePath()); 0404 QVERIFY(file2.open(QIODevice::ReadOnly)); 0405 cryptoHash.addData(file2.readAll()); 0406 const QByteArray mbox2Sha1 = cryptoHash.result(); 0407 0408 file2.close(); 0409 cryptoHash.reset(); 0410 0411 mStore->setPath(topDir.path()); 0412 0413 // common variables 0414 FileStore::ItemModifyJob *job = nullptr; 0415 0416 const QVariant colListVar = QVariant::fromValue<Collection::List>(Collection::List()); 0417 QVariant var; 0418 Collection::List collections; 0419 KMime::Message::Ptr msgPtr(new KMime::Message); 0420 0421 // test modifying a flag of a maildir items changes the entry name but not the 0422 // message contents 0423 Collection collection1; 0424 collection1.setName(QStringLiteral("collection1")); 0425 collection1.setRemoteId(QStringLiteral("collection1")); 0426 collection1.setParentCollection(mStore->topLevelCollection()); 0427 0428 // check that the \SEEN flag is not set yet 0429 QVERIFY(!md1.readEntryFlags(entryList1.first()).contains("\\SEEN")); 0430 0431 const QByteArray data1 = md1.readEntry(entryList1.first()); 0432 0433 msgPtr->setContent(KMime::CRLFtoLF(data1)); 0434 msgPtr->subject()->from7BitString("Modify Test"); 0435 msgPtr->assemble(); 0436 0437 Item item1; 0438 item1.setMimeType(KMime::Message::mimeType()); 0439 item1.setRemoteId(entryList1.first()); 0440 item1.setParentCollection(collection1); 0441 item1.setPayload<KMime::Message::Ptr>(msgPtr); 0442 item1.setFlag("\\SEEN"); 0443 0444 job = mStore->modifyItem(item1); 0445 // setting \SEEN, so indicate a flags change 0446 job->setParts(QSet<QByteArray>() << "FLAGS"); 0447 0448 QVERIFY(job->exec()); 0449 QCOMPARE(job->error(), 0); 0450 0451 Item item = job->item(); 0452 0453 // returned item should contain the change 0454 QVERIFY(item.flags().contains("\\SEEN")); 0455 0456 // remote ID has changed 0457 QVERIFY(item.remoteId() != entryList1.first()); 0458 QVERIFY(!md1.entryList().contains(entryList1.first())); 0459 0460 // no change in number of entries, one difference 0461 QStringList entryList3 = md1.entryList(); 0462 QCOMPARE(entryList3.count(), entryList1.count()); 0463 for (const QString &oldEntry : entryList1) { 0464 entryList3.removeAll(oldEntry); 0465 } 0466 QCOMPARE(entryList3.count(), 1); 0467 0468 // no change to data 0469 QCOMPARE(md1.readEntry(entryList3.first()), data1); 0470 0471 var = job->property("onDiskIndexInvalidated"); 0472 QVERIFY(var.isValid()); 0473 QCOMPARE(var.userType(), colListVar.userType()); 0474 0475 collections = var.value<Collection::List>(); 0476 QCOMPARE((int)collections.count(), 1); 0477 QCOMPARE(collections.first(), collection1); 0478 0479 // fetch new item, check flag 0480 item1 = Item(); 0481 item1.setMimeType(KMime::Message::mimeType()); 0482 item1.setRemoteId(entryList3.first()); 0483 item1.setParentCollection(collection1); 0484 0485 FileStore::ItemFetchJob *itemFetch = mStore->fetchItem(item1); 0486 0487 QVERIFY(itemFetch->exec()); 0488 QCOMPARE(itemFetch->error(), 0); 0489 0490 QCOMPARE(itemFetch->items().count(), 1); 0491 QEXPECT_FAIL("", "ItemFetch handling needs to be fixed to also fetch flags", Continue); 0492 QVERIFY(itemFetch->items()[0].flags().contains("\\SEEN")); 0493 0494 // test modifying flags of an mbox item "succeeds" (no error) but does not change 0495 // anything in store or on disk 0496 Collection collection2; 0497 collection2.setName(QStringLiteral("collection2")); 0498 collection2.setRemoteId(QStringLiteral("collection2")); 0499 collection2.setParentCollection(mStore->topLevelCollection()); 0500 0501 const QByteArray data2 = mbox2.readRawMessage(MBoxEntry(0)); 0502 0503 msgPtr->setContent(KMime::CRLFtoLF(data2)); 0504 msgPtr->subject()->from7BitString("Modify Test"); 0505 msgPtr->assemble(); 0506 0507 Item item2; 0508 item2.setMimeType(KMime::Message::mimeType()); 0509 item2.setRemoteId(QStringLiteral("0")); 0510 item2.setParentCollection(collection2); 0511 item2.setPayload<KMime::Message::Ptr>(msgPtr); 0512 item2.setFlag("\\SEEN"); 0513 0514 job = mStore->modifyItem(item2); 0515 // setting \SEEN, so indicate a flags change 0516 job->setParts(QSet<QByteArray>() << "FLAGS"); 0517 0518 QVERIFY(job->exec()); 0519 QCOMPARE(job->error(), 0); 0520 0521 item = job->item(); 0522 0523 // returned item should contain the change 0524 QVERIFY(item.flags().contains("\\SEEN")); 0525 0526 // mbox not changed 0527 QVERIFY(mbox2.load(mbox2.fileName())); 0528 MBoxEntry::List entryList = mbox2.entries(); 0529 QCOMPARE((int)entryList.count(), 4); 0530 0531 var = job->property("compactStore"); 0532 QVERIFY(!var.isValid()); 0533 0534 // file not modified 0535 QVERIFY(file2.open(QIODevice::ReadOnly)); 0536 cryptoHash.addData(file2.readAll()); 0537 QCOMPARE(cryptoHash.result(), mbox2Sha1); 0538 0539 file2.close(); 0540 cryptoHash.reset(); 0541 0542 // check index preservation is not triggered 0543 var = job->property("onDiskIndexInvalidated"); 0544 QVERIFY(!var.isValid()); 0545 } 0546 0547 void ItemModifyTest::testModifyFlagsAndPayload() 0548 { 0549 QDir topDir(mDir->path()); 0550 0551 QVERIFY(TestDataUtil::installFolder(QLatin1StringView("maildir"), topDir.path(), QStringLiteral("collection1"))); 0552 QVERIFY(TestDataUtil::installFolder(QLatin1StringView("mbox"), topDir.path(), QStringLiteral("collection2"))); 0553 0554 KPIM::Maildir topLevelMd(topDir.path(), true); 0555 0556 KPIM::Maildir md1 = topLevelMd.subFolder(QStringLiteral("collection1")); 0557 const QStringList entryList1 = md1.entryList(); 0558 QCOMPARE((int)entryList1.count(), 4); 0559 0560 QFileInfo fileInfo2(topDir.path(), QStringLiteral("collection2")); 0561 MBox mbox2; 0562 QVERIFY(mbox2.load(fileInfo2.absoluteFilePath())); 0563 MBoxEntry::List entryList2 = mbox2.entries(); 0564 QCOMPARE((int)entryList2.count(), 4); 0565 0566 mStore->setPath(topDir.path()); 0567 0568 // common variables 0569 FileStore::ItemModifyJob *job = nullptr; 0570 0571 const QVariant colListVar = QVariant::fromValue<Collection::List>(Collection::List()); 0572 QVariant var; 0573 Collection::List collections; 0574 KMime::Message::Ptr msgPtr(new KMime::Message); 0575 0576 // test modifying a flag of a maildir items changes the entry name but not the 0577 // message contents 0578 Collection collection1; 0579 collection1.setName(QStringLiteral("collection1")); 0580 collection1.setRemoteId(QStringLiteral("collection1")); 0581 collection1.setParentCollection(mStore->topLevelCollection()); 0582 0583 // check that the \SEEN flag is not set yet 0584 QVERIFY(!md1.readEntryFlags(entryList1.first()).contains("\\SEEN")); 0585 0586 const QByteArray data1 = md1.readEntry(entryList1.first()); 0587 0588 msgPtr->setContent(KMime::CRLFtoLF(data1)); 0589 msgPtr->subject()->from7BitString("Modify Test"); 0590 msgPtr->assemble(); 0591 0592 Item item1; 0593 item1.setMimeType(KMime::Message::mimeType()); 0594 item1.setRemoteId(entryList1.first()); 0595 item1.setParentCollection(collection1); 0596 item1.setPayload<KMime::Message::Ptr>(msgPtr); 0597 item1.setFlag("\\SEEN"); 0598 0599 job = mStore->modifyItem(item1); 0600 // setting \SEEN so indicate a flags change and 0601 // setting new subject so indicate a payload change 0602 job->setParts(QSet<QByteArray>() << "FLAGS" << QByteArray("PLD:") + QByteArray(MessagePart::Header)); 0603 0604 QVERIFY(job->exec()); 0605 QCOMPARE(job->error(), 0); 0606 0607 Item item = job->item(); 0608 0609 // returned item should contain the change 0610 QVERIFY(item.flags().contains("\\SEEN")); 0611 0612 // remote ID has changed 0613 QVERIFY(item.remoteId() != entryList1.first()); 0614 QVERIFY(!md1.entryList().contains(entryList1.first())); 0615 0616 // no change in number of entries, one difference 0617 QStringList entryList3 = md1.entryList(); 0618 QCOMPARE(entryList3.count(), entryList1.count()); 0619 for (const QString &oldEntry : entryList1) { 0620 entryList3.removeAll(oldEntry); 0621 } 0622 QCOMPARE(entryList3.count(), 1); 0623 0624 // data changed 0625 QCOMPARE(md1.readEntry(entryList3.first()), msgPtr->encodedContent()); 0626 0627 var = job->property("onDiskIndexInvalidated"); 0628 QVERIFY(var.isValid()); 0629 QCOMPARE(var.userType(), colListVar.userType()); 0630 0631 collections = var.value<Collection::List>(); 0632 QCOMPARE((int)collections.count(), 1); 0633 QCOMPARE(collections.first(), collection1); 0634 0635 // fetch new item, check flag 0636 item1 = Item(); 0637 item1.setMimeType(KMime::Message::mimeType()); 0638 item1.setRemoteId(entryList3.first()); 0639 item1.setParentCollection(collection1); 0640 0641 FileStore::ItemFetchJob *itemFetch = mStore->fetchItem(item1); 0642 itemFetch->fetchScope().fetchFullPayload(); 0643 0644 QVERIFY(itemFetch->exec()); 0645 QCOMPARE(itemFetch->error(), 0); 0646 0647 QCOMPARE(itemFetch->items().count(), 1); 0648 Item fetchedItem = itemFetch->items().first(); 0649 QEXPECT_FAIL("", "ItemFetch handling needs to be fixed to also fetch flags", Continue); 0650 QVERIFY(fetchedItem.flags().contains("\\SEEN")); 0651 0652 QVERIFY(fetchedItem.hasPayload<KMime::Message::Ptr>()); 0653 auto fetchedMsgPtr = fetchedItem.payload<KMime::Message::Ptr>(); 0654 QCOMPARE(msgPtr->encodedContent(), fetchedMsgPtr->encodedContent()); 0655 0656 // TODO test for mbox. 0657 } 0658 0659 QTEST_MAIN(ItemModifyTest) 0660 0661 #include "itemmodifytest.moc"