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 "abstractlocalstore.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 <KRandom>
24 #include <QRandomGenerator>
25
26 #include <QTest>
27
28 using namespace Akonadi;
29 using namespace Akonadi::FileStore;
30
31 class TestStore : public AbstractLocalStore
32 {
33 Q_OBJECT
34
35 public:
TestStore()36 TestStore()
37 : mLastCheckedJob(nullptr)
38 , mLastProcessedJob(nullptr)
39 , mErrorCode(0)
40 {
41 }
42
43 public:
44 mutable Akonadi::FileStore::Job *mLastCheckedJob = nullptr;
45 Akonadi::FileStore::Job *mLastProcessedJob = nullptr;
46
47 Collection mTopLevelCollection;
48
49 int mErrorCode;
50 QString mErrorText;
51
52 protected:
53 void processJob(Akonadi::FileStore::Job *job) override;
54
55 protected:
setTopLevelCollection(const Collection & collection)56 void setTopLevelCollection(const Collection &collection) override
57 {
58 mTopLevelCollection = collection;
59
60 Collection modifiedCollection = collection;
61 modifiedCollection.setContentMimeTypes(QStringList() << Collection::mimeType());
62
63 AbstractLocalStore::setTopLevelCollection(modifiedCollection);
64 }
65
checkCollectionCreate(Akonadi::FileStore::CollectionCreateJob * job,int & errorCode,QString & errorText) const66 void checkCollectionCreate(Akonadi::FileStore::CollectionCreateJob *job, int &errorCode, QString &errorText) const override
67 {
68 mLastCheckedJob = job;
69 errorCode = mErrorCode;
70 errorText = mErrorText;
71 }
72
checkCollectionDelete(Akonadi::FileStore::CollectionDeleteJob * job,int & errorCode,QString & errorText) const73 void checkCollectionDelete(Akonadi::FileStore::CollectionDeleteJob *job, int &errorCode, QString &errorText) const override
74 {
75 mLastCheckedJob = job;
76 errorCode = mErrorCode;
77 errorText = mErrorText;
78 }
79
checkCollectionFetch(Akonadi::FileStore::CollectionFetchJob * job,int & errorCode,QString & errorText) const80 void checkCollectionFetch(Akonadi::FileStore::CollectionFetchJob *job, int &errorCode, QString &errorText) const override
81 {
82 mLastCheckedJob = job;
83 errorCode = mErrorCode;
84 errorText = mErrorText;
85 }
86
checkCollectionModify(Akonadi::FileStore::CollectionModifyJob * job,int & errorCode,QString & errorText) const87 void checkCollectionModify(Akonadi::FileStore::CollectionModifyJob *job, int &errorCode, QString &errorText) const override
88 {
89 mLastCheckedJob = job;
90 errorCode = mErrorCode;
91 errorText = mErrorText;
92 }
93
checkCollectionMove(Akonadi::FileStore::CollectionMoveJob * job,int & errorCode,QString & errorText) const94 void checkCollectionMove(Akonadi::FileStore::CollectionMoveJob *job, int &errorCode, QString &errorText) const override
95 {
96 mLastCheckedJob = job;
97 errorCode = mErrorCode;
98 errorText = mErrorText;
99 }
100
checkItemCreate(Akonadi::FileStore::ItemCreateJob * job,int & errorCode,QString & errorText) const101 void checkItemCreate(Akonadi::FileStore::ItemCreateJob *job, int &errorCode, QString &errorText) const override
102 {
103 mLastCheckedJob = job;
104 errorCode = mErrorCode;
105 errorText = mErrorText;
106 }
107
checkItemDelete(Akonadi::FileStore::ItemDeleteJob * job,int & errorCode,QString & errorText) const108 void checkItemDelete(Akonadi::FileStore::ItemDeleteJob *job, int &errorCode, QString &errorText) const override
109 {
110 mLastCheckedJob = job;
111 errorCode = mErrorCode;
112 errorText = mErrorText;
113 }
114
checkItemFetch(Akonadi::FileStore::ItemFetchJob * job,int & errorCode,QString & errorText) const115 void checkItemFetch(Akonadi::FileStore::ItemFetchJob *job, int &errorCode, QString &errorText) const override
116 {
117 mLastCheckedJob = job;
118 errorCode = mErrorCode;
119 errorText = mErrorText;
120 }
121
checkItemModify(Akonadi::FileStore::ItemModifyJob * job,int & errorCode,QString & errorText) const122 void checkItemModify(Akonadi::FileStore::ItemModifyJob *job, int &errorCode, QString &errorText) const override
123 {
124 mLastCheckedJob = job;
125 errorCode = mErrorCode;
126 errorText = mErrorText;
127 }
128
checkItemMove(Akonadi::FileStore::ItemMoveJob * job,int & errorCode,QString & errorText) const129 void checkItemMove(Akonadi::FileStore::ItemMoveJob *job, int &errorCode, QString &errorText) const override
130 {
131 mLastCheckedJob = job;
132 errorCode = mErrorCode;
133 errorText = mErrorText;
134 }
135
checkStoreCompact(Akonadi::FileStore::StoreCompactJob * job,int & errorCode,QString & errorText) const136 void checkStoreCompact(Akonadi::FileStore::StoreCompactJob *job, int &errorCode, QString &errorText) const override
137 {
138 mLastCheckedJob = job;
139 errorCode = mErrorCode;
140 errorText = mErrorText;
141 }
142 };
143
processJob(Akonadi::FileStore::Job * job)144 void TestStore::processJob(Akonadi::FileStore::Job *job)
145 {
146 mLastProcessedJob = job;
147
148 QCOMPARE(currentJob(), job);
149 QVERIFY(job->error() == 0);
150
151 if (mErrorCode != 0) {
152 notifyError(mErrorCode, mErrorText);
153 }
154 }
155
156 class AbstractLocalStoreTest : public QObject
157 {
158 Q_OBJECT
159
160 public:
AbstractLocalStoreTest()161 AbstractLocalStoreTest()
162 : QObject()
163 , mStore(nullptr)
164 {
165 }
166
~AbstractLocalStoreTest()167 ~AbstractLocalStoreTest() override
168 {
169 delete mStore;
170 }
171
172 private:
173 TestStore *mStore = nullptr;
174
175 private Q_SLOTS:
176 void init();
177 void testSetPath();
178 void testCreateCollection();
179 void testDeleteCollection();
180 void testFetchCollection();
181 void testModifyCollection();
182 void testMoveCollection();
183 void testFetchItems();
184 void testFetchItem();
185 void testCreateItem();
186 void testDeleteItem();
187 void testModifyItem();
188 void testMoveItem();
189 void testCompactStore();
190 };
191
init()192 void AbstractLocalStoreTest::init()
193 {
194 delete mStore;
195 mStore = new TestStore;
196 }
197
testSetPath()198 void AbstractLocalStoreTest::testSetPath()
199 {
200 const QString file = KRandom::randomString(10);
201 const QString path = QLatin1String("/tmp/test/") + file;
202
203 // check that setTopLevelCollection() has been called
204 mStore->setPath(path);
205 QCOMPARE(mStore->mTopLevelCollection.remoteId(), path);
206
207 // check that the modified collection is the one returned by topLevelCollection()
208 QVERIFY(mStore->mTopLevelCollection.contentMimeTypes().isEmpty());
209 QCOMPARE(mStore->topLevelCollection().remoteId(), path);
210 QCOMPARE(mStore->topLevelCollection().contentMimeTypes(), QStringList() << Collection::mimeType());
211 QCOMPARE(mStore->topLevelCollection().name(), file);
212
213 // check that calling with the same path again, does not call the template method
214 mStore->mTopLevelCollection = Collection();
215 mStore->setPath(path);
216 QVERIFY(mStore->mTopLevelCollection.remoteId().isEmpty());
217 QCOMPARE(mStore->topLevelCollection().remoteId(), path);
218 QCOMPARE(mStore->topLevelCollection().contentMimeTypes(), QStringList() << Collection::mimeType());
219 QCOMPARE(mStore->topLevelCollection().name(), file);
220
221 // check that calling with a different path works like the first call
222 const QString file2 = KRandom::randomString(10);
223 const QString path2 = QLatin1String("/tmp/test2/") + file2;
224
225 mStore->setPath(path2);
226 QCOMPARE(mStore->mTopLevelCollection.remoteId(), path2);
227 QCOMPARE(mStore->topLevelCollection().remoteId(), path2);
228 QCOMPARE(mStore->topLevelCollection().contentMimeTypes(), QStringList() << Collection::mimeType());
229 QCOMPARE(mStore->topLevelCollection().name(), file2);
230 }
231
testCreateCollection()232 void AbstractLocalStoreTest::testCreateCollection()
233 {
234 Akonadi::FileStore::CollectionCreateJob *job = nullptr;
235
236 // test without setPath()
237 job = mStore->createCollection(Collection(), Collection());
238 QVERIFY(job != nullptr);
239 QCOMPARE(mStore->mLastCheckedJob, job);
240 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidStoreState);
241 QVERIFY(!job->errorText().isEmpty());
242
243 QVERIFY(!job->exec());
244 QVERIFY(mStore->mLastProcessedJob == nullptr);
245
246 // test with path but with invalid collections
247 mStore->setPath(QStringLiteral("/tmp/test"));
248 job = mStore->createCollection(Collection(), Collection());
249 QVERIFY(job != nullptr);
250 QCOMPARE(mStore->mLastCheckedJob, job);
251 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
252 QVERIFY(!job->errorText().isEmpty());
253
254 QVERIFY(!job->exec());
255 QVERIFY(mStore->mLastProcessedJob == nullptr);
256
257 // test with potentially valid collection (has remoteId), but invalid target parent
258 Collection collection;
259 collection.setRemoteId(QStringLiteral("/tmp/test/foo"));
260 job = mStore->createCollection(collection, Collection());
261 QVERIFY(job != nullptr);
262 QCOMPARE(mStore->mLastCheckedJob, job);
263 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
264 QVERIFY(!job->errorText().isEmpty());
265
266 QVERIFY(!job->exec());
267 QVERIFY(mStore->mLastProcessedJob == nullptr);
268
269 // test with potentially valid collections
270 Collection targetParent;
271 targetParent.setRemoteId(QStringLiteral("/tmp/test2"));
272 job = mStore->createCollection(collection, targetParent);
273 QVERIFY(job != nullptr);
274 QCOMPARE(mStore->mLastCheckedJob, job);
275 QCOMPARE(job->error(), 0);
276 QVERIFY(job->errorText().isEmpty());
277
278 QVERIFY(job->exec());
279 QCOMPARE(mStore->mLastProcessedJob, job);
280 mStore->mLastProcessedJob = nullptr;
281
282 // test template check method
283 mStore->mErrorCode = QRandomGenerator::global()->generate() + 1;
284 mStore->mErrorText = KRandom::randomString(10);
285
286 job = mStore->createCollection(collection, targetParent);
287 QVERIFY(job != nullptr);
288 QCOMPARE(mStore->mLastCheckedJob, job);
289 QCOMPARE(job->error(), mStore->mErrorCode);
290 QCOMPARE(job->errorText(), mStore->mErrorText);
291
292 QVERIFY(!job->exec());
293 QVERIFY(mStore->mLastProcessedJob == nullptr);
294 mStore->mErrorCode = 0;
295 mStore->mErrorText = QString();
296 }
297
testDeleteCollection()298 void AbstractLocalStoreTest::testDeleteCollection()
299 {
300 Akonadi::FileStore::CollectionDeleteJob *job = nullptr;
301
302 // test without setPath()
303 job = mStore->deleteCollection(Collection());
304 QVERIFY(job != nullptr);
305 QCOMPARE(mStore->mLastCheckedJob, job);
306 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidStoreState);
307 QVERIFY(!job->errorText().isEmpty());
308
309 QVERIFY(!job->exec());
310 QVERIFY(mStore->mLastProcessedJob == nullptr);
311
312 // test with path but with invalid collection
313 mStore->setPath(QStringLiteral("/tmp/test"));
314 job = mStore->deleteCollection(Collection());
315 QVERIFY(job != nullptr);
316 QCOMPARE(mStore->mLastCheckedJob, job);
317 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
318 QVERIFY(!job->errorText().isEmpty());
319
320 QVERIFY(!job->exec());
321 QVERIFY(mStore->mLastProcessedJob == nullptr);
322
323 // test with ivalid collection (has remoteId, but no parent collection remoteId)
324 Collection collection;
325 collection.setRemoteId(QStringLiteral("/tmp/test/foo"));
326 job = mStore->deleteCollection(collection);
327 QVERIFY(job != nullptr);
328 QCOMPARE(mStore->mLastCheckedJob, job);
329 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
330 QVERIFY(!job->errorText().isEmpty());
331
332 QVERIFY(!job->exec());
333 QVERIFY(mStore->mLastProcessedJob == nullptr);
334
335 // test with potentially valid collection (has remoteId and parent collection remoteId)
336 Collection parentCollection;
337 parentCollection.setRemoteId(QStringLiteral("/tmp/test"));
338 collection.setParentCollection(parentCollection);
339 job = mStore->deleteCollection(collection);
340 QVERIFY(job != nullptr);
341 QCOMPARE(mStore->mLastCheckedJob, job);
342 QCOMPARE(job->error(), 0);
343 QVERIFY(job->errorText().isEmpty());
344
345 QVERIFY(job->exec());
346 QCOMPARE(mStore->mLastProcessedJob, job);
347 mStore->mLastProcessedJob = nullptr;
348
349 // test template check method
350 mStore->mErrorCode = QRandomGenerator::global()->generate() + 1;
351 mStore->mErrorText = KRandom::randomString(10);
352
353 job = mStore->deleteCollection(collection);
354 QVERIFY(job != nullptr);
355 QCOMPARE(mStore->mLastCheckedJob, job);
356 QCOMPARE(job->error(), mStore->mErrorCode);
357 QCOMPARE(job->errorText(), mStore->mErrorText);
358
359 QVERIFY(!job->exec());
360 QVERIFY(mStore->mLastProcessedJob == nullptr);
361 mStore->mErrorCode = 0;
362 mStore->mErrorText = QString();
363 }
364
testFetchCollection()365 void AbstractLocalStoreTest::testFetchCollection()
366 {
367 Akonadi::FileStore::CollectionFetchJob *job = nullptr;
368
369 // test without setPath()
370 job = mStore->fetchCollections(Collection());
371 QVERIFY(job != nullptr);
372 QCOMPARE(mStore->mLastCheckedJob, job);
373 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidStoreState);
374 QVERIFY(!job->errorText().isEmpty());
375
376 QVERIFY(!job->exec());
377 QVERIFY(mStore->mLastProcessedJob == nullptr);
378
379 // test with path but with invalid collection
380 mStore->setPath(QStringLiteral("/tmp/test"));
381 job = mStore->fetchCollections(Collection());
382 QVERIFY(job != nullptr);
383 QCOMPARE(mStore->mLastCheckedJob, job);
384 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
385 QVERIFY(!job->errorText().isEmpty());
386
387 QVERIFY(!job->exec());
388 QVERIFY(mStore->mLastProcessedJob == nullptr);
389
390 // test with potentially valid collection (has remoteId)
391 Collection collection;
392 collection.setRemoteId(QStringLiteral("/tmp/test/foo"));
393 job = mStore->fetchCollections(collection);
394 QVERIFY(job != nullptr);
395 QCOMPARE(mStore->mLastCheckedJob, job);
396 QCOMPARE(job->error(), 0);
397 QVERIFY(job->errorText().isEmpty());
398
399 QVERIFY(job->exec());
400 QCOMPARE(mStore->mLastProcessedJob, job);
401 mStore->mLastProcessedJob = nullptr;
402
403 // test template check method
404 mStore->mErrorCode = QRandomGenerator::global()->generate() + 1;
405 mStore->mErrorText = KRandom::randomString(10);
406
407 job = mStore->fetchCollections(collection);
408 QVERIFY(job != nullptr);
409 QCOMPARE(mStore->mLastCheckedJob, job);
410 QCOMPARE(job->error(), mStore->mErrorCode);
411 QCOMPARE(job->errorText(), mStore->mErrorText);
412
413 QVERIFY(!job->exec());
414 QVERIFY(mStore->mLastProcessedJob == nullptr);
415 mStore->mErrorCode = 0;
416 mStore->mErrorText = QString();
417
418 // test fetch of top level collection only
419 collection.setRemoteId(mStore->topLevelCollection().remoteId());
420 job = mStore->fetchCollections(collection, Akonadi::FileStore::CollectionFetchJob::Base);
421 QVERIFY(job != nullptr);
422 QCOMPARE(mStore->mLastCheckedJob, job);
423 QCOMPARE(job->error(), 0);
424 QVERIFY(job->errorText().isEmpty());
425
426 QVERIFY(job->exec());
427 QVERIFY(mStore->mLastProcessedJob == nullptr); // job not handed to subclass because it is full processed in base class
428 QCOMPARE(job->collections().count(), 1);
429 QCOMPARE(job->collections()[0], mStore->topLevelCollection());
430 }
431
testModifyCollection()432 void AbstractLocalStoreTest::testModifyCollection()
433 {
434 Akonadi::FileStore::CollectionModifyJob *job = nullptr;
435
436 // test without setPath()
437 job = mStore->modifyCollection(Collection());
438 QVERIFY(job != nullptr);
439 QCOMPARE(mStore->mLastCheckedJob, job);
440 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidStoreState);
441 QVERIFY(!job->errorText().isEmpty());
442
443 QVERIFY(!job->exec());
444 QVERIFY(mStore->mLastProcessedJob == nullptr);
445
446 // test with path but with invalid item
447 mStore->setPath(QStringLiteral("/tmp/test"));
448 job = mStore->modifyCollection(Collection());
449 QVERIFY(job != nullptr);
450 QCOMPARE(mStore->mLastCheckedJob, job);
451 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
452 QVERIFY(!job->errorText().isEmpty());
453
454 QVERIFY(!job->exec());
455 QVERIFY(mStore->mLastProcessedJob == nullptr);
456
457 // test with potentially valid collection (has remoteId, but no parent remoteId)
458 Collection collection;
459 collection.setRemoteId(QStringLiteral("/tmp/test/foo"));
460 job = mStore->modifyCollection(collection);
461 QVERIFY(job != nullptr);
462 QCOMPARE(mStore->mLastCheckedJob, job);
463 QCOMPARE(job->error(), 0);
464 QVERIFY(job->errorText().isEmpty());
465
466 QVERIFY(job->exec());
467 QCOMPARE(mStore->mLastProcessedJob, job);
468 mStore->mLastProcessedJob = nullptr;
469
470 // test with potentially valid collection (has remoteId and parent remoteId)
471 Collection parentCollection;
472 parentCollection.setRemoteId(QStringLiteral("/tmp/test"));
473 collection.setParentCollection(parentCollection);
474 job = mStore->modifyCollection(collection);
475 QVERIFY(job != nullptr);
476 QCOMPARE(mStore->mLastCheckedJob, job);
477 QCOMPARE(job->error(), 0);
478 QVERIFY(job->errorText().isEmpty());
479
480 QVERIFY(job->exec());
481 QCOMPARE(mStore->mLastProcessedJob, job);
482 mStore->mLastProcessedJob = nullptr;
483
484 // test template check method
485 mStore->mErrorCode = QRandomGenerator::global()->generate() + 1;
486 mStore->mErrorText = KRandom::randomString(10);
487
488 job = mStore->modifyCollection(collection);
489 QVERIFY(job != nullptr);
490 QCOMPARE(mStore->mLastCheckedJob, job);
491 QCOMPARE(job->error(), mStore->mErrorCode);
492 QCOMPARE(job->errorText(), mStore->mErrorText);
493
494 QVERIFY(!job->exec());
495 QVERIFY(mStore->mLastProcessedJob == nullptr);
496 }
497
testMoveCollection()498 void AbstractLocalStoreTest::testMoveCollection()
499 {
500 Akonadi::FileStore::CollectionMoveJob *job = nullptr;
501
502 // test without setPath()
503 job = mStore->moveCollection(Collection(), Collection());
504 QVERIFY(job != nullptr);
505 QCOMPARE(mStore->mLastCheckedJob, job);
506 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidStoreState);
507 QVERIFY(!job->errorText().isEmpty());
508
509 QVERIFY(!job->exec());
510 QVERIFY(mStore->mLastProcessedJob == nullptr);
511
512 // test with path but with invalid collections
513 mStore->setPath(QStringLiteral("/tmp/test"));
514 job = mStore->moveCollection(Collection(), Collection());
515 QVERIFY(job != nullptr);
516 QCOMPARE(mStore->mLastCheckedJob, job);
517 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
518 QVERIFY(!job->errorText().isEmpty());
519
520 QVERIFY(!job->exec());
521 QVERIFY(mStore->mLastProcessedJob == nullptr);
522
523 // test with potentially valid collection (has remoteId and parent remoteId), but invalid target parent
524 Collection collection;
525 collection.setRemoteId(QStringLiteral("/tmp/test/foo"));
526 Collection parentCollection;
527 parentCollection.setRemoteId(QStringLiteral("/tmp/test"));
528 collection.setParentCollection(parentCollection);
529 job = mStore->moveCollection(collection, Collection());
530 QVERIFY(job != nullptr);
531 QCOMPARE(mStore->mLastCheckedJob, job);
532 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
533 QVERIFY(!job->errorText().isEmpty());
534
535 QVERIFY(!job->exec());
536 QVERIFY(mStore->mLastProcessedJob == nullptr);
537
538 // test with invalid parent collection, but with potentially valid collection and target parent
539 collection.setParentCollection(Collection());
540 job = mStore->moveCollection(collection, parentCollection);
541 QVERIFY(job != nullptr);
542 QCOMPARE(mStore->mLastCheckedJob, job);
543 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
544 QVERIFY(!job->errorText().isEmpty());
545
546 QVERIFY(!job->exec());
547 QVERIFY(mStore->mLastProcessedJob == nullptr);
548
549 // test with potentially valid collections
550 Collection targetParent;
551 targetParent.setRemoteId(QStringLiteral("/tmp/test2"));
552 collection.setParentCollection(parentCollection);
553 job = mStore->moveCollection(collection, targetParent);
554 QVERIFY(job != nullptr);
555 QCOMPARE(mStore->mLastCheckedJob, job);
556 QCOMPARE(job->error(), 0);
557 QVERIFY(job->errorText().isEmpty());
558
559 QVERIFY(job->exec());
560 QCOMPARE(mStore->mLastProcessedJob, job);
561 mStore->mLastProcessedJob = nullptr;
562
563 // test template check method
564 mStore->mErrorCode = QRandomGenerator::global()->generate() + 1;
565 mStore->mErrorText = KRandom::randomString(10);
566
567 job = mStore->moveCollection(collection, targetParent);
568 QVERIFY(job != nullptr);
569 QCOMPARE(mStore->mLastCheckedJob, job);
570 QCOMPARE(job->error(), mStore->mErrorCode);
571 QCOMPARE(job->errorText(), mStore->mErrorText);
572
573 QVERIFY(!job->exec());
574 QVERIFY(mStore->mLastProcessedJob == nullptr);
575 }
576
testFetchItems()577 void AbstractLocalStoreTest::testFetchItems()
578 {
579 Akonadi::FileStore::ItemFetchJob *job = nullptr;
580
581 // test without setPath()
582 job = mStore->fetchItems(Collection());
583 QVERIFY(job != nullptr);
584 QCOMPARE(mStore->mLastCheckedJob, job);
585 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidStoreState);
586 QVERIFY(!job->errorText().isEmpty());
587
588 QVERIFY(!job->exec());
589 QVERIFY(mStore->mLastProcessedJob == nullptr);
590
591 // test with path but with invalid collection
592 mStore->setPath(QStringLiteral("/tmp/test"));
593 job = mStore->fetchItems(Collection());
594 QVERIFY(job != nullptr);
595 QCOMPARE(mStore->mLastCheckedJob, job);
596 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
597 QVERIFY(!job->errorText().isEmpty());
598
599 QVERIFY(!job->exec());
600 QVERIFY(mStore->mLastProcessedJob == nullptr);
601
602 // test with potentially valid collection (has remoteId)
603 Collection collection;
604 collection.setRemoteId(QStringLiteral("/tmp/test/foo"));
605 job = mStore->fetchItems(collection);
606 QVERIFY(job != nullptr);
607 QCOMPARE(mStore->mLastCheckedJob, job);
608 QCOMPARE(job->error(), 0);
609 QVERIFY(job->errorText().isEmpty());
610
611 QVERIFY(job->exec());
612 QCOMPARE(mStore->mLastProcessedJob, job);
613 mStore->mLastProcessedJob = nullptr;
614
615 // test template check method
616 mStore->mErrorCode = QRandomGenerator::global()->generate() + 1;
617 mStore->mErrorText = KRandom::randomString(10);
618
619 job = mStore->fetchItems(collection);
620 QVERIFY(job != nullptr);
621 QCOMPARE(mStore->mLastCheckedJob, job);
622 QCOMPARE(job->error(), mStore->mErrorCode);
623 QCOMPARE(job->errorText(), mStore->mErrorText);
624
625 QVERIFY(!job->exec());
626 QVERIFY(mStore->mLastProcessedJob == nullptr);
627 mStore->mErrorCode = 0;
628 mStore->mErrorText = QString();
629 }
630
testFetchItem()631 void AbstractLocalStoreTest::testFetchItem()
632 {
633 Akonadi::FileStore::ItemFetchJob *job = nullptr;
634
635 // test without setPath()
636 job = mStore->fetchItem(Item());
637 QVERIFY(job != nullptr);
638 QCOMPARE(mStore->mLastCheckedJob, job);
639 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidStoreState);
640 QVERIFY(!job->errorText().isEmpty());
641
642 QVERIFY(!job->exec());
643 QVERIFY(mStore->mLastProcessedJob == nullptr);
644
645 // test with path but with invalid item
646 mStore->setPath(QStringLiteral("/tmp/test"));
647 job = mStore->fetchItem(Item());
648 QVERIFY(job != nullptr);
649 QCOMPARE(mStore->mLastCheckedJob, job);
650 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
651 QVERIFY(!job->errorText().isEmpty());
652
653 QVERIFY(!job->exec());
654 QVERIFY(mStore->mLastProcessedJob == nullptr);
655
656 // test with potentially valid item (has remoteId)
657 Item item;
658 item.setRemoteId(QStringLiteral("/tmp/test/foo"));
659 job = mStore->fetchItem(item);
660 QVERIFY(job != nullptr);
661 QCOMPARE(mStore->mLastCheckedJob, job);
662 QCOMPARE(job->error(), 0);
663 QVERIFY(job->errorText().isEmpty());
664
665 QVERIFY(job->exec());
666 QCOMPARE(mStore->mLastProcessedJob, job);
667 mStore->mLastProcessedJob = nullptr;
668
669 // test template check method
670 mStore->mErrorCode = QRandomGenerator::global()->generate() + 1;
671 mStore->mErrorText = KRandom::randomString(10);
672
673 job = mStore->fetchItem(item);
674 QVERIFY(job != nullptr);
675 QCOMPARE(mStore->mLastCheckedJob, job);
676 QCOMPARE(job->error(), mStore->mErrorCode);
677 QCOMPARE(job->errorText(), mStore->mErrorText);
678
679 QVERIFY(!job->exec());
680 QVERIFY(mStore->mLastProcessedJob == nullptr);
681 mStore->mErrorCode = 0;
682 mStore->mErrorText = QString();
683 }
684
testCreateItem()685 void AbstractLocalStoreTest::testCreateItem()
686 {
687 Akonadi::FileStore::ItemCreateJob *job = nullptr;
688
689 // test without setPath()
690 job = mStore->createItem(Item(), Collection());
691 QVERIFY(job != nullptr);
692 QCOMPARE(mStore->mLastCheckedJob, job);
693 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidStoreState);
694 QVERIFY(!job->errorText().isEmpty());
695
696 QVERIFY(!job->exec());
697 QVERIFY(mStore->mLastProcessedJob == nullptr);
698
699 // test with path but with invalid collection
700 mStore->setPath(QStringLiteral("/tmp/test"));
701 job = mStore->createItem(Item(), Collection());
702 QVERIFY(job != nullptr);
703 QCOMPARE(mStore->mLastCheckedJob, job);
704 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
705 QVERIFY(!job->errorText().isEmpty());
706
707 QVERIFY(!job->exec());
708 QVERIFY(mStore->mLastProcessedJob == nullptr);
709
710 // test with potentially valid collection (has remoteId)
711 Collection collection;
712 collection.setRemoteId(QStringLiteral("/tmp/test/foo"));
713 job = mStore->createItem(Item(), collection);
714 QVERIFY(job != nullptr);
715 QCOMPARE(mStore->mLastCheckedJob, job);
716 QCOMPARE(job->error(), 0);
717 QVERIFY(job->errorText().isEmpty());
718
719 QVERIFY(job->exec());
720 QCOMPARE(mStore->mLastProcessedJob, job);
721 mStore->mLastProcessedJob = nullptr;
722
723 // test template check method
724 mStore->mErrorCode = QRandomGenerator::global()->generate() + 1;
725 mStore->mErrorText = KRandom::randomString(10);
726
727 job = mStore->createItem(Item(), collection);
728 QVERIFY(job != nullptr);
729 QCOMPARE(mStore->mLastCheckedJob, job);
730 QCOMPARE(job->error(), mStore->mErrorCode);
731 QCOMPARE(job->errorText(), mStore->mErrorText);
732
733 QVERIFY(!job->exec());
734 QVERIFY(mStore->mLastProcessedJob == nullptr);
735 mStore->mErrorCode = 0;
736 mStore->mErrorText = QString();
737 }
738
testDeleteItem()739 void AbstractLocalStoreTest::testDeleteItem()
740 {
741 Akonadi::FileStore::ItemDeleteJob *job = nullptr;
742
743 // test without setPath()
744 job = mStore->deleteItem(Item());
745 QVERIFY(job != nullptr);
746 QCOMPARE(mStore->mLastCheckedJob, job);
747 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidStoreState);
748 QVERIFY(!job->errorText().isEmpty());
749
750 QVERIFY(!job->exec());
751 QVERIFY(mStore->mLastProcessedJob == nullptr);
752
753 // test with path but with invalid item
754 mStore->setPath(QStringLiteral("/tmp/test"));
755 job = mStore->deleteItem(Item());
756 QVERIFY(job != nullptr);
757 QCOMPARE(mStore->mLastCheckedJob, job);
758 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
759 QVERIFY(!job->errorText().isEmpty());
760
761 QVERIFY(!job->exec());
762 QVERIFY(mStore->mLastProcessedJob == nullptr);
763
764 // test with potentially valid item (has remoteId)
765 Item item;
766 item.setRemoteId(QStringLiteral("/tmp/test/foo"));
767 job = mStore->deleteItem(item);
768 QVERIFY(job != nullptr);
769 QCOMPARE(mStore->mLastCheckedJob, job);
770 QCOMPARE(job->error(), 0);
771 QVERIFY(job->errorText().isEmpty());
772
773 QVERIFY(job->exec());
774 QCOMPARE(mStore->mLastProcessedJob, job);
775 mStore->mLastProcessedJob = nullptr;
776
777 // test template check method
778 mStore->mErrorCode = QRandomGenerator::global()->generate() + 1;
779 mStore->mErrorText = KRandom::randomString(10);
780
781 job = mStore->deleteItem(item);
782 QVERIFY(job != nullptr);
783 QCOMPARE(mStore->mLastCheckedJob, job);
784 QCOMPARE(job->error(), mStore->mErrorCode);
785 QCOMPARE(job->errorText(), mStore->mErrorText);
786
787 QVERIFY(!job->exec());
788 QVERIFY(mStore->mLastProcessedJob == nullptr);
789 mStore->mErrorCode = 0;
790 mStore->mErrorText = QString();
791 }
792
testModifyItem()793 void AbstractLocalStoreTest::testModifyItem()
794 {
795 Akonadi::FileStore::ItemModifyJob *job = nullptr;
796
797 // test without setPath()
798 job = mStore->modifyItem(Item());
799 QVERIFY(job != nullptr);
800 QCOMPARE(mStore->mLastCheckedJob, job);
801 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidStoreState);
802 QVERIFY(!job->errorText().isEmpty());
803
804 QVERIFY(!job->exec());
805 QVERIFY(mStore->mLastProcessedJob == nullptr);
806
807 // test with path but with invalid item
808 mStore->setPath(QStringLiteral("/tmp/test"));
809 job = mStore->modifyItem(Item());
810 QVERIFY(job != nullptr);
811 QCOMPARE(mStore->mLastCheckedJob, job);
812 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
813 QVERIFY(!job->errorText().isEmpty());
814
815 QVERIFY(!job->exec());
816 QVERIFY(mStore->mLastProcessedJob == nullptr);
817
818 // test with potentially valid item (has remoteId)
819 Item item;
820 item.setRemoteId(QStringLiteral("/tmp/test/foo"));
821 job = mStore->modifyItem(item);
822 QVERIFY(job != nullptr);
823 QCOMPARE(mStore->mLastCheckedJob, job);
824 QCOMPARE(job->error(), 0);
825 QVERIFY(job->errorText().isEmpty());
826
827 QVERIFY(job->exec());
828 QCOMPARE(mStore->mLastProcessedJob, job);
829 mStore->mLastProcessedJob = nullptr;
830
831 // test template check method
832 mStore->mErrorCode = QRandomGenerator::global()->generate() + 1;
833 mStore->mErrorText = KRandom::randomString(10);
834
835 job = mStore->modifyItem(item);
836 QVERIFY(job != nullptr);
837 QCOMPARE(mStore->mLastCheckedJob, job);
838 QCOMPARE(job->error(), mStore->mErrorCode);
839 QCOMPARE(job->errorText(), mStore->mErrorText);
840
841 QVERIFY(!job->exec());
842 QVERIFY(mStore->mLastProcessedJob == nullptr);
843 }
844
testMoveItem()845 void AbstractLocalStoreTest::testMoveItem()
846 {
847 Akonadi::FileStore::ItemMoveJob *job = nullptr;
848
849 // test without setPath()
850 job = mStore->moveItem(Item(), Collection());
851 QVERIFY(job != nullptr);
852 QCOMPARE(mStore->mLastCheckedJob, job);
853 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidStoreState);
854 QVERIFY(!job->errorText().isEmpty());
855
856 QVERIFY(!job->exec());
857 QVERIFY(mStore->mLastProcessedJob == nullptr);
858
859 // test with path but with invalid item and collection
860 mStore->setPath(QStringLiteral("/tmp/test"));
861 job = mStore->moveItem(Item(), Collection());
862 QVERIFY(job != nullptr);
863 QCOMPARE(mStore->mLastCheckedJob, job);
864 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
865 QVERIFY(!job->errorText().isEmpty());
866
867 QVERIFY(!job->exec());
868 QVERIFY(mStore->mLastProcessedJob == nullptr);
869
870 // test with potentially valid item (has remoteId and parent remoteId), but invalid target parent
871 Item item;
872 item.setRemoteId(QStringLiteral("/tmp/test/foo"));
873 Collection parentCollection;
874 parentCollection.setRemoteId(QStringLiteral("/tmp/test"));
875 item.setParentCollection(parentCollection);
876 job = mStore->moveItem(item, Collection());
877 QVERIFY(job != nullptr);
878 QCOMPARE(mStore->mLastCheckedJob, job);
879 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
880 QVERIFY(!job->errorText().isEmpty());
881
882 QVERIFY(!job->exec());
883 QVERIFY(mStore->mLastProcessedJob == nullptr);
884
885 // test with invalid parent collection, but with potentially valid item and target parent
886 item.setParentCollection(Collection());
887 job = mStore->moveItem(item, parentCollection);
888 QVERIFY(job != nullptr);
889 QCOMPARE(mStore->mLastCheckedJob, job);
890 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidJobContext);
891 QVERIFY(!job->errorText().isEmpty());
892
893 QVERIFY(!job->exec());
894 QVERIFY(mStore->mLastProcessedJob == nullptr);
895
896 // test with potentially valid item and collections
897 Collection targetParent;
898 targetParent.setRemoteId(QStringLiteral("/tmp/test2"));
899 item.setParentCollection(parentCollection);
900 job = mStore->moveItem(item, targetParent);
901 QVERIFY(job != nullptr);
902 QCOMPARE(mStore->mLastCheckedJob, job);
903 QCOMPARE(job->error(), 0);
904 QVERIFY(job->errorText().isEmpty());
905
906 QVERIFY(job->exec());
907 QCOMPARE(mStore->mLastProcessedJob, job);
908 mStore->mLastProcessedJob = nullptr;
909
910 // test template check method
911 mStore->mErrorCode = QRandomGenerator::global()->generate() + 1;
912 mStore->mErrorText = KRandom::randomString(10);
913
914 job = mStore->moveItem(item, targetParent);
915 QVERIFY(job != nullptr);
916 QCOMPARE(mStore->mLastCheckedJob, job);
917 QCOMPARE(job->error(), mStore->mErrorCode);
918 QCOMPARE(job->errorText(), mStore->mErrorText);
919
920 QVERIFY(!job->exec());
921 QVERIFY(mStore->mLastProcessedJob == nullptr);
922 }
923
testCompactStore()924 void AbstractLocalStoreTest::testCompactStore()
925 {
926 Akonadi::FileStore::StoreCompactJob *job = nullptr;
927
928 // test without setPath()
929 job = mStore->compactStore();
930 QVERIFY(job != nullptr);
931 QCOMPARE(mStore->mLastCheckedJob, job);
932 QCOMPARE(job->error(), (int)Akonadi::FileStore::Job::InvalidStoreState);
933 QVERIFY(!job->errorText().isEmpty());
934
935 QVERIFY(!job->exec());
936 QVERIFY(mStore->mLastProcessedJob == nullptr);
937
938 // test with path
939 mStore->setPath(QStringLiteral("/tmp/test"));
940 job = mStore->compactStore();
941 QVERIFY(job != nullptr);
942 QCOMPARE(mStore->mLastCheckedJob, job);
943 QCOMPARE(job->error(), 0);
944 QVERIFY(job->errorText().isEmpty());
945
946 QVERIFY(job->exec());
947 QCOMPARE(mStore->mLastProcessedJob, job);
948 mStore->mLastProcessedJob = nullptr;
949
950 // test template check method
951 mStore->mErrorCode = QRandomGenerator::global()->generate() + 1;
952 mStore->mErrorText = KRandom::randomString(10);
953
954 job = mStore->compactStore();
955 QVERIFY(job != nullptr);
956 QCOMPARE(mStore->mLastCheckedJob, job);
957 QCOMPARE(job->error(), mStore->mErrorCode);
958 QCOMPARE(job->errorText(), mStore->mErrorText);
959
960 QVERIFY(!job->exec());
961 QVERIFY(mStore->mLastProcessedJob == nullptr);
962 mStore->mErrorCode = 0;
963 mStore->mErrorText = QString();
964 }
965
966 QTEST_MAIN(AbstractLocalStoreTest)
967
968 #include "abstractlocalstoretest.moc"
969