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 "testdatautil.h"
11
12 #include "filestore/collectionmovejob.h"
13 #include "filestore/itemfetchjob.h"
14
15 #include "libmaildir/maildir.h"
16
17 #include <QTemporaryDir>
18
19 #include <QDir>
20 #include <QFileInfo>
21 #include <QTest>
22
23 using namespace Akonadi;
24
25 class CollectionMoveTest : public QObject
26 {
27 Q_OBJECT
28
29 public:
CollectionMoveTest()30 CollectionMoveTest()
31 : QObject()
32 , mStore(nullptr)
33 , mDir(nullptr)
34 {
35 }
36
~CollectionMoveTest()37 ~CollectionMoveTest() override
38 {
39 delete mStore;
40 delete mDir;
41 }
42
43 private:
44 MixedMaildirStore *mStore = nullptr;
45 QTemporaryDir *mDir = nullptr;
46
47 private Q_SLOTS:
48 void init();
49 void cleanup();
50 void testMoveToTopLevel();
51 void testMoveToMaildir();
52 void testMoveToMBox();
53 };
54
init()55 void CollectionMoveTest::init()
56 {
57 mStore = new MixedMaildirStore;
58
59 mDir = new QTemporaryDir;
60 QVERIFY(mDir->isValid());
61 QVERIFY(QDir(mDir->path()).exists());
62 }
63
cleanup()64 void CollectionMoveTest::cleanup()
65 {
66 delete mStore;
67 mStore = nullptr;
68 delete mDir;
69 mDir = nullptr;
70 }
71
testMoveToTopLevel()72 void CollectionMoveTest::testMoveToTopLevel()
73 {
74 QDir topDir(mDir->path());
75
76 // top level dir
77 QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), topDir.path(), QStringLiteral("collection1")));
78 // QFileInfo fileInfo1(topDir, QStringLiteral("collection1"));
79 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), topDir.path(), QStringLiteral("collection2")));
80 // QFileInfo fileInfo2(topDir, QStringLiteral("collection2"));
81
82 // first level maildir parent
83 QDir subDir1 = topDir;
84 QVERIFY(subDir1.mkdir(QStringLiteral(".collection1.directory")));
85 QVERIFY(subDir1.cd(QStringLiteral(".collection1.directory")));
86 QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), subDir1.path(), QStringLiteral("collection1_1")));
87 QFileInfo fileInfo1_1(subDir1.path(), QStringLiteral("collection1_1"));
88 QVERIFY(fileInfo1_1.exists());
89 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), subDir1.path(), QStringLiteral("collection1_2")));
90 QFileInfo fileInfo1_2(subDir1.path(), QStringLiteral("collection1_2"));
91 QVERIFY(fileInfo1_2.exists());
92
93 // first level mbox parent
94 QDir subDir2 = topDir;
95 QVERIFY(subDir2.mkdir(QStringLiteral(".collection2.directory")));
96 QVERIFY(subDir2.cd(QStringLiteral(".collection2.directory")));
97 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), subDir2.path(), QStringLiteral("collection2_1")));
98 QFileInfo fileInfo2_1(subDir2.path(), QStringLiteral("collection2_1"));
99 QVERIFY(fileInfo2_1.exists());
100 QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), subDir2.path(), QStringLiteral("collection2_2")));
101 QFileInfo fileInfo2_2(subDir2.path(), QStringLiteral("collection2_2"));
102 QVERIFY(fileInfo2_2.exists());
103
104 mStore->setPath(topDir.path());
105
106 // common variables
107 FileStore::CollectionMoveJob *job = nullptr;
108 FileStore::ItemFetchJob *itemFetch = nullptr;
109 Collection collection;
110 const QVariant colListVar = QVariant::fromValue<Collection::List>(Collection::List());
111 QVariant var;
112 Collection::List collections;
113 Item::List items;
114 QMap<QByteArray, int> flagCounts;
115
116 // test moving maildir from maildir parent
117 Collection collection1;
118 collection1.setName(QStringLiteral("collection1"));
119 collection1.setRemoteId(QStringLiteral("collection1"));
120 collection1.setParentCollection(mStore->topLevelCollection());
121
122 Collection collection1_1;
123 collection1_1.setName(QStringLiteral("collection1_1"));
124 collection1_1.setRemoteId(QStringLiteral("collection1_1"));
125 collection1_1.setParentCollection(collection1);
126
127 job = mStore->moveCollection(collection1_1, mStore->topLevelCollection());
128
129 QVERIFY(job->exec());
130 QCOMPARE(job->error(), 0);
131
132 collection = job->collection();
133 QCOMPARE(collection.remoteId(), collection1_1.remoteId());
134 QCOMPARE(collection.parentCollection(), mStore->topLevelCollection());
135
136 fileInfo1_1.refresh();
137 QVERIFY(!fileInfo1_1.exists());
138 fileInfo1_1 = QFileInfo(topDir.path(), collection.remoteId());
139 QVERIFY(fileInfo1_1.exists());
140
141 // check for index preservation
142 var = job->property("onDiskIndexInvalidated");
143 QVERIFY(var.isValid());
144 QCOMPARE(var.userType(), colListVar.userType());
145
146 collections = var.value<Collection::List>();
147 QCOMPARE((int)collections.count(), 1);
148 QCOMPARE(collections.first(), collection);
149
150 // get the items and check the flags (see data/README)
151 itemFetch = mStore->fetchItems(collection);
152 QVERIFY(itemFetch->exec());
153 QCOMPARE(itemFetch->error(), 0);
154
155 items = itemFetch->items();
156 QCOMPARE((int)items.count(), 4);
157 for (const Item &item : std::as_const(items)) {
158 const auto flags = item.flags();
159 for (const QByteArray &flag : flags) {
160 ++flagCounts[flag];
161 }
162 }
163
164 QCOMPARE(flagCounts["\\SEEN"], 2);
165 QCOMPARE(flagCounts["\\FLAGGED"], 1);
166 QCOMPARE(flagCounts["$TODO"], 1);
167 flagCounts.clear();
168
169 // test moving mbox from maildir parent
170 Collection collection1_2;
171 collection1_2.setName(QStringLiteral("collection1_2"));
172 collection1_2.setRemoteId(QStringLiteral("collection1_2"));
173 collection1_2.setParentCollection(collection1);
174
175 job = mStore->moveCollection(collection1_2, mStore->topLevelCollection());
176
177 QVERIFY(job->exec());
178 QCOMPARE(job->error(), 0);
179
180 collection = job->collection();
181 QCOMPARE(collection.remoteId(), collection1_2.remoteId());
182 QCOMPARE(collection.parentCollection(), mStore->topLevelCollection());
183
184 fileInfo1_2.refresh();
185 QVERIFY(!fileInfo1_2.exists());
186 fileInfo1_2 = QFileInfo(topDir.path(), collection.remoteId());
187 QVERIFY(fileInfo1_2.exists());
188
189 // check for index preservation
190 var = job->property("onDiskIndexInvalidated");
191 QVERIFY(var.isValid());
192 QCOMPARE(var.userType(), colListVar.userType());
193
194 collections = var.value<Collection::List>();
195 QCOMPARE((int)collections.count(), 1);
196 QCOMPARE(collections.first(), collection);
197
198 // get the items and check the flags (see data/README)
199 itemFetch = mStore->fetchItems(collection);
200 QVERIFY(itemFetch->exec());
201 QCOMPARE(itemFetch->error(), 0);
202
203 items = itemFetch->items();
204 QCOMPARE((int)items.count(), 4);
205 for (const Item &item : std::as_const(items)) {
206 const auto flags = item.flags();
207 for (const QByteArray &flag : flags) {
208 ++flagCounts[flag];
209 }
210 }
211
212 QCOMPARE(flagCounts["\\SEEN"], 2);
213 QCOMPARE(flagCounts["\\FLAGGED"], 1);
214 QCOMPARE(flagCounts["$TODO"], 1);
215 flagCounts.clear();
216
217 // test moving mbox from mbox parent
218 Collection collection2;
219 collection2.setName(QStringLiteral("collection2"));
220 collection2.setRemoteId(QStringLiteral("collection2"));
221 collection2.setParentCollection(mStore->topLevelCollection());
222
223 Collection collection2_1;
224 collection2_1.setName(QStringLiteral("collection2_1"));
225 collection2_1.setRemoteId(QStringLiteral("collection2_1"));
226 collection2_1.setParentCollection(collection2);
227
228 job = mStore->moveCollection(collection2_1, mStore->topLevelCollection());
229
230 QVERIFY(job->exec());
231 QCOMPARE(job->error(), 0);
232
233 collection = job->collection();
234 QCOMPARE(collection.remoteId(), collection2_1.remoteId());
235 QCOMPARE(collection.parentCollection(), mStore->topLevelCollection());
236
237 fileInfo2_1.refresh();
238 QVERIFY(!fileInfo2_1.exists());
239 fileInfo2_1 = QFileInfo(topDir.path(), collection.remoteId());
240 QVERIFY(fileInfo2_1.exists());
241
242 // check for index preservation
243 var = job->property("onDiskIndexInvalidated");
244 QVERIFY(var.isValid());
245 QCOMPARE(var.userType(), colListVar.userType());
246
247 collections = var.value<Collection::List>();
248 QCOMPARE((int)collections.count(), 1);
249 QCOMPARE(collections.first(), collection);
250
251 // get the items and check the flags (see data/README)
252 itemFetch = mStore->fetchItems(collection);
253 QVERIFY(itemFetch->exec());
254 QCOMPARE(itemFetch->error(), 0);
255
256 items = itemFetch->items();
257 QCOMPARE((int)items.count(), 4);
258 for (const Item &item : std::as_const(items)) {
259 const auto flags = item.flags();
260 for (const QByteArray &flag : flags) {
261 ++flagCounts[flag];
262 }
263 }
264
265 QCOMPARE(flagCounts["\\SEEN"], 2);
266 QCOMPARE(flagCounts["\\FLAGGED"], 1);
267 QCOMPARE(flagCounts["$TODO"], 1);
268 flagCounts.clear();
269
270 // test moving maildir from mbox parent
271 Collection collection2_2;
272 collection2_2.setName(QStringLiteral("collection2_2"));
273 collection2_2.setRemoteId(QStringLiteral("collection2_2"));
274 collection2_2.setParentCollection(collection2);
275
276 job = mStore->moveCollection(collection2_2, mStore->topLevelCollection());
277
278 QVERIFY(job->exec());
279 QCOMPARE(job->error(), 0);
280
281 collection = job->collection();
282 QCOMPARE(collection.remoteId(), collection2_2.remoteId());
283 QCOMPARE(collection.parentCollection(), mStore->topLevelCollection());
284
285 fileInfo2_2.refresh();
286 QVERIFY(!fileInfo2_2.exists());
287 fileInfo2_2 = QFileInfo(topDir.path(), collection.remoteId());
288 QVERIFY(fileInfo2_2.exists());
289
290 // check for index preservation
291 var = job->property("onDiskIndexInvalidated");
292 QVERIFY(var.isValid());
293 QCOMPARE(var.userType(), colListVar.userType());
294
295 collections = var.value<Collection::List>();
296 QCOMPARE((int)collections.count(), 1);
297 QCOMPARE(collections.first(), collection);
298
299 // get the items and check the flags (see data/README)
300 itemFetch = mStore->fetchItems(collection);
301 QVERIFY(itemFetch->exec());
302 QCOMPARE(itemFetch->error(), 0);
303
304 items = itemFetch->items();
305 QCOMPARE((int)items.count(), 4);
306 for (const Item &item : std::as_const(items)) {
307 const auto flags = item.flags();
308 for (const QByteArray &flag : flags) {
309 ++flagCounts[flag];
310 }
311 }
312
313 QCOMPARE(flagCounts["\\SEEN"], 2);
314 QCOMPARE(flagCounts["\\FLAGGED"], 1);
315 QCOMPARE(flagCounts["$TODO"], 1);
316 flagCounts.clear();
317 }
318
testMoveToMaildir()319 void CollectionMoveTest::testMoveToMaildir()
320 {
321 QDir topDir(mDir->path());
322
323 // top level dir
324 QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), topDir.path(), QStringLiteral("collection1")));
325 QFileInfo fileInfo1(topDir, QStringLiteral("collection1"));
326 QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), topDir.path(), QStringLiteral("collection2")));
327 QFileInfo fileInfo2(topDir, QStringLiteral("collection2"));
328 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), topDir.path(), QStringLiteral("collection3")));
329 QFileInfo fileInfo3(topDir, QStringLiteral("collection3"));
330 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), topDir.path(), QStringLiteral("collection4")));
331 QFileInfo fileInfo4(topDir, QStringLiteral("collection4"));
332
333 // first level maildir parent
334 QDir subDir1 = topDir;
335 QVERIFY(subDir1.mkdir(QStringLiteral(".collection1.directory")));
336 QVERIFY(subDir1.cd(QStringLiteral(".collection1.directory")));
337 QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), subDir1.path(), QStringLiteral("collection1_1")));
338 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), subDir1.path(), QStringLiteral("collection1_2")));
339
340 // first level mbox parent
341 QDir subDir4 = topDir;
342 QVERIFY(subDir4.mkdir(QStringLiteral(".collection4.directory")));
343 QVERIFY(subDir4.cd(QStringLiteral(".collection4.directory")));
344 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), subDir4.path(), QStringLiteral("collection4_1")));
345 QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), subDir4.path(), QStringLiteral("collection4_2")));
346 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), subDir4.path(), QStringLiteral("collection4_3")));
347 QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), subDir4.path(), QStringLiteral("collection4_4")));
348
349 // target maildir
350 KPIM::Maildir topLevelMd(topDir.path(), true);
351 KPIM::Maildir targetMd(topLevelMd.addSubFolder(QStringLiteral("target")), false);
352 QVERIFY(targetMd.isValid());
353 QDir subDirTarget;
354
355 mStore->setPath(topDir.path());
356
357 // common variables
358 FileStore::CollectionMoveJob *job = nullptr;
359 FileStore::ItemFetchJob *itemFetch = nullptr;
360 Collection collection;
361 const QVariant colListVar = QVariant::fromValue<Collection::List>(Collection::List());
362 QVariant var;
363 Collection::List collections;
364 Item::List items;
365 QMap<QByteArray, int> flagCounts;
366
367 Collection target;
368 target.setName(QStringLiteral("target"));
369 target.setRemoteId(QStringLiteral("target"));
370 target.setParentCollection(mStore->topLevelCollection());
371
372 // test move leaf maildir into sibling
373 Collection collection2;
374 collection2.setName(QStringLiteral("collection2"));
375 collection2.setRemoteId(QStringLiteral("collection2"));
376 collection2.setParentCollection(mStore->topLevelCollection());
377
378 job = mStore->moveCollection(collection2, target);
379
380 QVERIFY(job->exec());
381 QCOMPARE(job->error(), 0);
382
383 subDirTarget = topDir;
384 QVERIFY(subDirTarget.cd(QStringLiteral(".target.directory")));
385
386 collection = job->collection();
387 QCOMPARE(collection.remoteId(), collection2.remoteId());
388 QCOMPARE(collection.parentCollection(), target);
389
390 fileInfo2.refresh();
391 QVERIFY(!fileInfo2.exists());
392 fileInfo2 = QFileInfo(subDirTarget, collection.remoteId());
393 QVERIFY(fileInfo2.exists());
394
395 // check for index preservation
396 var = job->property("onDiskIndexInvalidated");
397 QVERIFY(var.isValid());
398 QCOMPARE(var.userType(), colListVar.userType());
399
400 collections = var.value<Collection::List>();
401 QCOMPARE((int)collections.count(), 1);
402 QCOMPARE(collections.first(), collection);
403
404 // get the items and check the flags (see data/README)
405 itemFetch = mStore->fetchItems(collection);
406 QVERIFY(itemFetch->exec());
407 QCOMPARE(itemFetch->error(), 0);
408
409 items = itemFetch->items();
410 QCOMPARE((int)items.count(), 4);
411 for (const Item &item : std::as_const(items)) {
412 const auto flags{item.flags()};
413 for (const QByteArray &flag : flags) {
414 ++flagCounts[flag];
415 }
416 }
417
418 QCOMPARE(flagCounts["\\SEEN"], 2);
419 QCOMPARE(flagCounts["\\FLAGGED"], 1);
420 QCOMPARE(flagCounts["$TODO"], 1);
421 flagCounts.clear();
422
423 // test move leaf mbox into sibling
424 Collection collection3;
425 collection3.setName(QStringLiteral("collection3"));
426 collection3.setRemoteId(QStringLiteral("collection3"));
427 collection3.setParentCollection(mStore->topLevelCollection());
428
429 job = mStore->moveCollection(collection3, target);
430
431 QVERIFY(job->exec());
432 QCOMPARE(job->error(), 0);
433
434 collection = job->collection();
435 QCOMPARE(collection.remoteId(), collection3.remoteId());
436 QCOMPARE(collection.parentCollection(), target);
437
438 fileInfo3.refresh();
439 QVERIFY(!fileInfo3.exists());
440 fileInfo3 = QFileInfo(subDirTarget, collection.remoteId());
441 QVERIFY(fileInfo3.exists());
442
443 // check for index preservation
444 var = job->property("onDiskIndexInvalidated");
445 QVERIFY(var.isValid());
446 QCOMPARE(var.userType(), colListVar.userType());
447
448 collections = var.value<Collection::List>();
449 QCOMPARE((int)collections.count(), 1);
450 QCOMPARE(collections.first(), collection);
451
452 // get the items and check the flags (see data/README)
453 itemFetch = mStore->fetchItems(collection);
454 QVERIFY(itemFetch->exec());
455 QCOMPARE(itemFetch->error(), 0);
456
457 items = itemFetch->items();
458 QCOMPARE((int)items.count(), 4);
459 for (const Item &item : std::as_const(items)) {
460 const auto flags = item.flags();
461 for (const QByteArray &flag : flags) {
462 ++flagCounts[flag];
463 }
464 }
465
466 QCOMPARE(flagCounts["\\SEEN"], 2);
467 QCOMPARE(flagCounts["\\FLAGGED"], 1);
468 QCOMPARE(flagCounts["$TODO"], 1);
469 flagCounts.clear();
470
471 // test move maildir with subtree into sibling
472 Collection collection1;
473 collection1.setName(QStringLiteral("collection1"));
474 collection1.setRemoteId(QStringLiteral("collection1"));
475 collection1.setParentCollection(mStore->topLevelCollection());
476
477 // load sub collection index data to check for correct cache updates
478 Collection collection1_1;
479 collection1_1.setName(QStringLiteral("collection1_1"));
480 collection1_1.setRemoteId(QStringLiteral("collection1_1"));
481 collection1_1.setParentCollection(collection1);
482 itemFetch = mStore->fetchItems(collection1_1);
483 QVERIFY(itemFetch->exec());
484
485 Collection collection1_2;
486 collection1_2.setName(QStringLiteral("collection1_2"));
487 collection1_2.setRemoteId(QStringLiteral("collection1_2"));
488 collection1_2.setParentCollection(collection1);
489 itemFetch = mStore->fetchItems(collection1_2);
490 QVERIFY(itemFetch->exec());
491
492 job = mStore->moveCollection(collection1, target);
493
494 QVERIFY(job->exec());
495 QCOMPARE(job->error(), 0);
496
497 collection = job->collection();
498 QCOMPARE(collection.remoteId(), collection1.remoteId());
499 QCOMPARE(collection.parentCollection(), target);
500
501 fileInfo1.refresh();
502 QVERIFY(!fileInfo1.exists());
503 fileInfo1 = QFileInfo(subDirTarget, collection.remoteId());
504 QVERIFY(fileInfo1.exists());
505 QVERIFY(!subDir1.exists());
506 subDir1 = subDirTarget;
507 QVERIFY(subDir1.cd(QStringLiteral(".collection1.directory")));
508 QCOMPARE(subDir1.entryList(QStringList() << QStringLiteral("collection*")),
509 QStringList() << QStringLiteral("collection1_1") << QStringLiteral("collection1_2"));
510
511 // check for index preservation
512 var = job->property("onDiskIndexInvalidated");
513 QVERIFY(var.isValid());
514 QCOMPARE(var.userType(), colListVar.userType());
515
516 collections = var.value<Collection::List>();
517 QCOMPARE((int)collections.count(), 1);
518 QCOMPARE(collections.first(), collection);
519
520 // get the items and check the flags (see data/README)
521 itemFetch = mStore->fetchItems(collection);
522 QVERIFY(itemFetch->exec());
523 QCOMPARE(itemFetch->error(), 0);
524
525 items = itemFetch->items();
526 QCOMPARE((int)items.count(), 4);
527 for (const Item &item : std::as_const(items)) {
528 const auto flags{item.flags()};
529 for (const QByteArray &flag : flags) {
530 ++flagCounts[flag];
531 }
532 }
533
534 QCOMPARE(flagCounts["\\SEEN"], 2);
535 QCOMPARE(flagCounts["\\FLAGGED"], 1);
536 QCOMPARE(flagCounts["$TODO"], 1);
537 flagCounts.clear();
538
539 // check for children cache path updates
540 collection1.setParentCollection(target);
541 collection1_1.setParentCollection(collection1);
542 collection1_2.setParentCollection(collection1);
543
544 itemFetch = mStore->fetchItems(collection1_1);
545 QVERIFY(itemFetch->exec());
546 QCOMPARE(itemFetch->error(), 0);
547
548 items = itemFetch->items();
549 QCOMPARE((int)items.count(), 4);
550 for (const Item &item : std::as_const(items)) {
551 const auto flags = item.flags();
552 for (const QByteArray &flag : flags) {
553 ++flagCounts[flag];
554 }
555 }
556
557 QCOMPARE(flagCounts["\\SEEN"], 2);
558 QCOMPARE(flagCounts["\\FLAGGED"], 1);
559 QCOMPARE(flagCounts["$TODO"], 1);
560 flagCounts.clear();
561
562 itemFetch = mStore->fetchItems(collection1_2);
563 QVERIFY(itemFetch->exec());
564 QCOMPARE(itemFetch->error(), 0);
565
566 items = itemFetch->items();
567 QCOMPARE((int)items.count(), 4);
568 for (const Item &item : std::as_const(items)) {
569 const auto flags{item.flags()};
570 for (const QByteArray &flag : flags) {
571 ++flagCounts[flag];
572 }
573 }
574
575 QCOMPARE(flagCounts["\\SEEN"], 2);
576 QCOMPARE(flagCounts["\\FLAGGED"], 1);
577 QCOMPARE(flagCounts["$TODO"], 1);
578 flagCounts.clear();
579
580 // test move mbox with subtree into sibling
581 Collection collection4;
582 collection4.setName(QStringLiteral("collection4"));
583 collection4.setRemoteId(QStringLiteral("collection4"));
584 collection4.setParentCollection(mStore->topLevelCollection());
585
586 // load sub collection index data to check for correct cache updates
587 Collection collection4_1;
588 collection4_1.setName(QStringLiteral("collection4_1"));
589 collection4_1.setRemoteId(QStringLiteral("collection4_1"));
590 collection4_1.setParentCollection(collection4);
591 itemFetch = mStore->fetchItems(collection4_1);
592 QVERIFY(itemFetch->exec());
593
594 Collection collection4_2;
595 collection4_2.setName(QStringLiteral("collection4_2"));
596 collection4_2.setRemoteId(QStringLiteral("collection4_2"));
597 collection4_2.setParentCollection(collection4);
598 itemFetch = mStore->fetchItems(collection4_2);
599 QVERIFY(itemFetch->exec());
600
601 job = mStore->moveCollection(collection4, target);
602
603 QVERIFY(job->exec());
604 QCOMPARE(job->error(), 0);
605
606 collection = job->collection();
607 QCOMPARE(collection.remoteId(), collection4.remoteId());
608 QCOMPARE(collection.parentCollection(), target);
609
610 fileInfo4.refresh();
611 QVERIFY(!fileInfo4.exists());
612 fileInfo4 = QFileInfo(subDirTarget, collection.remoteId());
613 QVERIFY(fileInfo4.exists());
614 QVERIFY(!subDir4.exists());
615 subDir4 = subDirTarget;
616 QVERIFY(subDir4.cd(QStringLiteral(".collection4.directory")));
617 QCOMPARE(subDir4.entryList(QStringList() << QStringLiteral("collection*")),
618 QStringList() << QStringLiteral("collection4_1") << QStringLiteral("collection4_2") << QStringLiteral("collection4_3")
619 << QStringLiteral("collection4_4"));
620
621 // check for index preservation
622 var = job->property("onDiskIndexInvalidated");
623 QVERIFY(var.isValid());
624 QCOMPARE(var.userType(), colListVar.userType());
625
626 collections = var.value<Collection::List>();
627 QCOMPARE((int)collections.count(), 1);
628 QCOMPARE(collections.first(), collection);
629
630 // get the items and check the flags (see data/README)
631 itemFetch = mStore->fetchItems(collection);
632 QVERIFY(itemFetch->exec());
633 QCOMPARE(itemFetch->error(), 0);
634
635 items = itemFetch->items();
636 QCOMPARE((int)items.count(), 4);
637 for (const Item &item : std::as_const(items)) {
638 const auto flags = item.flags();
639 for (const QByteArray &flag : flags) {
640 ++flagCounts[flag];
641 }
642 }
643
644 QCOMPARE(flagCounts["\\SEEN"], 2);
645 QCOMPARE(flagCounts["\\FLAGGED"], 1);
646 QCOMPARE(flagCounts["$TODO"], 1);
647 flagCounts.clear();
648
649 // check for children cache path updates
650 collection4.setParentCollection(target);
651 collection4_1.setParentCollection(collection4);
652 collection4_2.setParentCollection(collection4);
653
654 itemFetch = mStore->fetchItems(collection4_1);
655 QVERIFY(itemFetch->exec());
656 QCOMPARE(itemFetch->error(), 0);
657
658 items = itemFetch->items();
659 QCOMPARE((int)items.count(), 4);
660 for (const Item &item : std::as_const(items)) {
661 const auto flags{item.flags()};
662 for (const QByteArray &flag : flags) {
663 ++flagCounts[flag];
664 }
665 }
666
667 QCOMPARE(flagCounts["\\SEEN"], 2);
668 QCOMPARE(flagCounts["\\FLAGGED"], 1);
669 QCOMPARE(flagCounts["$TODO"], 1);
670 flagCounts.clear();
671
672 itemFetch = mStore->fetchItems(collection4_2);
673 QVERIFY(itemFetch->exec());
674 QCOMPARE(itemFetch->error(), 0);
675
676 items = itemFetch->items();
677 QCOMPARE((int)items.count(), 4);
678 for (const Item &item : std::as_const(items)) {
679 const auto flags = item.flags();
680 for (const QByteArray &flag : flags) {
681 ++flagCounts[flag];
682 }
683 }
684
685 QCOMPARE(flagCounts["\\SEEN"], 2);
686 QCOMPARE(flagCounts["\\FLAGGED"], 1);
687 QCOMPARE(flagCounts["$TODO"], 1);
688 flagCounts.clear();
689
690 // move from parent maildir to parent's sibling
691 collection2.setParentCollection(target);
692
693 job = mStore->moveCollection(collection1_1, collection2);
694
695 QVERIFY(job->exec());
696 QCOMPARE(job->error(), 0);
697
698 QDir subDir2 = subDirTarget;
699 QVERIFY(subDir2.cd(QStringLiteral(".collection2.directory")));
700
701 collection = job->collection();
702 QCOMPARE(collection.remoteId(), collection1_1.remoteId());
703 QCOMPARE(collection.parentCollection(), collection2);
704
705 QFileInfo fileInfo1_1(subDir1, collection.remoteId());
706 QVERIFY(!fileInfo1_1.exists());
707 fileInfo1_1 = QFileInfo(subDir2, collection.remoteId());
708 QVERIFY(fileInfo1_1.exists());
709
710 // check for index preservation
711 var = job->property("onDiskIndexInvalidated");
712 QVERIFY(var.isValid());
713 QCOMPARE(var.userType(), colListVar.userType());
714
715 collections = var.value<Collection::List>();
716 QCOMPARE((int)collections.count(), 1);
717 QCOMPARE(collections.first(), collection);
718
719 // get the items and check the flags (see data/README)
720 itemFetch = mStore->fetchItems(collection);
721 QVERIFY(itemFetch->exec());
722 QCOMPARE(itemFetch->error(), 0);
723
724 items = itemFetch->items();
725 QCOMPARE((int)items.count(), 4);
726 for (const Item &item : std::as_const(items)) {
727 const auto flags = item.flags();
728 for (const QByteArray &flag : flags) {
729 ++flagCounts[flag];
730 }
731 }
732
733 QCOMPARE(flagCounts["\\SEEN"], 2);
734 QCOMPARE(flagCounts["\\FLAGGED"], 1);
735 QCOMPARE(flagCounts["$TODO"], 1);
736 flagCounts.clear();
737
738 // move from parent maildir to parent's sibling
739 job = mStore->moveCollection(collection1_2, collection2);
740
741 QVERIFY(job->exec());
742 QCOMPARE(job->error(), 0);
743
744 collection = job->collection();
745 QCOMPARE(collection.remoteId(), collection1_2.remoteId());
746 QCOMPARE(collection.parentCollection(), collection2);
747
748 QFileInfo fileInfo1_2(subDir1, collection.remoteId());
749 QVERIFY(!fileInfo1_2.exists());
750 fileInfo1_2 = QFileInfo(subDir2, collection.remoteId());
751 QVERIFY(fileInfo1_2.exists());
752
753 // check for index preservation
754 var = job->property("onDiskIndexInvalidated");
755 QVERIFY(var.isValid());
756 QCOMPARE(var.userType(), colListVar.userType());
757
758 collections = var.value<Collection::List>();
759 QCOMPARE((int)collections.count(), 1);
760 QCOMPARE(collections.first(), collection);
761
762 // get the items and check the flags (see data/README)
763 itemFetch = mStore->fetchItems(collection);
764 QVERIFY(itemFetch->exec());
765 QCOMPARE(itemFetch->error(), 0);
766
767 items = itemFetch->items();
768 QCOMPARE((int)items.count(), 4);
769 for (const Item &item : std::as_const(items)) {
770 const auto flags = item.flags();
771 for (const QByteArray &flag : flags) {
772 ++flagCounts[flag];
773 }
774 }
775
776 QCOMPARE(flagCounts["\\SEEN"], 2);
777 QCOMPARE(flagCounts["\\FLAGGED"], 1);
778 QCOMPARE(flagCounts["$TODO"], 1);
779 flagCounts.clear();
780
781 // move from parent mbox to parent's sibling
782 job = mStore->moveCollection(collection4_1, collection2);
783
784 QVERIFY(job->exec());
785 QCOMPARE(job->error(), 0);
786
787 collection = job->collection();
788 QCOMPARE(collection.remoteId(), collection4_1.remoteId());
789 QCOMPARE(collection.parentCollection(), collection2);
790
791 QFileInfo fileInfo4_1(subDir4, collection.remoteId());
792 QVERIFY(!fileInfo4_1.exists());
793 fileInfo4_1 = QFileInfo(subDir2, collection.remoteId());
794 QVERIFY(fileInfo4_1.exists());
795
796 // check for index preservation
797 var = job->property("onDiskIndexInvalidated");
798 QVERIFY(var.isValid());
799 QCOMPARE(var.userType(), colListVar.userType());
800
801 collections = var.value<Collection::List>();
802 QCOMPARE((int)collections.count(), 1);
803 QCOMPARE(collections.first(), collection);
804
805 // get the items and check the flags (see data/README)
806 itemFetch = mStore->fetchItems(collection);
807 QVERIFY(itemFetch->exec());
808 QCOMPARE(itemFetch->error(), 0);
809
810 items = itemFetch->items();
811 QCOMPARE((int)items.count(), 4);
812 for (const Item &item : std::as_const(items)) {
813 const auto flags = item.flags();
814 for (const QByteArray &flag : flags) {
815 ++flagCounts[flag];
816 }
817 }
818
819 QCOMPARE(flagCounts["\\SEEN"], 2);
820 QCOMPARE(flagCounts["\\FLAGGED"], 1);
821 QCOMPARE(flagCounts["$TODO"], 1);
822 flagCounts.clear();
823
824 // move from parent mbox to parent's sibling
825 job = mStore->moveCollection(collection4_2, collection2);
826
827 QVERIFY(job->exec());
828 QCOMPARE(job->error(), 0);
829
830 collection = job->collection();
831 QCOMPARE(collection.remoteId(), collection4_2.remoteId());
832 QCOMPARE(collection.parentCollection(), collection2);
833
834 QFileInfo fileInfo4_2(subDir4, collection.remoteId());
835 QVERIFY(!fileInfo4_2.exists());
836 fileInfo4_2 = QFileInfo(subDir2, collection.remoteId());
837 QVERIFY(fileInfo4_2.exists());
838
839 // check for index preservation
840 var = job->property("onDiskIndexInvalidated");
841 QVERIFY(var.isValid());
842 QCOMPARE(var.userType(), colListVar.userType());
843
844 collections = var.value<Collection::List>();
845 QCOMPARE((int)collections.count(), 1);
846 QCOMPARE(collections.first(), collection);
847
848 // get the items and check the flags (see data/README)
849 itemFetch = mStore->fetchItems(collection);
850 QVERIFY(itemFetch->exec());
851 QCOMPARE(itemFetch->error(), 0);
852
853 items = itemFetch->items();
854 QCOMPARE((int)items.count(), 4);
855 for (const Item &item : std::as_const(items)) {
856 const auto flags = item.flags();
857 for (const QByteArray &flag : flags) {
858 ++flagCounts[flag];
859 }
860 }
861
862 QCOMPARE(flagCounts["\\SEEN"], 2);
863 QCOMPARE(flagCounts["\\FLAGGED"], 1);
864 QCOMPARE(flagCounts["$TODO"], 1);
865 flagCounts.clear();
866
867 // move from parent maildir to grandparent
868 collection1_1.setParentCollection(collection2);
869
870 job = mStore->moveCollection(collection1_1, target);
871
872 QVERIFY(job->exec());
873 QCOMPARE(job->error(), 0);
874
875 collection = job->collection();
876 QCOMPARE(collection.remoteId(), collection1_1.remoteId());
877 QCOMPARE(collection.parentCollection(), target);
878
879 fileInfo1_1.refresh();
880 QVERIFY(!fileInfo1_1.exists());
881 fileInfo1_1 = QFileInfo(subDirTarget, collection.remoteId());
882 QVERIFY(fileInfo1_1.exists());
883
884 // check for index preservation
885 var = job->property("onDiskIndexInvalidated");
886 QVERIFY(var.isValid());
887 QCOMPARE(var.userType(), colListVar.userType());
888
889 collections = var.value<Collection::List>();
890 QCOMPARE((int)collections.count(), 1);
891 QCOMPARE(collections.first(), collection);
892
893 // get the items and check the flags (see data/README)
894 itemFetch = mStore->fetchItems(collection);
895 QVERIFY(itemFetch->exec());
896 QCOMPARE(itemFetch->error(), 0);
897
898 items = itemFetch->items();
899 QCOMPARE((int)items.count(), 4);
900 for (const Item &item : std::as_const(items)) {
901 const auto flags{item.flags()};
902 for (const QByteArray &flag : flags) {
903 ++flagCounts[flag];
904 }
905 }
906
907 QCOMPARE(flagCounts["\\SEEN"], 2);
908 QCOMPARE(flagCounts["\\FLAGGED"], 1);
909 QCOMPARE(flagCounts["$TODO"], 1);
910 flagCounts.clear();
911
912 // move from parent maildir to grandparent
913 collection1_2.setParentCollection(collection2);
914 job = mStore->moveCollection(collection1_2, target);
915
916 QVERIFY(job->exec());
917 QCOMPARE(job->error(), 0);
918
919 collection = job->collection();
920 QCOMPARE(collection.remoteId(), collection1_2.remoteId());
921 QCOMPARE(collection.parentCollection(), target);
922
923 fileInfo1_2.refresh();
924 QVERIFY(!fileInfo1_2.exists());
925 fileInfo1_2 = QFileInfo(subDirTarget, collection.remoteId());
926 QVERIFY(fileInfo1_2.exists());
927
928 // check for index preservation
929 var = job->property("onDiskIndexInvalidated");
930 QVERIFY(var.isValid());
931 QCOMPARE(var.userType(), colListVar.userType());
932
933 collections = var.value<Collection::List>();
934 QCOMPARE((int)collections.count(), 1);
935 QCOMPARE(collections.first(), collection);
936
937 // get the items and check the flags (see data/README)
938 itemFetch = mStore->fetchItems(collection);
939 QVERIFY(itemFetch->exec());
940 QCOMPARE(itemFetch->error(), 0);
941
942 items = itemFetch->items();
943 QCOMPARE((int)items.count(), 4);
944 for (const Item &item : std::as_const(items)) {
945 const auto flags{item.flags()};
946 for (const QByteArray &flag : flags) {
947 ++flagCounts[flag];
948 }
949 }
950
951 QCOMPARE(flagCounts["\\SEEN"], 2);
952 QCOMPARE(flagCounts["\\FLAGGED"], 1);
953 QCOMPARE(flagCounts["$TODO"], 1);
954 flagCounts.clear();
955
956 // move from parent mbox to grandparent
957 Collection collection4_3;
958 collection4_3.setName(QStringLiteral("collection4_3"));
959 collection4_3.setRemoteId(QStringLiteral("collection4_3"));
960 collection4_3.setParentCollection(collection4);
961
962 job = mStore->moveCollection(collection4_3, target);
963
964 QVERIFY(job->exec());
965 QCOMPARE(job->error(), 0);
966
967 collection = job->collection();
968 QCOMPARE(collection.remoteId(), collection4_3.remoteId());
969 QCOMPARE(collection.parentCollection(), target);
970
971 QFileInfo fileInfo4_3(subDir4, collection.remoteId());
972 QVERIFY(!fileInfo4_3.exists());
973 fileInfo4_3 = QFileInfo(subDirTarget, collection.remoteId());
974 QVERIFY(fileInfo4_3.exists());
975
976 // check for index preservation
977 var = job->property("onDiskIndexInvalidated");
978 QVERIFY(var.isValid());
979 QCOMPARE(var.userType(), colListVar.userType());
980
981 collections = var.value<Collection::List>();
982 QCOMPARE((int)collections.count(), 1);
983 QCOMPARE(collections.first(), collection);
984
985 // get the items and check the flags (see data/README)
986 itemFetch = mStore->fetchItems(collection);
987 QVERIFY(itemFetch->exec());
988 QCOMPARE(itemFetch->error(), 0);
989
990 items = itemFetch->items();
991 QCOMPARE((int)items.count(), 4);
992 for (const Item &item : std::as_const(items)) {
993 const auto flags{item.flags()};
994 for (const QByteArray &flag : flags) {
995 ++flagCounts[flag];
996 }
997 }
998
999 QCOMPARE(flagCounts["\\SEEN"], 2);
1000 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1001 QCOMPARE(flagCounts["$TODO"], 1);
1002 flagCounts.clear();
1003
1004 // move from parent mbox to grandparent
1005 Collection collection4_4;
1006 collection4_4.setName(QStringLiteral("collection4_4"));
1007 collection4_4.setRemoteId(QStringLiteral("collection4_4"));
1008 collection4_4.setParentCollection(collection4);
1009
1010 job = mStore->moveCollection(collection4_4, target);
1011
1012 QVERIFY(job->exec());
1013 QCOMPARE(job->error(), 0);
1014
1015 collection = job->collection();
1016 QCOMPARE(collection.remoteId(), collection4_4.remoteId());
1017 QCOMPARE(collection.parentCollection(), target);
1018
1019 QFileInfo fileInfo4_4(subDir4, collection.remoteId());
1020 QVERIFY(!fileInfo4_4.exists());
1021 fileInfo4_4 = QFileInfo(subDirTarget, collection.remoteId());
1022 QVERIFY(fileInfo4_4.exists());
1023
1024 // check for index preservation
1025 var = job->property("onDiskIndexInvalidated");
1026 QVERIFY(var.isValid());
1027 QCOMPARE(var.userType(), colListVar.userType());
1028
1029 collections = var.value<Collection::List>();
1030 QCOMPARE((int)collections.count(), 1);
1031 QCOMPARE(collections.first(), collection);
1032
1033 // get the items and check the flags (see data/README)
1034 itemFetch = mStore->fetchItems(collection);
1035 QVERIFY(itemFetch->exec());
1036 QCOMPARE(itemFetch->error(), 0);
1037
1038 items = itemFetch->items();
1039 QCOMPARE((int)items.count(), 4);
1040 for (const Item &item : std::as_const(items)) {
1041 const auto flags{item.flags()};
1042 for (const QByteArray &flag : flags) {
1043 ++flagCounts[flag];
1044 }
1045 }
1046
1047 QCOMPARE(flagCounts["\\SEEN"], 2);
1048 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1049 QCOMPARE(flagCounts["$TODO"], 1);
1050 flagCounts.clear();
1051
1052 // move from maildir to grandchild
1053 collection1_1.setParentCollection(target);
1054
1055 job = mStore->moveCollection(collection1_1, collection2);
1056
1057 QVERIFY(job->exec());
1058 QCOMPARE(job->error(), 0);
1059
1060 collection = job->collection();
1061 QCOMPARE(collection.remoteId(), collection1_1.remoteId());
1062 QCOMPARE(collection.parentCollection(), collection2);
1063
1064 fileInfo1_1.refresh();
1065 QVERIFY(!fileInfo1_1.exists());
1066 fileInfo1_1 = QFileInfo(subDir2, collection.remoteId());
1067 QVERIFY(fileInfo1_1.exists());
1068
1069 // check for index preservation
1070 var = job->property("onDiskIndexInvalidated");
1071 QVERIFY(var.isValid());
1072 QCOMPARE(var.userType(), colListVar.userType());
1073
1074 collections = var.value<Collection::List>();
1075 QCOMPARE((int)collections.count(), 1);
1076 QCOMPARE(collections.first(), collection);
1077
1078 // get the items and check the flags (see data/README)
1079 itemFetch = mStore->fetchItems(collection);
1080 QVERIFY(itemFetch->exec());
1081 QCOMPARE(itemFetch->error(), 0);
1082
1083 items = itemFetch->items();
1084 QCOMPARE((int)items.count(), 4);
1085 for (const Item &item : std::as_const(items)) {
1086 const auto flags{item.flags()};
1087 for (const QByteArray &flag : flags) {
1088 ++flagCounts[flag];
1089 }
1090 }
1091
1092 QCOMPARE(flagCounts["\\SEEN"], 2);
1093 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1094 QCOMPARE(flagCounts["$TODO"], 1);
1095 flagCounts.clear();
1096
1097 // move from maildir to grandchild
1098 collection1_2.setParentCollection(target);
1099
1100 job = mStore->moveCollection(collection1_2, collection2);
1101
1102 QVERIFY(job->exec());
1103 QCOMPARE(job->error(), 0);
1104
1105 collection = job->collection();
1106 QCOMPARE(collection.remoteId(), collection1_2.remoteId());
1107 QCOMPARE(collection.parentCollection(), collection2);
1108
1109 fileInfo1_2.refresh();
1110 QVERIFY(!fileInfo1_2.exists());
1111 fileInfo1_2 = QFileInfo(subDir2, collection.remoteId());
1112 QVERIFY(fileInfo1_2.exists());
1113
1114 // check for index preservation
1115 var = job->property("onDiskIndexInvalidated");
1116 QVERIFY(var.isValid());
1117 QCOMPARE(var.userType(), colListVar.userType());
1118
1119 collections = var.value<Collection::List>();
1120 QCOMPARE((int)collections.count(), 1);
1121 QCOMPARE(collections.first(), collection);
1122
1123 // get the items and check the flags (see data/README)
1124 itemFetch = mStore->fetchItems(collection);
1125 QVERIFY(itemFetch->exec());
1126 QCOMPARE(itemFetch->error(), 0);
1127
1128 items = itemFetch->items();
1129 QCOMPARE((int)items.count(), 4);
1130 for (const Item &item : std::as_const(items)) {
1131 const auto flags{item.flags()};
1132 for (const QByteArray &flag : flags) {
1133 ++flagCounts[flag];
1134 }
1135 }
1136
1137 QCOMPARE(flagCounts["\\SEEN"], 2);
1138 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1139 QCOMPARE(flagCounts["$TODO"], 1);
1140 flagCounts.clear();
1141 }
1142
testMoveToMBox()1143 void CollectionMoveTest::testMoveToMBox()
1144 {
1145 QDir topDir(mDir->path());
1146
1147 // top level dir
1148 QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), topDir.path(), QStringLiteral("collection1")));
1149 QFileInfo fileInfo1(topDir, QStringLiteral("collection1"));
1150 QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), topDir.path(), QStringLiteral("collection2")));
1151 QFileInfo fileInfo2(topDir, QStringLiteral("collection2"));
1152 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), topDir.path(), QStringLiteral("collection3")));
1153 QFileInfo fileInfo3(topDir, QStringLiteral("collection3"));
1154 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), topDir.path(), QStringLiteral("collection4")));
1155 QFileInfo fileInfo4(topDir, QStringLiteral("collection4"));
1156 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), topDir.path(), QStringLiteral("collection5")));
1157 QFileInfo fileInfo5(topDir, QStringLiteral("collection5"));
1158 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), topDir.path(), QStringLiteral("collection6")));
1159
1160 // first level maildir parent
1161 QDir subDir1 = topDir;
1162 QVERIFY(subDir1.mkdir(QStringLiteral(".collection1.directory")));
1163 QVERIFY(subDir1.cd(QStringLiteral(".collection1.directory")));
1164 QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), subDir1.path(), QStringLiteral("collection1_1")));
1165 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), subDir1.path(), QStringLiteral("collection1_2")));
1166 QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), subDir1.path(), QStringLiteral("collection1_3")));
1167 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), subDir1.path(), QStringLiteral("collection1_4")));
1168
1169 // first level mbox parent
1170 QDir subDir4 = topDir;
1171 QVERIFY(subDir4.mkdir(QStringLiteral(".collection4.directory")));
1172 QVERIFY(subDir4.cd(QStringLiteral(".collection4.directory")));
1173 QVERIFY(TestDataUtil::installFolder(QStringLiteral("mbox"), subDir4.path(), QStringLiteral("collection4_1")));
1174 QVERIFY(TestDataUtil::installFolder(QStringLiteral("maildir"), subDir4.path(), QStringLiteral("collection4_2")));
1175
1176 // target mbox
1177 QFileInfo fileInfoTarget(topDir.path(), QStringLiteral("target"));
1178 QFile fileTarget(fileInfoTarget.absoluteFilePath());
1179 QVERIFY(fileTarget.open(QIODevice::WriteOnly));
1180 fileTarget.close();
1181 QVERIFY(fileInfoTarget.exists());
1182
1183 QDir subDirTarget;
1184
1185 mStore->setPath(topDir.path());
1186
1187 // common variables
1188 FileStore::CollectionMoveJob *job = nullptr;
1189 FileStore::ItemFetchJob *itemFetch = nullptr;
1190 Collection collection;
1191 const QVariant colListVar = QVariant::fromValue<Collection::List>(Collection::List());
1192 QVariant var;
1193 Collection::List collections;
1194 Item::List items;
1195 QMap<QByteArray, int> flagCounts;
1196
1197 Collection target;
1198 target.setName(QStringLiteral("target"));
1199 target.setRemoteId(QStringLiteral("target"));
1200 target.setParentCollection(mStore->topLevelCollection());
1201
1202 // test move leaf maildir into sibling
1203 Collection collection2;
1204 collection2.setName(QStringLiteral("collection2"));
1205 collection2.setRemoteId(QStringLiteral("collection2"));
1206 collection2.setParentCollection(mStore->topLevelCollection());
1207
1208 job = mStore->moveCollection(collection2, target);
1209
1210 QVERIFY(job->exec());
1211 QCOMPARE(job->error(), 0);
1212
1213 subDirTarget = topDir;
1214 QVERIFY(subDirTarget.cd(QStringLiteral(".target.directory")));
1215
1216 collection = job->collection();
1217 QCOMPARE(collection.remoteId(), collection2.remoteId());
1218 QCOMPARE(collection.parentCollection(), target);
1219
1220 fileInfo2.refresh();
1221 QVERIFY(!fileInfo2.exists());
1222 fileInfo2 = QFileInfo(subDirTarget, collection.remoteId());
1223 QVERIFY(fileInfo2.exists());
1224
1225 // check for index preservation
1226 var = job->property("onDiskIndexInvalidated");
1227 QVERIFY(var.isValid());
1228 QCOMPARE(var.userType(), colListVar.userType());
1229
1230 collections = var.value<Collection::List>();
1231 QCOMPARE((int)collections.count(), 1);
1232 QCOMPARE(collections.first(), collection);
1233
1234 // get the items and check the flags (see data/README)
1235 itemFetch = mStore->fetchItems(collection);
1236 QVERIFY(itemFetch->exec());
1237 QCOMPARE(itemFetch->error(), 0);
1238
1239 items = itemFetch->items();
1240 QCOMPARE((int)items.count(), 4);
1241 for (const Item &item : std::as_const(items)) {
1242 const auto flags{item.flags()};
1243 for (const QByteArray &flag : flags) {
1244 ++flagCounts[flag];
1245 }
1246 }
1247
1248 QCOMPARE(flagCounts["\\SEEN"], 2);
1249 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1250 QCOMPARE(flagCounts["$TODO"], 1);
1251 flagCounts.clear();
1252
1253 // test move leaf mbox into sibling
1254 Collection collection3;
1255 collection3.setName(QStringLiteral("collection3"));
1256 collection3.setRemoteId(QStringLiteral("collection3"));
1257 collection3.setParentCollection(mStore->topLevelCollection());
1258
1259 job = mStore->moveCollection(collection3, target);
1260
1261 QVERIFY(job->exec());
1262 QCOMPARE(job->error(), 0);
1263
1264 collection = job->collection();
1265 QCOMPARE(collection.remoteId(), collection3.remoteId());
1266 QCOMPARE(collection.parentCollection(), target);
1267
1268 fileInfo3.refresh();
1269 QVERIFY(!fileInfo3.exists());
1270 fileInfo3 = QFileInfo(subDirTarget, collection.remoteId());
1271 QVERIFY(fileInfo3.exists());
1272
1273 // check for index preservation
1274 var = job->property("onDiskIndexInvalidated");
1275 QVERIFY(var.isValid());
1276 QCOMPARE(var.userType(), colListVar.userType());
1277
1278 collections = var.value<Collection::List>();
1279 QCOMPARE((int)collections.count(), 1);
1280 QCOMPARE(collections.first(), collection);
1281
1282 // get the items and check the flags (see data/README)
1283 itemFetch = mStore->fetchItems(collection);
1284 QVERIFY(itemFetch->exec());
1285 QCOMPARE(itemFetch->error(), 0);
1286
1287 items = itemFetch->items();
1288 QCOMPARE((int)items.count(), 4);
1289 for (const Item &item : std::as_const(items)) {
1290 const auto flags{item.flags()};
1291 for (const QByteArray &flag : flags) {
1292 ++flagCounts[flag];
1293 }
1294 }
1295
1296 QCOMPARE(flagCounts["\\SEEN"], 2);
1297 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1298 QCOMPARE(flagCounts["$TODO"], 1);
1299 flagCounts.clear();
1300
1301 // test move leaf mbox into sibling without subtree
1302 Collection collection5;
1303 collection5.setName(QStringLiteral("collection5"));
1304 collection5.setRemoteId(QStringLiteral("collection5"));
1305 collection5.setParentCollection(mStore->topLevelCollection());
1306
1307 Collection collection6;
1308 collection6.setName(QStringLiteral("collection6"));
1309 collection6.setRemoteId(QStringLiteral("collection6"));
1310 collection6.setParentCollection(mStore->topLevelCollection());
1311
1312 job = mStore->moveCollection(collection5, collection6);
1313
1314 QVERIFY(job->exec());
1315 QCOMPARE(job->error(), 0);
1316
1317 collection = job->collection();
1318 QCOMPARE(collection.remoteId(), collection5.remoteId());
1319 QCOMPARE(collection.parentCollection(), collection6);
1320
1321 fileInfo5.refresh();
1322 QVERIFY(!fileInfo5.exists());
1323 QDir subDir6 = topDir;
1324 QVERIFY(subDir6.cd(QStringLiteral(".collection6.directory")));
1325 fileInfo5 = QFileInfo(subDir6, collection.remoteId());
1326 QVERIFY(fileInfo5.exists());
1327
1328 // check for index preservation
1329 var = job->property("onDiskIndexInvalidated");
1330 QVERIFY(var.isValid());
1331 QCOMPARE(var.userType(), colListVar.userType());
1332
1333 collections = var.value<Collection::List>();
1334 QCOMPARE((int)collections.count(), 1);
1335 QCOMPARE(collections.first(), collection);
1336
1337 // get the items and check the flags (see data/README)
1338 itemFetch = mStore->fetchItems(collection);
1339 QVERIFY(itemFetch->exec());
1340 QCOMPARE(itemFetch->error(), 0);
1341
1342 items = itemFetch->items();
1343 QCOMPARE((int)items.count(), 4);
1344 for (const Item &item : std::as_const(items)) {
1345 const auto flags{item.flags()};
1346 for (const QByteArray &flag : flags) {
1347 ++flagCounts[flag];
1348 }
1349 }
1350
1351 QCOMPARE(flagCounts["\\SEEN"], 2);
1352 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1353 QCOMPARE(flagCounts["$TODO"], 1);
1354 flagCounts.clear();
1355
1356 // test move maildir with subtree into sibling
1357 Collection collection1;
1358 collection1.setName(QStringLiteral("collection1"));
1359 collection1.setRemoteId(QStringLiteral("collection1"));
1360 collection1.setParentCollection(mStore->topLevelCollection());
1361
1362 // load sub collection index data to check for correct cache updates
1363 Collection collection1_1;
1364 collection1_1.setName(QStringLiteral("collection1_1"));
1365 collection1_1.setRemoteId(QStringLiteral("collection1_1"));
1366 collection1_1.setParentCollection(collection1);
1367 itemFetch = mStore->fetchItems(collection1_1);
1368 QVERIFY(itemFetch->exec());
1369
1370 Collection collection1_2;
1371 collection1_2.setName(QStringLiteral("collection1_2"));
1372 collection1_2.setRemoteId(QStringLiteral("collection1_2"));
1373 collection1_2.setParentCollection(collection1);
1374 itemFetch = mStore->fetchItems(collection1_2);
1375 QVERIFY(itemFetch->exec());
1376
1377 job = mStore->moveCollection(collection1, target);
1378
1379 QVERIFY(job->exec());
1380 QCOMPARE(job->error(), 0);
1381
1382 collection = job->collection();
1383 QCOMPARE(collection.remoteId(), collection1.remoteId());
1384 QCOMPARE(collection.parentCollection(), target);
1385
1386 fileInfo1.refresh();
1387 QVERIFY(!fileInfo1.exists());
1388 fileInfo1 = QFileInfo(subDirTarget, collection.remoteId());
1389 QVERIFY(fileInfo1.exists());
1390 QVERIFY(!subDir1.exists());
1391 subDir1 = subDirTarget;
1392 QVERIFY(subDir1.cd(QStringLiteral(".collection1.directory")));
1393 QCOMPARE(subDir1.entryList(QStringList() << QStringLiteral("collection*")),
1394 QStringList() << QStringLiteral("collection1_1") << QStringLiteral("collection1_2") << QStringLiteral("collection1_3")
1395 << QStringLiteral("collection1_4"));
1396
1397 // check for index preservation
1398 var = job->property("onDiskIndexInvalidated");
1399 QVERIFY(var.isValid());
1400 QCOMPARE(var.userType(), colListVar.userType());
1401
1402 collections = var.value<Collection::List>();
1403 QCOMPARE((int)collections.count(), 1);
1404 QCOMPARE(collections.first(), collection);
1405
1406 // get the items and check the flags (see data/README)
1407 itemFetch = mStore->fetchItems(collection);
1408 QVERIFY(itemFetch->exec());
1409 QCOMPARE(itemFetch->error(), 0);
1410
1411 items = itemFetch->items();
1412 QCOMPARE((int)items.count(), 4);
1413 for (const Item &item : std::as_const(items)) {
1414 const auto flags{item.flags()};
1415 for (const QByteArray &flag : flags) {
1416 ++flagCounts[flag];
1417 }
1418 }
1419
1420 QCOMPARE(flagCounts["\\SEEN"], 2);
1421 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1422 QCOMPARE(flagCounts["$TODO"], 1);
1423 flagCounts.clear();
1424
1425 // check for children cache path updates
1426 collection1.setParentCollection(target);
1427 collection1_1.setParentCollection(collection1);
1428 collection1_2.setParentCollection(collection1);
1429
1430 itemFetch = mStore->fetchItems(collection1_1);
1431 QVERIFY(itemFetch->exec());
1432 QCOMPARE(itemFetch->error(), 0);
1433
1434 items = itemFetch->items();
1435 QCOMPARE((int)items.count(), 4);
1436 for (const Item &item : std::as_const(items)) {
1437 const auto flags{item.flags()};
1438 for (const QByteArray &flag : flags) {
1439 ++flagCounts[flag];
1440 }
1441 }
1442
1443 QCOMPARE(flagCounts["\\SEEN"], 2);
1444 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1445 QCOMPARE(flagCounts["$TODO"], 1);
1446 flagCounts.clear();
1447
1448 itemFetch = mStore->fetchItems(collection1_2);
1449 QVERIFY(itemFetch->exec());
1450 QCOMPARE(itemFetch->error(), 0);
1451
1452 items = itemFetch->items();
1453 QCOMPARE((int)items.count(), 4);
1454 for (const Item &item : std::as_const(items)) {
1455 const auto flags{item.flags()};
1456 for (const QByteArray &flag : flags) {
1457 ++flagCounts[flag];
1458 }
1459 }
1460
1461 QCOMPARE(flagCounts["\\SEEN"], 2);
1462 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1463 QCOMPARE(flagCounts["$TODO"], 1);
1464 flagCounts.clear();
1465
1466 // test move mbox with subtree into sibling
1467 Collection collection4;
1468 collection4.setName(QStringLiteral("collection4"));
1469 collection4.setRemoteId(QStringLiteral("collection4"));
1470 collection4.setParentCollection(mStore->topLevelCollection());
1471
1472 // load sub collection index data to check for correct cache updates
1473 Collection collection4_1;
1474 collection4_1.setName(QStringLiteral("collection4_1"));
1475 collection4_1.setRemoteId(QStringLiteral("collection4_1"));
1476 collection4_1.setParentCollection(collection4);
1477 itemFetch = mStore->fetchItems(collection4_1);
1478 QVERIFY(itemFetch->exec());
1479
1480 Collection collection4_2;
1481 collection4_2.setName(QStringLiteral("collection4_2"));
1482 collection4_2.setRemoteId(QStringLiteral("collection4_2"));
1483 collection4_2.setParentCollection(collection4);
1484 itemFetch = mStore->fetchItems(collection4_2);
1485 QVERIFY(itemFetch->exec());
1486
1487 job = mStore->moveCollection(collection4, target);
1488
1489 QVERIFY(job->exec());
1490 QCOMPARE(job->error(), 0);
1491
1492 collection = job->collection();
1493 QCOMPARE(collection.remoteId(), collection4.remoteId());
1494 QCOMPARE(collection.parentCollection(), target);
1495
1496 fileInfo4.refresh();
1497 QVERIFY(!fileInfo4.exists());
1498 fileInfo4 = QFileInfo(subDirTarget, collection.remoteId());
1499 QVERIFY(fileInfo4.exists());
1500 QVERIFY(!subDir4.exists());
1501 subDir4 = subDirTarget;
1502 QVERIFY(subDir4.cd(QStringLiteral(".collection4.directory")));
1503 QCOMPARE(subDir4.entryList(QStringList() << QStringLiteral("collection*")),
1504 QStringList() << QStringLiteral("collection4_1") << QStringLiteral("collection4_2"));
1505
1506 // check for index preservation
1507 var = job->property("onDiskIndexInvalidated");
1508 QVERIFY(var.isValid());
1509 QCOMPARE(var.userType(), colListVar.userType());
1510
1511 collections = var.value<Collection::List>();
1512 QCOMPARE((int)collections.count(), 1);
1513 QCOMPARE(collections.first(), collection);
1514
1515 // get the items and check the flags (see data/README)
1516 itemFetch = mStore->fetchItems(collection);
1517 QVERIFY(itemFetch->exec());
1518 QCOMPARE(itemFetch->error(), 0);
1519
1520 items = itemFetch->items();
1521 QCOMPARE((int)items.count(), 4);
1522 for (const Item &item : std::as_const(items)) {
1523 const auto flags{item.flags()};
1524 for (const QByteArray &flag : flags) {
1525 ++flagCounts[flag];
1526 }
1527 }
1528
1529 QCOMPARE(flagCounts["\\SEEN"], 2);
1530 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1531 QCOMPARE(flagCounts["$TODO"], 1);
1532 flagCounts.clear();
1533
1534 // check for children cache path updates
1535 collection4.setParentCollection(target);
1536 collection4_1.setParentCollection(collection4);
1537 collection4_2.setParentCollection(collection4);
1538
1539 itemFetch = mStore->fetchItems(collection4_1);
1540 QVERIFY(itemFetch->exec());
1541 QCOMPARE(itemFetch->error(), 0);
1542
1543 items = itemFetch->items();
1544 QCOMPARE((int)items.count(), 4);
1545 for (const Item &item : std::as_const(items)) {
1546 const auto flags{item.flags()};
1547 for (const QByteArray &flag : flags) {
1548 ++flagCounts[flag];
1549 }
1550 }
1551
1552 QCOMPARE(flagCounts["\\SEEN"], 2);
1553 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1554 QCOMPARE(flagCounts["$TODO"], 1);
1555 flagCounts.clear();
1556
1557 itemFetch = mStore->fetchItems(collection4_2);
1558 QVERIFY(itemFetch->exec());
1559 QCOMPARE(itemFetch->error(), 0);
1560
1561 items = itemFetch->items();
1562 QCOMPARE((int)items.count(), 4);
1563 for (const Item &item : std::as_const(items)) {
1564 const auto flags{item.flags()};
1565 for (const QByteArray &flag : flags) {
1566 ++flagCounts[flag];
1567 }
1568 }
1569
1570 QCOMPARE(flagCounts["\\SEEN"], 2);
1571 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1572 QCOMPARE(flagCounts["$TODO"], 1);
1573 flagCounts.clear();
1574
1575 // move from parent maildir to parent's sibling
1576 collection3.setParentCollection(target);
1577
1578 job = mStore->moveCollection(collection1_1, collection3);
1579
1580 QVERIFY(job->exec());
1581 QCOMPARE(job->error(), 0);
1582
1583 QDir subDir3 = subDirTarget;
1584 QVERIFY(subDir3.cd(QStringLiteral(".collection3.directory")));
1585
1586 collection = job->collection();
1587 QCOMPARE(collection.remoteId(), collection1_1.remoteId());
1588 QCOMPARE(collection.parentCollection(), collection3);
1589
1590 QFileInfo fileInfo1_1(subDir1, collection.remoteId());
1591 QVERIFY(!fileInfo1_1.exists());
1592 fileInfo1_1 = QFileInfo(subDir3, collection.remoteId());
1593 QVERIFY(fileInfo1_1.exists());
1594
1595 // check for index preservation
1596 var = job->property("onDiskIndexInvalidated");
1597 QVERIFY(var.isValid());
1598 QCOMPARE(var.userType(), colListVar.userType());
1599
1600 collections = var.value<Collection::List>();
1601 QCOMPARE((int)collections.count(), 1);
1602 QCOMPARE(collections.first(), collection);
1603
1604 // get the items and check the flags (see data/README)
1605 itemFetch = mStore->fetchItems(collection);
1606 QVERIFY(itemFetch->exec());
1607 QCOMPARE(itemFetch->error(), 0);
1608
1609 items = itemFetch->items();
1610 QCOMPARE((int)items.count(), 4);
1611 for (const Item &item : std::as_const(items)) {
1612 const auto flags{item.flags()};
1613 for (const QByteArray &flag : flags) {
1614 ++flagCounts[flag];
1615 }
1616 }
1617
1618 QCOMPARE(flagCounts["\\SEEN"], 2);
1619 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1620 QCOMPARE(flagCounts["$TODO"], 1);
1621 flagCounts.clear();
1622
1623 // move from parent maildir to parent's sibling
1624 job = mStore->moveCollection(collection1_2, collection3);
1625
1626 QVERIFY(job->exec());
1627 QCOMPARE(job->error(), 0);
1628
1629 collection = job->collection();
1630 QCOMPARE(collection.remoteId(), collection1_2.remoteId());
1631 QCOMPARE(collection.parentCollection(), collection3);
1632
1633 QFileInfo fileInfo1_2(subDir1, collection.remoteId());
1634 QVERIFY(!fileInfo1_2.exists());
1635 fileInfo1_2 = QFileInfo(subDir3, collection.remoteId());
1636 QVERIFY(fileInfo1_2.exists());
1637
1638 // check for index preservation
1639 var = job->property("onDiskIndexInvalidated");
1640 QVERIFY(var.isValid());
1641 QCOMPARE(var.userType(), colListVar.userType());
1642
1643 collections = var.value<Collection::List>();
1644 QCOMPARE((int)collections.count(), 1);
1645 QCOMPARE(collections.first(), collection);
1646
1647 // get the items and check the flags (see data/README)
1648 itemFetch = mStore->fetchItems(collection);
1649 QVERIFY(itemFetch->exec());
1650 QCOMPARE(itemFetch->error(), 0);
1651
1652 items = itemFetch->items();
1653 QCOMPARE((int)items.count(), 4);
1654 for (const Item &item : std::as_const(items)) {
1655 const auto flags{item.flags()};
1656 for (const QByteArray &flag : flags) {
1657 ++flagCounts[flag];
1658 }
1659 }
1660
1661 QCOMPARE(flagCounts["\\SEEN"], 2);
1662 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1663 QCOMPARE(flagCounts["$TODO"], 1);
1664 flagCounts.clear();
1665
1666 // move from parent mbox to parent's sibling
1667 job = mStore->moveCollection(collection4_1, collection3);
1668
1669 QVERIFY(job->exec());
1670 QCOMPARE(job->error(), 0);
1671
1672 collection = job->collection();
1673 QCOMPARE(collection.remoteId(), collection4_1.remoteId());
1674 QCOMPARE(collection.parentCollection(), collection3);
1675
1676 QFileInfo fileInfo4_1(subDir4, collection.remoteId());
1677 QVERIFY(!fileInfo4_1.exists());
1678 fileInfo4_1 = QFileInfo(subDir3, collection.remoteId());
1679 QVERIFY(fileInfo4_1.exists());
1680
1681 // check for index preservation
1682 var = job->property("onDiskIndexInvalidated");
1683 QVERIFY(var.isValid());
1684 QCOMPARE(var.userType(), colListVar.userType());
1685
1686 collections = var.value<Collection::List>();
1687 QCOMPARE((int)collections.count(), 1);
1688 QCOMPARE(collections.first(), collection);
1689
1690 // get the items and check the flags (see data/README)
1691 itemFetch = mStore->fetchItems(collection);
1692 QVERIFY(itemFetch->exec());
1693 QCOMPARE(itemFetch->error(), 0);
1694
1695 items = itemFetch->items();
1696 QCOMPARE((int)items.count(), 4);
1697 for (const Item &item : std::as_const(items)) {
1698 const auto flags{item.flags()};
1699 for (const QByteArray &flag : flags) {
1700 ++flagCounts[flag];
1701 }
1702 }
1703
1704 QCOMPARE(flagCounts["\\SEEN"], 2);
1705 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1706 QCOMPARE(flagCounts["$TODO"], 1);
1707 flagCounts.clear();
1708
1709 // move from parent mbox to parent's sibling
1710 job = mStore->moveCollection(collection4_2, collection3);
1711
1712 QVERIFY(job->exec());
1713 QCOMPARE(job->error(), 0);
1714
1715 collection = job->collection();
1716 QCOMPARE(collection.remoteId(), collection4_2.remoteId());
1717 QCOMPARE(collection.parentCollection(), collection3);
1718
1719 QFileInfo fileInfo4_2(subDir4, collection.remoteId());
1720 QVERIFY(!fileInfo4_2.exists());
1721 fileInfo4_2 = QFileInfo(subDir3, collection.remoteId());
1722 QVERIFY(fileInfo4_2.exists());
1723
1724 // check for index preservation
1725 var = job->property("onDiskIndexInvalidated");
1726 QVERIFY(var.isValid());
1727 QCOMPARE(var.userType(), colListVar.userType());
1728
1729 collections = var.value<Collection::List>();
1730 QCOMPARE((int)collections.count(), 1);
1731 QCOMPARE(collections.first(), collection);
1732
1733 // get the items and check the flags (see data/README)
1734 itemFetch = mStore->fetchItems(collection);
1735 QVERIFY(itemFetch->exec());
1736 QCOMPARE(itemFetch->error(), 0);
1737
1738 items = itemFetch->items();
1739 QCOMPARE((int)items.count(), 4);
1740 for (const Item &item : std::as_const(items)) {
1741 const auto flags{item.flags()};
1742 for (const QByteArray &flag : flags) {
1743 ++flagCounts[flag];
1744 }
1745 }
1746
1747 QCOMPARE(flagCounts["\\SEEN"], 2);
1748 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1749 QCOMPARE(flagCounts["$TODO"], 1);
1750 flagCounts.clear();
1751
1752 // move from parent mbox to grandparent
1753 collection1_1.setParentCollection(collection3);
1754
1755 job = mStore->moveCollection(collection1_1, target);
1756
1757 QVERIFY(job->exec());
1758 QCOMPARE(job->error(), 0);
1759
1760 collection = job->collection();
1761 QCOMPARE(collection.remoteId(), collection1_1.remoteId());
1762 QCOMPARE(collection.parentCollection(), target);
1763
1764 fileInfo1_1.refresh();
1765 QVERIFY(!fileInfo1_1.exists());
1766 fileInfo1_1 = QFileInfo(subDirTarget, collection.remoteId());
1767 QVERIFY(fileInfo1_1.exists());
1768
1769 // check for index preservation
1770 var = job->property("onDiskIndexInvalidated");
1771 QVERIFY(var.isValid());
1772 QCOMPARE(var.userType(), colListVar.userType());
1773
1774 collections = var.value<Collection::List>();
1775 QCOMPARE((int)collections.count(), 1);
1776 QCOMPARE(collections.first(), collection);
1777
1778 // get the items and check the flags (see data/README)
1779 itemFetch = mStore->fetchItems(collection);
1780 QVERIFY(itemFetch->exec());
1781 QCOMPARE(itemFetch->error(), 0);
1782
1783 items = itemFetch->items();
1784 QCOMPARE((int)items.count(), 4);
1785 for (const Item &item : std::as_const(items)) {
1786 const auto flags{item.flags()};
1787 for (const QByteArray &flag : flags) {
1788 ++flagCounts[flag];
1789 }
1790 }
1791
1792 QCOMPARE(flagCounts["\\SEEN"], 2);
1793 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1794 QCOMPARE(flagCounts["$TODO"], 1);
1795 flagCounts.clear();
1796
1797 // move from parent mbox to grandparent
1798 collection1_2.setParentCollection(collection3);
1799 job = mStore->moveCollection(collection1_2, target);
1800
1801 QVERIFY(job->exec());
1802 QCOMPARE(job->error(), 0);
1803
1804 collection = job->collection();
1805 QCOMPARE(collection.remoteId(), collection1_2.remoteId());
1806 QCOMPARE(collection.parentCollection(), target);
1807
1808 fileInfo1_2.refresh();
1809 QVERIFY(!fileInfo1_2.exists());
1810 fileInfo1_2 = QFileInfo(subDirTarget, collection.remoteId());
1811 QVERIFY(fileInfo1_2.exists());
1812
1813 // check for index preservation
1814 var = job->property("onDiskIndexInvalidated");
1815 QVERIFY(var.isValid());
1816 QCOMPARE(var.userType(), colListVar.userType());
1817
1818 collections = var.value<Collection::List>();
1819 QCOMPARE((int)collections.count(), 1);
1820 QCOMPARE(collections.first(), collection);
1821
1822 // get the items and check the flags (see data/README)
1823 itemFetch = mStore->fetchItems(collection);
1824 QVERIFY(itemFetch->exec());
1825 QCOMPARE(itemFetch->error(), 0);
1826
1827 items = itemFetch->items();
1828 QCOMPARE((int)items.count(), 4);
1829 for (const Item &item : std::as_const(items)) {
1830 const auto flags{item.flags()};
1831 for (const QByteArray &flag : flags) {
1832 ++flagCounts[flag];
1833 }
1834 }
1835
1836 QCOMPARE(flagCounts["\\SEEN"], 2);
1837 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1838 QCOMPARE(flagCounts["$TODO"], 1);
1839 flagCounts.clear();
1840
1841 // move from parent maildir to grandparent
1842 Collection collection1_3;
1843 collection1_3.setName(QStringLiteral("collection1_3"));
1844 collection1_3.setRemoteId(QStringLiteral("collection1_3"));
1845 collection1_3.setParentCollection(collection1);
1846
1847 job = mStore->moveCollection(collection1_3, target);
1848
1849 QVERIFY(job->exec());
1850 QCOMPARE(job->error(), 0);
1851
1852 collection = job->collection();
1853 QCOMPARE(collection.remoteId(), collection1_3.remoteId());
1854 QCOMPARE(collection.parentCollection(), target);
1855
1856 QFileInfo fileInfo1_3(subDir1, collection.remoteId());
1857 QVERIFY(!fileInfo1_3.exists());
1858 fileInfo1_3 = QFileInfo(subDirTarget, collection.remoteId());
1859 QVERIFY(fileInfo1_3.exists());
1860
1861 // check for index preservation
1862 var = job->property("onDiskIndexInvalidated");
1863 QVERIFY(var.isValid());
1864 QCOMPARE(var.userType(), colListVar.userType());
1865
1866 collections = var.value<Collection::List>();
1867 QCOMPARE((int)collections.count(), 1);
1868 QCOMPARE(collections.first(), collection);
1869
1870 // get the items and check the flags (see data/README)
1871 itemFetch = mStore->fetchItems(collection);
1872 QVERIFY(itemFetch->exec());
1873 QCOMPARE(itemFetch->error(), 0);
1874
1875 items = itemFetch->items();
1876 QCOMPARE((int)items.count(), 4);
1877 for (const Item &item : std::as_const(items)) {
1878 const auto flags{item.flags()};
1879 for (const QByteArray &flag : flags) {
1880 ++flagCounts[flag];
1881 }
1882 }
1883
1884 QCOMPARE(flagCounts["\\SEEN"], 2);
1885 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1886 QCOMPARE(flagCounts["$TODO"], 1);
1887 flagCounts.clear();
1888
1889 // move from parent maildir to grandparent
1890 Collection collection1_4;
1891 collection1_4.setName(QStringLiteral("collection1_4"));
1892 collection1_4.setRemoteId(QStringLiteral("collection1_4"));
1893 collection1_4.setParentCollection(collection1);
1894
1895 job = mStore->moveCollection(collection1_4, target);
1896
1897 QVERIFY(job->exec());
1898 QCOMPARE(job->error(), 0);
1899
1900 collection = job->collection();
1901 QCOMPARE(collection.remoteId(), collection1_4.remoteId());
1902 QCOMPARE(collection.parentCollection(), target);
1903
1904 QFileInfo fileInfo1_4(subDir1, collection.remoteId());
1905 QVERIFY(!fileInfo1_4.exists());
1906 fileInfo1_4 = QFileInfo(subDirTarget, collection.remoteId());
1907 QVERIFY(fileInfo1_4.exists());
1908
1909 // check for index preservation
1910 var = job->property("onDiskIndexInvalidated");
1911 QVERIFY(var.isValid());
1912 QCOMPARE(var.userType(), colListVar.userType());
1913
1914 collections = var.value<Collection::List>();
1915 QCOMPARE((int)collections.count(), 1);
1916 QCOMPARE(collections.first(), collection);
1917
1918 // get the items and check the flags (see data/README)
1919 itemFetch = mStore->fetchItems(collection);
1920 QVERIFY(itemFetch->exec());
1921 QCOMPARE(itemFetch->error(), 0);
1922
1923 items = itemFetch->items();
1924 QCOMPARE((int)items.count(), 4);
1925 for (const Item &item : std::as_const(items)) {
1926 const auto flags{item.flags()};
1927 for (const QByteArray &flag : flags) {
1928 ++flagCounts[flag];
1929 }
1930 }
1931
1932 QCOMPARE(flagCounts["\\SEEN"], 2);
1933 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1934 QCOMPARE(flagCounts["$TODO"], 1);
1935 flagCounts.clear();
1936
1937 // move from mbox to grandchild
1938 collection1_1.setParentCollection(target);
1939
1940 job = mStore->moveCollection(collection1_1, collection3);
1941
1942 QVERIFY(job->exec());
1943 QCOMPARE(job->error(), 0);
1944
1945 collection = job->collection();
1946 QCOMPARE(collection.remoteId(), collection1_1.remoteId());
1947 QCOMPARE(collection.parentCollection(), collection3);
1948
1949 fileInfo1_1.refresh();
1950 QVERIFY(!fileInfo1_1.exists());
1951 fileInfo1_1 = QFileInfo(subDir3, collection.remoteId());
1952 QVERIFY(fileInfo1_1.exists());
1953
1954 // check for index preservation
1955 var = job->property("onDiskIndexInvalidated");
1956 QVERIFY(var.isValid());
1957 QCOMPARE(var.userType(), colListVar.userType());
1958
1959 collections = var.value<Collection::List>();
1960 QCOMPARE((int)collections.count(), 1);
1961 QCOMPARE(collections.first(), collection);
1962
1963 // get the items and check the flags (see data/README)
1964 itemFetch = mStore->fetchItems(collection);
1965 QVERIFY(itemFetch->exec());
1966 QCOMPARE(itemFetch->error(), 0);
1967
1968 items = itemFetch->items();
1969 QCOMPARE((int)items.count(), 4);
1970 for (const Item &item : std::as_const(items)) {
1971 const auto flags{item.flags()};
1972 for (const QByteArray &flag : flags) {
1973 ++flagCounts[flag];
1974 }
1975 }
1976
1977 QCOMPARE(flagCounts["\\SEEN"], 2);
1978 QCOMPARE(flagCounts["\\FLAGGED"], 1);
1979 QCOMPARE(flagCounts["$TODO"], 1);
1980 flagCounts.clear();
1981
1982 // move from maildir to grandchild
1983 collection1_2.setParentCollection(target);
1984
1985 job = mStore->moveCollection(collection1_2, collection3);
1986
1987 QVERIFY(job->exec());
1988 QCOMPARE(job->error(), 0);
1989
1990 collection = job->collection();
1991 QCOMPARE(collection.remoteId(), collection1_2.remoteId());
1992 QCOMPARE(collection.parentCollection(), collection3);
1993
1994 fileInfo1_2.refresh();
1995 QVERIFY(!fileInfo1_2.exists());
1996 fileInfo1_2 = QFileInfo(subDir3, collection.remoteId());
1997 QVERIFY(fileInfo1_2.exists());
1998
1999 // check for index preservation
2000 var = job->property("onDiskIndexInvalidated");
2001 QVERIFY(var.isValid());
2002 QCOMPARE(var.userType(), colListVar.userType());
2003
2004 collections = var.value<Collection::List>();
2005 QCOMPARE((int)collections.count(), 1);
2006 QCOMPARE(collections.first(), collection);
2007
2008 // get the items and check the flags (see data/README)
2009 itemFetch = mStore->fetchItems(collection);
2010 QVERIFY(itemFetch->exec());
2011 QCOMPARE(itemFetch->error(), 0);
2012
2013 items = itemFetch->items();
2014 QCOMPARE((int)items.count(), 4);
2015 for (const Item &item : std::as_const(items)) {
2016 const auto flags{item.flags()};
2017 for (const QByteArray &flag : flags) {
2018 ++flagCounts[flag];
2019 }
2020 }
2021
2022 QCOMPARE(flagCounts["\\SEEN"], 2);
2023 QCOMPARE(flagCounts["\\FLAGGED"], 1);
2024 QCOMPARE(flagCounts["$TODO"], 1);
2025 flagCounts.clear();
2026 }
2027
2028 QTEST_MAIN(CollectionMoveTest)
2029
2030 #include "collectionmovetest.moc"
2031