File indexing completed on 2024-12-22 04:57:38

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-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "mixedmaildirstore.h"
0009 
0010 #include "testdatautil.h"
0011 
0012 #include "filestore/entitycompactchangeattribute.h"
0013 #include "filestore/itemfetchjob.h"
0014 #include "filestore/itemmovejob.h"
0015 #include "filestore/storecompactjob.h"
0016 
0017 #include "libmaildir/maildir.h"
0018 
0019 #include <KMbox/MBox>
0020 
0021 #include <KRandom>
0022 
0023 #include <QDir>
0024 #include <QFileInfo>
0025 #include <QRandomGenerator>
0026 #include <QTemporaryDir>
0027 #include <QTest>
0028 using namespace Akonadi;
0029 using namespace KMBox;
0030 
0031 static bool fullEntryCompare(const MBoxEntry &a, const MBoxEntry &b)
0032 {
0033     return a.messageOffset() == b.messageOffset() && a.separatorSize() == b.separatorSize() && a.messageSize() == b.messageSize();
0034 }
0035 
0036 static quint64 changedOffset(const Item &item)
0037 {
0038     Q_ASSERT(item.hasAttribute<FileStore::EntityCompactChangeAttribute>());
0039 
0040     const QString remoteId = item.attribute<FileStore::EntityCompactChangeAttribute>()->remoteId();
0041     Q_ASSERT(!remoteId.isEmpty());
0042 
0043     bool ok = false;
0044     const quint64 result = remoteId.toULongLong(&ok);
0045     Q_ASSERT(ok);
0046 
0047     return result;
0048 }
0049 
0050 class ItemMoveTest : public QObject
0051 {
0052     Q_OBJECT
0053 
0054 public:
0055     ItemMoveTest()
0056         : QObject()
0057         , mStore(nullptr)
0058         , mDir(nullptr)
0059     {
0060     }
0061 
0062     ~ItemMoveTest() override
0063     {
0064         delete mStore;
0065         delete mDir;
0066     }
0067 
0068 private:
0069     MixedMaildirStore *mStore = nullptr;
0070     QTemporaryDir *mDir = nullptr;
0071 
0072 private Q_SLOTS:
0073     void init();
0074     void cleanup();
0075     void testExpectedFail();
0076     void testMaildirItem();
0077     void testMBoxItem();
0078 };
0079 
0080 void ItemMoveTest::init()
0081 {
0082     mStore = new MixedMaildirStore;
0083 
0084     mDir = new QTemporaryDir;
0085     QVERIFY(mDir->isValid());
0086     QVERIFY(QDir(mDir->path()).exists());
0087 }
0088 
0089 void ItemMoveTest::cleanup()
0090 {
0091     delete mStore;
0092     mStore = nullptr;
0093     delete mDir;
0094     mDir = nullptr;
0095 }
0096 
0097 void ItemMoveTest::testExpectedFail()
0098 {
0099     QDir topDir(mDir->path());
0100 
0101     QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), topDir.path(), QStringLiteral("collection1")));
0102     QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), topDir.path(), QStringLiteral("collection2")));
0103 
0104     KPIM::Maildir topLevelMd(topDir.path(), true);
0105 
0106     KPIM::Maildir md1 = topLevelMd.subFolder(QStringLiteral("collection1"));
0107     QStringList md1EntryList = md1.entryList();
0108     QSet<QString> entrySet1(md1EntryList.cbegin(), md1EntryList.cend());
0109     QCOMPARE((int)entrySet1.count(), 4);
0110 
0111     QFileInfo fileInfo2(topDir.path(), QStringLiteral("collection2"));
0112     MBox mbox2;
0113     QVERIFY(mbox2.load(fileInfo2.absoluteFilePath()));
0114     const MBoxEntry::List entryList2 = mbox2.entries();
0115     QCOMPARE((int)entryList2.count(), 4);
0116 
0117     QSet<qint64> entrySet2;
0118     for (const MBoxEntry &entry : entryList2) {
0119         entrySet2 << entry.messageOffset();
0120     }
0121 
0122     mStore->setPath(topDir.path());
0123 
0124     // common variables
0125     FileStore::ItemMoveJob *job = nullptr;
0126 
0127     // test failure of moving from a non-existent collection
0128     Collection collection1;
0129     collection1.setName(QStringLiteral("collection1"));
0130     collection1.setRemoteId(QStringLiteral("collection1"));
0131     collection1.setParentCollection(mStore->topLevelCollection());
0132 
0133     Collection collection3;
0134     collection3.setName(QStringLiteral("collection3"));
0135     collection3.setRemoteId(QStringLiteral("collection3"));
0136     collection3.setParentCollection(mStore->topLevelCollection());
0137 
0138     Item item3;
0139     item3.setRemoteId(QStringLiteral("item3"));
0140     item3.setParentCollection(collection3);
0141 
0142     job = mStore->moveItem(item3, collection1);
0143     QVERIFY(!job->exec());
0144     QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
0145 
0146     md1EntryList = md1.entryList();
0147     QCOMPARE(QSet<QString>(md1EntryList.cbegin(), md1EntryList.cend()), entrySet1);
0148 
0149     // test failure of moving from maildir to non-existent collection
0150     Item item1;
0151     item1.setId(QRandomGenerator::global()->generate());
0152     item1.setRemoteId(*entrySet1.cbegin());
0153     item1.setParentCollection(collection1);
0154 
0155     job = mStore->moveItem(item1, collection3);
0156     QVERIFY(!job->exec());
0157     QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
0158 
0159     md1EntryList = md1.entryList();
0160     QCOMPARE(QSet<QString>(md1EntryList.cbegin(), md1EntryList.cend()), entrySet1);
0161 
0162     // test failure of moving from mbox to non-existent collection
0163     Collection collection2;
0164     collection2.setName(QStringLiteral("collection2"));
0165     collection2.setRemoteId(QStringLiteral("collection2"));
0166     collection2.setParentCollection(mStore->topLevelCollection());
0167 
0168     Item item2;
0169     item2.setId(QRandomGenerator::global()->generate());
0170     item2.setRemoteId(QStringLiteral("0"));
0171     item2.setParentCollection(collection2);
0172 
0173     job = mStore->moveItem(item1, collection3);
0174     QVERIFY(!job->exec());
0175     QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
0176 
0177     QVERIFY(mbox2.load(fileInfo2.absoluteFilePath()));
0178     MBoxEntry::List tmpEntryList = mbox2.entries();
0179     QVERIFY(std::equal(tmpEntryList.begin(), tmpEntryList.end(), entryList2.begin(), fullEntryCompare));
0180 
0181     // test failure of moving from maildir to top level collection
0182     job = mStore->moveItem(item1, mStore->topLevelCollection());
0183     QVERIFY(!job->exec());
0184     QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
0185 
0186     md1EntryList = md1.entryList();
0187     QCOMPARE(QSet<QString>(md1EntryList.cbegin(), md1EntryList.cend()), entrySet1);
0188 
0189     // test failure of moving from mbox to top level collection
0190     job = mStore->moveItem(item1, mStore->topLevelCollection());
0191     QVERIFY(!job->exec());
0192     QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
0193 
0194     QVERIFY(mbox2.load(fileInfo2.absoluteFilePath()));
0195     tmpEntryList = mbox2.entries();
0196     QVERIFY(std::equal(tmpEntryList.begin(), tmpEntryList.end(), entryList2.begin(), fullEntryCompare));
0197 
0198     // test failure of moving a non-existent maildir entry
0199     QString remoteId1;
0200     do {
0201         remoteId1 = KRandom::randomString(20);
0202     } while (entrySet1.contains(remoteId1));
0203 
0204     item1.setRemoteId(remoteId1);
0205 
0206     job = mStore->moveItem(item1, collection2);
0207     QVERIFY(!job->exec());
0208     QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
0209 
0210     md1EntryList = md1.entryList();
0211     QCOMPARE(QSet<QString>(md1EntryList.cbegin(), md1EntryList.cend()), entrySet1);
0212     QVERIFY(mbox2.load(fileInfo2.absoluteFilePath()));
0213     tmpEntryList = mbox2.entries();
0214     QVERIFY(std::equal(tmpEntryList.begin(), tmpEntryList.end(), entryList2.begin(), fullEntryCompare));
0215 
0216     // test failure of moving a non-existent mbox entry
0217     quint64 remoteId2;
0218     do {
0219         remoteId2 = QRandomGenerator::global()->generate();
0220     } while (entrySet2.contains(remoteId2));
0221 
0222     item2.setRemoteId(QString::number(remoteId2));
0223 
0224     job = mStore->moveItem(item2, collection1);
0225     QVERIFY(!job->exec());
0226     QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
0227 
0228     md1EntryList = md1.entryList();
0229     QCOMPARE(QSet<QString>(md1EntryList.cbegin(), md1EntryList.cend()), entrySet1);
0230     QVERIFY(mbox2.load(fileInfo2.absoluteFilePath()));
0231     tmpEntryList = mbox2.entries();
0232     QVERIFY(std::equal(tmpEntryList.begin(), tmpEntryList.end(), entryList2.begin(), fullEntryCompare));
0233 }
0234 
0235 void ItemMoveTest::testMaildirItem()
0236 {
0237     QDir topDir(mDir->path());
0238 
0239     QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), topDir.path(), QStringLiteral("collection1")));
0240     QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), topDir.path(), QStringLiteral("collection2")));
0241     QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), topDir.path(), QStringLiteral("collection5")));
0242 
0243     KPIM::Maildir topLevelMd(topDir.path(), true);
0244 
0245     KPIM::Maildir md1 = topLevelMd.subFolder(QStringLiteral("collection1"));
0246     QStringList md1EntryList = md1.entryList();
0247     QSet<QString> entrySet1(md1EntryList.cbegin(), md1EntryList.cend());
0248     QCOMPARE((int)entrySet1.count(), 4);
0249 
0250     QFileInfo fileInfo2(topDir.path(), QStringLiteral("collection2"));
0251     MBox mbox2;
0252     QVERIFY(mbox2.load(fileInfo2.absoluteFilePath()));
0253     MBoxEntry::List entryList2 = mbox2.entries();
0254     QCOMPARE((int)entryList2.count(), 4);
0255 
0256     KPIM::Maildir md3(topLevelMd.addSubFolder(QStringLiteral("collection3")), false);
0257     QVERIFY(md3.isValid());
0258     QStringList md3EntryList = md3.entryList();
0259     QSet<QString> entrySet3(md3EntryList.cbegin(), md3EntryList.cend());
0260     QCOMPARE((int)entrySet3.count(), 0);
0261 
0262     QFileInfo fileInfo4(topDir.path(), QStringLiteral("collection4"));
0263     QFile file4(fileInfo4.absoluteFilePath());
0264     QVERIFY(file4.open(QIODevice::WriteOnly));
0265     file4.close();
0266     fileInfo4.refresh();
0267     QVERIFY(fileInfo4.exists());
0268     MBox mbox4;
0269     QVERIFY(mbox4.load(fileInfo4.absoluteFilePath()));
0270     MBoxEntry::List entryList4 = mbox4.entries();
0271     QCOMPARE((int)entryList4.count(), 0);
0272 
0273     KPIM::Maildir md5 = topLevelMd.subFolder(QStringLiteral("collection5"));
0274     QStringList md5EntryList = md5.entryList();
0275     QSet<QString> entrySet5(md5EntryList.cbegin(), md5EntryList.cend());
0276     QCOMPARE((int)entrySet5.count(), 4);
0277 
0278     mStore->setPath(topDir.path());
0279 
0280     // common variables
0281     FileStore::ItemMoveJob *job = nullptr;
0282 
0283     const QVariant colListVar = QVariant::fromValue<Collection::List>(Collection::List());
0284     QVariant var;
0285     Collection::List collections;
0286     Item movedItem;
0287     MBoxEntry::List entryList;
0288 
0289     // test moving to an empty maildir
0290     Collection collection1;
0291     collection1.setName(QStringLiteral("collection1"));
0292     collection1.setRemoteId(QStringLiteral("collection1"));
0293     collection1.setParentCollection(mStore->topLevelCollection());
0294 
0295     Collection collection3;
0296     collection3.setName(QStringLiteral("collection3"));
0297     collection3.setRemoteId(QStringLiteral("collection3"));
0298     collection3.setParentCollection(mStore->topLevelCollection());
0299 
0300     Item item1;
0301     item1.setId(QRandomGenerator::global()->generate());
0302     item1.setRemoteId(*entrySet1.cbegin());
0303     item1.setParentCollection(collection1);
0304 
0305     job = mStore->moveItem(item1, collection3);
0306 
0307     QVERIFY(job->exec());
0308     QCOMPARE(job->error(), 0);
0309 
0310     movedItem = job->item();
0311     QCOMPARE(movedItem.id(), item1.id());
0312     QCOMPARE(movedItem.parentCollection(), collection3);
0313 
0314     entrySet3 << movedItem.remoteId();
0315     md3EntryList = md3.entryList();
0316     QCOMPARE(QSet<QString>(md3EntryList.cbegin(), md3EntryList.cend()), entrySet3);
0317     entrySet1.remove(item1.remoteId());
0318     md1EntryList = md1.entryList();
0319     QCOMPARE(QSet<QString>(md1EntryList.cbegin(), md1EntryList.cend()), entrySet1);
0320 
0321     // check for index preservation
0322     var = job->property("onDiskIndexInvalidated");
0323     QVERIFY(var.isValid());
0324     QCOMPARE(var.userType(), colListVar.userType());
0325 
0326     collections = var.value<Collection::List>();
0327     QCOMPARE((int)collections.count(), 1);
0328     QCOMPARE(collections.first(), collection1);
0329 
0330     // test moving to a non empty maildir
0331     item1.setRemoteId(*entrySet1.cbegin());
0332 
0333     Collection collection5;
0334     collection5.setName(QStringLiteral("collection5"));
0335     collection5.setRemoteId(QStringLiteral("collection5"));
0336     collection5.setParentCollection(mStore->topLevelCollection());
0337 
0338     job = mStore->moveItem(item1, collection5);
0339 
0340     QVERIFY(job->exec());
0341     QCOMPARE(job->error(), 0);
0342 
0343     movedItem = job->item();
0344     QCOMPARE(movedItem.id(), item1.id());
0345     QCOMPARE(movedItem.parentCollection(), collection5);
0346 
0347     entrySet5 << movedItem.remoteId();
0348     md5EntryList = md5.entryList();
0349     QCOMPARE(QSet<QString>(md5EntryList.cbegin(), md5EntryList.cend()), entrySet5);
0350     entrySet1.remove(item1.remoteId());
0351     md1EntryList = md1.entryList();
0352     QCOMPARE(QSet<QString>(md1EntryList.cbegin(), md1EntryList.cend()), entrySet1);
0353 
0354     // check for index preservation
0355     var = job->property("onDiskIndexInvalidated");
0356     QVERIFY(var.isValid());
0357     QCOMPARE(var.userType(), colListVar.userType());
0358 
0359     collections = var.value<Collection::List>();
0360     QCOMPARE((int)collections.count(), 2);
0361     QCOMPARE(collections, Collection::List() << collection1 << collection5);
0362 
0363     // test moving to an empty mbox
0364     Collection collection4;
0365     collection4.setName(QStringLiteral("collection4"));
0366     collection4.setRemoteId(QStringLiteral("collection4"));
0367     collection4.setParentCollection(mStore->topLevelCollection());
0368 
0369     item1.setRemoteId(*entrySet1.cbegin());
0370 
0371     job = mStore->moveItem(item1, collection4);
0372 
0373     QVERIFY(job->exec());
0374     QCOMPARE(job->error(), 0);
0375 
0376     movedItem = job->item();
0377     QCOMPARE(movedItem.id(), item1.id());
0378     QCOMPARE(movedItem.parentCollection(), collection4);
0379 
0380     QVERIFY(mbox4.load(mbox4.fileName()));
0381     entryList = mbox4.entries();
0382     QCOMPARE((int)entryList.count(), 1);
0383 
0384     QCOMPARE(entryList.last().messageOffset(), movedItem.remoteId().toULongLong());
0385     entrySet1.remove(item1.remoteId());
0386     md1EntryList = md1.entryList();
0387     QCOMPARE(QSet<QString>(md1EntryList.cbegin(), md1EntryList.cend()), entrySet1);
0388 
0389     // check for index preservation
0390     var = job->property("onDiskIndexInvalidated");
0391     QVERIFY(var.isValid());
0392     QCOMPARE(var.userType(), colListVar.userType());
0393 
0394     collections = var.value<Collection::List>();
0395     QCOMPARE((int)collections.count(), 1);
0396     QCOMPARE(collections.first(), collection1);
0397 
0398     // test moving to a non empty mbox
0399     item1.setRemoteId(*entrySet1.cbegin());
0400 
0401     Collection collection2;
0402     collection2.setName(QStringLiteral("collection2"));
0403     collection2.setRemoteId(QStringLiteral("collection2"));
0404     collection2.setParentCollection(mStore->topLevelCollection());
0405 
0406     job = mStore->moveItem(item1, collection2);
0407 
0408     QVERIFY(job->exec());
0409     QCOMPARE(job->error(), 0);
0410 
0411     movedItem = job->item();
0412     QCOMPARE(movedItem.id(), item1.id());
0413     QCOMPARE(movedItem.parentCollection(), collection2);
0414 
0415     QVERIFY(mbox2.load(mbox2.fileName()));
0416     entryList = mbox2.entries();
0417     QCOMPARE((int)entryList.count(), 5);
0418 
0419     QCOMPARE(entryList.last().messageOffset(), movedItem.remoteId().toULongLong());
0420     entrySet1.remove(item1.remoteId());
0421     md1EntryList = md1.entryList();
0422     QCOMPARE(QSet<QString>(md1EntryList.cbegin(), md1EntryList.cend()), entrySet1);
0423 
0424     // check for index preservation
0425     var = job->property("onDiskIndexInvalidated");
0426     QVERIFY(var.isValid());
0427     QCOMPARE(var.userType(), colListVar.userType());
0428 
0429     collections = var.value<Collection::List>();
0430     QCOMPARE((int)collections.count(), 2);
0431     QCOMPARE(collections, Collection::List() << collection1 << collection2);
0432 }
0433 
0434 void ItemMoveTest::testMBoxItem()
0435 {
0436     QDir topDir(mDir->path());
0437 
0438     QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), topDir.path(), QStringLiteral("collection1")));
0439     QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), topDir.path(), QStringLiteral("collection2")));
0440     QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), topDir.path(), QStringLiteral("collection5")));
0441 
0442     QFileInfo fileInfo1(topDir.path(), QStringLiteral("collection1"));
0443     MBox mbox1;
0444     QVERIFY(mbox1.load(fileInfo1.absoluteFilePath()));
0445     MBoxEntry::List entryList1 = mbox1.entries();
0446     QCOMPARE((int)entryList1.count(), 4);
0447 
0448     KPIM::Maildir topLevelMd(topDir.path(), true);
0449 
0450     KPIM::Maildir md2 = topLevelMd.subFolder(QStringLiteral("collection2"));
0451     QStringList md2EntryList = md2.entryList();
0452     QSet<QString> entrySet2(md2EntryList.cbegin(), md2EntryList.cend());
0453     QCOMPARE((int)entrySet2.count(), 4);
0454 
0455     KPIM::Maildir md3(topLevelMd.addSubFolder(QStringLiteral("collection3")), false);
0456     QVERIFY(md3.isValid());
0457     QStringList md3EntryList = md3.entryList();
0458     QSet<QString> entrySet3(md3EntryList.cbegin(), md3EntryList.cend());
0459     QCOMPARE((int)entrySet3.count(), 0);
0460 
0461     QFileInfo fileInfo4(topDir.path(), QStringLiteral("collection4"));
0462     QFile file4(fileInfo4.absoluteFilePath());
0463     QVERIFY(file4.open(QIODevice::WriteOnly));
0464     file4.close();
0465     fileInfo4.refresh();
0466     QVERIFY(fileInfo4.exists());
0467     MBox mbox4;
0468     QVERIFY(mbox4.load(fileInfo4.absoluteFilePath()));
0469     MBoxEntry::List entryList4 = mbox4.entries();
0470     QCOMPARE((int)entryList4.count(), 0);
0471 
0472     QFileInfo fileInfo5(topDir.path(), QStringLiteral("collection5"));
0473     MBox mbox5;
0474     QVERIFY(mbox5.load(fileInfo5.absoluteFilePath()));
0475     MBoxEntry::List entryList5 = mbox5.entries();
0476     QCOMPARE((int)entryList5.count(), 4);
0477 
0478     mStore->setPath(topDir.path());
0479 
0480     // common variables
0481     FileStore::ItemMoveJob *job = nullptr;
0482     FileStore::StoreCompactJob *compactStore = nullptr;
0483 
0484     const QVariant colListVar = QVariant::fromValue<Collection::List>(Collection::List());
0485     QVariant var;
0486     Collection::List collections;
0487     Item movedItem;
0488     MBoxEntry::List entryList;
0489     Item::List items;
0490 
0491     // test moving to an empty maildir
0492     Collection collection1;
0493     collection1.setName(QStringLiteral("collection1"));
0494     collection1.setRemoteId(QStringLiteral("collection1"));
0495     collection1.setParentCollection(mStore->topLevelCollection());
0496 
0497     Collection collection3;
0498     collection3.setName(QStringLiteral("collection3"));
0499     collection3.setRemoteId(QStringLiteral("collection3"));
0500     collection3.setParentCollection(mStore->topLevelCollection());
0501 
0502     Item item1;
0503     item1.setId(QRandomGenerator::global()->generate());
0504     item1.setRemoteId(QString::number(entryList1.first().messageOffset()));
0505     item1.setParentCollection(collection1);
0506 
0507     job = mStore->moveItem(item1, collection3);
0508 
0509     QVERIFY(job->exec());
0510     QCOMPARE(job->error(), 0);
0511 
0512     movedItem = job->item();
0513     QCOMPARE(movedItem.id(), item1.id());
0514     QCOMPARE(movedItem.parentCollection(), collection3);
0515 
0516     var = job->property("compactStore");
0517     QVERIFY(var.isValid());
0518     QCOMPARE(var.userType(), QMetaType::Bool);
0519     QCOMPARE(var.toBool(), true);
0520 
0521     compactStore = mStore->compactStore();
0522     QVERIFY(compactStore->exec());
0523 
0524     items = compactStore->changedItems();
0525     QCOMPARE((int)items.count(), 3);
0526 
0527     entrySet3 << movedItem.remoteId();
0528     md3EntryList = md3.entryList();
0529     QCOMPARE(QSet<QString>(md3EntryList.cbegin(), md3EntryList.cend()), entrySet3);
0530 
0531     entryList1.removeAt(0);
0532     entryList1[0] = MBoxEntry(changedOffset(items[0]));
0533     entryList1[1] = MBoxEntry(changedOffset(items[1]));
0534     entryList1[2] = MBoxEntry(changedOffset(items[2]));
0535     QVERIFY(mbox1.load(mbox1.fileName()));
0536     QCOMPARE(mbox1.entries(), entryList1);
0537 
0538     // test moving to a non empty mbox
0539     Collection collection5;
0540     collection5.setName(QStringLiteral("collection5"));
0541     collection5.setRemoteId(QStringLiteral("collection5"));
0542     collection5.setParentCollection(mStore->topLevelCollection());
0543 
0544     job = mStore->moveItem(item1, collection5);
0545 
0546     QVERIFY(job->exec());
0547     QCOMPARE(job->error(), 0);
0548 
0549     movedItem = job->item();
0550     QCOMPARE(movedItem.id(), item1.id());
0551     QCOMPARE(movedItem.parentCollection(), collection5);
0552 
0553     var = job->property("compactStore");
0554     QVERIFY(var.isValid());
0555     QCOMPARE(var.userType(), QMetaType::Bool);
0556     QCOMPARE(var.toBool(), true);
0557 
0558     // check for index preservation
0559     var = job->property("onDiskIndexInvalidated");
0560     QVERIFY(var.isValid());
0561     QCOMPARE(var.userType(), colListVar.userType());
0562 
0563     collections = var.value<Collection::List>();
0564     QCOMPARE((int)collections.count(), 2);
0565     QCOMPARE(collections, Collection::List() << collection1 << collection5);
0566 
0567     compactStore = mStore->compactStore();
0568     QVERIFY(compactStore->exec());
0569 
0570     items = compactStore->changedItems();
0571     QCOMPARE((int)items.count(), 2);
0572 
0573     QVERIFY(mbox5.load(mbox5.fileName()));
0574     QCOMPARE(mbox5.entries().count(), entryList5.count() + 1);
0575     QCOMPARE(mbox5.entries().last().messageOffset(), movedItem.remoteId().toULongLong());
0576 
0577     entryList1.removeAt(0);
0578     entryList1[0] = MBoxEntry(changedOffset(items[0]));
0579     entryList1[1] = MBoxEntry(changedOffset(items[1]));
0580     QVERIFY(mbox1.load(mbox1.fileName()));
0581     QCOMPARE(mbox1.entries(), entryList1);
0582 
0583     // test moving to an empty mbox
0584     Collection collection4;
0585     collection4.setName(QStringLiteral("collection4"));
0586     collection4.setRemoteId(QStringLiteral("collection4"));
0587     collection4.setParentCollection(mStore->topLevelCollection());
0588 
0589     job = mStore->moveItem(item1, collection4);
0590 
0591     QVERIFY(job->exec());
0592     QCOMPARE(job->error(), 0);
0593 
0594     movedItem = job->item();
0595     QCOMPARE(movedItem.id(), item1.id());
0596     QCOMPARE(movedItem.parentCollection(), collection4);
0597 
0598     QVERIFY(mbox4.load(mbox4.fileName()));
0599     entryList = mbox4.entries();
0600     QCOMPARE((int)entryList.count(), 1);
0601 
0602     QCOMPARE(entryList.last().messageOffset(), movedItem.remoteId().toULongLong());
0603 
0604     var = job->property("compactStore");
0605     QVERIFY(var.isValid());
0606     QCOMPARE(var.userType(), QMetaType::Bool);
0607     QCOMPARE(var.toBool(), true);
0608 
0609     // check for index preservation
0610     var = job->property("onDiskIndexInvalidated");
0611     QVERIFY(var.isValid());
0612     QCOMPARE(var.userType(), colListVar.userType());
0613 
0614     collections = var.value<Collection::List>();
0615     QCOMPARE((int)collections.count(), 1);
0616     QCOMPARE(collections.first(), collection1);
0617 
0618     compactStore = mStore->compactStore();
0619     QVERIFY(compactStore->exec());
0620 
0621     items = compactStore->changedItems();
0622     QCOMPARE((int)items.count(), 1);
0623 
0624     QCOMPARE(mbox4.entries().count(), entryList4.count() + 1);
0625     QCOMPARE(mbox4.entries().last().messageOffset(), movedItem.remoteId().toULongLong());
0626 
0627     entryList1.removeAt(0);
0628     entryList1[0] = MBoxEntry(changedOffset(items[0]));
0629     QVERIFY(mbox1.load(mbox1.fileName()));
0630     QCOMPARE(mbox1.entries(), entryList1);
0631 
0632     // test moving to a non empty maildir
0633     Collection collection2;
0634     collection2.setName(QStringLiteral("collection2"));
0635     collection2.setRemoteId(QStringLiteral("collection2"));
0636     collection2.setParentCollection(mStore->topLevelCollection());
0637 
0638     job = mStore->moveItem(item1, collection2);
0639 
0640     QVERIFY(job->exec());
0641     QCOMPARE(job->error(), 0);
0642 
0643     movedItem = job->item();
0644     QCOMPARE(movedItem.id(), item1.id());
0645     QCOMPARE(movedItem.parentCollection(), collection2);
0646 
0647     md2EntryList = md2.entryList();
0648     QSet<QString> entrySet(md2EntryList.cbegin(), md2EntryList.cend());
0649     QCOMPARE((int)entrySet.count(), 5);
0650 
0651     QVERIFY(entrySet.contains(movedItem.remoteId()));
0652 
0653     var = job->property("compactStore");
0654     QVERIFY(var.isValid());
0655     QCOMPARE(var.userType(), QMetaType::Bool);
0656     QCOMPARE(var.toBool(), true);
0657 
0658     // check for index preservation
0659     var = job->property("onDiskIndexInvalidated");
0660     QVERIFY(var.isValid());
0661     QCOMPARE(var.userType(), colListVar.userType());
0662 
0663     collections = var.value<Collection::List>();
0664     QCOMPARE((int)collections.count(), 2);
0665     QCOMPARE(collections.first(), collection1);
0666 
0667     compactStore = mStore->compactStore();
0668     QVERIFY(compactStore->exec());
0669 
0670     items = compactStore->changedItems();
0671     QCOMPARE((int)items.count(), 0);
0672 
0673     entryList1.removeAt(0);
0674     QVERIFY(mbox1.load(mbox1.fileName()));
0675     const MBoxEntry::List newEntryList = mbox1.entries();
0676     QVERIFY(std::equal(newEntryList.begin(), newEntryList.end(), entryList1.begin(), fullEntryCompare));
0677 }
0678 
0679 QTEST_MAIN(ItemMoveTest)
0680 
0681 #include "itemmovetest.moc"