1 /*
2     SPDX-FileCopyrightText: 2009 Constantin Berzan <exit3219@gmail.com>
3 
4     SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "localfolderstest.h"
8 
9 #include "collectionpathresolver.h"
10 #include "specialmailcollectionssettings.h"
11 
12 #include <QDBusConnection>
13 #include <QDBusConnectionInterface>
14 #include <QFile>
15 #include <QSignalSpy>
16 
17 #include "../src/specialmailcollectionstesting_p.h"
18 #include "specialcollectionattribute.h"
19 #include "specialcollections.h"
20 #include <Akonadi/AgentInstance>
21 #include <Akonadi/AgentManager>
22 #include <Akonadi/CollectionCreateJob>
23 #include <Akonadi/CollectionDeleteJob>
24 #include <Akonadi/CollectionFetchJob>
25 #include <Akonadi/CollectionModifyJob>
26 #include <Akonadi/ServerManager>
27 #include <KLocalizedString>
28 #include <QStandardPaths>
29 #include <akonadi/qtest_akonadi.h>
30 #include <control.h>
31 #include <specialmailcollections.h>
32 
33 using namespace Akonadi;
34 
35 typedef SpecialMailCollectionsSettings Settings;
36 
37 static Collection res1;
38 
initTestCase()39 void LocalFoldersTest::initTestCase()
40 {
41     qRegisterMetaType<Akonadi::AgentInstance>("Akonadi::AgentInstance");
42 
43     mDisplayNameMap.insert("local-mail", i18nc("local mail folder", "Local Folders"));
44     mDisplayNameMap.insert("inbox", i18nc("local mail folder", "inbox"));
45     mDisplayNameMap.insert("outbox", i18nc("local mail folder", "outbox"));
46     mDisplayNameMap.insert("sent-mail", i18nc("local mail folder", "sent-mail"));
47     mDisplayNameMap.insert("trash", i18nc("local mail folder", "trash"));
48     mDisplayNameMap.insert("drafts", i18nc("local mail folder", "drafts"));
49     mDisplayNameMap.insert("templates", i18nc("local mail folder", "templates"));
50 
51     mIconNameMap.insert("local-mail", QLatin1String("folder"));
52     mIconNameMap.insert("inbox", QLatin1String("mail-folder-inbox"));
53     mIconNameMap.insert("outbox", QLatin1String("mail-folder-outbox"));
54     mIconNameMap.insert("sent-mail", QLatin1String("mail-folder-sent"));
55     mIconNameMap.insert("trash", QLatin1String("user-trash"));
56     mIconNameMap.insert("drafts", QLatin1String("document-properties"));
57     mIconNameMap.insert("templates", QLatin1String("document-new"));
58 
59     QVERIFY(Control::start());
60     QTest::qWait(1000);
61 
62     CollectionPathResolver *resolver = new CollectionPathResolver(QStringLiteral("res1"), this);
63     QVERIFY(resolver->exec());
64     res1 = Collection(resolver->collection());
65 
66     CollectionFetchJob *fjob = new CollectionFetchJob(res1, CollectionFetchJob::Base, this);
67     AKVERIFYEXEC(fjob);
68     Q_ASSERT(fjob->collections().count() == 1);
69     res1 = fjob->collections().first();
70     QVERIFY(!res1.resource().isEmpty());
71 }
72 
testLock()73 void LocalFoldersTest::testLock()
74 {
75     QString dbusName = QString::fromLatin1("org.kde.pim.SpecialCollections");
76     if (ServerManager::hasInstanceIdentifier()) {
77         dbusName += Akonadi::ServerManager::instanceIdentifier();
78     }
79 
80     // Initially not locked.
81     QVERIFY(!QDBusConnection::sessionBus().interface()->isServiceRegistered(dbusName));
82 
83     // Get the lock.
84     {
85         GetLockJob *ljob = new GetLockJob(this);
86         AKVERIFYEXEC(ljob);
87         QVERIFY(QDBusConnection::sessionBus().interface()->isServiceRegistered(dbusName));
88     }
89 
90     // Getting the lock again should fail.
91     {
92         GetLockJob *ljob = new GetLockJob(this);
93         QVERIFY(!ljob->exec());
94     }
95 
96     // Release the lock.
97     QVERIFY(QDBusConnection::sessionBus().interface()->isServiceRegistered(dbusName));
98     releaseLock();
99     QVERIFY(!QDBusConnection::sessionBus().interface()->isServiceRegistered(dbusName));
100 }
101 
testInitialState()102 void LocalFoldersTest::testInitialState()
103 {
104     SpecialMailCollections *smc = SpecialMailCollections::self();
105     SpecialCollections *sc = smc;
106     SpecialMailCollectionsTesting *smct = SpecialMailCollectionsTesting::_t_self();
107     Q_ASSERT(smc);
108     Q_ASSERT(smct);
109     Q_UNUSED(smct)
110 
111     // No one has created the default resource.
112     QVERIFY(sc->d->defaultResource().identifier().isEmpty());
113 
114     // LF does not have a default Outbox folder (or any other).
115     QCOMPARE(smc->hasDefaultCollection(SpecialMailCollections::Outbox), false);
116     QVERIFY(!smc->defaultCollection(SpecialMailCollections::Outbox).isValid());
117 
118     // LF treats unknown resources correctly.
119     const QString resourceId = QString::fromLatin1("this_resource_does_not_exist");
120     QCOMPARE(smc->hasCollection(SpecialMailCollections::Outbox, AgentManager::self()->instance(resourceId)), false);
121     QVERIFY(!smc->collection(SpecialMailCollections::Outbox, AgentManager::self()->instance(resourceId)).isValid());
122 }
123 
testRegistrationErrors()124 void LocalFoldersTest::testRegistrationErrors()
125 {
126     SpecialMailCollections *smc = SpecialMailCollections::self();
127 
128     // A valid collection that can be registered.
129     Collection outbox;
130     outbox.setName(QLatin1String("my_outbox"));
131     outbox.setParentCollection(res1);
132     outbox.addAttribute(new SpecialCollectionAttribute("outbox"));
133     outbox.setResource(res1.resource());
134 
135     // Needs to be valid.
136     {
137         Collection col(outbox);
138         col.setId(-1);
139         QVERIFY(!smc->registerCollection(SpecialMailCollections::Outbox, col));
140     }
141 
142     // Needs to have a resourceId.
143     {
144         Collection col(outbox);
145         col.setResource(QString());
146         QVERIFY(!smc->registerCollection(SpecialMailCollections::Outbox, col));
147     }
148 
149     // Needs to have a LocalFolderAttribute.
150     {
151         Collection col(outbox);
152         col.removeAttribute<SpecialCollectionAttribute>();
153         QVERIFY(!smc->registerCollection(SpecialMailCollections::Outbox, col));
154     }
155 }
156 
testDefaultFolderRegistration()157 void LocalFoldersTest::testDefaultFolderRegistration()
158 {
159     SpecialMailCollections *smc = SpecialMailCollections::self();
160     SpecialCollections *sc = smc;
161     SpecialMailCollectionsTesting *smct = SpecialMailCollectionsTesting::_t_self();
162     Q_ASSERT(smc);
163     Q_ASSERT(smct);
164     QSignalSpy spy(smc, &SpecialMailCollections::collectionsChanged);
165     QSignalSpy defSpy(smc, &SpecialMailCollections::defaultCollectionsChanged);
166     QVERIFY(spy.isValid());
167     QVERIFY(defSpy.isValid());
168 
169     // No one has created the default resource.
170     QVERIFY(sc->d->defaultResource().identifier().isEmpty());
171 
172     // Set the default resource. LF should still have no folders.
173     smct->_t_setDefaultResourceId(res1.resource());
174     QCOMPARE(sc->d->defaultResource().identifier(), res1.resource());
175     QCOMPARE(smct->_t_knownResourceCount(), 0);
176     QCOMPARE(smct->_t_knownFolderCount(), 0);
177 
178     // Manually create an Outbox collection.
179     Collection outbox;
180     outbox.setName(QLatin1String("my_outbox"));
181     outbox.setParentCollection(res1);
182     outbox.addAttribute(new SpecialCollectionAttribute("outbox"));
183     CollectionCreateJob *cjob = new CollectionCreateJob(outbox, this);
184     AKVERIFYEXEC(cjob);
185     outbox = cjob->collection();
186 
187     // LF should still have no folders, since the Outbox wasn't registered.
188     QCOMPARE(smct->_t_knownResourceCount(), 0);
189     QCOMPARE(smct->_t_knownFolderCount(), 0);
190     QCOMPARE(spy.count(), 0);
191     QCOMPARE(defSpy.count(), 0);
192 
193     // Register the collection. LF should now know it.
194     bool ok = smc->registerCollection(SpecialMailCollections::Outbox, outbox);
195     QVERIFY(ok);
196     QVERIFY(smc->hasDefaultCollection(SpecialMailCollections::Outbox));
197     QCOMPARE(smc->defaultCollection(SpecialMailCollections::Outbox), outbox);
198     QCOMPARE(smct->_t_knownResourceCount(), 1);
199     QCOMPARE(smct->_t_knownFolderCount(), 1);
200     QCOMPARE(spy.count(), 1);
201     QCOMPARE(defSpy.count(), 1);
202 
203     // Forget all folders in the default resource.
204     smct->_t_forgetFoldersForResource(sc->d->defaultResource().identifier());
205     QCOMPARE(smc->hasDefaultCollection(SpecialMailCollections::Outbox), false);
206     QCOMPARE(smct->_t_knownResourceCount(), 0);
207     QCOMPARE(smct->_t_knownFolderCount(), 0);
208     QCOMPARE(spy.count(), 2);
209     QCOMPARE(defSpy.count(), 2);
210 
211     // Delete the collection.
212     CollectionDeleteJob *djob = new CollectionDeleteJob(outbox, this);
213     AKVERIFYEXEC(djob);
214 }
215 
testCustomFolderRegistration()216 void LocalFoldersTest::testCustomFolderRegistration()
217 {
218     SpecialMailCollections *smc = SpecialMailCollections::self();
219     SpecialMailCollectionsTesting *smct = SpecialMailCollectionsTesting::_t_self();
220     Q_ASSERT(smc);
221     Q_ASSERT(smct);
222     QSignalSpy spy(smc, &SpecialMailCollections::collectionsChanged);
223     QSignalSpy defSpy(smc, &SpecialMailCollections::defaultCollectionsChanged);
224     QVERIFY(spy.isValid());
225     QVERIFY(defSpy.isValid());
226 
227     // Set a fake default resource, so that res1.resource() isn't seen as the default one.
228     // LF should have no folders.
229     smct->_t_setDefaultResourceId("dummy");
230     QCOMPARE(smct->_t_knownResourceCount(), 0);
231     QCOMPARE(smct->_t_knownFolderCount(), 0);
232 
233     // Manually create an Outbox collection.
234     Collection outbox;
235     outbox.setName(QLatin1String("my_outbox"));
236     outbox.setParentCollection(res1);
237     outbox.addAttribute(new SpecialCollectionAttribute("outbox"));
238     CollectionCreateJob *cjob = new CollectionCreateJob(outbox, this);
239     AKVERIFYEXEC(cjob);
240     outbox = cjob->collection();
241 
242     // LF should still have no folders, since the Outbox wasn't registered.
243     QCOMPARE(smct->_t_knownResourceCount(), 0);
244     QCOMPARE(smct->_t_knownFolderCount(), 0);
245     QCOMPARE(spy.count(), 0);
246     QCOMPARE(defSpy.count(), 0);
247 
248     // Register the collection. LF should now know it.
249     bool ok = smc->registerCollection(SpecialMailCollections::Outbox, outbox);
250     QVERIFY(ok);
251     QVERIFY(!smc->hasDefaultCollection(SpecialMailCollections::Outbox));
252     QVERIFY(smc->hasCollection(SpecialMailCollections::Outbox, AgentManager::self()->instance(outbox.resource())));
253     QCOMPARE(smc->collection(SpecialMailCollections::Outbox, AgentManager::self()->instance(outbox.resource())), outbox);
254     QCOMPARE(smct->_t_knownResourceCount(), 1);
255     QCOMPARE(smct->_t_knownFolderCount(), 1);
256     QCOMPARE(spy.count(), 1);
257     QCOMPARE(defSpy.count(), 0);
258 
259     // Forget all folders in this resource.
260     smct->_t_forgetFoldersForResource(outbox.resource());
261     QCOMPARE(smc->hasDefaultCollection(SpecialMailCollections::Outbox), false);
262     QCOMPARE(smc->hasCollection(SpecialMailCollections::Outbox, AgentManager::self()->instance(outbox.resource())), false);
263     QCOMPARE(smct->_t_knownResourceCount(), 0);
264     QCOMPARE(smct->_t_knownFolderCount(), 0);
265     QCOMPARE(spy.count(), 2);
266     QCOMPARE(defSpy.count(), 0);
267 
268     // Delete the collection.
269     CollectionDeleteJob *djob = new CollectionDeleteJob(outbox, this);
270     AKVERIFYEXEC(djob);
271 }
272 
testCollectionDelete()273 void LocalFoldersTest::testCollectionDelete()
274 {
275     SpecialMailCollections *smc = SpecialMailCollections::self();
276     SpecialCollections *sc = smc;
277     SpecialMailCollectionsTesting *smct = SpecialMailCollectionsTesting::_t_self();
278     Q_ASSERT(smc);
279     Q_ASSERT(smct);
280     QSignalSpy spy(smc, &SpecialMailCollections::collectionsChanged);
281     QSignalSpy defSpy(smc, &SpecialMailCollections::defaultCollectionsChanged);
282     QVERIFY(spy.isValid());
283     QVERIFY(defSpy.isValid());
284 
285     // Set the default resource. LF should have no folders.
286     smct->_t_setDefaultResourceId(res1.resource());
287     QCOMPARE(sc->d->defaultResource().identifier(), res1.resource());
288     QCOMPARE(smct->_t_knownResourceCount(), 0);
289     QCOMPARE(smct->_t_knownFolderCount(), 0);
290 
291     // Manually create an Outbox collection.
292     Collection outbox;
293     outbox.setName(QLatin1String("my_outbox"));
294     outbox.setParentCollection(res1);
295     outbox.addAttribute(new SpecialCollectionAttribute("outbox"));
296     CollectionCreateJob *cjob = new CollectionCreateJob(outbox, this);
297     AKVERIFYEXEC(cjob);
298     outbox = cjob->collection();
299 
300     // LF should still have no folders, since the Outbox wasn't registered.
301     QCOMPARE(smct->_t_knownResourceCount(), 0);
302     QCOMPARE(smct->_t_knownFolderCount(), 0);
303     QCOMPARE(spy.count(), 0);
304     QCOMPARE(defSpy.count(), 0);
305 
306     // Register the collection. LF should now know it.
307     bool ok = smc->registerCollection(SpecialMailCollections::Outbox, outbox);
308     QVERIFY(ok);
309     QVERIFY(smc->hasDefaultCollection(SpecialMailCollections::Outbox));
310     QCOMPARE(smc->defaultCollection(SpecialMailCollections::Outbox), outbox);
311     QCOMPARE(smct->_t_knownResourceCount(), 1);
312     QCOMPARE(smct->_t_knownFolderCount(), 1);
313     QCOMPARE(spy.count(), 1);
314     QCOMPARE(defSpy.count(), 1);
315 
316     // Delete the collection. LF should watch for that.
317     CollectionDeleteJob *djob = new CollectionDeleteJob(outbox, this);
318     AKVERIFYEXEC(djob);
319     QTest::qWait(100);
320     QVERIFY(!smc->hasDefaultCollection(SpecialMailCollections::Outbox));
321     QCOMPARE(smct->_t_knownResourceCount(), 0);
322     QCOMPARE(smct->_t_knownFolderCount(), 0);
323     QCOMPARE(spy.count(), 2);
324     QCOMPARE(defSpy.count(), 2);
325 }
326 
testBatchRegister()327 void LocalFoldersTest::testBatchRegister()
328 {
329     SpecialMailCollections *smc = SpecialMailCollections::self();
330     SpecialCollections *sc = smc;
331     SpecialMailCollectionsTesting *smct = SpecialMailCollectionsTesting::_t_self();
332     Q_ASSERT(smc);
333     Q_ASSERT(smct);
334     QSignalSpy spy(smc, &SpecialMailCollections::collectionsChanged);
335     QSignalSpy defSpy(smc, &SpecialMailCollections::defaultCollectionsChanged);
336     QVERIFY(spy.isValid());
337     QVERIFY(defSpy.isValid());
338 
339     // Set the default resource. LF should have no folders.
340     smct->_t_setDefaultResourceId(res1.resource());
341     QCOMPARE(sc->d->defaultResource().identifier(), res1.resource());
342     QCOMPARE(smct->_t_knownResourceCount(), 0);
343     QCOMPARE(smct->_t_knownFolderCount(), 0);
344 
345     // Manually create an Outbox collection.
346     Collection outbox;
347     outbox.setName(QLatin1String("my_outbox"));
348     outbox.setParentCollection(res1);
349     outbox.addAttribute(new SpecialCollectionAttribute("outbox"));
350     CollectionCreateJob *cjob = new CollectionCreateJob(outbox, this);
351     AKVERIFYEXEC(cjob);
352     outbox = cjob->collection();
353 
354     // Manually create a Drafts collection.
355     Collection drafts;
356     drafts.setName(QLatin1String("my_drafts"));
357     drafts.setParentCollection(res1);
358     drafts.addAttribute(new SpecialCollectionAttribute("drafts"));
359     cjob = new CollectionCreateJob(drafts, this);
360     AKVERIFYEXEC(cjob);
361     drafts = cjob->collection();
362 
363     // LF should still have no folders, since the folders were not registered.
364     QCOMPARE(smct->_t_knownResourceCount(), 0);
365     QCOMPARE(smct->_t_knownFolderCount(), 0);
366     QCOMPARE(spy.count(), 0);
367     QCOMPARE(defSpy.count(), 0);
368 
369     // Register the folders in batch mode.
370     smct->_t_beginBatchRegister();
371     bool ok = smc->registerCollection(SpecialMailCollections::Outbox, outbox);
372     QVERIFY(ok);
373     QVERIFY(smc->hasDefaultCollection(SpecialMailCollections::Outbox));
374     QCOMPARE(smc->defaultCollection(SpecialMailCollections::Outbox), outbox);
375     QCOMPARE(smct->_t_knownResourceCount(), 1);
376     QCOMPARE(smct->_t_knownFolderCount(), 1);
377     QCOMPARE(spy.count(), 0);
378     QCOMPARE(defSpy.count(), 0);
379     ok = smc->registerCollection(SpecialMailCollections::Drafts, drafts);
380     QVERIFY(ok);
381     QVERIFY(smc->hasDefaultCollection(SpecialMailCollections::Drafts));
382     QCOMPARE(smc->defaultCollection(SpecialMailCollections::Drafts), drafts);
383     QCOMPARE(smct->_t_knownResourceCount(), 1);
384     QCOMPARE(smct->_t_knownFolderCount(), 2);
385     QCOMPARE(spy.count(), 0);
386     QCOMPARE(defSpy.count(), 0);
387     smct->_t_endBatchRegister();
388     QCOMPARE(smct->_t_knownResourceCount(), 1);
389     QCOMPARE(smct->_t_knownFolderCount(), 2);
390     QCOMPARE(spy.count(), 1);
391     QCOMPARE(defSpy.count(), 1);
392 
393     // Forget all folders in the default resource.
394     smct->_t_forgetFoldersForResource(sc->d->defaultResource().identifier());
395     QCOMPARE(smc->hasDefaultCollection(SpecialMailCollections::Outbox), false);
396     QCOMPARE(smc->hasDefaultCollection(SpecialMailCollections::Drafts), false);
397     QCOMPARE(smct->_t_knownResourceCount(), 0);
398     QCOMPARE(smct->_t_knownFolderCount(), 0);
399     QCOMPARE(spy.count(), 2);
400     QCOMPARE(defSpy.count(), 2);
401 
402     // Delete the collections.
403     CollectionDeleteJob *djob = new CollectionDeleteJob(outbox, this);
404     AKVERIFYEXEC(djob);
405     djob = new CollectionDeleteJob(drafts, this);
406     AKVERIFYEXEC(djob);
407 }
408 
testResourceScanErrors()409 void LocalFoldersTest::testResourceScanErrors()
410 {
411     // Job fails if no resourceId is given.
412     ResourceScanJob *resjob = new ResourceScanJob(QString(), Settings::self(), this);
413     QVERIFY(!resjob->exec());
414 }
415 
testResourceScan()416 void LocalFoldersTest::testResourceScan()
417 {
418     // Verify that res1 has no collections.
419     {
420         CollectionFetchJob *fjob = new CollectionFetchJob(res1, CollectionFetchJob::Recursive, this);
421         AKVERIFYEXEC(fjob);
422         QCOMPARE(fjob->collections().count(), 0);
423     }
424 
425     // Manually create an Outbox collection.
426     Collection outbox;
427     {
428         outbox.setName(QLatin1String("my_outbox"));
429         outbox.setParentCollection(res1);
430         outbox.addAttribute(new SpecialCollectionAttribute("outbox"));
431         CollectionCreateJob *cjob = new CollectionCreateJob(outbox, this);
432         AKVERIFYEXEC(cjob);
433         outbox = cjob->collection();
434     }
435 
436     // Manually create a Drafts collection.
437     Collection drafts;
438     {
439         drafts.setName(QLatin1String("my_drafts"));
440         drafts.setParentCollection(res1);
441         drafts.addAttribute(new SpecialCollectionAttribute("drafts"));
442         CollectionCreateJob *cjob = new CollectionCreateJob(drafts, this);
443         AKVERIFYEXEC(cjob);
444         drafts = cjob->collection();
445     }
446 
447     // Manually create a non-LocalFolder collection.
448     Collection intruder;
449     {
450         intruder.setName(QLatin1String("intruder"));
451         intruder.setParentCollection(res1);
452         CollectionCreateJob *cjob = new CollectionCreateJob(intruder, this);
453         AKVERIFYEXEC(cjob);
454         intruder = cjob->collection();
455     }
456 
457     // Verify that the collections have been created properly.
458     {
459         CollectionFetchJob *fjob = new CollectionFetchJob(res1, CollectionFetchJob::Recursive, this);
460         AKVERIFYEXEC(fjob);
461         QCOMPARE(fjob->collections().count(), 3);
462     }
463 
464     // Test that ResourceScanJob finds everything correctly.
465     ResourceScanJob *resjob = new ResourceScanJob(res1.resource(), Settings::self(), this);
466     AKVERIFYEXEC(resjob);
467     QCOMPARE(resjob->rootResourceCollection(), res1);
468     const Collection::List folders = resjob->specialCollections();
469     QCOMPARE(folders.count(), 2);
470     QVERIFY(folders.contains(outbox));
471     QVERIFY(folders.contains(drafts));
472 
473     // Clean up after ourselves.
474     CollectionDeleteJob *djob = new CollectionDeleteJob(outbox, this);
475     AKVERIFYEXEC(djob);
476     djob = new CollectionDeleteJob(drafts, this);
477     AKVERIFYEXEC(djob);
478     djob = new CollectionDeleteJob(intruder, this);
479     AKVERIFYEXEC(djob);
480 
481     SpecialMailCollections::self()->destroy();
482 }
483 
testDefaultResourceJob()484 void LocalFoldersTest::testDefaultResourceJob()
485 {
486     SpecialMailCollectionsTesting *scmt = SpecialMailCollectionsTesting::_t_self();
487     scmt->_t_setDefaultResourceId(QLatin1String("akonadi_maildir_resource"));
488 
489     // Initially the default maildir does not exist.
490     QVERIFY(!QFile::exists(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/local-mail")));
491 
492     // Run the job.
493     Collection maildirRoot;
494     QString resourceId;
495     {
496         DefaultResourceJob *resjob = new DefaultResourceJob(Settings::self(), this);
497         resjob->setDefaultResourceType(QLatin1String("akonadi_maildir_resource"));
498 
499         QVariantMap options;
500         options.insert(QLatin1String("Name"), i18nc("local mail folder", "Local Folders"));
501         options.insert(QLatin1String("Path"), QString(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/local-mail")));
502         resjob->setDefaultResourceOptions(options);
503         resjob->setTypes(mDisplayNameMap.keys());
504         resjob->setNameForTypeMap(mDisplayNameMap);
505         resjob->setIconForTypeMap(mIconNameMap);
506 
507         AKVERIFYEXEC(resjob);
508         resourceId = resjob->resourceId();
509         const Collection::List folders = resjob->specialCollections();
510         QCOMPARE(folders.count(), 1);
511         maildirRoot = folders.first();
512         QVERIFY(maildirRoot.hasAttribute<SpecialCollectionAttribute>());
513         QCOMPARE(maildirRoot.attribute<SpecialCollectionAttribute>()->collectionType(), QByteArray("local-mail"));
514     }
515 
516     // The maildir should exist now.
517     QVERIFY(QFile::exists(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/local-mail")));
518 
519     // Create a LocalFolder in the default resource.
520     Collection outbox;
521     {
522         outbox.setName(QLatin1String("outbox"));
523         outbox.setParentCollection(maildirRoot);
524         outbox.addAttribute(new SpecialCollectionAttribute("outbox"));
525         CollectionCreateJob *cjob = new CollectionCreateJob(outbox, this);
526         AKVERIFYEXEC(cjob);
527         outbox = cjob->collection();
528 
529         // Wait for the maildir resource to actually create the folder on disk...
530         // (needed in testRecoverDefaultResource())
531         QTest::qWait(500);
532     }
533 
534     // Run the job again.
535     {
536         DefaultResourceJob *resjob = new DefaultResourceJob(Settings::self(), this);
537         resjob->setDefaultResourceType(QLatin1String("akonadi_maildir_resource"));
538 
539         QVariantMap options;
540         options.insert(QLatin1String("Name"), i18nc("local mail folder", "Local Folders"));
541         options.insert(QLatin1String("Path"), QString(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/local-mail")));
542         resjob->setDefaultResourceOptions(options);
543         resjob->setTypes(mDisplayNameMap.keys());
544         resjob->setNameForTypeMap(mDisplayNameMap);
545         resjob->setIconForTypeMap(mIconNameMap);
546 
547         AKVERIFYEXEC(resjob);
548         QCOMPARE(resourceId, resjob->resourceId()); // Did not mistakenly create another resource.
549         const Collection::List folders = resjob->specialCollections();
550         QCOMPARE(folders.count(), 2);
551         QVERIFY(folders.contains(maildirRoot));
552         QVERIFY(folders.contains(outbox));
553     }
554 }
555 
testRecoverDefaultResource()556 void LocalFoldersTest::testRecoverDefaultResource()
557 {
558     // The maildirs should exist (created in testDefaultResourceJob).
559     const QString xdgPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/');
560     const QString rootPath = xdgPath + QLatin1String("local-mail");
561     const QString outboxPath = xdgPath + QString::fromLatin1(".%1.directory/%2").arg(QLatin1String("local-mail")).arg(QLatin1String("outbox"));
562     QVERIFY(QFile::exists(rootPath));
563     QVERIFY(QFile::exists(outboxPath));
564 
565     // Kill the default resource.
566     const QString oldResourceId = static_cast<SpecialCollections *>(SpecialMailCollections::self())->d->defaultResource().identifier();
567     const AgentInstance resource = AgentManager::self()->instance(oldResourceId);
568     QVERIFY(resource.isValid());
569     AgentManager::self()->removeInstance(resource);
570     QTest::qWait(100);
571 
572     // Run the DefaultResourceJob now. It should recover the Root and Outbox folders
573     // created in testDefaultResourceJob.
574     {
575         DefaultResourceJob *resjob = new DefaultResourceJob(Settings::self(), this);
576         resjob->setDefaultResourceType(QLatin1String("akonadi_maildir_resource"));
577 
578         QVariantMap options;
579         options.insert(QLatin1String("Name"), i18nc("local mail folder", "Local Folders"));
580         options.insert(QLatin1String("Path"), QString(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/local-mail")));
581         resjob->setDefaultResourceOptions(options);
582         resjob->setTypes(mDisplayNameMap.keys());
583         resjob->setNameForTypeMap(mDisplayNameMap);
584         resjob->setIconForTypeMap(mIconNameMap);
585 
586         AKVERIFYEXEC(resjob);
587         QVERIFY(resjob->resourceId() != oldResourceId); // Created another resource.
588         Collection::List folders = resjob->specialCollections();
589         QCOMPARE(folders.count(), 2);
590 
591         // Reorder the folders.
592         if (folders.first().parentCollection() != Collection::root()) {
593             folders.move(1, 0);
594         }
595 
596         // The first folder should be the Root.
597         {
598             Collection col = folders[0];
599             QCOMPARE(col.name(), QLatin1String("Local Folders"));
600             QVERIFY(col.hasAttribute<SpecialCollectionAttribute>());
601             QCOMPARE(col.attribute<SpecialCollectionAttribute>()->collectionType(), QByteArray("local-mail"));
602         }
603 
604         // The second folder should be the Outbox.
605         {
606             Collection col = folders[1];
607             QCOMPARE(col.name(), QLatin1String("outbox"));
608             QVERIFY(col.hasAttribute<SpecialCollectionAttribute>());
609             QCOMPARE(col.attribute<SpecialCollectionAttribute>()->collectionType(), QByteArray("outbox"));
610         }
611     }
612 }
613 
614 QTEST_AKONADIMAIN(LocalFoldersTest)
615