/* * Copyright (C) 2016 Christian Mollekopf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "mailthreadtest.h" #include #include #include #include #include "store.h" #include "resourcecontrol.h" #include "log.h" #include "test.h" #include "standardqueries.h" using namespace Sink; using namespace Sink::ApplicationDomain; //TODO extract resource test // void MailThreadTest::initTestCase() { Test::initTest(); QVERIFY(isBackendAvailable()); resetTestEnvironment(); auto resource = createResource(); QVERIFY(!resource.identifier().isEmpty()); VERIFYEXEC(Store::create(resource)); mResourceInstanceIdentifier = resource.identifier(); mCapabilities = resource.getProperty("capabilities").value(); } void MailThreadTest::cleanup() { VERIFYEXEC(ResourceControl::shutdown(mResourceInstanceIdentifier)); removeResourceFromDisk(mResourceInstanceIdentifier); } void MailThreadTest::init() { VERIFYEXEC(ResourceControl::start(mResourceInstanceIdentifier)); } void MailThreadTest::testListThreadLeader() { Sink::Query query; query.resourceFilter(mResourceInstanceIdentifier); query.request().request().request().request(); query.sort(); query.reduce(Query::Reduce::Selector::max()).count("count").collect("senders"); // Ensure all local data is processed VERIFYEXEC(Store::synchronize(query)); VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier)); auto mails = Store::read(query); QCOMPARE(mails.size(), 1); QVERIFY(mails.first().getSubject().startsWith(QString("ThreadLeader"))); auto threadSize = mails.first().getProperty("count").toInt(); QCOMPARE(threadSize, 2); QCOMPARE(mails.first().aggregatedIds().size(), 2); } /* * Thread: * 1. * 2. * 3. * * 3. first, should result in a new thread. * 1. second, should be merged by subject * 2. last, should complete the thread. */ void MailThreadTest::testIndexInMixedOrder() { auto folder = Folder::create(mResourceInstanceIdentifier); folder.setName("folder"); VERIFYEXEC(Store::create(folder)); auto message1 = KMime::Message::Ptr::create(); message1->subject(true)->fromUnicodeString("1", "utf8"); message1->messageID(true)->generate("foobar.com"); message1->date(true)->setDateTime(QDateTime::currentDateTimeUtc()); message1->assemble(); auto message2 = KMime::Message::Ptr::create(); message2->subject(true)->fromUnicodeString("Re: 1", "utf8"); message2->messageID(true)->generate("foobar.com"); message2->inReplyTo(true)->appendIdentifier(message1->messageID(true)->identifier()); message2->date(true)->setDateTime(QDateTime::currentDateTimeUtc().addSecs(1)); message2->assemble(); auto message3 = KMime::Message::Ptr::create(); message3->subject(true)->fromUnicodeString("Re: Re: 1", "utf8"); message3->messageID(true)->generate("foobar.com"); message3->inReplyTo(true)->appendIdentifier(message2->messageID(true)->identifier()); message3->date(true)->setDateTime(QDateTime::currentDateTimeUtc().addSecs(2)); message3->assemble(); { auto mail = Mail::create(mResourceInstanceIdentifier); mail.setMimeMessage(message3->encodedContent(true)); mail.setFolder(folder); VERIFYEXEC(Store::create(mail)); } VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier)); auto query = Sink::StandardQueries::threadLeaders(folder); query.resourceFilter(mResourceInstanceIdentifier); query.request().request().request().request(); Mail threadLeader; //Ensure we find the thread leader { auto mails = Store::read(query); QCOMPARE(mails.size(), 1); auto mail = mails.first(); threadLeader = mail; QCOMPARE(mail.getSubject(), QString::fromLatin1("Re: Re: 1")); } { auto mail = Mail::create(mResourceInstanceIdentifier); mail.setMimeMessage(message2->encodedContent(true)); mail.setFolder(folder); VERIFYEXEC(Store::create(mail)); } VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier)); //Ensure we find the thread leader still { auto mails = Store::read(query); QCOMPARE(mails.size(), 1); auto mail = mails.first(); QCOMPARE(mail.getSubject(), QString::fromLatin1("Re: Re: 1")); } { auto mail = Mail::create(mResourceInstanceIdentifier); mail.setMimeMessage(message1->encodedContent(true)); mail.setFolder(folder); VERIFYEXEC(Store::create(mail)); } VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier)); //Ensure the thread is complete { auto query = Sink::StandardQueries::completeThread(threadLeader); query.request().request().request().request(); auto mails = Store::read(query); QCOMPARE(mails.size(), 3); auto mail = mails.first(); QCOMPARE(mail.getSubject(), QString::fromLatin1("Re: Re: 1")); } /* VERIFYEXEC(Store::remove(mail)); */ /* VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier)); */ /* { */ /* auto job = Store::fetchAll(Query::RequestedProperties(QByteArrayList() << Mail::Folder::name << Mail::Subject::name)) */ /* .then([=](const QList &mails) { */ /* QCOMPARE(mails.size(), 0); */ /* }); */ /* VERIFYEXEC(job); */ /* } */ /* VERIFYEXEC(ResourceControl::flushReplayQueue(QByteArrayList() << mResourceInstanceIdentifier)); */ } static QByteArray readMailFromFile(const QString &mailFile) { QFile file(QLatin1String(THREADTESTDATAPATH) + QLatin1Char('/') + mailFile); file.open(QIODevice::ReadOnly); Q_ASSERT(file.isOpen()); return file.readAll(); } static KMime::Message::Ptr readMail(const QString &mailFile) { auto msg = KMime::Message::Ptr::create(); msg->setContent(readMailFromFile(mailFile)); msg->parse(); return msg; } void MailThreadTest::testRealWorldThread() { auto folder = Folder::create(mResourceInstanceIdentifier); folder.setName("folder"); VERIFYEXEC(Store::create(folder)); auto createMail = [this, folder] (KMime::Message::Ptr msg) { auto mail = Mail::create(mResourceInstanceIdentifier); mail.setMimeMessage(msg->encodedContent(true)); mail.setFolder(folder); VERIFYEXEC(Store::create(mail)); }; createMail(readMail("thread1")); VERIFYEXEC(ResourceControl::flushMessageQueue(QByteArrayList() << mResourceInstanceIdentifier)); auto query = Sink::StandardQueries::threadLeaders(folder); query.resourceFilter(mResourceInstanceIdentifier); query.request().request().request().request(); //Ensure we find the thread leader Mail threadLeader = [&] { auto mails = Store::read(query); Q_ASSERT(mails.size() == 1); return mails.first(); }(); createMail(readMail("thread2")); createMail(readMail("thread3")); createMail(readMail("thread4")); createMail(readMail("thread5")); createMail(readMail("thread6")); createMail(readMail("thread7")); createMail(readMail("thread8")); //This mail is breaking the thread VERIFYEXEC(ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); //Ensure the thread is complete { auto query = Sink::StandardQueries::completeThread(threadLeader); query.request().request().request().request(); auto mails = Store::read(query); QCOMPARE(mails.size(), 8); } }