From 2061ba0cf16b6a0a3313f861f79b90cf2905efce Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Tue, 31 May 2016 15:11:54 +0200 Subject: The maildir resource passes the maildirmailsync test --- common/domain/applicationdomaintype.cpp | 2 +- examples/maildirresource/CMakeLists.txt | 2 + examples/maildirresource/maildirresource.cpp | 8 +- examples/maildirresource/tests/CMakeLists.txt | 2 + .../cur/1365777830.R28.localhost.localdomain:2,S | 72 +++++++++++ .../maildirresource/tests/maildirmailsynctest.cpp | 132 +++++++++++++++++++ tests/mailsynctest.cpp | 141 +++++++++++++++++---- tests/mailsynctest.h | 20 ++- 8 files changed, 343 insertions(+), 36 deletions(-) create mode 100644 examples/maildirresource/tests/data/maildir1/test/cur/1365777830.R28.localhost.localdomain:2,S create mode 100644 examples/maildirresource/tests/maildirmailsynctest.cpp diff --git a/common/domain/applicationdomaintype.cpp b/common/domain/applicationdomaintype.cpp index 7d8ab48..1e111ec 100644 --- a/common/domain/applicationdomaintype.cpp +++ b/common/domain/applicationdomaintype.cpp @@ -267,7 +267,7 @@ namespace ImapResource { auto &&resource = ApplicationDomainType::createEntity(); resource.setProperty("type", "org.kde.imap"); resource.setProperty("account", account); - resource.setProperty("capabilities", QVariant::fromValue(QByteArrayList() << "storage")); + resource.setProperty("capabilities", QVariant::fromValue(QByteArrayList() << "storage" << "folder.hierarchy")); return resource; } } diff --git a/examples/maildirresource/CMakeLists.txt b/examples/maildirresource/CMakeLists.txt index 3a1430c..e4d113c 100644 --- a/examples/maildirresource/CMakeLists.txt +++ b/examples/maildirresource/CMakeLists.txt @@ -11,5 +11,7 @@ target_link_libraries(${PROJECT_NAME} sink maildir KF5::Mime) install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${SINK_RESOURCE_PLUGINS_PATH}) +add_definitions(-DTESTDATAPATH="${CMAKE_CURRENT_SOURCE_DIR}/tests/data") + add_subdirectory(libmaildir) add_subdirectory(tests) diff --git a/examples/maildirresource/maildirresource.cpp b/examples/maildirresource/maildirresource.cpp index ca20fa3..268f506 100644 --- a/examples/maildirresource/maildirresource.cpp +++ b/examples/maildirresource/maildirresource.cpp @@ -373,7 +373,11 @@ public: KAsync::Job synchronizeWithSource() Q_DECL_OVERRIDE { Log() << " Synchronizing"; - return KAsync::start([this]() { + return KAsync::start >([this]() { + KPIM::Maildir maildir(mMaildirPath, true); + if (!maildir.isValid(false)) { + return KAsync::error(1, "Maildir path doesn't point to a valid maildir: " + mMaildirPath); + } synchronizeFolders(); //The next sync needs the folders available commit(); @@ -385,6 +389,7 @@ public: commitSync(); } Log() << "Done Synchronizing"; + return KAsync::null(); }); } @@ -410,7 +415,6 @@ public: }); } else if (operation == Sink::Operation_Removal) { Trace() << "Removing a mail: " << oldRemoteId; - // QFile::remove(oldRemoteId); return KAsync::null(); } else if (operation == Sink::Operation_Modification) { Trace() << "Modifying a mail: " << oldRemoteId; diff --git a/examples/maildirresource/tests/CMakeLists.txt b/examples/maildirresource/tests/CMakeLists.txt index ffe9286..d6f0fe7 100644 --- a/examples/maildirresource/tests/CMakeLists.txt +++ b/examples/maildirresource/tests/CMakeLists.txt @@ -7,5 +7,7 @@ include(SinkTest) auto_tests ( maildirmailtest + maildirmailsynctest ) target_link_libraries(maildirmailtest sink_resource_maildir) +target_link_libraries(maildirmailsynctest sink_resource_maildir) diff --git a/examples/maildirresource/tests/data/maildir1/test/cur/1365777830.R28.localhost.localdomain:2,S b/examples/maildirresource/tests/data/maildir1/test/cur/1365777830.R28.localhost.localdomain:2,S new file mode 100644 index 0000000..91231b5 --- /dev/null +++ b/examples/maildirresource/tests/data/maildir1/test/cur/1365777830.R28.localhost.localdomain:2,S @@ -0,0 +1,72 @@ +Return-Path: +Received: from compute4.internal (compute4.nyi.mail.srv.osa [10.202.2.44]) + by slots3a1p1 (Cyrus git2.5+0-git-fastmail-8998) with LMTPA; + Mon, 11 Mar 2013 14:28:42 -0400 +X-Sieve: CMU Sieve 2.4 +X-Spam-score: 0.0 +X-Spam-hits: BAYES_00 -1.9, RCVD_IN_DNSWL_MED -2.3, RP_MATCHES_RCVD -0.704, + LANGUAGES unknown, BAYES_USED global, SA_VERSION 3.3.1 +X-Spam-source: IP='46.4.96.248', Host='postbox.kde.org', Country='unk', FromHeader='org', + MailFrom='org' +X-Spam-charsets: plain='us-ascii' +X-Resolved-to: chrigi_1@fastmail.fm +X-Delivered-to: chrigi_1@fastmail.fm +X-Mail-from: nepomuk-bounces@kde.org +Received: from mx4.nyi.mail.srv.osa ([10.202.2.203]) + by compute4.internal (LMTPProxy); Mon, 11 Mar 2013 14:28:42 -0400 +Received: from postbox.kde.org (postbox.kde.org [46.4.96.248]) + by mx4.messagingengine.com (Postfix) with ESMTP id 1C9D2440F88 + for ; Mon, 11 Mar 2013 14:28:42 -0400 (EDT) +Received: from postbox.kde.org (localhost [IPv6:::1]) + by postbox.kde.org (Postfix) with ESMTP id 00FFEB3732B; + Mon, 11 Mar 2013 18:28:40 +0000 (UTC) +DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=kde.org; s=default; + t=1363026520; bh=cOdvyBAJJ8ho64q0H7rxkl+cB2y6TiyVOX0fO3yZ64U=; + h=Date:From:To:Message-ID:In-Reply-To:References:MIME-Version: + Subject:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help: + List-Subscribe:Content-Type:Content-Transfer-Encoding:Sender; b=dv + dJAFu+6JCuNun5WIuP4ysfKpLh0DeuhEEfy2cQavUGMICJ27k7tI73x6gN37V5Q/evJ + NDFna3/IhNBsAQeLiXs28HKxzcVhbnq5jdFR6fbyo6k1fOKt5vTT1GTDZ+3zIGPD1CU + ioDBGxPb/Ds6gee90tjadOj6o+Oc+2ZSq94= +X-Original-To: nepomuk@kde.org +X-Remote-Delivered-To: nepomuk@localhost.kde.org +Received: from build.kde.org (build.kde.org [IPv6:2a01:4f8:160:9363::5]) + by postbox.kde.org (Postfix) with ESMTP id 4491CB3732B + for ; Mon, 11 Mar 2013 18:28:27 +0000 (UTC) +Received: from localhost ([127.0.0.1]) by build.kde.org with esmtp (Exim 4.72) + (envelope-from ) id 1UF7SV-0000gs-11 + for nepomuk@kde.org; Mon, 11 Mar 2013 18:28:27 +0000 +Date: Mon, 11 Mar 2013 18:28:27 +0000 (UTC) +From: KDE CI System +To: nepomuk@kde.org +Message-ID: <1977027405.27.1363026507008.JavaMail.jenkins@build> +In-Reply-To: <880663748.26.1363026023717.JavaMail.jenkins@build> +References: <880663748.26.1363026023717.JavaMail.jenkins@build> +MIME-Version: 1.0 +X-Jenkins-Job: nepomuk-core_stable +X-Jenkins-Result: UNSTABLE +X-Scanned-By: MIMEDefang 2.71 on 46.4.96.248 +Subject: [Nepomuk] Jenkins build is still unstable: nepomuk-core_stable #158 +X-BeenThere: nepomuk@kde.org +X-Mailman-Version: 2.1.14 +Precedence: list +List-Id: The Semantic KDE +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +Errors-To: nepomuk-bounces@kde.org +Sender: nepomuk-bounces@kde.org +X-Truedomain: NotChecked + +See + +_______________________________________________ +Nepomuk mailing list +Nepomuk@kde.org +https://mail.kde.org/mailman/listinfo/nepomuk diff --git a/examples/maildirresource/tests/maildirmailsynctest.cpp b/examples/maildirresource/tests/maildirmailsynctest.cpp new file mode 100644 index 0000000..444fb42 --- /dev/null +++ b/examples/maildirresource/tests/maildirmailsynctest.cpp @@ -0,0 +1,132 @@ +/* + * 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 + +#include +#include "../maildirresource.h" +#include "../libmaildir/maildir.h" + +#include "common/test.h" +#include "common/domain/applicationdomaintype.h" + +using namespace Sink; +using namespace Sink::ApplicationDomain; + +static bool copyRecursively(const QString &srcFilePath, const QString &tgtFilePath) +{ + QFileInfo srcFileInfo(srcFilePath); + if (srcFileInfo.isDir()) { + QDir targetDir(tgtFilePath); + targetDir.cdUp(); + if (!targetDir.mkdir(QFileInfo(srcFilePath).fileName())) { + qWarning() << "Failed to create directory " << tgtFilePath; + return false; + } + QDir sourceDir(srcFilePath); + QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System); + foreach (const QString &fileName, fileNames) { + const QString newSrcFilePath = srcFilePath + QLatin1Char('/') + fileName; + const QString newTgtFilePath = tgtFilePath + QLatin1Char('/') + fileName; + if (!copyRecursively(newSrcFilePath, newTgtFilePath)) + return false; + } + } else { + if (!QFile::copy(srcFilePath, tgtFilePath)) { + qWarning() << "Failed to copy file " << tgtFilePath; + return false; + } + } + return true; +} + +/** + * Test of complete system using the maildir resource. + * + * This test requires the maildir resource installed. + */ +class MaildirMailSyncTest : public Sink::MailSyncTest +{ + Q_OBJECT + + QTemporaryDir tempDir; + QString targetPath; + +protected: + void resetTestEnvironment() Q_DECL_OVERRIDE + { + targetPath = tempDir.path() + "/maildir1/"; + QDir dir(targetPath); + dir.removeRecursively(); + copyRecursively(TESTDATAPATH "/maildir1", targetPath); + } + + Sink::ApplicationDomain::SinkResource createResource() Q_DECL_OVERRIDE + { + auto resource = ApplicationDomain::MaildirResource::create("account1"); + resource.setProperty("path", targetPath); + return resource; + } + + Sink::ApplicationDomain::SinkResource createFaultyResource() Q_DECL_OVERRIDE + { + auto resource = ApplicationDomain::MaildirResource::create("account1"); + resource.setProperty("path", ""); + return resource; + } + + void removeResourceFromDisk(const QByteArray &identifier) Q_DECL_OVERRIDE + { + ::MaildirResource::removeFromDisk(identifier); + } + + void createFolder(const QStringList &folderPath) Q_DECL_OVERRIDE + { + auto rootPath = tempDir.path() + "/maildir1/"; + KPIM::Maildir maildir(rootPath + folderPath.join('/'), false); + maildir.create(); + } + + void removeFolder(const QStringList &folderPath) Q_DECL_OVERRIDE + { + auto rootPath = tempDir.path() + "/maildir1/"; + KPIM::Maildir maildir(rootPath + folderPath.join('/'), false); + maildir.remove(); + QDir dir(rootPath + folderPath.join('/')); + dir.removeRecursively(); + // QVERIFY(maildir.removeSubFolder(name)); + } + + QByteArray createMessage(const QStringList &folderPath, const QByteArray &message) Q_DECL_OVERRIDE + { + auto rootPath = tempDir.path() + "/maildir1/"; + KPIM::Maildir maildir(rootPath + folderPath.join('/')); + return maildir.addEntry(message).toUtf8(); + } + + void removeMessage(const QStringList &folderPath, const QByteArray &messageIdentifier) Q_DECL_OVERRIDE + { + auto rootPath = tempDir.path() + "/maildir1/"; + KPIM::Maildir maildir(rootPath + folderPath.join('/')); + maildir.removeEntry(messageIdentifier); + } +}; + +QTEST_MAIN(MaildirMailSyncTest) + +#include "maildirmailsynctest.moc" diff --git a/tests/mailsynctest.cpp b/tests/mailsynctest.cpp index b86fbae..2fc8568 100644 --- a/tests/mailsynctest.cpp +++ b/tests/mailsynctest.cpp @@ -47,6 +47,7 @@ void MailSyncTest::initTestCase() void MailSyncTest::cleanup() { + //TODO the shutdown job fails if the resource is already shut down // VERIFYEXEC(ResourceControl::shutdown(mResourceInstanceIdentifier)); ResourceControl::shutdown(mResourceInstanceIdentifier).exec().waitForFinished(); removeResourceFromDisk(mResourceInstanceIdentifier); @@ -62,6 +63,21 @@ void MailSyncTest::init() void MailSyncTest::testListFolders() { + int baseCount = 0; + //First figure out how many folders we have by default + { + auto job = Store::fetchAll(Query()) + .then>([&](const QList &folders) { + QStringList names; + for (const auto &folder : folders) { + names << folder->getName(); + } + Trace() << "base folder: " << names; + baseCount = folders.size(); + }); + VERIFYEXEC(job); + } + Sink::Query query; query.resources << mResourceInstanceIdentifier; query.request(); @@ -70,20 +86,78 @@ void MailSyncTest::testListFolders() VERIFYEXEC(Store::synchronize(query)); ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); - auto job = Store::fetchAll(query).then>([](const QList &folders) { - QCOMPARE(folders.size(), 2); + auto job = Store::fetchAll(query).then>([=](const QList &folders) { QStringList names; for (const auto &folder : folders) { names << folder->getName(); } + //Workaround for maildir + if (names.contains("maildir1")) { + names.removeAll("maildir1"); + } + if (mCapabilities.contains("drafts")) { + QVERIFY(names.contains("drafts")); + names.removeAll("drafts"); + } + QCOMPARE(names.size(), 2); QVERIFY(names.contains("INBOX")); QVERIFY(names.contains("test")); }); VERIFYEXEC(job); } +void MailSyncTest::testListNewFolder() +{ + Sink::Query query; + query.resources << mResourceInstanceIdentifier; + query.request(); + + createFolder(QStringList() << "test2"); + + // Ensure all local data is processed + VERIFYEXEC(Store::synchronize(query)); + ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); + + auto job = Store::fetchAll(query).then>([](const QList &folders) { + QStringList names; + for (const auto &folder : folders) { + names << folder->getName(); + } + QVERIFY(names.contains("test2")); + }); + VERIFYEXEC(job); +} + +void MailSyncTest::testListRemovedFolder() +{ + Sink::Query query; + query.resources << mResourceInstanceIdentifier; + query.request(); + + VERIFYEXEC(Store::synchronize(query)); + ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); + + removeFolder(QStringList() << "test2"); + + // Ensure all local data is processed + VERIFYEXEC(Store::synchronize(query)); + ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); + + auto job = Store::fetchAll(query).then>([](const QList &folders) { + QStringList names; + for (const auto &folder : folders) { + names << folder->getName(); + } + QVERIFY(!names.contains("test2")); + }); + VERIFYEXEC(job); +} + void MailSyncTest::testListFolderHierarchy() { + if (!mCapabilities.contains("folder.hierarchy")) { + QSKIP("Missing capability folder.hierarchy"); + } Sink::Query query; query.resources << mResourceInstanceIdentifier; query.request().request(); @@ -94,19 +168,35 @@ void MailSyncTest::testListFolderHierarchy() VERIFYEXEC(Store::synchronize(query)); ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); - auto job = Store::fetchAll(query).then>([](const QList &folders) { - QCOMPARE(folders.size(), 3); + auto job = Store::fetchAll(query).then>([=](const QList &folders) { QHash map; for (const auto &folder : folders) { map.insert(folder->getName(), folder); } + QStringList names; + for (const auto &folder : folders) { + names << folder->getName(); + } + + //Workaround for maildir + if (names.contains("maildir1")) { + names.removeAll("maildir1"); + } + if (mCapabilities.contains("drafts")) { + QVERIFY(names.contains("drafts")); + names.removeAll("drafts"); + } + QCOMPARE(names.size(), 3); QCOMPARE(map.value("sub")->getParent(), map.value("test")->identifier()); }); VERIFYEXEC(job); } -void MailSyncTest::testListNewFolders() +void MailSyncTest::testListNewSubFolder() { + if (!mCapabilities.contains("folder.hierarchy")) { + QSKIP("Missing capability folder.hierarchy"); + } Sink::Query query; query.resources << mResourceInstanceIdentifier; query.request(); @@ -127,8 +217,11 @@ void MailSyncTest::testListNewFolders() VERIFYEXEC(job); } -void MailSyncTest::testListRemovedFolders() +void MailSyncTest::testListRemovedSubFolder() { + if (!mCapabilities.contains("folder.hierarchy")) { + QSKIP("Missing capability folder.hierarchy"); + } Sink::Query query; query.resources << mResourceInstanceIdentifier; query.request(); @@ -176,7 +269,7 @@ void MailSyncTest::testListMails() VERIFYEXEC(job); } -void MailSyncTest::testFetchNewMessages() +void MailSyncTest::testFetchNewRemovedMessages() { Sink::Query query; query.resources << mResourceInstanceIdentifier; @@ -189,36 +282,30 @@ void MailSyncTest::testFetchNewMessages() auto msg = KMime::Message::Ptr::create(); msg->subject(true)->fromUnicodeString("Foobar", "utf8"); msg->assemble(); - createMessage(QStringList() << "test", msg->encodedContent(true)); + auto messageIdentifier = createMessage(QStringList() << "test", msg->encodedContent(true)); Store::synchronize(query).exec().waitForFinished(); ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); - auto job = Store::fetchAll(query).then>([](const QList &mails) { - QCOMPARE(mails.size(), 2); - }); - VERIFYEXEC(job); -} + { + auto job = Store::fetchAll(query).then>([](const QList &mails) { + QCOMPARE(mails.size(), 2); + }); + VERIFYEXEC(job); + } -void MailSyncTest::testFetchRemovedMessages() -{ - Sink::Query query; - query.resources << mResourceInstanceIdentifier; - query.request().request(); - // Ensure all local data is processed - VERIFYEXEC(Store::synchronize(query)); - ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); - - removeMessage(QStringList() << "test", "2:*"); + removeMessage(QStringList() << "test", messageIdentifier); Store::synchronize(query).exec().waitForFinished(); ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); - auto job = Store::fetchAll(query).then>([](const QList &mails) { - QCOMPARE(mails.size(), 1); - }); - VERIFYEXEC(job); + { + auto job = Store::fetchAll(query).then>([](const QList &mails) { + QCOMPARE(mails.size(), 1); + }); + VERIFYEXEC(job); + } } //TODO test flag sync diff --git a/tests/mailsynctest.h b/tests/mailsynctest.h index f9ee7be..b0fda7c 100644 --- a/tests/mailsynctest.h +++ b/tests/mailsynctest.h @@ -45,6 +45,13 @@ do {\ namespace Sink { +/** + * Tests if the resource can synchronize (read-only) emails. + * + * The default testenvironment is: + * * INBOX + * * INBOX.test + */ class MailSyncTest : public QObject { Q_OBJECT @@ -59,8 +66,8 @@ protected: virtual void removeResourceFromDisk(const QByteArray &mResourceInstanceIdentifier) = 0; virtual void createFolder(const QStringList &folderPath) = 0; virtual void removeFolder(const QStringList &folderPath) = 0; - virtual void createMessage(const QStringList &folderPath, const QByteArray &message) = 0; - virtual void removeMessage(const QStringList &folderPath, const QByteArray &message) = 0; + virtual QByteArray createMessage(const QStringList &folderPath, const QByteArray &message) = 0; + virtual void removeMessage(const QStringList &folderPath, const QByteArray &messageIdentifier) = 0; private slots: void initTestCase(); @@ -68,13 +75,14 @@ private slots: void cleanup(); void testListFolders(); + void testListNewFolder(); + void testListRemovedFolder(); void testListFolderHierarchy(); - void testListNewFolders(); - void testListRemovedFolders(); + void testListNewSubFolder(); + void testListRemovedSubFolder(); void testListMails(); - void testFetchNewMessages(); - void testFetchRemovedMessages(); + void testFetchNewRemovedMessages(); void testFailingSync(); }; -- cgit v1.2.3