summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2016-05-24 23:48:28 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2016-05-24 23:48:28 +0200
commitb4be5caff7691b5a4325938dc10abc02432af26e (patch)
treecd41cde8bea050f9793ce5fc4e451945aec6082c
parent78a59b874ba088caec06c10761ebacaba3f120b5 (diff)
downloadsink-b4be5caff7691b5a4325938dc10abc02432af26e.tar.gz
sink-b4be5caff7691b5a4325938dc10abc02432af26e.zip
A much more comprehensive mail test
-rw-r--r--common/genericresource.cpp2
-rw-r--r--common/genericresource.h2
-rw-r--r--examples/maildirresource/maildirresource.cpp105
-rw-r--r--tests/mailtest.cpp110
-rw-r--r--tests/mailtest.h3
5 files changed, 176 insertions, 46 deletions
diff --git a/common/genericresource.cpp b/common/genericresource.cpp
index 74e829c..637e371 100644
--- a/common/genericresource.cpp
+++ b/common/genericresource.cpp
@@ -643,7 +643,7 @@ void GenericResource::scanForRemovals(Sink::Storage::Transaction &transaction, S
643 }); 643 });
644} 644}
645 645
646static QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> getLatest(const Sink::Storage::NamedDatabase &db, const QByteArray &uid, DomainTypeAdaptorFactoryInterface &adaptorFactory) 646QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> GenericResource::getLatest(const Sink::Storage::NamedDatabase &db, const QByteArray &uid, DomainTypeAdaptorFactoryInterface &adaptorFactory)
647{ 647{
648 QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> current; 648 QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> current;
649 db.findLatest(uid, 649 db.findLatest(uid,
diff --git a/common/genericresource.h b/common/genericresource.h
index 9665d6b..9582f06 100644
--- a/common/genericresource.h
+++ b/common/genericresource.h
@@ -114,6 +114,8 @@ protected:
114 void createOrModify(Sink::Storage::Transaction &transaction, Sink::Storage::Transaction &synchronizationTransaction, DomainTypeAdaptorFactoryInterface &adaptorFactory, 114 void createOrModify(Sink::Storage::Transaction &transaction, Sink::Storage::Transaction &synchronizationTransaction, DomainTypeAdaptorFactoryInterface &adaptorFactory,
115 const QByteArray &bufferType, const QByteArray &remoteId, const Sink::ApplicationDomain::ApplicationDomainType &entity); 115 const QByteArray &bufferType, const QByteArray &remoteId, const Sink::ApplicationDomain::ApplicationDomainType &entity);
116 116
117 static QSharedPointer<Sink::ApplicationDomain::BufferAdaptor> getLatest(const Sink::Storage::NamedDatabase &db, const QByteArray &uid, DomainTypeAdaptorFactoryInterface &adaptorFactory);
118
117 MessageQueue mUserQueue; 119 MessageQueue mUserQueue;
118 MessageQueue mSynchronizerQueue; 120 MessageQueue mSynchronizerQueue;
119 QByteArray mResourceInstanceIdentifier; 121 QByteArray mResourceInstanceIdentifier;
diff --git a/examples/maildirresource/maildirresource.cpp b/examples/maildirresource/maildirresource.cpp
index 42da667..6dc9990 100644
--- a/examples/maildirresource/maildirresource.cpp
+++ b/examples/maildirresource/maildirresource.cpp
@@ -49,6 +49,22 @@
49#undef DEBUG_AREA 49#undef DEBUG_AREA
50#define DEBUG_AREA "resource.maildir" 50#define DEBUG_AREA "resource.maildir"
51 51
52static QString getFilePathFromMimeMessagePath(const QString &mimeMessagePath)
53{
54 auto parts = mimeMessagePath.split('/');
55 const auto key = parts.takeLast();
56 const auto path = parts.join("/") + "/cur/";
57
58 QDir dir(path);
59 const QFileInfoList list = dir.entryInfoList(QStringList() << (key+"*"), QDir::Files);
60 if (list.size() != 1) {
61 Warning() << "Failed to find message " << mimeMessagePath;
62 Warning() << "Failed to find message " << path;
63 return QString();
64 }
65 return list.first().filePath();
66}
67
52class FolderUpdater : public Sink::Preprocessor 68class FolderUpdater : public Sink::Preprocessor
53{ 69{
54public: 70public:
@@ -76,7 +92,7 @@ public:
76 }); 92 });
77 return folderPath; 93 return folderPath;
78 } 94 }
79 95
80 QString moveMessage(const QString &oldPath, const QByteArray &folder, Sink::Storage::Transaction &transaction) 96 QString moveMessage(const QString &oldPath, const QByteArray &folder, Sink::Storage::Transaction &transaction)
81 { 97 {
82 if (oldPath.startsWith(Sink::temporaryFileLocation())) { 98 if (oldPath.startsWith(Sink::temporaryFileLocation())) {
@@ -90,22 +106,13 @@ public:
90 } 106 }
91 return oldPath; 107 return oldPath;
92 } 108 }
109
93 void updatedIndexedProperties(Sink::ApplicationDomain::BufferAdaptor &newEntity) 110 void updatedIndexedProperties(Sink::ApplicationDomain::BufferAdaptor &newEntity)
94 { 111 {
95 const auto mimeMessagePath = newEntity.getProperty("mimeMessage").toString(); 112 const auto filePath = getFilePathFromMimeMessagePath(newEntity.getProperty("mimeMessage").toString());
96 auto parts = mimeMessagePath.split('/');
97 const auto key = parts.takeLast();
98 const auto path = parts.join("/") + "/cur/";
99
100 QDir dir(path);
101 const QFileInfoList list = dir.entryInfoList(QStringList() << (key+"*"), QDir::Files);
102 if (list.size() != 1) {
103 Warning() << "Failed to find message " << path << key << list.size();
104 return;
105 }
106 113
107 KMime::Message *msg = new KMime::Message; 114 KMime::Message *msg = new KMime::Message;
108 msg->setHead(KMime::CRLFtoLF(KPIM::Maildir::readEntryHeadersFromFile(list.first().filePath()))); 115 msg->setHead(KMime::CRLFtoLF(KPIM::Maildir::readEntryHeadersFromFile(filePath)));
109 msg->parse(); 116 msg->parse();
110 117
111 newEntity.setProperty("subject", msg->subject(true)->asUnicodeString()); 118 newEntity.setProperty("subject", msg->subject(true)->asUnicodeString());
@@ -408,15 +415,7 @@ KAsync::Job<void> MaildirResource::replay(Sink::Storage &synchronizationStore, c
408 } else if (type == ENTITY_TYPE_MAIL) { 415 } else if (type == ENTITY_TYPE_MAIL) {
409 if (operation == Sink::Operation_Creation) { 416 if (operation == Sink::Operation_Creation) {
410 const Sink::ApplicationDomain::Mail mail(mResourceInstanceIdentifier, Sink::Storage::uidFromKey(key), revision, mMailAdaptorFactory->createAdaptor(entity)); 417 const Sink::ApplicationDomain::Mail mail(mResourceInstanceIdentifier, Sink::Storage::uidFromKey(key), revision, mMailAdaptorFactory->createAdaptor(entity));
411 auto parentFolder = mail.getProperty("folder").toByteArray(); 418 const auto remoteId = getFilePathFromMimeMessagePath(mail.getMimeMessagePath());
412 QByteArray parentFolderRemoteId;
413 if (!parentFolder.isEmpty()) {
414 parentFolderRemoteId = resolveLocalId(ENTITY_TYPE_FOLDER, parentFolder, synchronizationTransaction);
415 } else {
416 parentFolderRemoteId = mMaildirPath.toUtf8();
417 }
418 const auto parentFolderPath = parentFolderRemoteId;
419 const auto remoteId = mail.getProperty("mimeMessage").toString().split('/').last();
420 Trace() << "Creating a new mail." << remoteId; 419 Trace() << "Creating a new mail." << remoteId;
421 if (remoteId.isEmpty()) { 420 if (remoteId.isEmpty()) {
422 Warning() << "Failed to create mail: " << remoteId; 421 Warning() << "Failed to create mail: " << remoteId;
@@ -436,11 +435,18 @@ KAsync::Job<void> MaildirResource::replay(Sink::Storage &synchronizationStore, c
436 const auto remoteId = resolveLocalId(ENTITY_TYPE_MAIL, uid, synchronizationTransaction); 435 const auto remoteId = resolveLocalId(ENTITY_TYPE_MAIL, uid, synchronizationTransaction);
437 Trace() << "Modifying a mail: " << remoteId; 436 Trace() << "Modifying a mail: " << remoteId;
438 437
439 const auto maildirPath = KPIM::Maildir::getDirectoryFromFile(remoteId); 438 const Sink::ApplicationDomain::Mail mail(mResourceInstanceIdentifier, Sink::Storage::uidFromKey(key), revision, mMailAdaptorFactory->createAdaptor(entity));
439
440 const auto filePath = getFilePathFromMimeMessagePath(mail.getMimeMessagePath());
441 const auto maildirPath = KPIM::Maildir::getDirectoryFromFile(filePath);
440 KPIM::Maildir maildir(maildirPath, false); 442 KPIM::Maildir maildir(maildirPath, false);
441 443
442 const Sink::ApplicationDomain::Mail mail(mResourceInstanceIdentifier, Sink::Storage::uidFromKey(key), revision, mMailAdaptorFactory->createAdaptor(entity)); 444 const auto messagePathParts = filePath.split("/");
443 auto newIdentifier = mail.getMimeMessagePath().split("/").last(); 445 if (messagePathParts.isEmpty()) {
446 Warning() << "No message path available: " << remoteId;
447 return KAsync::error<void>(1, "No message path available.");
448 }
449 const auto newIdentifier = messagePathParts.last();
444 QString identifier; 450 QString identifier;
445 if (newIdentifier != KPIM::Maildir::getKeyFromFile(remoteId)) { 451 if (newIdentifier != KPIM::Maildir::getKeyFromFile(remoteId)) {
446 //Remove the old mime message if it changed 452 //Remove the old mime message if it changed
@@ -449,6 +455,7 @@ KAsync::Job<void> MaildirResource::replay(Sink::Storage &synchronizationStore, c
449 identifier = newIdentifier; 455 identifier = newIdentifier;
450 } else { 456 } else {
451 //The identifier needs to contain the flags for changeEntryFlags to work 457 //The identifier needs to contain the flags for changeEntryFlags to work
458 Q_ASSERT(!remoteId.split('/').isEmpty());
452 identifier = remoteId.split('/').last(); 459 identifier = remoteId.split('/').last();
453 } 460 }
454 461
@@ -480,12 +487,23 @@ KAsync::Job<void> MaildirResource::inspect(int inspectionType, const QByteArray
480{ 487{
481 auto synchronizationStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Sink::Storage::ReadOnly); 488 auto synchronizationStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Sink::Storage::ReadOnly);
482 auto synchronizationTransaction = synchronizationStore->createTransaction(Sink::Storage::ReadOnly); 489 auto synchronizationTransaction = synchronizationStore->createTransaction(Sink::Storage::ReadOnly);
490
491 auto mainStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier, Sink::Storage::ReadOnly);
492 auto transaction = mainStore->createTransaction(Sink::Storage::ReadOnly);
493
483 Trace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue; 494 Trace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue;
495
484 if (domainType == ENTITY_TYPE_MAIL) { 496 if (domainType == ENTITY_TYPE_MAIL) {
497 auto mainDatabase = Sink::Storage::mainDatabase(transaction, ENTITY_TYPE_MAIL);
498 auto bufferAdaptor = getLatest(mainDatabase, entityId, *mMailAdaptorFactory);
499 Q_ASSERT(bufferAdaptor);
500
501 const Sink::ApplicationDomain::Mail mail(mResourceInstanceIdentifier, entityId, 0, bufferAdaptor);
502 const auto filePath = getFilePathFromMimeMessagePath(mail.getMimeMessagePath());
503
485 if (inspectionType == Sink::ResourceControl::Inspection::PropertyInspectionType) { 504 if (inspectionType == Sink::ResourceControl::Inspection::PropertyInspectionType) {
486 if (property == "unread") { 505 if (property == "unread") {
487 const auto remoteId = resolveLocalId(ENTITY_TYPE_MAIL, entityId, synchronizationTransaction); 506 const auto flags = KPIM::Maildir::readEntryFlags(filePath.split('/').last());
488 const auto flags = KPIM::Maildir::readEntryFlags(remoteId.split('/').last());
489 if (expectedValue.toBool() && (flags & KPIM::Maildir::Seen)) { 507 if (expectedValue.toBool() && (flags & KPIM::Maildir::Seen)) {
490 return KAsync::error<void>(1, "Expected unread but couldn't find it."); 508 return KAsync::error<void>(1, "Expected unread but couldn't find it.");
491 } 509 }
@@ -495,10 +513,8 @@ KAsync::Job<void> MaildirResource::inspect(int inspectionType, const QByteArray
495 return KAsync::null<void>(); 513 return KAsync::null<void>();
496 } 514 }
497 if (property == "subject") { 515 if (property == "subject") {
498 const auto remoteId = resolveLocalId(ENTITY_TYPE_MAIL, entityId, synchronizationTransaction);
499
500 KMime::Message *msg = new KMime::Message; 516 KMime::Message *msg = new KMime::Message;
501 msg->setHead(KMime::CRLFtoLF(KPIM::Maildir::readEntryHeadersFromFile(remoteId))); 517 msg->setHead(KMime::CRLFtoLF(KPIM::Maildir::readEntryHeadersFromFile(filePath)));
502 msg->parse(); 518 msg->parse();
503 519
504 if (msg->subject(true)->asUnicodeString() != expectedValue.toString()) { 520 if (msg->subject(true)->asUnicodeString() != expectedValue.toString()) {
@@ -508,9 +524,32 @@ KAsync::Job<void> MaildirResource::inspect(int inspectionType, const QByteArray
508 } 524 }
509 } 525 }
510 if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) { 526 if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) {
511 const auto remoteId = resolveLocalId(ENTITY_TYPE_MAIL, entityId, synchronizationTransaction); 527 if (QFileInfo(filePath).exists() != expectedValue.toBool()) {
512 if (QFileInfo(remoteId).exists() != expectedValue.toBool()) { 528 return KAsync::error<void>(1, "Wrong file existence: " + filePath);
513 return KAsync::error<void>(1, "Wrong file existence: " + remoteId); 529 }
530 }
531 }
532 if (domainType == ENTITY_TYPE_FOLDER) {
533 const auto remoteId = resolveLocalId(ENTITY_TYPE_FOLDER, entityId, synchronizationTransaction);
534
535 if (inspectionType == Sink::ResourceControl::Inspection::CacheIntegrityInspectionType) {
536 if (!QDir(remoteId).exists()) {
537 return KAsync::error<void>(1, "The directory is not existing: " + remoteId);
538 }
539
540 int expectedCount = 0;
541 Index index("mail.index.folder", transaction);
542 index.lookup(entityId, [&](const QByteArray &sinkId) {
543 expectedCount++;
544 },
545 [&](const Index::Error &error) {
546 Warning() << "Error in index: " << error.message << property;
547 });
548
549 QDir dir(remoteId + "/cur");
550 const QFileInfoList list = dir.entryInfoList(QDir::Files);
551 if (list.size() != expectedCount) {
552 return KAsync::error<void>(1, QString("Wrong number of files; found %1 instead of %2.").arg(list.size()).arg(expectedCount));
514 } 553 }
515 } 554 }
516 } 555 }
diff --git a/tests/mailtest.cpp b/tests/mailtest.cpp
index 3ca8eaa..496b7ef 100644
--- a/tests/mailtest.cpp
+++ b/tests/mailtest.cpp
@@ -42,6 +42,7 @@ void MailTest::initTestCase()
42 VERIFYEXEC(Store::create(resource)); 42 VERIFYEXEC(Store::create(resource));
43 43
44 mResourceInstanceIdentifier = resource.identifier(); 44 mResourceInstanceIdentifier = resource.identifier();
45 mCapabilities = resource.getProperty("capabilities").value<QByteArrayList>();
45} 46}
46 47
47void MailTest::cleanup() 48void MailTest::cleanup()
@@ -131,13 +132,8 @@ void MailTest::testCreateModifyDeleteFolder()
131 132
132void MailTest::testCreateModifyDeleteMail() 133void MailTest::testCreateModifyDeleteMail()
133{ 134{
134
135 const auto subject = QString::fromLatin1("Foobar"); 135 const auto subject = QString::fromLatin1("Foobar");
136 136
137 Query query;
138 query.resources << mResourceInstanceIdentifier;
139 query.request<Mail::Folder>().request<Mail::Subject>();
140
141 auto folder = Folder::create(mResourceInstanceIdentifier); 137 auto folder = Folder::create(mResourceInstanceIdentifier);
142 folder.setName("folder"); 138 folder.setName("folder");
143 VERIFYEXEC(Store::create(folder)); 139 VERIFYEXEC(Store::create(folder));
@@ -151,7 +147,7 @@ void MailTest::testCreateModifyDeleteMail()
151 mail.setFolder(folder); 147 mail.setFolder(folder);
152 148
153 VERIFYEXEC(Store::create(mail)); 149 VERIFYEXEC(Store::create(mail));
154 VERIFYEXEC(ResourceControl::flushMessageQueue(query.resources)); 150 VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier));
155 { 151 {
156 auto job = Store::fetchAll<Mail>(Query::RequestedProperties(QByteArrayList() << Mail::Folder::name << Mail::Subject::name << Mail::MimeMessage::name)) 152 auto job = Store::fetchAll<Mail>(Query::RequestedProperties(QByteArrayList() << Mail::Folder::name << Mail::Subject::name << Mail::MimeMessage::name))
157 .then<void, QList<Mail::Ptr>>([=](const QList<Mail::Ptr> &mails) { 153 .then<void, QList<Mail::Ptr>>([=](const QList<Mail::Ptr> &mails) {
@@ -160,14 +156,13 @@ void MailTest::testCreateModifyDeleteMail()
160 QCOMPARE(mail.getSubject(), subject); 156 QCOMPARE(mail.getSubject(), subject);
161 QCOMPARE(mail.getFolder(), folder.identifier()); 157 QCOMPARE(mail.getFolder(), folder.identifier());
162 QVERIFY(QFile(mail.getMimeMessagePath()).exists()); 158 QVERIFY(QFile(mail.getMimeMessagePath()).exists());
163
164 // return Store::remove(*mail)
165 // .then(ResourceControl::flushReplayQueue(query.resources)) // The change needs to be replayed already
166 // .then(ResourceControl::inspect<Mail>(ResourceControl::Inspection::ExistenceInspection(*mail, false)));
167 }); 159 });
168 VERIFYEXEC(job); 160 VERIFYEXEC(job);
169 } 161 }
170 162
163 VERIFYEXEC(ResourceControl::inspect<ApplicationDomain::Mail>(ResourceControl::Inspection::ExistenceInspection(mail, true)));
164 VERIFYEXEC(ResourceControl::inspect<ApplicationDomain::Folder>(ResourceControl::Inspection::CacheIntegrityInspection(folder)));
165
171 const auto subject2 = QString::fromLatin1("Foobar2"); 166 const auto subject2 = QString::fromLatin1("Foobar2");
172 auto message2 = KMime::Message::Ptr::create(); 167 auto message2 = KMime::Message::Ptr::create();
173 message2->subject(true)->fromUnicodeString(subject2, "utf8"); 168 message2->subject(true)->fromUnicodeString(subject2, "utf8");
@@ -175,7 +170,7 @@ void MailTest::testCreateModifyDeleteMail()
175 mail.setMimeMessage(message2->encodedContent()); 170 mail.setMimeMessage(message2->encodedContent());
176 171
177 VERIFYEXEC(Store::modify(mail)); 172 VERIFYEXEC(Store::modify(mail));
178 VERIFYEXEC(ResourceControl::flushMessageQueue(query.resources)); 173 VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier));
179 { 174 {
180 auto job = Store::fetchAll<Mail>(Query::RequestedProperties(QByteArrayList() << Mail::Folder::name << Mail::Subject::name)) 175 auto job = Store::fetchAll<Mail>(Query::RequestedProperties(QByteArrayList() << Mail::Folder::name << Mail::Subject::name))
181 .then<void, QList<Mail::Ptr>>([=](const QList<Mail::Ptr> &mails) { 176 .then<void, QList<Mail::Ptr>>([=](const QList<Mail::Ptr> &mails) {
@@ -188,9 +183,11 @@ void MailTest::testCreateModifyDeleteMail()
188 }); 183 });
189 VERIFYEXEC(job); 184 VERIFYEXEC(job);
190 } 185 }
186 VERIFYEXEC(ResourceControl::inspect<ApplicationDomain::Mail>(ResourceControl::Inspection::ExistenceInspection(mail, true)));
187 VERIFYEXEC(ResourceControl::inspect<ApplicationDomain::Folder>(ResourceControl::Inspection::CacheIntegrityInspection(folder)));
191 188
192 VERIFYEXEC(Store::remove(mail)); 189 VERIFYEXEC(Store::remove(mail));
193 VERIFYEXEC(ResourceControl::flushMessageQueue(query.resources)); 190 VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier));
194 { 191 {
195 auto job = Store::fetchAll<Mail>(Query::RequestedProperties(QByteArrayList() << Mail::Folder::name << Mail::Subject::name)) 192 auto job = Store::fetchAll<Mail>(Query::RequestedProperties(QByteArrayList() << Mail::Folder::name << Mail::Subject::name))
196 .then<void, QList<Mail::Ptr>>([=](const QList<Mail::Ptr> &mails) { 193 .then<void, QList<Mail::Ptr>>([=](const QList<Mail::Ptr> &mails) {
@@ -198,6 +195,95 @@ void MailTest::testCreateModifyDeleteMail()
198 }); 195 });
199 VERIFYEXEC(job); 196 VERIFYEXEC(job);
200 } 197 }
198 VERIFYEXEC(ResourceControl::inspect<ApplicationDomain::Mail>(ResourceControl::Inspection::ExistenceInspection(mail, false)));
199 VERIFYEXEC(ResourceControl::inspect<ApplicationDomain::Folder>(ResourceControl::Inspection::CacheIntegrityInspection(folder)));
200}
201
202void MailTest::testMarkMailAsRead()
203{
204 auto folder = Folder::create(mResourceInstanceIdentifier);
205 folder.setName("folder");
206 VERIFYEXEC(Store::create(folder));
207
208 auto message = KMime::Message::Ptr::create();
209 message->subject(true)->fromUnicodeString("subject", "utf8");
210 message->assemble();
211
212 auto mail = Mail::create(mResourceInstanceIdentifier);
213 mail.setMimeMessage(message->encodedContent());
214 mail.setFolder(folder);
215 mail.setUnread(false);
216 VERIFYEXEC(Store::create(mail));
217 VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier));
218
219 auto job = Store::fetchAll<Mail>(Query::ResourceFilter(mResourceInstanceIdentifier) +
220 Query::RequestedProperties(QByteArrayList() << Mail::Folder::name
221 << Mail::Subject::name))
222 .then<void, KAsync::Job<void>, QList<Mail::Ptr>>([this](const QList<Mail::Ptr> &mails) {
223 ASYNCCOMPARE(mails.size(), 1);
224 auto mail = mails.first();
225 mail->setProperty("unread", true);
226 return Store::modify(*mail)
227 .then<void>(ResourceControl::flushReplayQueue(QByteArrayList() << mResourceInstanceIdentifier)) // The change needs to be replayed already
228 .then(ResourceControl::inspect<Mail>(ResourceControl::Inspection::PropertyInspection(*mail, Mail::Unread::name, true)))
229 .then(ResourceControl::inspect<Mail>(ResourceControl::Inspection::PropertyInspection(*mail, Mail::Subject::name, mail->getSubject())));
230 });
231 VERIFYEXEC(job);
232
233 // Verify that we can still query for all relevant information
234 auto job2 = Store::fetchAll<Mail>(
235 Query::ResourceFilter(mResourceInstanceIdentifier) + Query::RequestedProperties(QByteArrayList() << Mail::Folder::name
236 << Mail::Subject::name
237 << Mail::MimeMessage::name
238 << Mail::Unread::name))
239 .then<void, KAsync::Job<void>, QList<Mail::Ptr>>([](const QList<Mail::Ptr> &mails) {
240 ASYNCCOMPARE(mails.size(), 1);
241 auto mail = mails.first();
242 ASYNCVERIFY(!mail->getSubject().isEmpty());
243 ASYNCCOMPARE(mail->getUnread(), true);
244 ASYNCVERIFY(QFileInfo(mail->getMimeMessagePath()).exists());
245 return KAsync::null<void>();
246 });
247 VERIFYEXEC(job2);
248}
249
250void MailTest::testCreateDraft()
251{
252 if (!mCapabilities.contains("drafts")) {
253 QSKIP("Resource doesn't have the drafts capability");
254 }
255
256 auto message = KMime::Message::Ptr::create();
257 message->subject(true)->fromUnicodeString(QString::fromLatin1("Foobar"), "utf8");
258 message->assemble();
259
260 auto mail = ApplicationDomain::Mail::create(mResourceInstanceIdentifier);
261 mail.setMimeMessage(message->encodedContent());
262 mail.setDraft(true);
263
264 VERIFYEXEC(Store::create(mail));
265 VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier));
266
267 QByteArray folderIdentifier;
268 auto job = Store::fetchOne<ApplicationDomain::Mail>(Query::IdentityFilter(mail.identifier()) + Query::RequestedProperties(QByteArrayList() << Mail::MimeMessage::name << Mail::Folder::name))
269 .then<void, ApplicationDomain::Mail>([&](const ApplicationDomain::Mail &mail) {
270 folderIdentifier = mail.getProperty("folder").toByteArray();
271 QVERIFY(!folderIdentifier.isEmpty());
272 });
273 VERIFYEXEC(job);
274
275 //Ensure we can also query by folder
276 auto job2 = Store::fetchAll<ApplicationDomain::Mail>(Query::PropertyFilter("folder", folderIdentifier))
277 .then<void, QList<ApplicationDomain::Mail::Ptr> >([&](const QList<ApplicationDomain::Mail::Ptr> &mails) {
278 bool found = false;
279 for (const auto m : mails) {
280 if (m->identifier() == mail.identifier()) {
281 found = true;
282 }
283 }
284 QVERIFY(found);
285 });
286 VERIFYEXEC(job2);
201} 287}
202 288
203#include "mailtest.moc" 289#include "mailtest.moc"
diff --git a/tests/mailtest.h b/tests/mailtest.h
index 0729a91..43d4f75 100644
--- a/tests/mailtest.h
+++ b/tests/mailtest.h
@@ -51,6 +51,7 @@ class MailTest : public QObject
51 51
52protected: 52protected:
53 QByteArray mResourceInstanceIdentifier; 53 QByteArray mResourceInstanceIdentifier;
54 QByteArrayList mCapabilities;
54 55
55 virtual void resetTestEnvironment() = 0; 56 virtual void resetTestEnvironment() = 0;
56 virtual Sink::ApplicationDomain::SinkResource createResource() = 0; 57 virtual Sink::ApplicationDomain::SinkResource createResource() = 0;
@@ -63,6 +64,8 @@ private slots:
63 64
64 void testCreateModifyDeleteFolder(); 65 void testCreateModifyDeleteFolder();
65 void testCreateModifyDeleteMail(); 66 void testCreateModifyDeleteMail();
67 void testMarkMailAsRead();
68 void testCreateDraft();
66}; 69};
67 70
68} 71}