diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-06-10 15:49:48 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-06-10 15:49:48 +0200 |
commit | 638e75d6f3d00fb473fd45e325fcfb34c6340c65 (patch) | |
tree | 4db057d7dff07c9e03cf5a732c660e705c17327a | |
parent | ce0feb3ef62c9438b0aedd601461cbb340faa021 (diff) | |
download | sink-638e75d6f3d00fb473fd45e325fcfb34c6340c65.tar.gz sink-638e75d6f3d00fb473fd45e325fcfb34c6340c65.zip |
Create the drafts folder if necessary and merge it with the source
version
-rw-r--r-- | common/synchronizer.cpp | 61 | ||||
-rw-r--r-- | common/synchronizer.h | 3 | ||||
-rw-r--r-- | examples/imapresource/imapresource.cpp | 128 | ||||
-rw-r--r-- | examples/imapresource/tests/resetmailbox.sh | 1 | ||||
-rw-r--r-- | tests/mailsynctest.cpp | 17 |
5 files changed, 194 insertions, 16 deletions
diff --git a/common/synchronizer.cpp b/common/synchronizer.cpp index 0314997..b127ec5 100644 --- a/common/synchronizer.cpp +++ b/common/synchronizer.cpp | |||
@@ -164,6 +164,59 @@ void Synchronizer::createOrModify(const QByteArray &bufferType, const QByteArray | |||
164 | } | 164 | } |
165 | } | 165 | } |
166 | 166 | ||
167 | template<typename DomainType> | ||
168 | void Synchronizer::createOrModify(const QByteArray &bufferType, const QByteArray &remoteId, const DomainType &entity, const QHash<QByteArray, Sink::Query::Comparator> &mergeCriteria) | ||
169 | { | ||
170 | |||
171 | Trace() << "Create or modify" << bufferType << remoteId; | ||
172 | auto mainDatabase = Storage::mainDatabase(transaction(), bufferType); | ||
173 | const auto sinkId = syncStore().resolveRemoteId(bufferType, remoteId); | ||
174 | const auto found = mainDatabase.contains(sinkId); | ||
175 | auto adaptorFactory = Sink::AdaptorFactoryRegistry::instance().getFactory(mResourceType, bufferType); | ||
176 | if (!found) { | ||
177 | if (!mergeCriteria.isEmpty()) { | ||
178 | Sink::Query query; | ||
179 | query.propertyFilter = mergeCriteria; | ||
180 | bool merge = false; | ||
181 | Sink::EntityReader<DomainType> reader(mResourceInstanceIdentifier, mResourceType, transaction()); | ||
182 | reader.query(query, | ||
183 | [this, bufferType, remoteId, &merge](const DomainType &o) -> bool{ | ||
184 | merge = true; | ||
185 | Trace() << "Merging local entity with remote entity: " << o.identifier() << remoteId; | ||
186 | syncStore().recordRemoteId(bufferType, o.identifier(), remoteId); | ||
187 | return false; | ||
188 | }); | ||
189 | if (!merge) { | ||
190 | Trace() << "Found a new entity: " << remoteId; | ||
191 | createEntity( | ||
192 | sinkId, bufferType, entity, *adaptorFactory, [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::CreateEntityCommand, buffer); }); | ||
193 | } | ||
194 | } else { | ||
195 | Trace() << "Found a new entity: " << remoteId; | ||
196 | createEntity( | ||
197 | sinkId, bufferType, entity, *adaptorFactory, [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::CreateEntityCommand, buffer); }); | ||
198 | } | ||
199 | } else { // modification | ||
200 | qint64 retrievedRevision = 0; | ||
201 | if (auto current = EntityReaderUtils::getLatest(mainDatabase, sinkId, *adaptorFactory, retrievedRevision)) { | ||
202 | bool changed = false; | ||
203 | for (const auto &property : entity.changedProperties()) { | ||
204 | if (entity.getProperty(property) != current->getProperty(property)) { | ||
205 | Trace() << "Property changed " << sinkId << property; | ||
206 | changed = true; | ||
207 | } | ||
208 | } | ||
209 | if (changed) { | ||
210 | Trace() << "Found a modified entity: " << remoteId; | ||
211 | modifyEntity(sinkId, Sink::Storage::maxRevision(transaction()), bufferType, entity, *adaptorFactory, | ||
212 | [this](const QByteArray &buffer) { enqueueCommand(Sink::Commands::ModifyEntityCommand, buffer); }); | ||
213 | } | ||
214 | } else { | ||
215 | Warning() << "Failed to get current entity"; | ||
216 | } | ||
217 | } | ||
218 | } | ||
219 | |||
167 | KAsync::Job<void> Synchronizer::synchronize() | 220 | KAsync::Job<void> Synchronizer::synchronize() |
168 | { | 221 | { |
169 | Trace() << "Synchronizing"; | 222 | Trace() << "Synchronizing"; |
@@ -202,3 +255,11 @@ Sink::Storage::Transaction &Synchronizer::syncTransaction() | |||
202 | } | 255 | } |
203 | return mSyncTransaction; | 256 | return mSyncTransaction; |
204 | } | 257 | } |
258 | |||
259 | #define REGISTER_TYPE(T) \ | ||
260 | template void Synchronizer::createOrModify(const QByteArray &bufferType, const QByteArray &remoteId, const T &entity, const QHash<QByteArray, Sink::Query::Comparator> &mergeCriteria) | ||
261 | |||
262 | REGISTER_TYPE(ApplicationDomain::Event); | ||
263 | REGISTER_TYPE(ApplicationDomain::Mail); | ||
264 | REGISTER_TYPE(ApplicationDomain::Folder); | ||
265 | |||
diff --git a/common/synchronizer.h b/common/synchronizer.h index 17e7003..8442aa2 100644 --- a/common/synchronizer.h +++ b/common/synchronizer.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <QObject> | 23 | #include <QObject> |
24 | #include <Async/Async> | 24 | #include <Async/Async> |
25 | #include <domainadaptor.h> | 25 | #include <domainadaptor.h> |
26 | #include <query.h> | ||
26 | 27 | ||
27 | #include "storage.h" | 28 | #include "storage.h" |
28 | 29 | ||
@@ -81,6 +82,8 @@ protected: | |||
81 | * Depending on whether the entity is locally available, or has changed. | 82 | * Depending on whether the entity is locally available, or has changed. |
82 | */ | 83 | */ |
83 | void createOrModify(const QByteArray &bufferType, const QByteArray &remoteId, const Sink::ApplicationDomain::ApplicationDomainType &entity); | 84 | void createOrModify(const QByteArray &bufferType, const QByteArray &remoteId, const Sink::ApplicationDomain::ApplicationDomainType &entity); |
85 | template <typename DomainType> | ||
86 | void createOrModify(const QByteArray &bufferType, const QByteArray &remoteId, const DomainType &entity, const QHash<QByteArray, Sink::Query::Comparator> &mergeCriteria); | ||
84 | 87 | ||
85 | virtual KAsync::Job<void> synchronizeWithSource() = 0; | 88 | virtual KAsync::Job<void> synchronizeWithSource() = 0; |
86 | 89 | ||
diff --git a/examples/imapresource/imapresource.cpp b/examples/imapresource/imapresource.cpp index fee479a..ac75432 100644 --- a/examples/imapresource/imapresource.cpp +++ b/examples/imapresource/imapresource.cpp | |||
@@ -39,12 +39,14 @@ | |||
39 | #include "sourcewriteback.h" | 39 | #include "sourcewriteback.h" |
40 | #include "entitystore.h" | 40 | #include "entitystore.h" |
41 | #include "remoteidmap.h" | 41 | #include "remoteidmap.h" |
42 | #include "query.h" | ||
42 | #include <QDate> | 43 | #include <QDate> |
43 | #include <QUuid> | 44 | #include <QUuid> |
44 | #include <QDir> | 45 | #include <QDir> |
45 | #include <QDirIterator> | 46 | #include <QDirIterator> |
46 | 47 | ||
47 | #include "imapserverproxy.h" | 48 | #include "imapserverproxy.h" |
49 | #include "entityreader.h" | ||
48 | 50 | ||
49 | //This is the resources entity type, and not the domain type | 51 | //This is the resources entity type, and not the domain type |
50 | #define ENTITY_TYPE_MAIL "mail" | 52 | #define ENTITY_TYPE_MAIL "mail" |
@@ -56,6 +58,77 @@ | |||
56 | using namespace Imap; | 58 | using namespace Imap; |
57 | using namespace Sink; | 59 | using namespace Sink; |
58 | 60 | ||
61 | static QHash<QByteArray, QString> specialPurposeFolders() | ||
62 | { | ||
63 | QHash<QByteArray, QString> hash; | ||
64 | //FIXME localize | ||
65 | hash.insert("drafts", "Drafts"); | ||
66 | return hash; | ||
67 | } | ||
68 | |||
69 | static QHash<QString, QByteArray> specialPurposeNames() | ||
70 | { | ||
71 | QHash<QString, QByteArray> hash; | ||
72 | for (const auto &value : specialPurposeFolders().values()) { | ||
73 | hash.insert(value.toLower(), specialPurposeFolders().key(value)); | ||
74 | } | ||
75 | return hash; | ||
76 | } | ||
77 | |||
78 | //specialpurpose, name | ||
79 | static QHash<QByteArray, QString> sSpecialPurposeFolders = specialPurposeFolders(); | ||
80 | //Lowercase-name, specialpurpose | ||
81 | static QHash<QString, QByteArray> sSpecialPurposeNames = specialPurposeNames(); | ||
82 | |||
83 | class DraftsProcessor : public Sink::Preprocessor | ||
84 | { | ||
85 | public: | ||
86 | DraftsProcessor() {} | ||
87 | |||
88 | QByteArray ensureDraftsFolder(Sink::Storage::Transaction &transaction) | ||
89 | { | ||
90 | if (mDraftsFolder.isEmpty()) { | ||
91 | //Try to find an existing drafts folder | ||
92 | Sink::EntityReader<ApplicationDomain::Folder> reader(mResourceInstanceIdentifier, mResourceType, transaction); | ||
93 | reader.query(Sink::Query().filter<ApplicationDomain::Folder::SpecialPurpose>(Query::Comparator("drafts", Query::Comparator::Contains)), | ||
94 | [this](const ApplicationDomain::Folder &f) -> bool{ | ||
95 | mDraftsFolder = f.identifier(); | ||
96 | return false; | ||
97 | }); | ||
98 | if (mDraftsFolder.isEmpty()) { | ||
99 | Trace() << "Failed to find a drafts folder, creating a new one"; | ||
100 | auto folder = ApplicationDomain::Folder::create(mResourceInstanceIdentifier); | ||
101 | folder.setSpecialPurpose(QByteArrayList() << "drafts"); | ||
102 | folder.setName(sSpecialPurposeFolders.value("drafts")); | ||
103 | folder.setIcon("folder"); | ||
104 | //This processes the pipeline synchronously | ||
105 | createEntity(folder); | ||
106 | mDraftsFolder = folder.identifier(); | ||
107 | } | ||
108 | } | ||
109 | return mDraftsFolder; | ||
110 | } | ||
111 | |||
112 | void newEntity(const QByteArray &uid, qint64 revision, Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | ||
113 | { | ||
114 | if (newEntity.getProperty("draft").toBool()) { | ||
115 | newEntity.setProperty("folder", ensureDraftsFolder(transaction)); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | void modifiedEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, Sink::ApplicationDomain::BufferAdaptor &newEntity, | ||
120 | Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | ||
121 | { | ||
122 | if (newEntity.getProperty("draft").toBool()) { | ||
123 | newEntity.setProperty("folder", ensureDraftsFolder(transaction)); | ||
124 | } | ||
125 | } | ||
126 | |||
127 | QByteArray mDraftsFolder; | ||
128 | QByteArray mResourceInstanceIdentifier; | ||
129 | QByteArray mResourceType; | ||
130 | }; | ||
131 | |||
59 | class MailPropertyExtractor : public Sink::Preprocessor | 132 | class MailPropertyExtractor : public Sink::Preprocessor |
60 | { | 133 | { |
61 | public: | 134 | public: |
@@ -97,10 +170,6 @@ public: | |||
97 | updatedIndexedProperties(newEntity); | 170 | updatedIndexedProperties(newEntity); |
98 | } | 171 | } |
99 | 172 | ||
100 | void deletedEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE | ||
101 | { | ||
102 | } | ||
103 | |||
104 | }; | 173 | }; |
105 | 174 | ||
106 | static qint64 uidFromMailRid(const QByteArray &remoteId) | 175 | static qint64 uidFromMailRid(const QByteArray &remoteId) |
@@ -142,13 +211,19 @@ public: | |||
142 | const auto remoteId = folderPath.toUtf8(); | 211 | const auto remoteId = folderPath.toUtf8(); |
143 | const auto bufferType = ENTITY_TYPE_FOLDER; | 212 | const auto bufferType = ENTITY_TYPE_FOLDER; |
144 | Sink::ApplicationDomain::Folder folder; | 213 | Sink::ApplicationDomain::Folder folder; |
145 | folder.setProperty("name", folderName); | 214 | folder.setProperty(ApplicationDomain::Folder::Name::name, folderName); |
146 | folder.setProperty("icon", icon); | 215 | folder.setProperty(ApplicationDomain::Folder::Icon::name, icon); |
216 | QHash<QByteArray, Query::Comparator> mergeCriteria; | ||
217 | if (sSpecialPurposeNames.contains(folderName.toLower())) { | ||
218 | auto type = sSpecialPurposeNames.value(folderName.toLower()); | ||
219 | folder.setProperty(ApplicationDomain::Folder::SpecialPurpose::name, QVariant::fromValue(QByteArrayList() << type)); | ||
220 | mergeCriteria.insert(ApplicationDomain::Folder::SpecialPurpose::name, Query::Comparator(type, Query::Comparator::Contains)); | ||
221 | } | ||
147 | 222 | ||
148 | if (!parentFolderRid.isEmpty()) { | 223 | if (!parentFolderRid.isEmpty()) { |
149 | folder.setProperty("parent", syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, parentFolderRid.toUtf8())); | 224 | folder.setProperty("parent", syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, parentFolderRid.toUtf8())); |
150 | } | 225 | } |
151 | createOrModify(bufferType, remoteId, folder); | 226 | createOrModify(bufferType, remoteId, folder, mergeCriteria); |
152 | return remoteId; | 227 | return remoteId; |
153 | } | 228 | } |
154 | 229 | ||
@@ -434,14 +509,47 @@ public: | |||
434 | } | 509 | } |
435 | Trace() << "Creating a new folder: " << parentFolder << folder.getName(); | 510 | Trace() << "Creating a new folder: " << parentFolder << folder.getName(); |
436 | auto rid = QSharedPointer<QByteArray>::create(); | 511 | auto rid = QSharedPointer<QByteArray>::create(); |
437 | return login.then<QString>(imap->createSubfolder(parentFolder, folder.getName())) | 512 | auto createFolder = login.then<QString>(imap->createSubfolder(parentFolder, folder.getName())) |
438 | .then<void, QString>([imap, rid](const QString &createdFolder) { | 513 | .then<void, QString>([imap, rid](const QString &createdFolder) { |
439 | Trace() << "Finished creating a new folder: " << createdFolder; | 514 | Trace() << "Finished creating a new folder: " << createdFolder; |
440 | *rid = createdFolder.toUtf8(); | 515 | *rid = createdFolder.toUtf8(); |
441 | }) | 516 | }); |
517 | if (folder.getSpecialPurpose().isEmpty()) { | ||
518 | return createFolder | ||
519 | .then<QByteArray>([rid](){ | ||
520 | return *rid; | ||
521 | }); | ||
522 | } else { //We try to merge special purpose folders first | ||
523 | auto specialPurposeFolders = QSharedPointer<QHash<QByteArray, QString>>::create(); | ||
524 | auto mergeJob = imap->login(mUser, mPassword) | ||
525 | .then<void>(imap->fetchFolders([=](const QVector<Imap::Folder> &folders) { | ||
526 | for (const auto &f : folders) { | ||
527 | if (sSpecialPurposeNames.contains(f.pathParts.last().toLower())) { | ||
528 | specialPurposeFolders->insert(sSpecialPurposeNames.value(f.pathParts.last().toLower()), f.path); | ||
529 | }; | ||
530 | } | ||
531 | })) | ||
532 | .then<void, KAsync::Job<void>>([specialPurposeFolders, folder, imap, parentFolder, rid]() -> KAsync::Job<void> { | ||
533 | for (const auto &purpose : folder.getSpecialPurpose()) { | ||
534 | if (specialPurposeFolders->contains(purpose)) { | ||
535 | auto f = specialPurposeFolders->value(purpose); | ||
536 | Trace() << "Merging specialpurpose folder with: " << f << " with purpose: " << purpose; | ||
537 | *rid = f.toUtf8(); | ||
538 | return KAsync::null<void>(); | ||
539 | } | ||
540 | Trace() << "No match found for merging, creating a new folder"; | ||
541 | return imap->createSubfolder(parentFolder, folder.getName()) | ||
542 | .then<void, QString>([imap, rid](const QString &createdFolder) { | ||
543 | Trace() << "Finished creating a new folder: " << createdFolder; | ||
544 | *rid = createdFolder.toUtf8(); | ||
545 | }); | ||
546 | |||
547 | }) | ||
442 | .then<QByteArray>([rid](){ | 548 | .then<QByteArray>([rid](){ |
443 | return *rid; | 549 | return *rid; |
444 | }); | 550 | }); |
551 | return mergeJob; | ||
552 | } | ||
445 | } else if (operation == Sink::Operation_Removal) { | 553 | } else if (operation == Sink::Operation_Removal) { |
446 | Trace() << "Removing a folder: " << oldRemoteId; | 554 | Trace() << "Removing a folder: " << oldRemoteId; |
447 | return login.then<void>(imap->remove(oldRemoteId)) | 555 | return login.then<void>(imap->remove(oldRemoteId)) |
@@ -495,7 +603,7 @@ ImapResource::ImapResource(const QByteArray &instanceIdentifier, const QSharedPo | |||
495 | changereplay->mPassword = mPassword; | 603 | changereplay->mPassword = mPassword; |
496 | setupChangereplay(changereplay); | 604 | setupChangereplay(changereplay); |
497 | 605 | ||
498 | setupPreprocessors(ENTITY_TYPE_MAIL, QVector<Sink::Preprocessor*>() << new MailPropertyExtractor << new DefaultIndexUpdater<Sink::ApplicationDomain::Mail>); | 606 | setupPreprocessors(ENTITY_TYPE_MAIL, QVector<Sink::Preprocessor*>() << new DraftsProcessor << new MailPropertyExtractor << new DefaultIndexUpdater<Sink::ApplicationDomain::Mail>); |
499 | setupPreprocessors(ENTITY_TYPE_FOLDER, QVector<Sink::Preprocessor*>() << new DefaultIndexUpdater<Sink::ApplicationDomain::Folder>); | 607 | setupPreprocessors(ENTITY_TYPE_FOLDER, QVector<Sink::Preprocessor*>() << new DefaultIndexUpdater<Sink::ApplicationDomain::Folder>); |
500 | } | 608 | } |
501 | 609 | ||
diff --git a/examples/imapresource/tests/resetmailbox.sh b/examples/imapresource/tests/resetmailbox.sh index 5e52d6f..8834b51 100644 --- a/examples/imapresource/tests/resetmailbox.sh +++ b/examples/imapresource/tests/resetmailbox.sh | |||
@@ -3,6 +3,7 @@ | |||
3 | sudo echo "sam user.doe.* cyrus c" | cyradm --auth PLAIN -u cyrus -w admin localhost | 3 | sudo echo "sam user.doe.* cyrus c" | cyradm --auth PLAIN -u cyrus -w admin localhost |
4 | sudo echo "dm user.doe.*" | cyradm --auth PLAIN -u cyrus -w admin localhost | 4 | sudo echo "dm user.doe.*" | cyradm --auth PLAIN -u cyrus -w admin localhost |
5 | sudo echo "cm user.doe.test" | cyradm --auth PLAIN -u cyrus -w admin localhost | 5 | sudo echo "cm user.doe.test" | cyradm --auth PLAIN -u cyrus -w admin localhost |
6 | sudo echo "cm user.doe.Drafts" | cyradm --auth PLAIN -u cyrus -w admin localhost | ||
6 | sudo echo "sam user.doe cyrus c" | cyradm --auth PLAIN -u cyrus -w admin localhost | 7 | sudo echo "sam user.doe cyrus c" | cyradm --auth PLAIN -u cyrus -w admin localhost |
7 | sudo cp /work/source/Sink/examples/imapresource/tests/data/1365777830.R28.localhost.localdomain\:2\,S /var/spool/imap/d/user/doe/test/1. | 8 | sudo cp /work/source/Sink/examples/imapresource/tests/data/1365777830.R28.localhost.localdomain\:2\,S /var/spool/imap/d/user/doe/test/1. |
8 | sudo chown cyrus:mail /var/spool/imap/d/user/doe/test/1. | 9 | sudo chown cyrus:mail /var/spool/imap/d/user/doe/test/1. |
diff --git a/tests/mailsynctest.cpp b/tests/mailsynctest.cpp index 6c91381..ff56030 100644 --- a/tests/mailsynctest.cpp +++ b/tests/mailsynctest.cpp | |||
@@ -80,7 +80,7 @@ void MailSyncTest::testListFolders() | |||
80 | 80 | ||
81 | Sink::Query query; | 81 | Sink::Query query; |
82 | query.resources << mResourceInstanceIdentifier; | 82 | query.resources << mResourceInstanceIdentifier; |
83 | query.request<Folder::Name>(); | 83 | query.request<Folder::Name>().request<Folder::SpecialPurpose>(); |
84 | 84 | ||
85 | // Ensure all local data is processed | 85 | // Ensure all local data is processed |
86 | VERIFYEXEC(Store::synchronize(query)); | 86 | VERIFYEXEC(Store::synchronize(query)); |
@@ -88,16 +88,21 @@ void MailSyncTest::testListFolders() | |||
88 | 88 | ||
89 | auto job = Store::fetchAll<Folder>(query).then<void, QList<Folder::Ptr>>([=](const QList<Folder::Ptr> &folders) { | 89 | auto job = Store::fetchAll<Folder>(query).then<void, QList<Folder::Ptr>>([=](const QList<Folder::Ptr> &folders) { |
90 | QStringList names; | 90 | QStringList names; |
91 | QHash<QByteArray, QByteArray> specialPurposeFolders; | ||
91 | for (const auto &folder : folders) { | 92 | for (const auto &folder : folders) { |
92 | names << folder->getName(); | 93 | names << folder->getName(); |
94 | for (const auto &purpose : folder->getSpecialPurpose()) { | ||
95 | specialPurposeFolders.insert(purpose, folder->identifier()); | ||
96 | } | ||
93 | } | 97 | } |
94 | //Workaround for maildir | 98 | //Workaround for maildir |
95 | if (names.contains("maildir1")) { | 99 | if (names.contains("maildir1")) { |
96 | names.removeAll("maildir1"); | 100 | names.removeAll("maildir1"); |
97 | } | 101 | } |
98 | if (mCapabilities.contains(ResourceCapabilities::Mail::drafts)) { | 102 | if (mCapabilities.contains(ResourceCapabilities::Mail::drafts)) { |
99 | QVERIFY(names.contains("drafts")); | 103 | QVERIFY(names.contains("Drafts")); |
100 | names.removeAll("drafts"); | 104 | names.removeAll("Drafts"); |
105 | QVERIFY(specialPurposeFolders.contains("drafts")); | ||
101 | } | 106 | } |
102 | QCOMPARE(names.size(), 2); | 107 | QCOMPARE(names.size(), 2); |
103 | QVERIFY(names.contains("INBOX")); | 108 | QVERIFY(names.contains("INBOX")); |
@@ -183,8 +188,8 @@ void MailSyncTest::testListFolderHierarchy() | |||
183 | names.removeAll("maildir1"); | 188 | names.removeAll("maildir1"); |
184 | } | 189 | } |
185 | if (mCapabilities.contains(ResourceCapabilities::Mail::drafts)) { | 190 | if (mCapabilities.contains(ResourceCapabilities::Mail::drafts)) { |
186 | QVERIFY(names.contains("drafts")); | 191 | QVERIFY(names.contains("Drafts")); |
187 | names.removeAll("drafts"); | 192 | names.removeAll("Drafts"); |
188 | } | 193 | } |
189 | QCOMPARE(names.size(), 3); | 194 | QCOMPARE(names.size(), 3); |
190 | QCOMPARE(map.value("sub")->getParent(), map.value("test")->identifier()); | 195 | QCOMPARE(map.value("sub")->getParent(), map.value("test")->identifier()); |
@@ -195,7 +200,7 @@ void MailSyncTest::testListFolderHierarchy() | |||
195 | void MailSyncTest::testListNewSubFolder() | 200 | void MailSyncTest::testListNewSubFolder() |
196 | { | 201 | { |
197 | if (!mCapabilities.contains(ResourceCapabilities::Mail::folderhierarchy)) { | 202 | if (!mCapabilities.contains(ResourceCapabilities::Mail::folderhierarchy)) { |
198 | QSKIP("Missing capability folder.hierarchy"); | 203 | QSKIP("Missing capability mail.folderhierarchy"); |
199 | } | 204 | } |
200 | Sink::Query query; | 205 | Sink::Query query; |
201 | query.resources << mResourceInstanceIdentifier; | 206 | query.resources << mResourceInstanceIdentifier; |