1 /*  This file is part of the KDE project
2     SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
3     SPDX-FileContributor: Kevin Krammer <krake@kdab.com>
4 
5     SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #include "mixedmaildirstore.h"
9 
10 #include "collectioncreatejob.h"
11 #include "collectiondeletejob.h"
12 #include "collectionfetchjob.h"
13 #include "collectionmodifyjob.h"
14 #include "collectionmovejob.h"
15 #include "itemcreatejob.h"
16 #include "itemdeletejob.h"
17 #include "itemfetchjob.h"
18 #include "itemmodifyjob.h"
19 #include "itemmovejob.h"
20 #include "sessionimpls_p.h"
21 #include "storecompactjob.h"
22 
23 #include <Akonadi/KMime/MessageParts>
24 
25 #include <Akonadi/CachePolicy>
26 
27 #include <KMime/Message>
28 
29 #include <KRandom>
30 #include <QRandomGenerator>
31 #include <QTemporaryDir>
32 
33 #include <QTest>
34 
35 using namespace Akonadi;
36 
37 class TestStore : public MixedMaildirStore
38 {
39     Q_OBJECT
40 
41 public:
TestStore()42     TestStore()
43         : mLastCheckedJob(nullptr)
44         , mErrorCode(0)
45     {
46     }
47 
48 public:
49     Collection mTopLevelCollection;
50 
51     mutable FileStore::Job *mLastCheckedJob = nullptr;
52     mutable int mErrorCode;
53     mutable QString mErrorText;
54 
55 protected:
setTopLevelCollection(const Collection & collection)56     void setTopLevelCollection(const Collection &collection) override
57     {
58         MixedMaildirStore::setTopLevelCollection(collection);
59     }
60 
checkCollectionMove(FileStore::CollectionMoveJob * job,int & errorCode,QString & errorText) const61     void checkCollectionMove(FileStore::CollectionMoveJob *job, int &errorCode, QString &errorText) const override
62     {
63         MixedMaildirStore::checkCollectionMove(job, errorCode, errorText);
64 
65         mLastCheckedJob = job;
66         mErrorCode = errorCode;
67         mErrorText = errorText;
68     }
69 
checkItemCreate(FileStore::ItemCreateJob * job,int & errorCode,QString & errorText) const70     void checkItemCreate(FileStore::ItemCreateJob *job, int &errorCode, QString &errorText) const override
71     {
72         MixedMaildirStore::checkItemCreate(job, errorCode, errorText);
73 
74         mLastCheckedJob = job;
75         mErrorCode = errorCode;
76         mErrorText = errorText;
77     }
78 };
79 
80 class TemplateMethodsTest : public QObject
81 {
82     Q_OBJECT
83 
84 public:
TemplateMethodsTest()85     TemplateMethodsTest()
86         : QObject()
87         , mStore(nullptr)
88     {
89     }
90 
~TemplateMethodsTest()91     ~TemplateMethodsTest() override
92     {
93         delete mStore;
94     }
95 
96 private:
97     QTemporaryDir mDir;
98     TestStore *mStore = nullptr;
99 
100 private Q_SLOTS:
101     void init();
102     void testSetTopLevelCollection();
103     void testMoveCollection();
104     void testCreateItem();
105 };
106 
init()107 void TemplateMethodsTest::init()
108 {
109     delete mStore;
110     mStore = new TestStore;
111     QVERIFY(mDir.isValid());
112     QVERIFY(QDir(mDir.path()).exists());
113 }
114 
testSetTopLevelCollection()115 void TemplateMethodsTest::testSetTopLevelCollection()
116 {
117     const QString file = KRandom::randomString(10);
118     const QString path = mDir.path() + file;
119 
120     mStore->setPath(path);
121 
122     // check the adjustments on the top level collection
123     const Collection collection = mStore->topLevelCollection();
124     QCOMPARE(collection.contentMimeTypes(), QStringList() << Collection::mimeType());
125     QCOMPARE(collection.rights(), Collection::CanCreateCollection | Collection::CanChangeCollection | Collection::CanDeleteCollection);
126     const CachePolicy cachePolicy = collection.cachePolicy();
127     QVERIFY(!cachePolicy.inheritFromParent());
128     QCOMPARE(cachePolicy.localParts(), QStringList() << QLatin1String(MessagePart::Envelope));
129     QVERIFY(cachePolicy.syncOnDemand());
130 }
131 
testMoveCollection()132 void TemplateMethodsTest::testMoveCollection()
133 {
134     mStore->setPath(mDir.path());
135 
136     FileStore::CollectionMoveJob *job = nullptr;
137 
138     // test moving into itself
139     Collection collection(QRandomGenerator::global()->generate());
140     collection.setParentCollection(mStore->topLevelCollection());
141     collection.setRemoteId(QStringLiteral("collection"));
142     job = mStore->moveCollection(collection, collection);
143     QVERIFY(job != nullptr);
144     QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
145     QVERIFY(!job->errorText().isEmpty());
146     QCOMPARE(mStore->mLastCheckedJob, job);
147     QCOMPARE(mStore->mErrorCode, job->error());
148     QCOMPARE(mStore->mErrorText, job->errorText());
149 
150     QVERIFY(!job->exec());
151 
152     // test moving into child
153     Collection childCollection(collection.id() + 1);
154     childCollection.setParentCollection(collection);
155     childCollection.setRemoteId(QStringLiteral("child"));
156     job = mStore->moveCollection(collection, childCollection);
157     QVERIFY(job != nullptr);
158     QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
159     QVERIFY(!job->errorText().isEmpty());
160     QCOMPARE(mStore->mLastCheckedJob, job);
161     QCOMPARE(mStore->mErrorCode, job->error());
162     QCOMPARE(mStore->mErrorText, job->errorText());
163 
164     QVERIFY(!job->exec());
165 
166     // test moving into grand child child
167     Collection grandChildCollection(collection.id() + 2);
168     grandChildCollection.setParentCollection(childCollection);
169     grandChildCollection.setRemoteId(QStringLiteral("grandchild"));
170     job = mStore->moveCollection(collection, grandChildCollection);
171     QVERIFY(job != nullptr);
172     QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
173     QVERIFY(!job->errorText().isEmpty());
174     QCOMPARE(mStore->mLastCheckedJob, job);
175     QCOMPARE(mStore->mErrorCode, job->error());
176     QCOMPARE(mStore->mErrorText, job->errorText());
177 
178     QVERIFY(!job->exec());
179 
180     // test moving into unrelated collection
181     Collection otherCollection(collection.id() + QRandomGenerator::global()->generate());
182     otherCollection.setParentCollection(mStore->topLevelCollection());
183     otherCollection.setRemoteId(QStringLiteral("other"));
184     job = mStore->moveCollection(collection, otherCollection);
185     QVERIFY(job != nullptr);
186     QCOMPARE(job->error(), 0);
187     QVERIFY(job->errorText().isEmpty());
188     QCOMPARE(mStore->mLastCheckedJob, job);
189 
190     // collections don't exist in the store, so processing still fails
191     QVERIFY(!job->exec());
192 }
193 
testCreateItem()194 void TemplateMethodsTest::testCreateItem()
195 {
196     mStore->setPath(mDir.path());
197 
198     Collection collection(QRandomGenerator::global()->generate());
199     collection.setParentCollection(mStore->topLevelCollection());
200     collection.setRemoteId(QStringLiteral("collection"));
201 
202     FileStore::ItemCreateJob *job = nullptr;
203 
204     // test item without payload
205     Item item(KMime::Message::mimeType());
206     job = mStore->createItem(item, collection);
207     QVERIFY(job != nullptr);
208     QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
209     QVERIFY(!job->errorText().isEmpty());
210     QCOMPARE(mStore->mLastCheckedJob, job);
211     QCOMPARE(mStore->mErrorCode, job->error());
212     QCOMPARE(mStore->mErrorText, job->errorText());
213 
214     QVERIFY(!job->exec());
215 
216     // test item with payload
217     item.setPayloadFromData("Subject: dummy payload\n\nwith some content");
218     job = mStore->createItem(item, collection);
219     QVERIFY(job != nullptr);
220     QCOMPARE(job->error(), 0);
221     QVERIFY(job->errorText().isEmpty());
222     QCOMPARE(mStore->mLastCheckedJob, job);
223 
224     // collections don't exist in the store, so processing still fails
225     QVERIFY(!job->exec());
226 }
227 
228 QTEST_MAIN(TemplateMethodsTest)
229 
230 #include "templatemethodstest.moc"
231